aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/amd64
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-06-17 15:12:16 -0700
committerRuss Cox <rsc@golang.org>2009-06-17 15:12:16 -0700
commit7343e03c433ebb0c302ed97bf832ad3bd3170de6 (patch)
tree26899cbde2c38fd1275b590dcdd6bf92ab0f80c9 /src/pkg/runtime/amd64
parent3b576a770413e799d487e861e3a75027f59ee81c (diff)
downloadgo-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.h26
-rw-r--r--src/pkg/runtime/amd64/asm.s134
-rw-r--r--src/pkg/runtime/amd64/traceback.c32
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.