}
// deferStructFnField is the field index of _defer.fn.
-const deferStructFnField = 4
+const deferStructFnField = 3
var deferType *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.
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.
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.
}
for d1 := d; ; d1 = d1.link {
d1.sp = d0.sp
- d1.pc = d0.pc
if d1.link == nil {
d1.link = tail
break
d.heap = false
d.rangefunc = false
d.sp = sys.GetCallerSP()
- d.pc = sys.GetCallerPC()
// The lines below implement:
// d.panic = nil
// d.fd = nil
fn := d.fn
- p.retpc = d.pc
-
// Unlink and free.
popDefer(gp)
// 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
}
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.
// 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
}
// 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