runtime: let stack copier update Panic structs for us

It already is updating parts of them; we're just getting lucky
retraversing them and not finding much to do.
Change argp to a pointer so that it will be updated too.
Existing tests break if you apply the change to adjustpanics
without also updating the type of argp.

LGTM=khr
R=khr
CC=golang-codereviews
https://golang.org/cl/139380043
This commit is contained in:
Russ Cox 2014-09-08 21:02:36 -04:00
parent c93f74d34b
commit 0f99a91bb5
3 changed files with 13 additions and 15 deletions

View file

@ -287,9 +287,9 @@ func gopanic(e interface{}) {
gp._defer = (*_defer)(noescape(unsafe.Pointer(&dabort))) gp._defer = (*_defer)(noescape(unsafe.Pointer(&dabort)))
p._defer = d p._defer = d
p.argp = getargp(0) p.argp = unsafe.Pointer(getargp(0))
reflectcall(unsafe.Pointer(d.fn), unsafe.Pointer(&d.args), uint32(d.siz), uint32(d.siz)) reflectcall(unsafe.Pointer(d.fn), unsafe.Pointer(&d.args), uint32(d.siz), uint32(d.siz))
p.argp = 0 p.argp = nil
// reflectcall did not panic. Remove dabort. // reflectcall did not panic. Remove dabort.
if gp._defer != &dabort { if gp._defer != &dabort {
@ -362,7 +362,7 @@ func gorecover(argp uintptr) interface{} {
// If they match, the caller is the one who can recover. // If they match, the caller is the one who can recover.
gp := getg() gp := getg()
p := gp._panic p := gp._panic
if p != nil && !p.recovered && argp == p.argp { if p != nil && !p.recovered && argp == uintptr(p.argp) {
p.recovered = true p.recovered = true
return p.arg return p.arg
} }

View file

@ -653,7 +653,7 @@ struct Defer
*/ */
struct Panic struct Panic
{ {
uintptr argp; // pointer to arguments of deferred call run during panic; cannot move - known to liblink void* argp; // pointer to arguments of deferred call run during panic; cannot move - known to liblink
Eface arg; // argument to panic Eface arg; // argument to panic
Panic* link; // link to earlier panic Panic* link; // link to earlier panic
Defer* defer; // current executing defer Defer* defer; // current executing defer

View file

@ -712,6 +712,10 @@ adjustdefers(G *gp, AdjustInfo *adjinfo)
// get adjusted appropriately. // get adjusted appropriately.
// This only happens for runtime.main and runtime.gopanic now, // This only happens for runtime.main and runtime.gopanic now,
// but a compiler optimization could do more of this. // but a compiler optimization could do more of this.
// If such an optimization were introduced, Defer.argp should
// change to have pointer type so that it will be updated by
// the stack copying. Today both of those on-stack defers
// set argp = NoArgs, so no adjustment is necessary.
*dp = (Defer*)((byte*)d + adjinfo->delta); *dp = (Defer*)((byte*)d + adjinfo->delta);
continue; continue;
} }
@ -751,17 +755,11 @@ adjustdefers(G *gp, AdjustInfo *adjinfo)
static void static void
adjustpanics(G *gp, AdjustInfo *adjinfo) adjustpanics(G *gp, AdjustInfo *adjinfo)
{ {
Panic *p, **l; // Panic structs are all on the stack
// and are adjusted by stack copying.
// only the topmost panic is on the current stack // The only pointer we need to update is gp->panic, the head of the list.
for(l = &gp->panic; (p = *l) != nil; ) { if(adjinfo->oldstk <= (byte*)gp->panic && (byte*)gp->panic < adjinfo->oldbase)
if(adjinfo->oldstk <= (byte*)p && (byte*)p < adjinfo->oldbase) gp->panic = (Panic*)((byte*)gp->panic + adjinfo->delta);
*l = (Panic*)((byte*)p + adjinfo->delta);
l = &p->link;
if(adjinfo->oldstk <= (byte*)p->argp && (byte*)p->argp < adjinfo->oldbase)
p->argp += adjinfo->delta;
}
} }
static void static void