diff options
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/arch1_amd64.go | 2 | ||||
| -rw-r--r-- | src/runtime/asm_amd64.s | 26 | ||||
| -rw-r--r-- | src/runtime/cgocall.go | 5 | ||||
| -rw-r--r-- | src/runtime/proc1.go | 3 | ||||
| -rw-r--r-- | src/runtime/runtime2.go | 1 | ||||
| -rw-r--r-- | src/runtime/stack1.go | 17 | ||||
| -rw-r--r-- | src/runtime/traceback.go | 6 |
7 files changed, 56 insertions, 4 deletions
diff --git a/src/runtime/arch1_amd64.go b/src/runtime/arch1_amd64.go index 794b7f65c4..7a7f3e75fc 100644 --- a/src/runtime/arch1_amd64.go +++ b/src/runtime/arch1_amd64.go @@ -8,7 +8,7 @@ const ( thechar = '6' _BigEndian = 0 _CacheLineSize = 64 - _RuntimeGogoBytes = 64 + (goos_plan9|goos_solaris|goos_windows)*16 + _RuntimeGogoBytes = 80 + (goos_plan9|goos_solaris|goos_windows)*16 _PhysPageSize = 4096 _PCQuantum = 1 _Int64Align = 8 diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index b1bf4ca987..f09e5ae250 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -134,6 +134,7 @@ TEXT runtime·gosave(SB), NOSPLIT, $0-8 MOVQ BX, gobuf_pc(AX) MOVQ $0, gobuf_ret(AX) MOVQ $0, gobuf_ctxt(AX) + MOVQ BP, gobuf_bp(AX) get_tls(CX) MOVQ g(CX), BX MOVQ BX, gobuf_g(AX) @@ -150,9 +151,11 @@ TEXT runtime·gogo(SB), NOSPLIT, $0-8 MOVQ gobuf_sp(BX), SP // restore SP MOVQ gobuf_ret(BX), AX MOVQ gobuf_ctxt(BX), DX + MOVQ gobuf_bp(BX), BP MOVQ $0, gobuf_sp(BX) // clear to help garbage collector MOVQ $0, gobuf_ret(BX) MOVQ $0, gobuf_ctxt(BX) + MOVQ $0, gobuf_bp(BX) MOVQ gobuf_pc(BX), BX JMP BX @@ -170,6 +173,7 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-8 LEAQ fn+0(FP), BX // caller's SP MOVQ BX, (g_sched+gobuf_sp)(AX) MOVQ AX, (g_sched+gobuf_g)(AX) + MOVQ BP, (g_sched+gobuf_bp)(AX) // switch to m->g0 & its stack, call fn MOVQ g(CX), BX @@ -228,6 +232,7 @@ switch: MOVQ SI, (g_sched+gobuf_pc)(AX) MOVQ SP, (g_sched+gobuf_sp)(AX) MOVQ AX, (g_sched+gobuf_g)(AX) + MOVQ BP, (g_sched+gobuf_bp)(AX) // switch to g0 MOVQ DX, g(CX) @@ -303,6 +308,7 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0 LEAQ 8(SP), AX // f's SP MOVQ AX, (g_sched+gobuf_sp)(SI) MOVQ DX, (g_sched+gobuf_ctxt)(SI) + MOVQ BP, (g_sched+gobuf_bp)(SI) // Call newstack on m->g0's stack. MOVQ m_g0(BX), BX @@ -592,6 +598,7 @@ TEXT gosave<>(SB),NOSPLIT,$0 MOVQ R9, (g_sched+gobuf_sp)(R8) MOVQ $0, (g_sched+gobuf_ret)(R8) MOVQ $0, (g_sched+gobuf_ctxt)(R8) + MOVQ BP, (g_sched+gobuf_bp)(R8) RET // asmcgocall(void(*fn)(void*), void *arg) @@ -747,17 +754,30 @@ havem: MOVQ (g_sched+gobuf_sp)(SI), DI // prepare stack as DI MOVQ (g_sched+gobuf_pc)(SI), BX MOVQ BX, -8(DI) - LEAQ -(8+8)(DI), SP + // Compute the size of the frame, including return PC and, if + // GOEXPERIMENT=framepointer, the saved based pointer + LEAQ x+0(FP), AX + SUBQ SP, AX + SUBQ AX, DI + MOVQ DI, SP + MOVQ R8, 0(SP) CALL runtime·cgocallbackg(SB) MOVQ 0(SP), R8 + // Compute the size of the frame again. FP and SP have + // completely different values here than they did above, + // but only their difference matters. + LEAQ x+0(FP), AX + SUBQ SP, AX + // Restore g->sched (== m->curg->sched) from saved values. get_tls(CX) MOVQ g(CX), SI - MOVQ 8(SP), BX + MOVQ SP, DI + ADDQ AX, DI + MOVQ -8(DI), 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. diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 96873cc2da..e7aeb7bee3 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -225,6 +225,11 @@ func cgocallbackg1() { cb = (*args)(unsafe.Pointer(sp + 4*ptrSize)) case "amd64": // On amd64, stack frame is one word, plus caller PC. + if framepointer_enabled { + // In this case, there's also saved BP. + cb = (*args)(unsafe.Pointer(sp + 3*ptrSize)) + break + } cb = (*args)(unsafe.Pointer(sp + 2*ptrSize)) case "386": // On 386, stack frame is three words, plus caller PC. diff --git a/src/runtime/proc1.go b/src/runtime/proc1.go index 8f5aaa8630..31bbd0d366 100644 --- a/src/runtime/proc1.go +++ b/src/runtime/proc1.go @@ -113,6 +113,9 @@ func schedinit() { sched.maxmcount = 10000 + // Cache the framepointer experiment. This affects stack unwinding. + framepointer_enabled = haveexperiment("framepointer") + tracebackinit() symtabinit() stackinit() diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index fd448901a6..e38d11a59d 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -125,6 +125,7 @@ type gobuf struct { ctxt unsafe.Pointer // this has to be a pointer so that gc scans it ret uintreg lr uintptr + bp uintptr // for GOEXPERIMENT=framepointer } // Known to compiler. diff --git a/src/runtime/stack1.go b/src/runtime/stack1.go index 8ad331777c..1e9ccfebb5 100644 --- a/src/runtime/stack1.go +++ b/src/runtime/stack1.go @@ -46,6 +46,9 @@ var stackpoolmu mutex var stackfreequeue stack +// Cached value of haveexperiment("framepointer") +var framepointer_enabled bool + func stackinit() { if _StackCacheSize&_PageMask != 0 { throw("cache size must be a multiple of page size") @@ -308,6 +311,8 @@ var mapnames = []string{ // | args from caller | // +------------------+ <- frame->argp // | return address | +// +------------------+ +// | caller's BP (*) | (*) if framepointer_enabled && varp < sp // +------------------+ <- frame->varp // | locals | // +------------------+ @@ -460,6 +465,18 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool { adjustpointers(unsafe.Pointer(frame.varp-size), &bv, adjinfo, f) } + // Adjust saved base pointer if there is one. + if thechar == '6' && frame.argp-frame.varp == 2*ptrSize { + if !framepointer_enabled { + print("runtime: found space for saved base pointer, but no framepointer experiment") + throw("bad frame layout") + } + if stackDebug >= 3 { + print(" saved bp\n") + } + adjustpointer(adjinfo, unsafe.Pointer(frame.varp)) + } + // Adjust arguments. if frame.arglen > 0 { var bv bitvector diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 499256f42d..c813453399 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -232,6 +232,12 @@ func gentraceback(pc0 uintptr, sp0 uintptr, lr0 uintptr, gp *g, skip int, pcbuf frame.varp -= regSize } + // If framepointer_enabled and there's a frame, then + // there's a saved bp here. + if GOARCH == "amd64" && frame.varp > frame.sp && framepointer_enabled { + frame.varp -= ptrSize + } + // Derive size of arguments. // Most functions have a fixed-size argument block, // so we can use metadata about the function f. |
