Skip to content

Instantly share code, notes, and snippets.

@emk
Created December 29, 2011 17:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emk/1535189 to your computer and use it in GitHub Desktop.
Save emk/1535189 to your computer and use it in GitHub Desktop.
Pass by value/reference in Go, take 2
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)
}
;; 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
}
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