]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: remove the pc field of _defer struct
authorYoulin Feng <fengyoulin@live.com>
Fri, 31 Oct 2025 02:45:26 +0000 (10:45 +0800)
committerKeith Randall <khr@golang.org>
Mon, 3 Nov 2025 17:26:36 +0000 (09:26 -0800)
Since we always can get the address of `CALL runtime.deferreturn(SB)`
from the unwinder, so it is not necessary to record the caller's pc
in the _defer struct. For the stack allocated _defer, this CL makes
the frame smaller.

Change-Id: I0fd347e4bc07cf8a9b954816323df30fc52552b6
Reviewed-on: https://go-review.googlesource.com/c/go/+/716720
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/cmd/compile/internal/ssagen/ssa.go
src/runtime/heapdump.go
src/runtime/panic.go
src/runtime/runtime2.go

index ae7d57566f7e0defe86b3de2591e0dc739f00ed5..db2ffb5752f1ce842554154038d34bd95a028941 100644 (file)
@@ -7797,7 +7797,7 @@ func callTargetLSym(callee *ir.Name) *obj.LSym {
 }
 
 // deferStructFnField is the field index of _defer.fn.
-const deferStructFnField = 4
+const deferStructFnField = 3
 
 var deferType *types.Type
 
@@ -7817,7 +7817,6 @@ 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.
index 3671c65ab731513141dfc521b7f145620016ed27..3a8c374fc0f497b276169c32c6faa86c256440ef 100644 (file)
@@ -382,7 +382,6 @@ 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 {
index 175452fec9c08bebd3213d72091f0e4a6b5ddea0..aee1cd0eed4570a3d212b33e9f71f49c94838458 100644 (file)
@@ -354,7 +354,6 @@ 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.
@@ -458,7 +457,6 @@ 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.
@@ -518,7 +516,6 @@ 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
@@ -547,7 +544,6 @@ func deferprocStack(d *_defer) {
        d.heap = false
        d.rangefunc = false
        d.sp = sys.GetCallerSP()
-       d.pc = sys.GetCallerPC()
        // The lines below implement:
        //   d.panic = nil
        //   d.fd = nil
@@ -977,8 +973,6 @@ func (p *_panic) nextDefer() (func(), bool) {
 
                        fn := d.fn
 
-                       p.retpc = d.pc
-
                        // Unlink and free.
                        popDefer(gp)
 
@@ -1018,6 +1012,12 @@ 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
                        }
 
@@ -1273,15 +1273,6 @@ 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.
@@ -1304,7 +1295,7 @@ func recovery(gp *g) {
                // 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
                }
@@ -1367,7 +1358,7 @@ func recovery(gp *g) {
 
        // 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
index b346337d60354c0007eb4cc94776e7a3c3d3428f..3672b19f76461a1c05991d24a66447d1247d93a0 100644 (file)
@@ -1090,7 +1090,6 @@ 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!