mirror of
https://github.com/golang/go
synced 2024-11-17 20:04:47 -07:00
runtime: framepointers are no longer an experiment - hard code them
I think they are no longer experimental status. Might as well promote them to permanent. Change-Id: Id1259601b3dd2061dd60df86ee48080bfb575d2f Reviewed-on: https://go-review.googlesource.com/c/go/+/249857 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
29634436fd
commit
5c2c6d3fbf
@ -507,7 +507,7 @@ func createSimpleVar(fnsym *obj.LSym, n *Node) *dwarf.Var {
|
|||||||
if Ctxt.FixedFrameSize() == 0 {
|
if Ctxt.FixedFrameSize() == 0 {
|
||||||
offs -= int64(Widthptr)
|
offs -= int64(Widthptr)
|
||||||
}
|
}
|
||||||
if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) || objabi.GOARCH == "arm64" {
|
if objabi.Framepointer_enabled || objabi.GOARCH == "arm64" {
|
||||||
// There is a word space for FP on ARM64 even if the frame pointer is disabled
|
// There is a word space for FP on ARM64 even if the frame pointer is disabled
|
||||||
offs -= int64(Widthptr)
|
offs -= int64(Widthptr)
|
||||||
}
|
}
|
||||||
@ -703,7 +703,7 @@ func stackOffset(slot ssa.LocalSlot) int32 {
|
|||||||
if Ctxt.FixedFrameSize() == 0 {
|
if Ctxt.FixedFrameSize() == 0 {
|
||||||
base -= int64(Widthptr)
|
base -= int64(Widthptr)
|
||||||
}
|
}
|
||||||
if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) || objabi.GOARCH == "arm64" {
|
if objabi.Framepointer_enabled || objabi.GOARCH == "arm64" {
|
||||||
// There is a word space for FP on ARM64 even if the frame pointer is disabled
|
// There is a word space for FP on ARM64 even if the frame pointer is disabled
|
||||||
base -= int64(Widthptr)
|
base -= int64(Widthptr)
|
||||||
}
|
}
|
||||||
|
@ -588,7 +588,7 @@ func (s *regAllocState) init(f *Func) {
|
|||||||
if s.f.Config.hasGReg {
|
if s.f.Config.hasGReg {
|
||||||
s.allocatable &^= 1 << s.GReg
|
s.allocatable &^= 1 << s.GReg
|
||||||
}
|
}
|
||||||
if s.f.Config.ctxt.Framepointer_enabled && s.f.Config.FPReg >= 0 {
|
if objabi.Framepointer_enabled && s.f.Config.FPReg >= 0 {
|
||||||
s.allocatable &^= 1 << uint(s.f.Config.FPReg)
|
s.allocatable &^= 1 << uint(s.f.Config.FPReg)
|
||||||
}
|
}
|
||||||
if s.f.Config.LinkReg != -1 {
|
if s.f.Config.LinkReg != -1 {
|
||||||
|
@ -621,7 +621,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||||||
|
|
||||||
prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd)
|
prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd)
|
||||||
|
|
||||||
if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
|
if objabi.Framepointer_enabled {
|
||||||
q1 = obj.Appendp(q1, c.newprog)
|
q1 = obj.Appendp(q1, c.newprog)
|
||||||
q1.Pos = p.Pos
|
q1.Pos = p.Pos
|
||||||
q1.As = AMOVD
|
q1.As = AMOVD
|
||||||
@ -764,7 +764,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||||||
p.To.Reg = REGSP
|
p.To.Reg = REGSP
|
||||||
p.Spadj = -c.autosize
|
p.Spadj = -c.autosize
|
||||||
|
|
||||||
if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
|
if objabi.Framepointer_enabled {
|
||||||
p = obj.Appendp(p, c.newprog)
|
p = obj.Appendp(p, c.newprog)
|
||||||
p.As = ASUB
|
p.As = ASUB
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
@ -777,7 +777,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||||||
} else {
|
} else {
|
||||||
/* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
|
/* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
|
||||||
|
|
||||||
if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
|
if objabi.Framepointer_enabled {
|
||||||
p.As = AMOVD
|
p.As = AMOVD
|
||||||
p.From.Type = obj.TYPE_MEM
|
p.From.Type = obj.TYPE_MEM
|
||||||
p.From.Reg = REGSP
|
p.From.Reg = REGSP
|
||||||
@ -865,7 +865,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case obj.ADUFFCOPY:
|
case obj.ADUFFCOPY:
|
||||||
if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
|
if objabi.Framepointer_enabled {
|
||||||
// ADR ret_addr, R27
|
// ADR ret_addr, R27
|
||||||
// STP (FP, R27), -24(SP)
|
// STP (FP, R27), -24(SP)
|
||||||
// SUB 24, SP, FP
|
// SUB 24, SP, FP
|
||||||
@ -918,7 +918,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case obj.ADUFFZERO:
|
case obj.ADUFFZERO:
|
||||||
if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
|
if objabi.Framepointer_enabled {
|
||||||
// ADR ret_addr, R27
|
// ADR ret_addr, R27
|
||||||
// STP (FP, R27), -24(SP)
|
// STP (FP, R27), -24(SP)
|
||||||
// SUB 24, SP, FP
|
// SUB 24, SP, FP
|
||||||
|
@ -682,10 +682,9 @@ type Link struct {
|
|||||||
GenAbstractFunc func(fn *LSym)
|
GenAbstractFunc func(fn *LSym)
|
||||||
Errors int
|
Errors int
|
||||||
|
|
||||||
InParallel bool // parallel backend phase in effect
|
InParallel bool // parallel backend phase in effect
|
||||||
Framepointer_enabled bool
|
UseBASEntries bool // use Base Address Selection Entries in location lists and PC ranges
|
||||||
UseBASEntries bool // use Base Address Selection Entries in location lists and PC ranges
|
IsAsm bool // is the source assembly language, which may contain surprising idioms (e.g., call tables)
|
||||||
IsAsm bool // is the source assembly language, which may contain surprising idioms (e.g., call tables)
|
|
||||||
|
|
||||||
// state for writing objects
|
// state for writing objects
|
||||||
Text []*LSym
|
Text []*LSym
|
||||||
|
@ -53,7 +53,6 @@ func Linknew(arch *LinkArch) *Link {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctxt.Flag_optimize = true
|
ctxt.Flag_optimize = true
|
||||||
ctxt.Framepointer_enabled = objabi.Framepointer_enabled(objabi.GOOS, arch.Name)
|
|
||||||
return ctxt
|
return ctxt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4833,12 +4833,12 @@ func (ab *AsmBuf) doasm(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog) {
|
|||||||
ctxt.Diag("directly calling duff when dynamically linking Go")
|
ctxt.Diag("directly calling duff when dynamically linking Go")
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxt.Framepointer_enabled && yt.zcase == Zcallduff && ctxt.Arch.Family == sys.AMD64 {
|
if yt.zcase == Zcallduff && ctxt.Arch.Family == sys.AMD64 {
|
||||||
// Maintain BP around call, since duffcopy/duffzero can't do it
|
// Maintain BP around call, since duffcopy/duffzero can't do it
|
||||||
// (the call jumps into the middle of the function).
|
// (the call jumps into the middle of the function).
|
||||||
// This makes it possible to see call sites for duffcopy/duffzero in
|
// This makes it possible to see call sites for duffcopy/duffzero in
|
||||||
// BP-based profiling tools like Linux perf (which is the
|
// BP-based profiling tools like Linux perf (which is the
|
||||||
// whole point of obj.Framepointer_enabled).
|
// whole point of maintaining frame pointers in Go).
|
||||||
// MOVQ BP, -16(SP)
|
// MOVQ BP, -16(SP)
|
||||||
// LEAQ -16(SP), BP
|
// LEAQ -16(SP), BP
|
||||||
ab.Put(bpduff1)
|
ab.Put(bpduff1)
|
||||||
@ -4852,7 +4852,7 @@ func (ab *AsmBuf) doasm(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog) {
|
|||||||
r.Siz = 4
|
r.Siz = 4
|
||||||
ab.PutInt32(0)
|
ab.PutInt32(0)
|
||||||
|
|
||||||
if ctxt.Framepointer_enabled && yt.zcase == Zcallduff && ctxt.Arch.Family == sys.AMD64 {
|
if yt.zcase == Zcallduff && ctxt.Arch.Family == sys.AMD64 {
|
||||||
// Pop BP pushed above.
|
// Pop BP pushed above.
|
||||||
// MOVQ 0(BP), BP
|
// MOVQ 0(BP), BP
|
||||||
ab.Put(bpduff2)
|
ab.Put(bpduff2)
|
||||||
|
@ -582,7 +582,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var bpsize int
|
var bpsize int
|
||||||
if ctxt.Arch.Family == sys.AMD64 && ctxt.Framepointer_enabled &&
|
if ctxt.Arch.Family == sys.AMD64 &&
|
||||||
!p.From.Sym.NoFrame() && // (1) below
|
!p.From.Sym.NoFrame() && // (1) below
|
||||||
!(autoffset == 0 && p.From.Sym.NoSplit()) && // (2) below
|
!(autoffset == 0 && p.From.Sym.NoSplit()) && // (2) below
|
||||||
!(autoffset == 0 && !hasCall) { // (3) below
|
!(autoffset == 0 && !hasCall) { // (3) below
|
||||||
|
@ -133,9 +133,8 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Framepointer_enabled(goos, goarch string) bool {
|
// Note: must agree with runtime.framepointer_enabled.
|
||||||
return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && (goos == "linux" || goos == "darwin"))
|
var Framepointer_enabled = GOARCH == "amd64" || GOARCH == "arm64" && (GOOS == "linux" || GOOS == "darwin")
|
||||||
}
|
|
||||||
|
|
||||||
func addexp(s string) {
|
func addexp(s string) {
|
||||||
// Could do general integer parsing here, but the runtime copy doesn't yet.
|
// Could do general integer parsing here, but the runtime copy doesn't yet.
|
||||||
@ -159,7 +158,6 @@ func addexp(s string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
framepointer_enabled int = 1
|
|
||||||
Fieldtrack_enabled int
|
Fieldtrack_enabled int
|
||||||
Preemptibleloops_enabled int
|
Preemptibleloops_enabled int
|
||||||
Staticlockranking_enabled int
|
Staticlockranking_enabled int
|
||||||
@ -174,7 +172,6 @@ var exper = []struct {
|
|||||||
val *int
|
val *int
|
||||||
}{
|
}{
|
||||||
{"fieldtrack", &Fieldtrack_enabled},
|
{"fieldtrack", &Fieldtrack_enabled},
|
||||||
{"framepointer", &framepointer_enabled},
|
|
||||||
{"preemptibleloops", &Preemptibleloops_enabled},
|
{"preemptibleloops", &Preemptibleloops_enabled},
|
||||||
{"staticlockranking", &Staticlockranking_enabled},
|
{"staticlockranking", &Staticlockranking_enabled},
|
||||||
}
|
}
|
||||||
|
@ -775,14 +775,6 @@ func (ctxt *Link) linksetup() {
|
|||||||
sb.SetSize(0)
|
sb.SetSize(0)
|
||||||
sb.AddUint8(uint8(objabi.GOARM))
|
sb.AddUint8(uint8(objabi.GOARM))
|
||||||
}
|
}
|
||||||
|
|
||||||
if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
|
|
||||||
fpe := ctxt.loader.LookupOrCreateSym("runtime.framepointer_enabled", 0)
|
|
||||||
sb := ctxt.loader.MakeSymbolUpdater(fpe)
|
|
||||||
sb.SetType(sym.SNOPTRDATA)
|
|
||||||
sb.SetSize(0)
|
|
||||||
sb.AddUint8(1)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// If OTOH the module does not contain the runtime package,
|
// If OTOH the module does not contain the runtime package,
|
||||||
// create a local symbol for the moduledata.
|
// create a local symbol for the moduledata.
|
||||||
|
@ -286,13 +286,8 @@ func cgocallbackg1(ctxt uintptr) {
|
|||||||
// Additional two words (16-byte alignment) are for saving FP.
|
// Additional two words (16-byte alignment) are for saving FP.
|
||||||
cb = (*args)(unsafe.Pointer(sp + 7*sys.PtrSize))
|
cb = (*args)(unsafe.Pointer(sp + 7*sys.PtrSize))
|
||||||
case "amd64":
|
case "amd64":
|
||||||
// On amd64, stack frame is two words, plus caller PC.
|
// On amd64, stack frame is two words, plus caller PC and BP.
|
||||||
if framepointer_enabled {
|
cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
|
||||||
// In this case, there's also saved BP.
|
|
||||||
cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
cb = (*args)(unsafe.Pointer(sp + 3*sys.PtrSize))
|
|
||||||
case "386":
|
case "386":
|
||||||
// On 386, stack frame is three words, plus caller PC.
|
// On 386, stack frame is three words, plus caller PC.
|
||||||
cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
|
cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
|
||||||
|
@ -5459,9 +5459,6 @@ func setMaxThreads(in int) (out int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func haveexperiment(name string) bool {
|
func haveexperiment(name string) bool {
|
||||||
if name == "framepointer" {
|
|
||||||
return framepointer_enabled // set by linker
|
|
||||||
}
|
|
||||||
x := sys.Goexperiment
|
x := sys.Goexperiment
|
||||||
for x != "" {
|
for x != "" {
|
||||||
xname := ""
|
xname := ""
|
||||||
|
@ -329,7 +329,7 @@ type gobuf struct {
|
|||||||
ctxt unsafe.Pointer
|
ctxt unsafe.Pointer
|
||||||
ret sys.Uintreg
|
ret sys.Uintreg
|
||||||
lr uintptr
|
lr uintptr
|
||||||
bp uintptr // for GOEXPERIMENT=framepointer
|
bp uintptr // for framepointer-enabled architectures
|
||||||
}
|
}
|
||||||
|
|
||||||
// sudog represents a g in a wait list, such as for sending/receiving
|
// sudog represents a g in a wait list, such as for sending/receiving
|
||||||
@ -1046,8 +1046,7 @@ var (
|
|||||||
isIntel bool
|
isIntel bool
|
||||||
lfenceBeforeRdtsc bool
|
lfenceBeforeRdtsc bool
|
||||||
|
|
||||||
goarm uint8 // set by cmd/link on arm systems
|
goarm uint8 // set by cmd/link on arm systems
|
||||||
framepointer_enabled bool // set by cmd/link
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Set by the linker so the runtime can determine the buildmode.
|
// Set by the linker so the runtime can determine the buildmode.
|
||||||
@ -1055,3 +1054,6 @@ var (
|
|||||||
islibrary bool // -buildmode=c-shared
|
islibrary bool // -buildmode=c-shared
|
||||||
isarchive bool // -buildmode=c-archive
|
isarchive bool // -buildmode=c-archive
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Must agree with cmd/internal/objabi.Framepointer_enabled.
|
||||||
|
const framepointer_enabled = GOARCH == "amd64" || GOARCH == "arm64" && (GOOS == "linux" || GOOS == "darwin")
|
||||||
|
@ -648,12 +648,8 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Adjust saved base pointer if there is one.
|
// Adjust saved base pointer if there is one.
|
||||||
|
// TODO what about arm64 frame pointer adjustment?
|
||||||
if sys.ArchFamily == sys.AMD64 && frame.argp-frame.varp == 2*sys.RegSize {
|
if sys.ArchFamily == sys.AMD64 && frame.argp-frame.varp == 2*sys.RegSize {
|
||||||
if !framepointer_enabled {
|
|
||||||
print("runtime: found space for saved base pointer, but no framepointer experiment\n")
|
|
||||||
print("argp=", hex(frame.argp), " varp=", hex(frame.varp), "\n")
|
|
||||||
throw("bad frame layout")
|
|
||||||
}
|
|
||||||
if stackDebug >= 3 {
|
if stackDebug >= 3 {
|
||||||
print(" saved bp\n")
|
print(" saved bp\n")
|
||||||
}
|
}
|
||||||
|
@ -269,9 +269,9 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
|
|||||||
frame.varp -= sys.RegSize
|
frame.varp -= sys.RegSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// If framepointer_enabled and there's a frame, then
|
// For architectures with frame pointers, if there's
|
||||||
// there's a saved bp here.
|
// a frame, then there's a saved frame pointer here.
|
||||||
if frame.varp > frame.sp && (framepointer_enabled && GOARCH == "amd64" || GOARCH == "arm64") {
|
if frame.varp > frame.sp && (GOARCH == "amd64" || GOARCH == "arm64") {
|
||||||
frame.varp -= sys.RegSize
|
frame.varp -= sys.RegSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user