1
0
mirror of https://github.com/golang/go synced 2024-11-19 02:04:42 -07:00

runtime: change top-most return PC from goexit to goexit+PCQuantum

If you get a stack of PCs from Callers, it would be expected
that every PC is immediately after a call instruction, so to find
the line of the call, you look up the line for PC-1.
CL 163550043 now explicitly documents that.

The most common exception to this is the top-most return PC
on the stack, which is the entry address of the runtime.goexit
function. Subtracting 1 from that PC will end up in a different
function entirely.

To remove this special case, make the top-most return PC
goexit+PCQuantum and then implement goexit in assembly
so that the first instruction can be skipped.

Fixes #7690.

LGTM=r
R=r
CC=golang-codereviews
https://golang.org/cl/170720043
This commit is contained in:
Russ Cox 2014-10-29 20:37:44 -04:00
parent f9c4c16dce
commit a5a0733144
5 changed files with 27 additions and 5 deletions

View File

@ -2284,3 +2284,9 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
MOVL m_curg(AX), AX MOVL m_curg(AX), AX
MOVL (g_stack+stack_hi)(AX), AX MOVL (g_stack+stack_hi)(AX), AX
RET RET
// The top-most function running on a goroutine
// returns to goexit+PCQuantum.
TEXT runtime·goexit(SB),NOSPLIT,$0-0
BYTE $0x90 // NOP
CALL runtime·goexit1(SB) // does not return

View File

@ -2229,3 +2229,9 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
MOVQ m_curg(AX), AX MOVQ m_curg(AX), AX
MOVQ (g_stack+stack_hi)(AX), AX MOVQ (g_stack+stack_hi)(AX), AX
RET RET
// The top-most function running on a goroutine
// returns to goexit+PCQuantum.
TEXT runtime·goexit(SB),NOSPLIT,$0-0
BYTE $0x90 // NOP
CALL runtime·goexit1(SB) // does not return

View File

@ -1079,3 +1079,9 @@ TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
TEXT runtime·return0(SB), NOSPLIT, $0 TEXT runtime·return0(SB), NOSPLIT, $0
MOVL $0, AX MOVL $0, AX
RET RET
// The top-most function running on a goroutine
// returns to goexit+PCQuantum.
TEXT runtime·goexit(SB),NOSPLIT,$0-0
BYTE $0x90 // NOP
CALL runtime·goexit1(SB) // does not return

View File

@ -1320,3 +1320,9 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$8
MOVW saveG-8(SP), g MOVW saveG-8(SP), g
MOVW saveR11-4(SP), R11 MOVW saveR11-4(SP), R11
RET RET
// The top-most function running on a goroutine
// returns to goexit+PCQuantum.
TEXT runtime·goexit(SB),NOSPLIT,$-4-0
MOVW R0, R0 // NOP
BL runtime·goexit1(SB) // does not return

View File

@ -1643,12 +1643,10 @@ runtime·gosched_m(G *gp)
} }
// Finishes execution of the current goroutine. // Finishes execution of the current goroutine.
// Need to mark it as nosplit, because it runs with sp > stackbase. // Must be NOSPLIT because it is called from Go.
// Since it does not return it does not matter. But if it is preempted
// at the split stack check, GC will complain about inconsistent sp.
#pragma textflag NOSPLIT #pragma textflag NOSPLIT
void void
runtime·goexit(void) runtime·goexit1(void)
{ {
void (*fn)(G*); void (*fn)(G*);
@ -2192,7 +2190,7 @@ runtime·newproc1(FuncVal *fn, byte *argp, int32 narg, int32 nret, void *callerp
runtime·memclr((byte*)&newg->sched, sizeof newg->sched); runtime·memclr((byte*)&newg->sched, sizeof newg->sched);
newg->sched.sp = (uintptr)sp; newg->sched.sp = (uintptr)sp;
newg->sched.pc = (uintptr)runtime·goexit; newg->sched.pc = (uintptr)runtime·goexit + PCQuantum; // +PCQuantum so that previous instruction is in same function
newg->sched.g = newg; newg->sched.g = newg;
runtime·gostartcallfn(&newg->sched, fn); runtime·gostartcallfn(&newg->sched, fn);
newg->gopc = (uintptr)callerpc; newg->gopc = (uintptr)callerpc;