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 fn == nil {
+ dumpint(uint64(uintptr(unsafe.Pointer(d.fn))))
+ if d.fn == nil {
// d.fn can be nil for open-coded defers
dumpint(uint64(0))
} else {
- dumpint(uint64(uintptr(unsafe.Pointer(fn.fn))))
+ dumpint(uint64(uintptr(unsafe.Pointer(d.fn.fn))))
}
dumpint(uint64(uintptr(unsafe.Pointer(d.link))))
}
// Create a new deferred function fn, which has no arguments and results.
// The compiler turns a defer statement into a call to this.
-func deferproc(fn func()) {
+func deferproc(fn *funcval) { // TODO: Make deferproc just take a func().
gp := getg()
if gp.m.curg != gp {
// go code on the system stack can't defer
// been set and must not be clobbered.
}
+// deferFunc returns d's deferred function. This is temporary while we
+// support both modes of GOEXPERIMENT=regabidefer. Once we commit to
+// that experiment, we should change the type of d.fn.
+//go:nosplit
+func deferFunc(d *_defer) func() {
+ var fn func()
+ *(**funcval)(unsafe.Pointer(&fn)) = d.fn
+ return fn
+}
+
// Each P holds a pool for defers.
// Allocate a Defer, usually using per-P pool.
// called with a callback on an LR architecture and jmpdefer is on the
// stack, because the stack trace can be incorrect in that case - see
// issue #8153).
- if fn == nil {
- fn()
- }
+ _ = fn.fn
jmpdefer(fn, argp)
}
} else {
// Save the pc/sp in deferCallSave(), so we can "recover" back to this
// loop if necessary.
- deferCallSave(&p, d.fn)
+ deferCallSave(&p, deferFunc(d))
}
if p.aborted {
// We had a recursive panic in the defer d we started, and
if deferBits&(1<<i) == 0 {
continue
}
- closure := *(*func())(unsafe.Pointer(d.varp - uintptr(closureOffset)))
+ closure := *(**funcval)(unsafe.Pointer(d.varp - uintptr(closureOffset)))
d.fn = closure
deferBits = deferBits &^ (1 << i)
*(*uint8)(unsafe.Pointer(d.varp - uintptr(deferBitsOffset))) = deferBits
p := d._panic
- deferCallSave(p, d.fn)
+ deferCallSave(p, deferFunc(d))
if p != nil && p.aborted {
break
}
}
} else {
p.argp = unsafe.Pointer(getargp())
- d.fn()
+ fn := deferFunc(d)
+ fn()
}
p.argp = nil
// defers. We have only one defer record for the entire frame (which may
// currently have 0, 1, or more defers active).
openDefer bool
- sp uintptr // sp at time of defer
- pc uintptr // pc at time of defer
- fn func() // can be nil for open-coded defers
- _panic *_panic // panic that is running defer
+ sp uintptr // sp at time of defer
+ pc uintptr // pc at time of defer
+ fn *funcval // can be nil for open-coded defers
+ _panic *_panic // panic that is running defer
link *_defer
// If openDefer is true, the fields below record values about the stack