Created
December 29, 2011 17:41
-
-
Save emk/1535189 to your computer and use it in GitHub Desktop.
Pass by value/reference in Go, take 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
// Holds any type of value. | |
var mixedSlice = make([]interface{}, 0) | |
// Holds only quaternions. | |
var quaternionSlice = make([]Quaternion, 0) | |
// A huge pass-by-value type: 256 bits wide. | |
type Quaternion struct { | |
real, i, j, k float64 | |
} | |
// We take a simple (large) value as an argument. | |
func pushQuaternion(q Quaternion) { | |
quaternionSlice = append(quaternionSlice, q) | |
} | |
// We take an arbitrary interface as an argument. This might be an | |
// integer, a pointer, or a giant struct like Quaternion. | |
func pushMixed(i interface{}) { | |
mixedSlice = append(mixedSlice, i) | |
} | |
// Call our functions with various types of arguments. | |
func main() { | |
pushQuaternion(Quaternion{0,1,2,3}) | |
pushMixed(int32(1)) | |
pushMixed(Quaternion{4,5,6,7}) | |
pushMixed(&Quaternion{4,5,6,7}) | |
pushMixed(nil) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; objdump -d -M intel --no-show-raw-insn 6.out | |
0000000000400dfe <main.main>: | |
// Call our functions with various types of arguments. | |
func main() { | |
;; Grow our stack frame if necessary. | |
400dfe: mov rcx,QWORD PTR fs:0xfffffffffffffff0 | |
400e07: cmp rsp,QWORD PTR [rcx] | |
400e0a: ja 400e11 <main.main+0x13> | |
400e0c: call 401c80 <runtime.morestack00> | |
;; Allocate space on the stack. | |
400e11: sub rsp,0x78 | |
pushQuaternion(Quaternion{0,1,2,3}) | |
;; Copy 64 bits from data segment to local variable. | |
400e15: lea rsi,ds:0x417870 | |
400e1d: lea rdi,[rsp+0x38] | |
400e22: mov rcx,0x4 | |
400e29: rep movs QWORD PTR es:[rdi],QWORD PTR ds:[rsi] | |
;; Copy 64 bits from local variable to top of stack. | |
;; The optimizer leaves something to be desired here. | |
400e2c: lea rsi,[rsp+0x38] | |
400e31: lea rdi,[rsp] | |
400e35: mov rcx,0x4 | |
400e3c: rep movs QWORD PTR es:[rdi],QWORD PTR ds:[rsi] | |
;; Call pushQuaternion. | |
400e3f: call 400c00 <main.pushQuaternion> | |
pushMixed(int32(1)) | |
;; Box an int32 with type tag 0x40fa88. | |
400e44: mov QWORD PTR [rsp],0x40fa88 | |
400e4c: mov DWORD PTR [rsp+0x8],0x1 | |
400e54: call 4024b9 <runtime.convT2E> | |
;; Boxed value gets returned at rsp+0x10, so copy those | |
;; 16 bytes and pass them as a parameter to pushMixed. | |
400e59: lea rsi,[rsp+0x10] | |
400e5e: lea rdi,[rsp] | |
400e62: movs QWORD PTR es:[rdi],QWORD PTR ds:[rsi] | |
400e64: movs QWORD PTR es:[rdi],QWORD PTR ds:[rsi] | |
;; Call pushMixed. | |
400e66: call 400cfe <main.pushMixed> | |
pushMixed(Quaternion{4,5,6,7}) | |
;; Copy 64 bits from data segment to local variable. | |
400e6b: lea rsi,ds:0x417890 | |
400e73: lea rdi,[rsp+0x58] | |
400e78: mov rcx,0x4 | |
400e7f: rep movs QWORD PTR es:[rdi],QWORD PTR ds:[rsi] | |
;; Pass type tag 0x411cb0 as parameter. | |
400e82: mov QWORD PTR [rsp],0x411cb0 | |
;; Pass local variable as parameter. | |
400e8a: lea rsi,[rsp+0x58] | |
400e8f: lea rdi,[rsp+0x8] | |
400e94: mov rcx,0x4 | |
400e9b: rep movs QWORD PTR es:[rdi],QWORD PTR ds:[rsi] | |
;; Box our Quaternion. | |
400e9e: call 4024b9 <runtime.convT2E> | |
;; Pass 16 bytes to pushMixed, as before. Our Quaternion | |
;; doesn't fit in 16 bytes (with or without a type tag), | |
;; so it now lives in allocated storage. | |
400ea3: lea rsi,[rsp+0x28] | |
400ea8: lea rdi,[rsp] | |
400eac: movs QWORD PTR es:[rdi],QWORD PTR ds:[rsi] | |
400eae: movs QWORD PTR es:[rdi],QWORD PTR ds:[rsi] | |
400eb0: call 400cfe <main.pushMixed> | |
pushMixed(&Quaternion{4,5,6,7}) | |
;; Allocate 32 bytes of storage for our Quaternion. | |
400eb5: mov DWORD PTR [rsp],0x20 | |
400ebc: call 403501 <runtime.new> | |
400ec1: mov rax,QWORD PTR [rsp+0x8] | |
400ec6: movsd xmm0,QWORD PTR ds:0x423018 | |
400ecf: movsd QWORD PTR [rax],xmm0 | |
400ed3: movsd xmm0,QWORD PTR ds:0x423020 | |
400edc: movsd QWORD PTR [rax+0x8],xmm0 | |
400ee1: movsd xmm0,QWORD PTR ds:0x423028 | |
400eea: movsd QWORD PTR [rax+0x10],xmm0 | |
400eef: movsd xmm0,QWORD PTR ds:0x423030 | |
400ef8: movsd QWORD PTR [rax+0x18],xmm0 | |
;; Box our *Quaternion with tag 0x40e640. Note that | |
;; this is different than the tag for Quaternion itself. | |
400efd: mov QWORD PTR [rsp],0x40e640 | |
400f05: mov QWORD PTR [rsp+0x8],rax | |
400f0a: call 4024b9 <runtime.convT2E> | |
;; Pass 16 bytes to pushMixed, as usual. | |
400f0f: lea rsi,[rsp+0x10] | |
400f14: lea rdi,[rsp] | |
400f18: movs QWORD PTR es:[rdi],QWORD PTR ds:[rsi] | |
400f1a: movs QWORD PTR es:[rdi],QWORD PTR ds:[rsi] | |
400f1c: call 400cfe <main.pushMixed> | |
} | |
;; Reset our stack pointer and return. | |
400f21: add rsp,0x78 | |
400f25: ret | |
000000000040238a <copyin>: | |
static void | |
copyin(Type *t, void *src, void **dst) | |
40238a: mov rcx,QWORD PTR fs:0xfffffffffffffff0 | |
402393: cmp rsp,QWORD PTR [rcx] | |
402396: ja 40239d <copyin+0x13> | |
402398: call 401ceb <runtime.morestack24> | |
40239d: sub rsp,0x38 | |
4023a1: mov rcx,QWORD PTR [rsp+0x40] | |
{ | |
int32 wid, alg; | |
void *p; | |
wid = t->size; | |
4023a6: mov rdx,QWORD PTR [rcx+0x10] | |
4023aa: movsxd rdx,edx | |
alg = t->alg; | |
4023ad: movzx eax,BYTE PTR [rcx+0x1c] | |
4023b1: mov ebx,eax | |
4023b3: mov DWORD PTR [rsp+0x30],eax | |
if(wid <= sizeof(*dst)) | |
4023b7: cmp edx,0x8 | |
4023ba: jg 4023e9 <copyin+0x5f> | |
runtime·algarray[alg].copy(wid, dst, src); | |
4023bc: mov DWORD PTR [rsp],edx | |
4023bf: mov rax,QWORD PTR [rsp+0x50] | |
4023c4: mov QWORD PTR [rsp+0x8],rax | |
4023c9: mov rax,QWORD PTR [rsp+0x48] | |
4023ce: mov QWORD PTR [rsp+0x10],rax | |
4023d3: movsxd rcx,ebx | |
4023d6: shl rcx,0x5 | |
4023da: mov rax,QWORD PTR [rcx*1+0x423ae0] | |
4023e2: call rax | |
else { | |
p = runtime·mal(wid); | |
runtime·algarray[alg].copy(wid, p, src); | |
*dst = p; | |
4023e4: add rsp,0x38 | |
4023e8: ret | |
alg = t->alg; | |
if(wid <= sizeof(*dst)) | |
runtime·algarray[alg].copy(wid, dst, src); | |
else { | |
p = runtime·mal(wid); | |
4023e9: mov DWORD PTR [rsp+0x34],edx | |
4023ed: movsxd rcx,edx | |
4023f0: mov QWORD PTR [rsp],rcx | |
4023f4: call 4034bd <runtime.mal> | |
4023f9: mov rcx,rax | |
runtime·algarray[alg].copy(wid, p, src); | |
4023fc: mov eax,DWORD PTR [rsp+0x34] | |
402400: mov DWORD PTR [rsp],eax | |
402403: mov QWORD PTR [rsp+0x28],rcx | |
402408: mov QWORD PTR [rsp+0x8],rcx | |
40240d: mov rax,QWORD PTR [rsp+0x48] | |
402412: mov QWORD PTR [rsp+0x10],rax | |
402417: mov ecx,DWORD PTR [rsp+0x30] | |
40241b: movsxd rcx,ecx | |
40241e: shl rcx,0x5 | |
402422: mov rax,QWORD PTR [rcx*1+0x423ae0] | |
40242a: call rax | |
*dst = p; | |
40242c: mov rax,QWORD PTR [rsp+0x50] | |
402431: mov rcx,QWORD PTR [rsp+0x28] | |
402436: mov QWORD PTR [rax],rcx | |
402439: jmp 4023e4 <copyin+0x5a> | |
} | |
} | |
00000000004024b9 <runtime.convT2E>: | |
// func convT2E(typ *byte, elem any) (ret any) | |
#pragma textflag 7 | |
void | |
runtime·convT2E(Type *t, ...) | |
4024b9: sub rsp,0x40 | |
{ | |
byte *elem; | |
Eface *ret; | |
int32 wid; | |
elem = (byte*)(&t+1); | |
4024bd: lea rax,[rsp+0x50] | |
4024c2: mov QWORD PTR [rsp+0x38],rax | |
wid = t->size; | |
4024c7: mov rax,QWORD PTR [rsp+0x48] | |
4024cc: mov rax,QWORD PTR [rax+0x10] | |
4024d0: movsxd rax,eax | |
ret = (Eface*)(elem + runtime·rnd(wid, Structrnd)); | |
4024d3: mov DWORD PTR [rsp],eax | |
4024d6: mov ecx,0x8 | |
4024db: mov DWORD PTR [rsp+0x4],ecx | |
4024df: call 40a276 <runtime.rnd> | |
4024e4: mov rbp,QWORD PTR [rsp+0x38] | |
4024e9: mov rbx,QWORD PTR [rsp+0x48] | |
4024ee: add rax,rbp | |
ret->type = t; | |
4024f1: mov QWORD PTR [rax],rbx | |
copyin(t, elem, &ret->data); | |
4024f4: mov QWORD PTR [rsp],rbx | |
4024f8: mov QWORD PTR [rsp+0x8],rbp | |
4024fd: add rax,0x8 | |
402501: mov QWORD PTR [rsp+0x10],rax | |
402506: call 40238a <copyin> | |
40250b: add rsp,0x40 | |
40250f: ret | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pushMixed(nil) | |
400f21: lea rdi,[rsp] | |
400f25: xor rax,rax | |
400f28: stos QWORD PTR es:[rdi],rax | |
400f2a: stos QWORD PTR es:[rdi],rax | |
400f2c: call 400cfe <main.pushMixed> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment