1
0
mirror of https://github.com/golang/go synced 2024-11-23 20:50:04 -07:00

runtime: eliminate uses of BP on amd64

Any place that clobbers BP in the runtime can potentially interfere
with frame pointer unwinding with GOEXPERIMENT=framepointer.  This
change eliminates uses of BP in the runtime to address this problem.
We have spare registers everywhere this occurs, so there's no downside
to eliminating BP.  Where possible, this uses the same new register as
the amd64p32 runtime, which doesn't use BP due to restrictions placed
on it by NaCL.

One nice side effect of this is that it will let perf/VTune unwind the
call stack even through a call to systemstack, which will let us get
really good call graphs from the garbage collector.

Change-Id: I0ffa14cb4dd2b613a7049b8ec59df37c52286212
Reviewed-on: https://go-review.googlesource.com/3390
Reviewed-by: Minux Ma <minux@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Austin Clements 2015-01-27 18:29:02 -05:00
parent 28b5118415
commit 20a6ff7261
6 changed files with 61 additions and 61 deletions

View File

@ -96,8 +96,8 @@ ok:
CALL runtime·schedinit(SB)
// create a new goroutine to start program
MOVQ $runtime·main·f(SB), BP // entry
PUSHQ BP
MOVQ $runtime·main·f(SB), AX // entry
PUSHQ AX
PUSHQ $0 // arg size
CALL runtime·newproc(SB)
POPQ AX
@ -213,8 +213,8 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-8
CMPQ AX, DX
JEQ noswitch
MOVQ m_curg(BX), BP
CMPQ AX, BP
MOVQ m_curg(BX), R8
CMPQ AX, R8
JEQ switch
// Bad: g is not gsignal, not g0, not curg. What is it?
@ -224,8 +224,8 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-8
switch:
// save our state in g->sched. Pretend to
// be systemstack_switch if the G stack is scanned.
MOVQ $runtime·systemstack_switch(SB), BP
MOVQ BP, (g_sched+gobuf_pc)(AX)
MOVQ $runtime·systemstack_switch(SB), SI
MOVQ SI, (g_sched+gobuf_pc)(AX)
MOVQ SP, (g_sched+gobuf_sp)(AX)
MOVQ AX, (g_sched+gobuf_g)(AX)
@ -305,9 +305,9 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0
MOVQ DX, (g_sched+gobuf_ctxt)(SI)
// Call newstack on m->g0's stack.
MOVQ m_g0(BX), BP
MOVQ BP, g(CX)
MOVQ (g_sched+gobuf_sp)(BP), SP
MOVQ m_g0(BX), BX
MOVQ BX, g(CX)
MOVQ (g_sched+gobuf_sp)(BX), SP
CALL runtime·newstack(SB)
MOVQ $0, 0x1003 // crash if newstack returns
RET
@ -619,17 +619,17 @@ TEXT asmcgocall<>(SB),NOSPLIT,$0-0
// We get called to create new OS threads too, and those
// come in on the m->g0 stack already.
get_tls(CX)
MOVQ g(CX), BP
MOVQ g_m(BP), BP
MOVQ m_g0(BP), SI
MOVQ g(CX), R8
MOVQ g_m(R8), R8
MOVQ m_g0(R8), SI
MOVQ g(CX), DI
CMPQ SI, DI
JEQ nosave
MOVQ m_gsignal(BP), SI
MOVQ m_gsignal(R8), SI
CMPQ SI, DI
JEQ nosave
MOVQ m_g0(BP), SI
MOVQ m_g0(R8), SI
CALL gosave<>(SB)
MOVQ SI, g(CX)
MOVQ (g_sched+gobuf_sp)(SI), SP
@ -683,15 +683,15 @@ TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-24
// the linker analysis by using an indirect call through AX.
get_tls(CX)
#ifdef GOOS_windows
MOVL $0, BP
MOVL $0, BX
CMPQ CX, $0
JEQ 2(PC)
#endif
MOVQ g(CX), BP
CMPQ BP, $0
MOVQ g(CX), BX
CMPQ BX, $0
JEQ needm
MOVQ g_m(BP), BP
MOVQ BP, R8 // holds oldm until end of function
MOVQ g_m(BX), BX
MOVQ BX, R8 // holds oldm until end of function
JMP havem
needm:
MOVQ $0, 0(SP)
@ -699,8 +699,8 @@ needm:
CALL AX
MOVQ 0(SP), R8
get_tls(CX)
MOVQ g(CX), BP
MOVQ g_m(BP), BP
MOVQ g(CX), BX
MOVQ g_m(BX), BX
// Set m->sched.sp = SP, so that if a panic happens
// during the function we are about to execute, it will
@ -713,7 +713,7 @@ needm:
// and then systemstack will try to use it. If we don't set it here,
// that restored SP will be uninitialized (typically 0) and
// will not be usable.
MOVQ m_g0(BP), SI
MOVQ m_g0(BX), SI
MOVQ SP, (g_sched+gobuf_sp)(SI)
havem:
@ -722,7 +722,7 @@ havem:
// Save current sp in m->g0->sched.sp in preparation for
// switch back to m->curg stack.
// NOTE: unwindm knows that the saved g->sched.sp is at 0(SP).
MOVQ m_g0(BP), SI
MOVQ m_g0(BX), SI
MOVQ (g_sched+gobuf_sp)(SI), AX
MOVQ AX, 0(SP)
MOVQ SP, (g_sched+gobuf_sp)(SI)
@ -742,11 +742,11 @@ havem:
// the earlier calls.
//
// In the new goroutine, 0(SP) holds the saved R8.
MOVQ m_curg(BP), SI
MOVQ m_curg(BX), SI
MOVQ SI, g(CX)
MOVQ (g_sched+gobuf_sp)(SI), DI // prepare stack as DI
MOVQ (g_sched+gobuf_pc)(SI), BP
MOVQ BP, -8(DI)
MOVQ (g_sched+gobuf_pc)(SI), BX
MOVQ BX, -8(DI)
LEAQ -(8+8)(DI), SP
MOVQ R8, 0(SP)
CALL runtime·cgocallbackg(SB)
@ -755,17 +755,17 @@ havem:
// Restore g->sched (== m->curg->sched) from saved values.
get_tls(CX)
MOVQ g(CX), SI
MOVQ 8(SP), BP
MOVQ BP, (g_sched+gobuf_pc)(SI)
MOVQ 8(SP), BX
MOVQ BX, (g_sched+gobuf_pc)(SI)
LEAQ (8+8)(SP), DI
MOVQ DI, (g_sched+gobuf_sp)(SI)
// Switch back to m->g0's stack and restore m->g0->sched.sp.
// (Unlike m->curg, the g0 goroutine never uses sched.pc,
// so we do not have to restore it.)
MOVQ g(CX), BP
MOVQ g_m(BP), BP
MOVQ m_g0(BP), SI
MOVQ g(CX), BX
MOVQ g_m(BX), BX
MOVQ m_g0(BX), SI
MOVQ SI, g(CX)
MOVQ (g_sched+gobuf_sp)(SI), SP
MOVQ 0(SP), AX
@ -915,8 +915,8 @@ aes0to15:
// a page boundary, so we can load it directly.
MOVOU -16(AX), X0
ADDQ CX, CX
MOVQ $masks<>(SB), BP
PAND (BP)(CX*8), X0
MOVQ $masks<>(SB), AX
PAND (AX)(CX*8), X0
// scramble 3 times
AESENC X6, X0
@ -931,8 +931,8 @@ endofpage:
// Then shift bytes down using pshufb.
MOVOU -32(AX)(CX*1), X0
ADDQ CX, CX
MOVQ $shifts<>(SB), BP
PSHUFB (BP)(CX*8), X0
MOVQ $shifts<>(SB), AX
PSHUFB (AX)(CX*8), X0
AESENC X6, X0
AESENC X7, X0
AESENC X7, X0
@ -1384,13 +1384,13 @@ TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
CMPQ SI, DI
JEQ allsame
CMPQ BX, DX
MOVQ DX, BP
CMOVQLT BX, BP // BP = min(alen, blen) = # of bytes to compare
CMPQ BP, $8
MOVQ DX, R8
CMOVQLT BX, R8 // R8 = min(alen, blen) = # of bytes to compare
CMPQ R8, $8
JB small
loop:
CMPQ BP, $16
CMPQ R8, $16
JBE _0through16
MOVOU (SI), X0
MOVOU (DI), X1
@ -1400,7 +1400,7 @@ loop:
JNE diff16 // branch if at least one byte is not equal
ADDQ $16, SI
ADDQ $16, DI
SUBQ $16, BP
SUBQ $16, R8
JMP loop
// AX = bit mask of differences
@ -1415,15 +1415,15 @@ diff16:
// 0 through 16 bytes left, alen>=8, blen>=8
_0through16:
CMPQ BP, $8
CMPQ R8, $8
JBE _0through8
MOVQ (SI), AX
MOVQ (DI), CX
CMPQ AX, CX
JNE diff8
_0through8:
MOVQ -8(SI)(BP*1), AX
MOVQ -8(DI)(BP*1), CX
MOVQ -8(SI)(R8*1), AX
MOVQ -8(DI)(R8*1), CX
CMPQ AX, CX
JEQ allsame
@ -1440,7 +1440,7 @@ diff8:
// 0-7 bytes in common
small:
LEAQ (BP*8), CX // bytes left -> bits left
LEAQ (R8*8), CX // bytes left -> bits left
NEGQ CX // - bits lift (== 64 - bits left mod 64)
JEQ allsame
@ -1450,7 +1450,7 @@ small:
MOVQ (SI), SI
JMP si_finish
si_high:
MOVQ -8(SI)(BP*1), SI
MOVQ -8(SI)(R8*1), SI
SHRQ CX, SI
si_finish:
SHLQ CX, SI
@ -1461,7 +1461,7 @@ si_finish:
MOVQ (DI), DI
JMP di_finish
di_high:
MOVQ -8(DI)(BP*1), DI
MOVQ -8(DI)(R8*1), DI
SHRQ CX, DI
di_finish:
SHLQ CX, DI

View File

@ -186,9 +186,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
MOVQ R10, 40(SP)
// g = m->signal
MOVQ g_m(R10), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
MOVQ g_m(R10), AX
MOVQ m_gsignal(AX), AX
MOVQ AX, g(BX)
MOVQ DI, 0(SP)
MOVQ SI, 8(SP)

View File

@ -180,9 +180,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
MOVQ R10, 40(SP)
// g = m->signal
MOVQ g_m(R10), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
MOVQ g_m(R10), AX
MOVQ m_gsignal(AX), AX
MOVQ AX, g(BX)
MOVQ DI, 0(SP)
MOVQ SI, 8(SP)

View File

@ -216,9 +216,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
MOVQ R10, 40(SP)
// g = m->gsignal
MOVQ g_m(R10), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
MOVQ g_m(R10), AX
MOVQ m_gsignal(AX), AX
MOVQ AX, g(BX)
MOVQ DI, 0(SP)
MOVQ SI, 8(SP)

View File

@ -236,9 +236,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
MOVQ R10, 40(SP)
// g = m->signal
MOVQ g_m(R10), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
MOVQ g_m(R10), AX
MOVQ m_gsignal(AX), AX
MOVQ AX, g(BX)
MOVQ DI, 0(SP)
MOVQ SI, 8(SP)

View File

@ -227,9 +227,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$64
MOVQ R10, 40(SP)
// g = m->signal
MOVQ g_m(R10), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
MOVQ g_m(R10), AX
MOVQ m_gsignal(AX), AX
MOVQ AX, g(BX)
MOVQ DI, 0(SP)
MOVQ SI, 8(SP)