Descriptionruntime, cmd/gc, cmd/ld: ignore method wrappers in recover
Bug #1:
Issue 5406 identified an interesting case:
defer iface.M()
may end up calling a wrapper that copies an indirect receiver
from the iface value and then calls the real M method. That's
two calls down, not just one, and so recover() == nil always
in the real M method, even during a panic.
[For the purposes of this entire discussion, a wrapper's
implementation is a function containing an ordinary call, not
the optimized tail call form that is somtimes possible. The
tail call does not create a second frame, so it is already
handled correctly.]
Fix this bug by introducing g->panicwrap, which counts the
number of bytes on current stack segment that are due to
wrapper calls that should not count against the recover
check. All wrapper functions must now adjust g->panicwrap up
on entry and back down on exit. This adds slightly to their
expense; on the x86 it is a single instruction at entry and
exit; on the ARM it is three. However, the alternative is to
make a call to recover depend on being able to walk the stack,
which I very much want to avoid. We have enough problems
walking the stack for garbage collection and profiling.
Also, if performance is critical in a specific case, it is already
faster to use a pointer receiver and avoid this kind of wrapper
entirely.
Bug #2:
The old code, which did not consider the possibility of two
calls, already contained a check to see if the call had split
its stack and so the panic-created segment was one behind the
current segment. In the wrapper case, both of the two calls
might split their stacks, so the panic-created segment can be
two behind the current segment.
Fix this by propagating the Stktop.panic flag forward during
stack splits instead of looking backward during recover.
Fixes issue 5406.
Patch Set 1 #Patch Set 2 : diff -r 0a3f59715a28 https://code.google.com/p/go/ #Patch Set 3 : diff -r 0a3f59715a28 https://code.google.com/p/go/ #
Total comments: 12
Patch Set 4 : diff -r 0a3f59715a28 https://code.google.com/p/go/ #Patch Set 5 : diff -r 0a3f59715a28 https://code.google.com/p/go/ #Patch Set 6 : diff -r 0a3f59715a28 https://code.google.com/p/go/ #
Total comments: 2
Patch Set 7 : diff -r 5694c6095fc7 https://code.google.com/p/go/ #
MessagesTotal messages: 8
|