mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: remove the pc field of _defer struct
Since we always can get the address of `CALL runtime.deferreturn(SB)` from the unwinder, so it is not necessary to record the caller's pc in the _defer struct. For the stack allocated _defer, this CL makes the frame smaller. Change-Id: I0fd347e4bc07cf8a9b954816323df30fc52552b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/716720 Reviewed-by: Keith Randall <khr@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
parent
00ee1860ce
commit
361d51a6b5
4 changed files with 9 additions and 21 deletions
|
|
@ -7797,7 +7797,7 @@ func callTargetLSym(callee *ir.Name) *obj.LSym {
|
|||
}
|
||||
|
||||
// deferStructFnField is the field index of _defer.fn.
|
||||
const deferStructFnField = 4
|
||||
const deferStructFnField = 3
|
||||
|
||||
var deferType *types.Type
|
||||
|
||||
|
|
@ -7817,7 +7817,6 @@ func deferstruct() *types.Type {
|
|||
makefield("heap", types.Types[types.TBOOL]),
|
||||
makefield("rangefunc", types.Types[types.TBOOL]),
|
||||
makefield("sp", types.Types[types.TUINTPTR]),
|
||||
makefield("pc", types.Types[types.TUINTPTR]),
|
||||
// Note: the types here don't really matter. Defer structures
|
||||
// are always scanned explicitly during stack copying and GC,
|
||||
// so we make them uintptr type even though they are real pointers.
|
||||
|
|
|
|||
|
|
@ -382,7 +382,6 @@ func dumpgoroutine(gp *g) {
|
|||
dumpint(uint64(uintptr(unsafe.Pointer(d))))
|
||||
dumpint(uint64(uintptr(unsafe.Pointer(gp))))
|
||||
dumpint(uint64(d.sp))
|
||||
dumpint(uint64(d.pc))
|
||||
fn := *(**funcval)(unsafe.Pointer(&d.fn))
|
||||
dumpint(uint64(uintptr(unsafe.Pointer(fn))))
|
||||
if d.fn == nil {
|
||||
|
|
|
|||
|
|
@ -354,7 +354,6 @@ func deferproc(fn func()) {
|
|||
d.link = gp._defer
|
||||
gp._defer = d
|
||||
d.fn = fn
|
||||
d.pc = sys.GetCallerPC()
|
||||
// We must not be preempted between calling GetCallerSP and
|
||||
// storing it to d.sp because GetCallerSP's result is a
|
||||
// uintptr stack pointer.
|
||||
|
|
@ -458,7 +457,6 @@ func deferrangefunc() any {
|
|||
d := newdefer()
|
||||
d.link = gp._defer
|
||||
gp._defer = d
|
||||
d.pc = sys.GetCallerPC()
|
||||
// We must not be preempted between calling GetCallerSP and
|
||||
// storing it to d.sp because GetCallerSP's result is a
|
||||
// uintptr stack pointer.
|
||||
|
|
@ -518,7 +516,6 @@ func deferconvert(d0 *_defer) {
|
|||
}
|
||||
for d1 := d; ; d1 = d1.link {
|
||||
d1.sp = d0.sp
|
||||
d1.pc = d0.pc
|
||||
if d1.link == nil {
|
||||
d1.link = tail
|
||||
break
|
||||
|
|
@ -547,7 +544,6 @@ func deferprocStack(d *_defer) {
|
|||
d.heap = false
|
||||
d.rangefunc = false
|
||||
d.sp = sys.GetCallerSP()
|
||||
d.pc = sys.GetCallerPC()
|
||||
// The lines below implement:
|
||||
// d.panic = nil
|
||||
// d.fd = nil
|
||||
|
|
@ -977,8 +973,6 @@ func (p *_panic) nextDefer() (func(), bool) {
|
|||
|
||||
fn := d.fn
|
||||
|
||||
p.retpc = d.pc
|
||||
|
||||
// Unlink and free.
|
||||
popDefer(gp)
|
||||
|
||||
|
|
@ -1018,6 +1012,12 @@ func (p *_panic) nextFrame() (ok bool) {
|
|||
// it's non-zero.
|
||||
|
||||
if u.frame.sp == limit {
|
||||
f := u.frame.fn
|
||||
if f.deferreturn == 0 {
|
||||
throw("no deferreturn")
|
||||
}
|
||||
p.retpc = f.entry() + uintptr(f.deferreturn)
|
||||
|
||||
break // found a frame with linked defers
|
||||
}
|
||||
|
||||
|
|
@ -1273,15 +1273,6 @@ func recovery(gp *g) {
|
|||
pc, sp, fp := p.retpc, uintptr(p.sp), uintptr(p.fp)
|
||||
p0, saveOpenDeferState := p, p.deferBitsPtr != nil && *p.deferBitsPtr != 0
|
||||
|
||||
// The linker records the f-relative address of a call to deferreturn in f's funcInfo.
|
||||
// Assuming a "normal" call to recover() inside one of f's deferred functions
|
||||
// invoked for a panic, that is the desired PC for exiting f.
|
||||
f := findfunc(pc)
|
||||
if f.deferreturn == 0 {
|
||||
throw("no deferreturn")
|
||||
}
|
||||
gotoPc := f.entry() + uintptr(f.deferreturn)
|
||||
|
||||
// Unwind the panic stack.
|
||||
for ; p != nil && uintptr(p.startSP) < sp; p = p.link {
|
||||
// Don't allow jumping past a pending Goexit.
|
||||
|
|
@ -1304,7 +1295,7 @@ func recovery(gp *g) {
|
|||
// With how subtle defer handling is, this might not actually be
|
||||
// worthwhile though.
|
||||
if p.goexit {
|
||||
gotoPc, sp = p.startPC, uintptr(p.startSP)
|
||||
pc, sp = p.startPC, uintptr(p.startSP)
|
||||
saveOpenDeferState = false // goexit is unwinding the stack anyway
|
||||
break
|
||||
}
|
||||
|
|
@ -1367,7 +1358,7 @@ func recovery(gp *g) {
|
|||
|
||||
// branch directly to the deferreturn
|
||||
gp.sched.sp = sp
|
||||
gp.sched.pc = gotoPc
|
||||
gp.sched.pc = pc
|
||||
gp.sched.lr = 0
|
||||
// Restore the bp on platforms that support frame pointers.
|
||||
// N.B. It's fine to not set anything for platforms that don't
|
||||
|
|
|
|||
|
|
@ -1090,7 +1090,6 @@ type _defer struct {
|
|||
heap bool
|
||||
rangefunc bool // true for rangefunc list
|
||||
sp uintptr // sp at time of defer
|
||||
pc uintptr // pc at time of defer
|
||||
fn func() // can be nil for open-coded defers
|
||||
link *_defer // next defer on G; can point to either heap or stack!
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue