Skip to content

Commit ea94e5d

Browse files
committed
[dev.typeparams] runtime: use func() for deferred functions
Prior to regabi, a deferred function could have any signature, so the runtime always manipulated them as funcvals. Now, a deferred function is always func(). Hence, this CL makes the runtime's manipulation of deferred functions more type-safe by using func() directly instead of *funcval. Change-Id: Ib55f38ed49107f74149725c65044e4690761971d Reviewed-on: https://go-review.googlesource.com/c/go/+/337650 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
1 parent 4480e3b commit ea94e5d

File tree

6 files changed

+19
-28
lines changed

6 files changed

+19
-28
lines changed

src/runtime/asm_amd64.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ TEXT ·publicationBarrier(SB),NOSPLIT,$0-0
662662
// compile barrier.
663663
RET
664664

665-
// func jmpdefer(fv *funcval, argp uintptr)
665+
// func jmpdefer(fv func(), argp uintptr)
666666
// argp is a caller SP.
667667
// called from deferreturn.
668668
// 1. pop the caller

src/runtime/asm_riscv64.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
248248
MOV gobuf_pc(T0), T0
249249
JALR ZERO, T0
250250

251-
// func jmpdefer(fv *funcval, argp uintptr)
251+
// func jmpdefer(fv func(), argp uintptr)
252252
// called from deferreturn
253253
// 1. grab stored return address from the caller's frame
254254
// 2. sub 8 bytes to get back to JAL deferreturn

src/runtime/heapdump.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,12 +381,13 @@ func dumpgoroutine(gp *g) {
381381
dumpint(uint64(uintptr(unsafe.Pointer(gp))))
382382
dumpint(uint64(d.sp))
383383
dumpint(uint64(d.pc))
384-
dumpint(uint64(uintptr(unsafe.Pointer(d.fn))))
384+
fn := *(**funcval)(unsafe.Pointer(&d.fn))
385+
dumpint(uint64(uintptr(unsafe.Pointer(fn))))
385386
if d.fn == nil {
386387
// d.fn can be nil for open-coded defers
387388
dumpint(uint64(0))
388389
} else {
389-
dumpint(uint64(uintptr(unsafe.Pointer(d.fn.fn))))
390+
dumpint(uint64(uintptr(unsafe.Pointer(fn.fn))))
390391
}
391392
dumpint(uint64(uintptr(unsafe.Pointer(d.link))))
392393
}

src/runtime/panic.go

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ func panicmemAddr(addr uintptr) {
227227

228228
// Create a new deferred function fn, which has no arguments and results.
229229
// The compiler turns a defer statement into a call to this.
230-
func deferproc(fn *funcval) { // TODO: Make deferproc just take a func().
230+
func deferproc(fn func()) {
231231
gp := getg()
232232
if gp.m.curg != gp {
233233
// go code on the system stack can't defer
@@ -303,16 +303,6 @@ func deferprocStack(d *_defer) {
303303
// been set and must not be clobbered.
304304
}
305305

306-
// deferFunc returns d's deferred function. This is temporary while we
307-
// support both modes of GOEXPERIMENT=regabidefer. Once we commit to
308-
// that experiment, we should change the type of d.fn.
309-
//go:nosplit
310-
func deferFunc(d *_defer) func() {
311-
var fn func()
312-
*(**funcval)(unsafe.Pointer(&fn)) = d.fn
313-
return fn
314-
}
315-
316306
// Each P holds a pool for defers.
317307

318308
// Allocate a Defer, usually using per-P pool.
@@ -470,9 +460,8 @@ func deferreturn() {
470460
// If the defer function pointer is nil, force the seg fault to happen
471461
// here rather than in jmpdefer. gentraceback() throws an error if it is
472462
// called with a callback on an LR architecture and jmpdefer is on the
473-
// stack, because the stack trace can be incorrect in that case - see
474-
// issue #8153).
475-
_ = fn.fn
463+
// stack, because jmpdefer manipulates SP (see issue #8153).
464+
_ = **(**funcval)(unsafe.Pointer(&fn))
476465
jmpdefer(fn, argp)
477466
}
478467

@@ -536,7 +525,7 @@ func Goexit() {
536525
} else {
537526
// Save the pc/sp in deferCallSave(), so we can "recover" back to this
538527
// loop if necessary.
539-
deferCallSave(&p, deferFunc(d))
528+
deferCallSave(&p, d.fn)
540529
}
541530
if p.aborted {
542531
// We had a recursive panic in the defer d we started, and
@@ -728,12 +717,14 @@ func runOpenDeferFrame(gp *g, d *_defer) bool {
728717
if deferBits&(1<<i) == 0 {
729718
continue
730719
}
731-
closure := *(**funcval)(unsafe.Pointer(d.varp - uintptr(closureOffset)))
720+
closure := *(*func())(unsafe.Pointer(d.varp - uintptr(closureOffset)))
732721
d.fn = closure
733722
deferBits = deferBits &^ (1 << i)
734723
*(*uint8)(unsafe.Pointer(d.varp - uintptr(deferBitsOffset))) = deferBits
735724
p := d._panic
736-
deferCallSave(p, deferFunc(d))
725+
// Call the defer. Note that this can change d.varp if
726+
// the stack moves.
727+
deferCallSave(p, d.fn)
737728
if p != nil && p.aborted {
738729
break
739730
}
@@ -854,8 +845,7 @@ func gopanic(e interface{}) {
854845
}
855846
} else {
856847
p.argp = unsafe.Pointer(getargp())
857-
fn := deferFunc(d)
858-
fn()
848+
d.fn()
859849
}
860850
p.argp = nil
861851

src/runtime/runtime2.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -953,10 +953,10 @@ type _defer struct {
953953
// defers. We have only one defer record for the entire frame (which may
954954
// currently have 0, 1, or more defers active).
955955
openDefer bool
956-
sp uintptr // sp at time of defer
957-
pc uintptr // pc at time of defer
958-
fn *funcval // can be nil for open-coded defers
959-
_panic *_panic // panic that is running defer
956+
sp uintptr // sp at time of defer
957+
pc uintptr // pc at time of defer
958+
fn func() // can be nil for open-coded defers
959+
_panic *_panic // panic that is running defer
960960
link *_defer
961961

962962
// If openDefer is true, the fields below record values about the stack

src/runtime/stubs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func cgocallback(fn, frame, ctxt uintptr)
177177
func gogo(buf *gobuf)
178178

179179
//go:noescape
180-
func jmpdefer(fv *funcval, argp uintptr)
180+
func jmpdefer(fv func(), argp uintptr)
181181
func asminit()
182182
func setg(gg *g)
183183
func breakpoint()

0 commit comments

Comments
 (0)