mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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:
parent
8111104a21
commit
48c7fa13c6
4 changed files with 21 additions and 9 deletions
|
|
@ -7797,7 +7797,7 @@ func callTargetLSym(callee *ir.Name) *obj.LSym {
|
||||||
}
|
}
|
||||||
|
|
||||||
// deferStructFnField is the field index of _defer.fn.
|
// deferStructFnField is the field index of _defer.fn.
|
||||||
const deferStructFnField = 3
|
const deferStructFnField = 4
|
||||||
|
|
||||||
var deferType *types.Type
|
var deferType *types.Type
|
||||||
|
|
||||||
|
|
@ -7817,6 +7817,7 @@ func deferstruct() *types.Type {
|
||||||
makefield("heap", types.Types[types.TBOOL]),
|
makefield("heap", types.Types[types.TBOOL]),
|
||||||
makefield("rangefunc", types.Types[types.TBOOL]),
|
makefield("rangefunc", types.Types[types.TBOOL]),
|
||||||
makefield("sp", types.Types[types.TUINTPTR]),
|
makefield("sp", types.Types[types.TUINTPTR]),
|
||||||
|
makefield("pc", types.Types[types.TUINTPTR]),
|
||||||
// Note: the types here don't really matter. Defer structures
|
// Note: the types here don't really matter. Defer structures
|
||||||
// are always scanned explicitly during stack copying and GC,
|
// are always scanned explicitly during stack copying and GC,
|
||||||
// so we make them uintptr type even though they are real pointers.
|
// so we make them uintptr type even though they are real pointers.
|
||||||
|
|
|
||||||
|
|
@ -382,6 +382,7 @@ func dumpgoroutine(gp *g) {
|
||||||
dumpint(uint64(uintptr(unsafe.Pointer(d))))
|
dumpint(uint64(uintptr(unsafe.Pointer(d))))
|
||||||
dumpint(uint64(uintptr(unsafe.Pointer(gp))))
|
dumpint(uint64(uintptr(unsafe.Pointer(gp))))
|
||||||
dumpint(uint64(d.sp))
|
dumpint(uint64(d.sp))
|
||||||
|
dumpint(uint64(d.pc))
|
||||||
fn := *(**funcval)(unsafe.Pointer(&d.fn))
|
fn := *(**funcval)(unsafe.Pointer(&d.fn))
|
||||||
dumpint(uint64(uintptr(unsafe.Pointer(fn))))
|
dumpint(uint64(uintptr(unsafe.Pointer(fn))))
|
||||||
if d.fn == nil {
|
if d.fn == nil {
|
||||||
|
|
|
||||||
|
|
@ -354,6 +354,7 @@ func deferproc(fn func()) {
|
||||||
d.link = gp._defer
|
d.link = gp._defer
|
||||||
gp._defer = d
|
gp._defer = d
|
||||||
d.fn = fn
|
d.fn = fn
|
||||||
|
d.pc = sys.GetCallerPC()
|
||||||
// We must not be preempted between calling GetCallerSP and
|
// We must not be preempted between calling GetCallerSP and
|
||||||
// storing it to d.sp because GetCallerSP's result is a
|
// storing it to d.sp because GetCallerSP's result is a
|
||||||
// uintptr stack pointer.
|
// uintptr stack pointer.
|
||||||
|
|
@ -457,6 +458,7 @@ func deferrangefunc() any {
|
||||||
d := newdefer()
|
d := newdefer()
|
||||||
d.link = gp._defer
|
d.link = gp._defer
|
||||||
gp._defer = d
|
gp._defer = d
|
||||||
|
d.pc = sys.GetCallerPC()
|
||||||
// We must not be preempted between calling GetCallerSP and
|
// We must not be preempted between calling GetCallerSP and
|
||||||
// storing it to d.sp because GetCallerSP's result is a
|
// storing it to d.sp because GetCallerSP's result is a
|
||||||
// uintptr stack pointer.
|
// uintptr stack pointer.
|
||||||
|
|
@ -516,6 +518,7 @@ func deferconvert(d0 *_defer) {
|
||||||
}
|
}
|
||||||
for d1 := d; ; d1 = d1.link {
|
for d1 := d; ; d1 = d1.link {
|
||||||
d1.sp = d0.sp
|
d1.sp = d0.sp
|
||||||
|
d1.pc = d0.pc
|
||||||
if d1.link == nil {
|
if d1.link == nil {
|
||||||
d1.link = tail
|
d1.link = tail
|
||||||
break
|
break
|
||||||
|
|
@ -544,6 +547,7 @@ func deferprocStack(d *_defer) {
|
||||||
d.heap = false
|
d.heap = false
|
||||||
d.rangefunc = false
|
d.rangefunc = false
|
||||||
d.sp = sys.GetCallerSP()
|
d.sp = sys.GetCallerSP()
|
||||||
|
d.pc = sys.GetCallerPC()
|
||||||
// The lines below implement:
|
// The lines below implement:
|
||||||
// d.link = gp._defer
|
// d.link = gp._defer
|
||||||
// d.head = nil
|
// d.head = nil
|
||||||
|
|
@ -971,6 +975,8 @@ func (p *_panic) nextDefer() (func(), bool) {
|
||||||
|
|
||||||
fn := d.fn
|
fn := d.fn
|
||||||
|
|
||||||
|
p.retpc = d.pc
|
||||||
|
|
||||||
// Unlink and free.
|
// Unlink and free.
|
||||||
popDefer(gp)
|
popDefer(gp)
|
||||||
|
|
||||||
|
|
@ -1010,12 +1016,6 @@ func (p *_panic) nextFrame() (ok bool) {
|
||||||
// it's non-zero.
|
// it's non-zero.
|
||||||
|
|
||||||
if u.frame.sp == limit {
|
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
|
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)
|
pc, sp, fp := p.retpc, uintptr(p.sp), uintptr(p.fp)
|
||||||
p0, saveOpenDeferState := p, p.deferBitsPtr != nil && *p.deferBitsPtr != 0
|
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.
|
// Unwind the panic stack.
|
||||||
for ; p != nil && uintptr(p.startSP) < sp; p = p.link {
|
for ; p != nil && uintptr(p.startSP) < sp; p = p.link {
|
||||||
// Don't allow jumping past a pending Goexit.
|
// 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
|
// With how subtle defer handling is, this might not actually be
|
||||||
// worthwhile though.
|
// worthwhile though.
|
||||||
if p.goexit {
|
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
|
saveOpenDeferState = false // goexit is unwinding the stack anyway
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -1356,7 +1365,7 @@ func recovery(gp *g) {
|
||||||
|
|
||||||
// branch directly to the deferreturn
|
// branch directly to the deferreturn
|
||||||
gp.sched.sp = sp
|
gp.sched.sp = sp
|
||||||
gp.sched.pc = pc
|
gp.sched.pc = gotoPc
|
||||||
gp.sched.lr = 0
|
gp.sched.lr = 0
|
||||||
// Restore the bp on platforms that support frame pointers.
|
// Restore the bp on platforms that support frame pointers.
|
||||||
// N.B. It's fine to not set anything for platforms that don't
|
// N.B. It's fine to not set anything for platforms that don't
|
||||||
|
|
|
||||||
|
|
@ -1090,6 +1090,7 @@ type _defer struct {
|
||||||
heap bool
|
heap bool
|
||||||
rangefunc bool // true for rangefunc list
|
rangefunc bool // true for rangefunc list
|
||||||
sp uintptr // sp at time of defer
|
sp uintptr // sp at time of defer
|
||||||
|
pc uintptr // pc at time of defer
|
||||||
fn func() // can be nil for open-coded defers
|
fn func() // can be nil for open-coded defers
|
||||||
link *_defer // next defer on G; can point to either heap or stack!
|
link *_defer // next defer on G; can point to either heap or stack!
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue