diff options
| author | Russ Cox <rsc@golang.org> | 2009-06-17 15:12:16 -0700 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2009-06-17 15:12:16 -0700 |
| commit | 7343e03c433ebb0c302ed97bf832ad3bd3170de6 (patch) | |
| tree | 26899cbde2c38fd1275b590dcdd6bf92ab0f80c9 /src/pkg/runtime/amd64 | |
| parent | 3b576a770413e799d487e861e3a75027f59ee81c (diff) | |
| download | go-7343e03c433ebb0c302ed97bf832ad3bd3170de6.tar.xz | |
runtime: stack growth adjustments, cleanup
* keep coherent SP/PC in gobuf
(i.e., SP that would be in use at that PC)
* gogocall replaces setspgoto,
should work better in presence of link registers
* delete unused system calls
only amd64; 386 is now broken
R=r
DELTA=548 (183 added, 183 deleted, 182 changed)
OCL=30381
CL=30442
Diffstat (limited to 'src/pkg/runtime/amd64')
| -rw-r--r-- | src/pkg/runtime/amd64/asm.h | 26 | ||||
| -rw-r--r-- | src/pkg/runtime/amd64/asm.s | 134 | ||||
| -rw-r--r-- | src/pkg/runtime/amd64/traceback.c | 32 |
3 files changed, 122 insertions, 70 deletions
diff --git a/src/pkg/runtime/amd64/asm.h b/src/pkg/runtime/amd64/asm.h new file mode 100644 index 0000000000..c32da75445 --- /dev/null +++ b/src/pkg/runtime/amd64/asm.h @@ -0,0 +1,26 @@ +// Assembly constants + +#define g R15 +#define m R14 + +// offsets in m +#define m_g0 0 +#define m_morepc 8 +#define m_morebuf 16 +#define m_morearg 40 +#define m_cret 48 +#define m_procid 56 +#define m_gsignal 64 +#define m_tls 72 +#define m_sched 104 + +// offsets in gobuf +#define gobuf_sp 0 +#define gobuf_pc 8 +#define gobuf_g 16 + +// offsets in g +#define g_stackguard 0 +#define g_stackbase 8 +#define g_defer 16 +#define g_sched 24 diff --git a/src/pkg/runtime/amd64/asm.s b/src/pkg/runtime/amd64/asm.s index 6fc01bbc98..825acc4657 100644 --- a/src/pkg/runtime/amd64/asm.s +++ b/src/pkg/runtime/amd64/asm.s @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +#include "amd64/asm.h" TEXT _rt0_amd64(SB),7,$-8 // copy arguments forward on an even stack - MOVQ 0(SP), AX // argc LEAQ 8(SP), BX // argv SUBQ $(4*8+7), SP // 2args 2auto @@ -15,16 +15,14 @@ TEXT _rt0_amd64(SB),7,$-8 MOVQ BX, 24(SP) // set the per-goroutine and per-mach registers - - LEAQ m0(SB), R14 // dedicated m. register - LEAQ g0(SB), R15 // dedicated g. register - MOVQ R15, 0(R14) // m has pointer to its g0 + LEAQ m0(SB), m + LEAQ g0(SB), g + MOVQ g, m_g0(m) // m has pointer to its g0 // create istack out of the given (operating system) stack - LEAQ (-8192+104)(SP), AX - MOVQ AX, 0(R15) // 0(R15) is stack limit (w 104b guard) - MOVQ SP, 8(R15) // 8(R15) is base + MOVQ AX, g_stackguard(g) + MOVQ SP, g_stackbase(g) CLD // convention is D is always left cleared CALL check(SB) @@ -39,7 +37,7 @@ TEXT _rt0_amd64(SB),7,$-8 // create a new goroutine to start program PUSHQ $mainstart(SB) // entry - PUSHQ $16 // arg size + PUSHQ $0 // arg size CALL sys·newproc(SB) POPQ AX POPQ AX @@ -67,57 +65,105 @@ TEXT breakpoint(SB),7,$0 /* * go-routine */ -TEXT gogo(SB), 7, $0 - MOVQ 8(SP), AX // gobuf - MOVQ 0(AX), SP // restore SP - MOVQ 8(AX), AX - MOVQ AX, 0(SP) // put PC on the stack - MOVL $1, AX // return 1 - RET +// uintptr gosave(Gobuf*) +// save state in Gobuf; setjmp TEXT gosave(SB), 7, $0 MOVQ 8(SP), AX // gobuf - MOVQ SP, 0(AX) // save SP - MOVQ 0(SP), BX - MOVQ BX, 8(AX) // save PC + LEAQ 8(SP), BX // caller's SP + MOVQ BX, gobuf_sp(AX) + MOVQ 0(SP), BX // caller's PC + MOVQ BX, gobuf_pc(AX) + MOVQ g, gobuf_g(AX) MOVL $0, AX // return 0 RET +// void gogo(Gobuf*, uintptr) +// restore state from Gobuf; longjmp +TEXT gogo(SB), 7, $0 + MOVQ 16(SP), AX // return 2nd arg + MOVQ 8(SP), BX // gobuf + MOVQ gobuf_g(BX), g + MOVQ 0(g), CX // make sure g != nil + MOVQ gobuf_sp(BX), SP // restore SP + MOVQ gobuf_pc(BX), BX + JMP BX + +// void gogocall(Gobuf*, void (*fn)(void)) +// restore state from Gobuf but then call fn. +// (call fn, returning to state in Gobuf) +TEXT gogocall(SB), 7, $0 + MOVQ 16(SP), AX // fn + MOVQ 8(SP), BX // gobuf + MOVQ gobuf_g(BX), g + MOVQ 0(g), CX // make sure g != nil + MOVQ gobuf_sp(BX), SP // restore SP + MOVQ gobuf_pc(BX), BX + PUSHQ BX + JMP AX + POPQ BX // not reached + /* * support for morestack */ +// Called during function prolog when more stack is needed. +TEXT sys·morestack(SB),7,$0 + // Called from f. + // Set m->morebuf to f's caller. + MOVQ 8(SP), AX // f's caller's PC + MOVQ AX, (m_morebuf+gobuf_pc)(m) + LEAQ 16(SP), AX // f's caller's SP + MOVQ AX, (m_morebuf+gobuf_sp)(m) + MOVQ g, (m_morebuf+gobuf_g)(m) + + // Set m->morepc to f's PC. + MOVQ 0(SP), AX + MOVQ AX, m_morepc(m) + + // Call newstack on m's scheduling stack. + MOVQ m_g0(m), g + MOVQ (m_sched+gobuf_sp)(m), SP + CALL newstack(SB) + MOVQ $0, 0x1003 // crash if newstack returns + RET + +// Return point when leaving stack. +TEXT sys·lessstack(SB), 7, $0 + // Save return value in m->cret + MOVQ AX, m_cret(m) + + // Call oldstack on m's scheduling stack. + MOVQ m_g0(m), g + MOVQ (m_sched+gobuf_sp)(m), SP + CALL oldstack(SB) + MOVQ $0, 0x1004 // crash if oldstack returns + RET + // morestack trampolines TEXT sys·morestack00+0(SB),7,$0 MOVQ $0, AX - MOVQ AX, 8(R14) + MOVQ AX, m_morearg(m) MOVQ $sys·morestack+0(SB), AX JMP AX TEXT sys·morestack01+0(SB),7,$0 SHLQ $32, AX - MOVQ AX, 8(R14) + MOVQ AX, m_morearg(m) MOVQ $sys·morestack+0(SB), AX JMP AX TEXT sys·morestack10+0(SB),7,$0 MOVLQZX AX, AX - MOVQ AX, 8(R14) + MOVQ AX, m_morearg(m) MOVQ $sys·morestack+0(SB), AX JMP AX TEXT sys·morestack11+0(SB),7,$0 - MOVQ AX, 8(R14) + MOVQ AX, m_morearg(m) MOVQ $sys·morestack+0(SB), AX JMP AX -TEXT sys·morestackx(SB),7,$0 - POPQ AX - SHLQ $35, AX - MOVQ AX, 8(R14) - MOVQ $sys·morestack(SB), AX - JMP AX - // subcases of morestack01 // with const of 8,16,...48 TEXT sys·morestack8(SB),7,$0 @@ -150,31 +196,13 @@ TEXT sys·morestack48(SB),7,$0 MOVQ $sys·morestackx(SB), AX JMP AX -// return point when leaving new stack. save AX, jmp to lessstack to switch back -TEXT retfromnewstack(SB), 7, $0 - MOVQ AX, 16(R14) // save AX in m->cret - MOVQ $lessstack(SB), AX +TEXT sys·morestackx(SB),7,$0 + POPQ AX + SHLQ $35, AX + MOVQ AX, m_morearg(m) + MOVQ $sys·morestack(SB), AX JMP AX -// gogo, returning 2nd arg instead of 1 -TEXT gogoret(SB), 7, $0 - MOVQ 16(SP), AX // return 2nd arg - MOVQ 8(SP), BX // gobuf - MOVQ 0(BX), SP // restore SP - MOVQ 8(BX), BX - MOVQ BX, 0(SP) // put PC on the stack - RET - -TEXT setspgoto(SB), 7, $0 - MOVQ 8(SP), AX // SP - MOVQ 16(SP), BX // fn to call - MOVQ 24(SP), CX // fn to return - MOVQ AX, SP - PUSHQ CX - JMP BX - POPQ AX // not reached - RET - // bool cas(int32 *val, int32 old, int32 new) // Atomically: // if(*val == old){ diff --git a/src/pkg/runtime/amd64/traceback.c b/src/pkg/runtime/amd64/traceback.c index 16d7bed72e..80e79b0e8b 100644 --- a/src/pkg/runtime/amd64/traceback.c +++ b/src/pkg/runtime/amd64/traceback.c @@ -24,12 +24,11 @@ traceback(byte *pc0, byte *sp, G *g) stk = (Stktop*)g->stackbase; for(n=0; n<100; n++) { - while(pc == (uint64)retfromnewstack) { + if(pc == (uint64)sys·lessstack) { // pop to earlier stack block - sp = stk->oldsp; - stk = (Stktop*)stk->oldbase; - pc = *(uint64*)(sp+8); - sp += 16; // two irrelevant calls on stack: morestack plus its call + pc = (uintptr)stk->gobuf.pc; + sp = stk->gobuf.sp; + stk = (Stktop*)stk->stackbase; } f = findfunc(pc); if(f == nil) { @@ -46,8 +45,8 @@ traceback(byte *pc0, byte *sp, G *g) printf("%p unknown pc\n", pc); return; } - if(f->frame < 8) // assembly funcs say 0 but lie - sp += 8; + if(f->frame < sizeof(uintptr)) // assembly funcs say 0 but lie + sp += sizeof(uintptr); else sp += f->frame; @@ -56,7 +55,7 @@ traceback(byte *pc0, byte *sp, G *g) // main(0x1, 0x2, 0x3) printf("%S", f->name); if(pc > f->entry) - printf("+%X", pc - f->entry); + printf("+%p", (uintptr)(pc - f->entry)); printf(" %S:%d\n", f->src, funcline(f, pc-1)); // -1 to get to CALL instr. printf("\t%S(", f->name); for(i = 0; i < f->args; i++) { @@ -70,7 +69,7 @@ traceback(byte *pc0, byte *sp, G *g) } prints(")\n"); - pc = *(uint64*)(sp-8); + pc = *(uintptr*)(sp-sizeof(uintptr)); if(pc <= 0x1000) return; } @@ -106,20 +105,19 @@ runtime·Caller(int32 n, uint64 retpc, String retfile, int32 retline, bool retbo // now unwind n levels stk = (Stktop*)g->stackbase; while(n-- > 0) { - while(pc == (uint64)retfromnewstack) { - sp = stk->oldsp; - stk = (Stktop*)stk->oldbase; - pc = *(uint64*)(sp+8); - sp += 16; + while(pc == (uintptr)sys·lessstack) { + pc = (uintptr)stk->gobuf.pc; + sp = stk->gobuf.sp; + stk = (Stktop*)stk->stackbase; } - if(f->frame < 8) // assembly functions lie - sp += 8; + if(f->frame < sizeof(uintptr)) // assembly functions lie + sp += sizeof(uintptr); else sp += f->frame; loop: - pc = *(uint64*)(sp-8); + pc = *((uintptr*)sp - 1); if(pc <= 0x1000 || (f = findfunc(pc)) == nil) { // dangerous, but let's try this. // see if it is a closure. |
