Revert "runtime: remove the pc field of _defer struct"

This reverts commit 361d51a6b5.

Reason for revert: Breaks some tests inside Google (on arm64?)

Change-Id: Iaea45fdcf9b4f9d36553687ca7f479750fe559da
Reviewed-on: https://go-review.googlesource.com/c/go/+/718066
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Youlin Feng <fengyoulin@live.com>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Keith Randall 2025-11-05 18:05:42 -08:00 committed by David Chase
parent 8111104a21
commit 48c7fa13c6
4 changed files with 21 additions and 9 deletions

View file

@ -7797,7 +7797,7 @@ func callTargetLSym(callee *ir.Name) *obj.LSym {
}
// deferStructFnField is the field index of _defer.fn.
const deferStructFnField = 3
const deferStructFnField = 4
var deferType *types.Type
@ -7817,6 +7817,7 @@ 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.

View file

@ -382,6 +382,7 @@ 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 {

View file

@ -354,6 +354,7 @@ 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.
@ -457,6 +458,7 @@ 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.
@ -516,6 +518,7 @@ 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
@ -544,6 +547,7 @@ func deferprocStack(d *_defer) {
d.heap = false
d.rangefunc = false
d.sp = sys.GetCallerSP()
d.pc = sys.GetCallerPC()
// The lines below implement:
// d.link = gp._defer
// d.head = nil
@ -971,6 +975,8 @@ func (p *_panic) nextDefer() (func(), bool) {
fn := d.fn
p.retpc = d.pc
// Unlink and free.
popDefer(gp)
@ -1010,12 +1016,6 @@ 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
}
@ -1271,6 +1271,15 @@ 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.
@ -1293,7 +1302,7 @@ func recovery(gp *g) {
// With how subtle defer handling is, this might not actually be
// worthwhile though.
if p.goexit {
pc, sp = p.startPC, uintptr(p.startSP)
gotoPc, sp = p.startPC, uintptr(p.startSP)
saveOpenDeferState = false // goexit is unwinding the stack anyway
break
}
@ -1356,7 +1365,7 @@ func recovery(gp *g) {
// branch directly to the deferreturn
gp.sched.sp = sp
gp.sched.pc = pc
gp.sched.pc = gotoPc
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

View file

@ -1090,6 +1090,7 @@ 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!