Skip to content

Commit 48c7fa1

Browse files
randall77dr2chase
authored andcommitted
Revert "runtime: remove the pc field of _defer struct"
This reverts commit 361d51a. 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>
1 parent 8111104 commit 48c7fa1

File tree

4 files changed

+21
-9
lines changed

4 files changed

+21
-9
lines changed

src/cmd/compile/internal/ssagen/ssa.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7797,7 +7797,7 @@ func callTargetLSym(callee *ir.Name) *obj.LSym {
77977797
}
77987798

77997799
// deferStructFnField is the field index of _defer.fn.
7800-
const deferStructFnField = 3
7800+
const deferStructFnField = 4
78017801

78027802
var deferType *types.Type
78037803

@@ -7817,6 +7817,7 @@ func deferstruct() *types.Type {
78177817
makefield("heap", types.Types[types.TBOOL]),
78187818
makefield("rangefunc", types.Types[types.TBOOL]),
78197819
makefield("sp", types.Types[types.TUINTPTR]),
7820+
makefield("pc", types.Types[types.TUINTPTR]),
78207821
// Note: the types here don't really matter. Defer structures
78217822
// are always scanned explicitly during stack copying and GC,
78227823
// so we make them uintptr type even though they are real pointers.

src/runtime/heapdump.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ func dumpgoroutine(gp *g) {
382382
dumpint(uint64(uintptr(unsafe.Pointer(d))))
383383
dumpint(uint64(uintptr(unsafe.Pointer(gp))))
384384
dumpint(uint64(d.sp))
385+
dumpint(uint64(d.pc))
385386
fn := *(**funcval)(unsafe.Pointer(&d.fn))
386387
dumpint(uint64(uintptr(unsafe.Pointer(fn))))
387388
if d.fn == nil {

src/runtime/panic.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ func deferproc(fn func()) {
354354
d.link = gp._defer
355355
gp._defer = d
356356
d.fn = fn
357+
d.pc = sys.GetCallerPC()
357358
// We must not be preempted between calling GetCallerSP and
358359
// storing it to d.sp because GetCallerSP's result is a
359360
// uintptr stack pointer.
@@ -457,6 +458,7 @@ func deferrangefunc() any {
457458
d := newdefer()
458459
d.link = gp._defer
459460
gp._defer = d
461+
d.pc = sys.GetCallerPC()
460462
// We must not be preempted between calling GetCallerSP and
461463
// storing it to d.sp because GetCallerSP's result is a
462464
// uintptr stack pointer.
@@ -516,6 +518,7 @@ func deferconvert(d0 *_defer) {
516518
}
517519
for d1 := d; ; d1 = d1.link {
518520
d1.sp = d0.sp
521+
d1.pc = d0.pc
519522
if d1.link == nil {
520523
d1.link = tail
521524
break
@@ -544,6 +547,7 @@ func deferprocStack(d *_defer) {
544547
d.heap = false
545548
d.rangefunc = false
546549
d.sp = sys.GetCallerSP()
550+
d.pc = sys.GetCallerPC()
547551
// The lines below implement:
548552
// d.link = gp._defer
549553
// d.head = nil
@@ -971,6 +975,8 @@ func (p *_panic) nextDefer() (func(), bool) {
971975

972976
fn := d.fn
973977

978+
p.retpc = d.pc
979+
974980
// Unlink and free.
975981
popDefer(gp)
976982

@@ -1010,12 +1016,6 @@ func (p *_panic) nextFrame() (ok bool) {
10101016
// it's non-zero.
10111017

10121018
if u.frame.sp == limit {
1013-
f := u.frame.fn
1014-
if f.deferreturn == 0 {
1015-
throw("no deferreturn")
1016-
}
1017-
p.retpc = f.entry() + uintptr(f.deferreturn)
1018-
10191019
break // found a frame with linked defers
10201020
}
10211021

@@ -1271,6 +1271,15 @@ func recovery(gp *g) {
12711271
pc, sp, fp := p.retpc, uintptr(p.sp), uintptr(p.fp)
12721272
p0, saveOpenDeferState := p, p.deferBitsPtr != nil && *p.deferBitsPtr != 0
12731273

1274+
// The linker records the f-relative address of a call to deferreturn in f's funcInfo.
1275+
// Assuming a "normal" call to recover() inside one of f's deferred functions
1276+
// invoked for a panic, that is the desired PC for exiting f.
1277+
f := findfunc(pc)
1278+
if f.deferreturn == 0 {
1279+
throw("no deferreturn")
1280+
}
1281+
gotoPc := f.entry() + uintptr(f.deferreturn)
1282+
12741283
// Unwind the panic stack.
12751284
for ; p != nil && uintptr(p.startSP) < sp; p = p.link {
12761285
// Don't allow jumping past a pending Goexit.
@@ -1293,7 +1302,7 @@ func recovery(gp *g) {
12931302
// With how subtle defer handling is, this might not actually be
12941303
// worthwhile though.
12951304
if p.goexit {
1296-
pc, sp = p.startPC, uintptr(p.startSP)
1305+
gotoPc, sp = p.startPC, uintptr(p.startSP)
12971306
saveOpenDeferState = false // goexit is unwinding the stack anyway
12981307
break
12991308
}
@@ -1356,7 +1365,7 @@ func recovery(gp *g) {
13561365

13571366
// branch directly to the deferreturn
13581367
gp.sched.sp = sp
1359-
gp.sched.pc = pc
1368+
gp.sched.pc = gotoPc
13601369
gp.sched.lr = 0
13611370
// Restore the bp on platforms that support frame pointers.
13621371
// N.B. It's fine to not set anything for platforms that don't

src/runtime/runtime2.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,7 @@ type _defer struct {
10901090
heap bool
10911091
rangefunc bool // true for rangefunc list
10921092
sp uintptr // sp at time of defer
1093+
pc uintptr // pc at time of defer
10931094
fn func() // can be nil for open-coded defers
10941095
link *_defer // next defer on G; can point to either heap or stack!
10951096

0 commit comments

Comments
 (0)