In perl.git, the branch smoke-me/davem/eval_temps has been created
<http://perl5.git.perl.org/perl.git/commitdiff/659bd1a98f7851706f4fc741c237ec82f5509386?hp=0000000000000000000000000000000000000000>
at 659bd1a98f7851706f4fc741c237ec82f5509386 (commit)
- Log -----------------------------------------------------------------
commit 659bd1a98f7851706f4fc741c237ec82f5509386
Author: David Mitchell <[email protected]>
Date: Thu Jun 30 10:56:28 2016 +0100
FREEMPS when leaving eval, even when void or dying
When a scope is exited normally (e.g. pp_leavetry, pp_leavesub),
we do a FREETMPS only in scalar or list context; in void context
we don't bother for efficiency reasons. Similarly, when there's an
exception and we unwind to (and then pop) an EVAL context, we haven't
been bothering to FREETMPS.
The problem with this in try/eval (exiting normally or via an exception)
is that it can delay some SVs getting freed until *after* $@ has been
set. If that freeing calls a destructor which happens to set $@,
then that overwrites the "real" value of $@.
For example
sub DESTROY { eval { die "died in DESTROY"; } }
eval { bless []; };
is ($@, "");
Before this commit, that test would fail because $@ is "died in DESTROY".
This commit ensures that leaving an eval/try by whatever means always
clears the tmps stack before setting $@.
See http://nntp.perl.org/group/perl.perl5.porters/237380.
For now, I haven't added a FREETMPS to the other pp_leavefoo()
void context cases, since I can't think of a case where it would
matter.
M pp_ctl.c
M t/op/eval.t
commit 574223467942023278046b181a107453998eab33
Author: David Mitchell <[email protected]>
Date: Thu Jun 30 10:12:06 2016 +0100
die_unwind(): mortalise, not mortalcopy the err SV
The error string needs to be preserved while unwinding the stacks,
but doing a simple sv_2mortal() and bumping the reference count seems
sufficient, rather than making a complete copy.
Also, avoid the mortalised SV's buffer from being stolen by using the
SV_NOSTEAL flag rather than unsetting SvTEMP.
Finally, add some basic comments above Perl_die_unwind() explaining what
it's for.
M pp_ctl.c
commit 4ff754019a3ad50be911c1c753453e33c8a3e0c9
Author: David Mitchell <[email protected]>
Date: Wed Jun 29 09:16:51 2016 +0100
cx_popeval(): don't mortalise blk_eval.old_namesv
Currently whenever we pop an eval context used for a require, rather than
freeing the SV holding the name of the require, we just mortalise it,
since some callers of cx_popeval() need the SV to remain long enough to
use it to "undo" %INC and to croak with a message such as ""$name did not
return a true value".
Now that all those usages have been gathered into one place
(S_pop_eval_context_maybe_croak), make that function responsible for
mortalising when there's a require error, and make the general-case case
of cx_popeval() just decrement the reference count.
M inline.h
M pp_ctl.c
commit e9837488af01f31466d4f951a6c8184e76e892d2
Author: David Mitchell <[email protected]>
Date: Tue Jun 28 21:22:39 2016 +0100
expand and rename S_undo_inc_then_croak()
This function is called from 3 places in pp_ctl.c to do things on require
failure like:
delete $INC{$name};
croak "$errsv: Compilation failed in require"
After some previous commits, all 3 callers are now very similar around the
time they call this function: for example they all do
CX_LEAVE_SCOPE(cx);
cx_popeval(cx);
cx_popblock(cx);
So incorporate all that into the function too, and rename it to
S_pop_eval_context_maybe_croak() to reflect its expanded role.
M pp_ctl.c
commit 6bffa452b2eef2deeed8855ac49cbc900cd26623
Author: David Mitchell <[email protected]>
Date: Tue Jun 28 17:14:41 2016 +0100
harmonise die_unwind, doeval_compile, leaveeval
There is some similar code in each of these functions. Reorganise each of
those blocks to make them more similar. In particular, move some of the
EVAL context field preserving to earlier; i.e. change
CX_LEAVE_SCOPE(cx);
cx_popeval(cx);
cx_popblock(cx);
saved_foo = cx->blk_eval.foo;
to
saved_foo = cx->blk_eval.foo;
CX_LEAVE_SCOPE(cx);
cx_popeval(cx);
cx_popblock(cx);
and always examine the context entry to determine whether the EVAL is a
require, rather than using any other method (but assert they're the same);
and for leaveeval, move the CvDEPTH(evalcv)=0 setting earlier.
M pp_ctl.c
commit 0294ea712d2681e55c840ed80bcc3cafa5d18676
Author: David Mitchell <[email protected]>
Date: Tue Jun 28 16:31:45 2016 +0100
tidy doeval_compile()
After the previous commit removed some dead code, the rest of the
code can be re-arranged to be slightly tidier. In particular, this
structure:
if (foo) {
...;
}
if (in_require) {
assert(foo);
croak(...);
}
becomes the logically equivalent
if (foo) {
...;
if (in_require) {
croak(...);
}
}
assert(!in_require);
M pp_ctl.c
commit b377a7333de65a7b5fcf360bea3700350ddaa4d1
Author: David Mitchell <[email protected]>
Date: Tue Jun 28 16:22:03 2016 +0100
doeval_compile(): remove dead code
The combination of in_require and yystatus ==3 (i.e. we caught a
JUMPENV(3)) should never happen, so remove the code that handles this
combo and replace with an assertion.
I think the dead code was wrong anyway - it re-croaked without having
first popped he current EVAL context.
M pp_ctl.c
-----------------------------------------------------------------------
--
Perl5 Master Repository