1
0
mirror of https://github.com/golang/go synced 2024-09-29 16:34:31 -06:00

runtime: use TOPFRAME to identify top-of-frame functions

No change to actual runtime, but helps reduce the laundry list
of functions.

mcall, morestack, and asmcgocall are not actually top-of-frame,
so those need more attention in follow-up CLs.

mstart moved to assembly so that it can be marked TOPFRAME.

Since TOPFRAME also tells DWARF consumers not to unwind
this way, this change should also improve debuggers a
marginal amount.

This CL is part of a stack adding windows/arm64
support (#36439), intended to land in the Go 1.17 cycle.
This CL is, however, not windows/arm64-specific.
It is cleanup meant to make the port (and future ports) easier.

Change-Id: If1e0d46ca973de5e46b62948d076f675f285b5d9
Reviewed-on: https://go-review.googlesource.com/c/go/+/288802
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Russ Cox 2021-01-28 16:22:52 -05:00
parent fbe74dbf42
commit 54da3ab385
15 changed files with 62 additions and 22 deletions

View File

@ -89,7 +89,7 @@ GLOBL _rt0_386_lib_argc<>(SB),NOPTR, $4
DATA _rt0_386_lib_argv<>(SB)/4, $0
GLOBL _rt0_386_lib_argv<>(SB),NOPTR, $4
TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME,$0
TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
// Copy arguments forward on an even stack.
// Users of this function jump to it, they don't call it.
MOVL 0(SP), AX
@ -269,6 +269,10 @@ TEXT runtime·asminit(SB),NOSPLIT,$0-0
FLDCW runtime·controlWord64(SB)
RET
TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
CALL runtime·mstart0(SB)
RET // not reached
/*
* go-routine
*/
@ -1307,7 +1311,7 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
// The top-most function running on a goroutine
// returns to goexit+PCQuantum.
TEXT runtime·goexit(SB),NOSPLIT,$0-0
TEXT runtime·goexit(SB),NOSPLIT|TOPFRAME,$0-0
BYTE $0x90 // NOP
CALL runtime·goexit1(SB) // does not return
// traceback from goexit1 must hit code range of goexit

View File

@ -84,7 +84,7 @@ GLOBL _rt0_amd64_lib_argc<>(SB),NOPTR, $8
DATA _rt0_amd64_lib_argv<>(SB)/8, $0
GLOBL _rt0_amd64_lib_argv<>(SB),NOPTR, $8
TEXT runtime·rt0_go(SB),NOSPLIT,$0
TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
// copy arguments forward on an even stack
MOVQ DI, AX // argc
MOVQ SI, BX // argv
@ -250,6 +250,10 @@ TEXT runtime·asminit(SB),NOSPLIT,$0-0
// No per-thread init.
RET
TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
CALL runtime·mstart0(SB)
RET // not reached
/*
* go-routine
*/
@ -1440,7 +1444,7 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
// so as to make it identifiable to traceback (this
// function it used as a sentinel; traceback wants to
// see the func PC, not a wrapper PC).
TEXT runtime·goexit<ABIInternal>(SB),NOSPLIT,$0-0
TEXT runtime·goexit<ABIInternal>(SB),NOSPLIT|TOPFRAME,$0-0
BYTE $0x90 // NOP
CALL runtime·goexit1(SB) // does not return
// traceback from goexit1 must hit code range of goexit

View File

@ -112,7 +112,7 @@ GLOBL _rt0_arm_lib_argv<>(SB),NOPTR,$4
// using NOFRAME means do not save LR on stack.
// argc is in R0, argv is in R1.
TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME,$0
TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
MOVW $0xcafebabe, R12
// copy arguments forward on an even stack
@ -202,6 +202,10 @@ TEXT runtime·asminit(SB),NOSPLIT,$0-0
WORD $0xeee1ba10 // vmsr fpscr, r11
RET
TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
BL runtime·mstart0(SB)
RET // not reached
/*
* go-routine
*/

View File

@ -8,7 +8,7 @@
#include "funcdata.h"
#include "textflag.h"
TEXT runtime·rt0_go(SB),NOSPLIT,$0
TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
// SP = stack; R0 = argc; R1 = argv
SUB $32, RSP
@ -109,6 +109,10 @@ TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
RET
TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
BL runtime·mstart0(SB)
RET // not reached
/*
* go-routine
*/

View File

@ -11,7 +11,7 @@
#define REGCTXT R22
TEXT runtime·rt0_go(SB),NOSPLIT,$0
TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
// R29 = stack; R4 = argc; R5 = argv
ADDV $-24, R29
@ -85,6 +85,10 @@ TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
RET
TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
JAL runtime·mstart0(SB)
RET // not reached
/*
* go-routine
*/

View File

@ -11,7 +11,7 @@
#define REGCTXT R22
TEXT runtime·rt0_go(SB),NOSPLIT,$0
TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
// R29 = stack; R4 = argc; R5 = argv
ADDU $-12, R29
@ -86,6 +86,10 @@ TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
TEXT runtime·asminit(SB),NOSPLIT,$0-0
RET
TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
JAL runtime·mstart0(SB)
RET // not reached
/*
* go-routine
*/

View File

@ -16,7 +16,7 @@
#define cgoCalleeStackSize 32
#endif
TEXT runtime·rt0_go(SB),NOSPLIT,$0
TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
// R1 = stack; R3 = argc; R4 = argv; R13 = C TLS base pointer
// initialize essential registers
@ -124,6 +124,10 @@ TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0
XOR R0, R0
RET
TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
BL runtime·mstart0(SB)
RET // not reached
/*
* go-routine
*/

View File

@ -7,7 +7,7 @@
#include "textflag.h"
// func rt0_go()
TEXT runtime·rt0_go(SB),NOSPLIT,$0
TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
// X2 = stack; A0 = argc; A1 = argv
ADD $-24, X2
MOV A0, 8(X2) // argc
@ -70,6 +70,10 @@ nocgo:
WORD $0 // crash if reached
RET
TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
CALL runtime·mstart0(SB)
RET // not reached
// void setg_gcc(G*); set g called from gcc with g in A0
TEXT setg_gcc<>(SB),NOSPLIT,$0-0
MOV A0, g

View File

@ -84,7 +84,7 @@ GLOBL _rt0_s390x_lib_argc<>(SB), NOPTR, $8
DATA _rt0_s90x_lib_argv<>(SB)/8, $0
GLOBL _rt0_s390x_lib_argv<>(SB), NOPTR, $8
TEXT runtime·rt0_go(SB),NOSPLIT,$0
TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
// R2 = argc; R3 = argv; R11 = temp; R13 = g; R15 = stack pointer
// C TLS base pointer in AR0:AR1
@ -170,6 +170,10 @@ TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
RET
TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
CALL runtime·mstart0(SB)
RET // not reached
/*
* go-routine
*/

View File

@ -7,7 +7,7 @@
#include "funcdata.h"
#include "textflag.h"
TEXT runtime·rt0_go(SB), NOSPLIT|NOFRAME, $0
TEXT runtime·rt0_go(SB), NOSPLIT|NOFRAME|TOPFRAME, $0
// save m->g0 = g0
MOVD $runtime·g0(SB), runtime·m0+m_g0(SB)
// save m0 to g0->m
@ -24,6 +24,10 @@ TEXT runtime·rt0_go(SB), NOSPLIT|NOFRAME, $0
CALL runtime·mstart(SB) // WebAssembly stack will unwind when switching to another goroutine
UNDEF
TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
CALL runtime·mstart0(SB)
RET // not reached
DATA runtime·mainPC+0(SB)/8,$runtime·main(SB)
GLOBL runtime·mainPC(SB),RODATA,$8
@ -424,7 +428,7 @@ CALLFN(·call268435456, 268435456)
CALLFN(·call536870912, 536870912)
CALLFN(·call1073741824, 1073741824)
TEXT runtime·goexit(SB), NOSPLIT, $0-0
TEXT runtime·goexit(SB), NOSPLIT|TOPFRAME, $0-0
NOP // first PC of goexit is skipped
CALL runtime·goexit1(SB) // does not return
UNDEF

View File

@ -1234,7 +1234,10 @@ func mStackIsSystemAllocated() bool {
}
// mstart is the entry-point for new Ms.
//
// It is written in assembly, marked TOPFRAME, and calls mstart0.
func mstart()
// mstart0 is the Go entry-point for new Ms.
// This must not split the stack because we may not even have stack
// bounds set up yet.
//
@ -1243,7 +1246,7 @@ func mStackIsSystemAllocated() bool {
//
//go:nosplit
//go:nowritebarrierrec
func mstart() {
func mstart0() {
_g_ := getg()
osStack := _g_.stack.lo == 0

View File

@ -174,7 +174,7 @@ TEXT runtime·profileloop(SB),NOSPLIT,$0
ADDL $12, SP
JMP CX
TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
TEXT runtime·externalthreadhandler(SB),NOSPLIT|TOPFRAME,$0
PUSHL BP
MOVL SP, BP
PUSHL BX

View File

@ -215,7 +215,7 @@ TEXT runtime·profileloop(SB),NOSPLIT|NOFRAME,$8
CALL runtime·externalthreadhandler(SB)
RET
TEXT runtime·externalthreadhandler(SB),NOSPLIT|NOFRAME,$0
TEXT runtime·externalthreadhandler(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
PUSHQ BP
MOVQ SP, BP
PUSHQ BX

View File

@ -257,7 +257,7 @@ TEXT runtime·profileloop(SB),NOSPLIT|NOFRAME,$0
// 0 | retval |
// +----------------+
//
TEXT runtime·externalthreadhandler(SB),NOSPLIT|NOFRAME,$0
TEXT runtime·externalthreadhandler(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
MOVM.DB.W [R4-R11, R14], (R13) // push {r4-r11, lr}
SUB $(m__size + g__size + 20), R13 // space for locals
MOVW R0, 12(R13)

View File

@ -1002,12 +1002,9 @@ func tracebackHexdump(stk stack, frame *stkframe, bad uintptr) {
// Does f mark the top of a goroutine stack?
func topofstack(f funcInfo, g0 bool) bool {
return f.funcID == funcID_goexit ||
f.funcID == funcID_mstart ||
return f.flag&funcFlag_TOPFRAME != 0 ||
f.funcID == funcID_mcall ||
f.funcID == funcID_morestack ||
f.funcID == funcID_rt0_go ||
f.funcID == funcID_externalthreadhandler ||
// asmcgocall is TOS on the system stack because it
// switches to the system stack, but in this case we
// can come back to the regular stack and still want