Skip to content

Instantly share code, notes, and snippets.

@freeformz
Created June 30, 2017 04:28
Show Gist options
  • Save freeformz/810f8877f68facee80138bf7e6f5952f to your computer and use it in GitHub Desktop.
Save freeformz/810f8877f68facee80138bf7e6f5952f to your computer and use it in GitHub Desktop.
00096 (main.go:21) TEXT "".nooops(SB)
00097 (main.go:21) FUNCDATA $0, "".gcargs·4(SB)
00098 (main.go:21) FUNCDATA $1, "".gclocals·5(SB)
00099 (main.go:21) TYPE s(FP), type.[]int(SB)
00100 (main.go:21) TYPE .autotmp_14-8(SP), type.*int(SB)
00101 (main.go:21) TYPE .autotmp_13-16(SP), type.int(SB)
00102 (main.go:21) TYPE v-24(SP), type.int(SB)
00103 (main.go:22) MOVQ $0, AX // AX = 0
00104 (main.go:22) MOVQ "".s(FP), CX // CX = pointer to first value in array
00105 (main.go:22) MOVQ AX, ""..autotmp_13-16(SP) // autotmp_13 = 0
00106 (main.go:22) MOVQ CX, ""..autotmp_14-8(SP) // autotmp_14 = pointer to first value in array
00107 (main.go:22) MOVQ "".s+8(FP), DX // DX = length of slice (len=6)
00108 (main.go:22) CMPQ AX, DX // compare and jump to 128 if AX (0) = DX(6)
00109 (main.go:22) JGE $0, 128
00110 (main.go:22) MOVQ (CX), BX // BX = first array value (CX is pointing to the first value in the array)
00111 (main.go:22) MOVQ BX, "".v-24(SP) // v = first array value
00112 (main.go:23) MOVQ "".s+16(FP), SI // SI = the capacity of the slice (cap=6)
00113 (main.go:23) CMPQ SI, $2 // compare and jump to 126 (panic) if capacity (6) <= 2
00114 (main.go:23) JCS $0, 126
00115 (main.go:24) CALL runtime.printlock(SB) // setup and do println
00116 (main.go:24) MOVQ "".v-24(SP), AX
00117 (main.go:24) MOVQ AX, (SP)
00118 (main.go:24) CALL runtime.printint(SB)
00119 (main.go:24) CALL runtime.printnl(SB)
00120 (main.go:24) CALL runtime.printunlock(SB)
00121 (main.go:22) MOVQ ""..autotmp_14-8(SP), AX // AX = pointer to first value in array
00122 (main.go:22) LEAQ 8(AX), CX // CX = AX + 8 quadwords; pointer to 2nd value in array
00123 (main.go:22) MOVQ ""..autotmp_13-16(SP), AX // AX = 0
00124 (main.go:22) INCQ AX // AX = 1
00125 (main.go:22) JMP 105 // jump to the top of the loop. At this point CX is pointing to the second item in the array and AX was incremented.
// rinse and repeate until the compare on 108 fails and we jump to 128, which returns.
00126 (main.go:23) CALL runtime.panicslice(SB)
00127 (main.go:23) UNDEF
00128 (main.go:27) RET
00129 (<unknown line number>) END
@freeformz
Copy link
Author

freeformz commented Jun 30, 2017

Actual function in question:
screen shot 2017-06-29 at 9 32 02 pm

Which is similar to : https://play.golang.org/p/OXhdsneBec

@davecheney
Copy link

00103 (main.go:22) MOVQ $0, AX // AX = 0

AX is the loop induction variable; the i in for i := 0; i < len(s); i++ {
It does not have a local, ie not an autotmp, so it only lives in registers, if it is spilled, it will be reloaded from the stack.

00104 (main.go:22) MOVQ "".s(FP), CX // CX = pointer to first value in array

This should have been printed as "".s+0(FP), CX which is the first value passed to the function, on the stack. The first 3 words following the frame pointer are a slice header, s+0(FP) is the ptr to the backing array, s+8 is the len, and s+16 is the cap.

00105 (main.go:22) MOVQ AX, ""..autotmp_13-16(SP) // autotmp_13 = 0
00106 (main.go:22) MOVQ CX, ""..autotmp_14-8(SP) // autotmp_14 = pointer to first value in array

Compiler is spilling these to the stack, probably because AX and CX are used in the call to println.

00107 (main.go:22) MOVQ "".s+8(FP), DX // DX = length of slice (len=6)
00108 (main.go:22) CMPQ AX, DX // compare and jump to 128 if AX (0) = DX(6)
00109 (main.go:22) JGE $0, 128

load the slice's len and compare the current induction variable with len; jump out of the loop if we've passed len.

Ignoring all the flushing of AX to the stack unnecessarily (maybe this code was compiled with -N), this line

00124 (main.go:22) INCQ AX // AX = 1
00125 (main.go:22) JMP 105 // jump to the top of the loop. At this point CX is pointing to the second item in the array and AX was incremented.

Jump above the load of DX from s+8(FP), which is odd. I always expected

for i, v := range s to compile into

for i, n := 0, len(s); i < n; i++ { v := s[[i]; /// }

but this reads like

for i := 0; i < len(s); i++ { ... }

Did this come out of the compiler, or was it by hand?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment