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:
parent
f9c4c16dce
commit
a5a0733144
@ -2284,3 +2284,9 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
|
||||
MOVL m_curg(AX), AX
|
||||
MOVL (g_stack+stack_hi)(AX), AX
|
||||
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
|
||||
|
@ -2229,3 +2229,9 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
|
||||
MOVQ m_curg(AX), AX
|
||||
MOVQ (g_stack+stack_hi)(AX), AX
|
||||
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
|
||||
|
@ -1079,3 +1079,9 @@ TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
|
||||
TEXT runtime·return0(SB), NOSPLIT, $0
|
||||
MOVL $0, AX
|
||||
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
|
||||
|
@ -1320,3 +1320,9 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$8
|
||||
MOVW saveG-8(SP), g
|
||||
MOVW saveR11-4(SP), R11
|
||||
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
|
||||
|
@ -1643,12 +1643,10 @@ runtime·gosched_m(G *gp)
|
||||
}
|
||||
|
||||
// Finishes execution of the current goroutine.
|
||||
// Need to mark it as nosplit, because it runs with sp > stackbase.
|
||||
// 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.
|
||||
// Must be NOSPLIT because it is called from Go.
|
||||
#pragma textflag NOSPLIT
|
||||
void
|
||||
runtime·goexit(void)
|
||||
runtime·goexit1(void)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
runtime·gostartcallfn(&newg->sched, fn);
|
||||
newg->gopc = (uintptr)callerpc;
|
||||
|
Loading…
Reference in New Issue
Block a user