summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2015-06-09 15:48:15 +0100
committerDavid Mitchell <davem@iabyn.com>2015-06-19 08:44:18 +0100
commit334ea179145c48d0a781ab77c8b4d619e0036cf6 (patch)
treed447625ffbf4a288a9d87425522196b671ceb50c
parent1f0ba93b9eac4ae12dd4b0e2702f798a6cbf224c (diff)
downloadperl-334ea179145c48d0a781ab77c8b4d619e0036cf6.tar.gz
pp_return(): tail call pp_leavetry()
When 'return'ing from an eval { BLOCK }, rather than handling it ourselves, fall through to pp_leavetry(). pp_return() is now only responsible for popping any extra contexts and junk from the stack. This helps avoid two different blocks of code doing roughly the same thing. The functional changes caused by this commit signify the divergence over time between pp_leavetry and the try-ish parts of pp_return. After this commit, a return will: * now do an PERL_ASYNC_CHECK(); * be smarter about not unnecessarily creating mortal copies of returned args; * restore PL_curpm *before* the LEAVE() rather than after. The first two are probably good things; I'm not sure about the latter; it may well be a regression, but nothing tests for it. At least it's consistent now.
-rw-r--r--pp_ctl.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index a826569dae..72229f9151 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2448,7 +2448,9 @@ PP(pp_return)
cx = &cxstack[cxix];
- if (CxTYPE(cx) == CXt_SUB) {
+ if (CxTYPE(cx) == CXt_SUB
+ || (CxTYPE(cx) == CXt_EVAL && CxTRYBLOCK(cx)))
+ {
SV **oldsp = PL_stack_base + cx->blk_oldsp;
if (oldsp != MARK) {
/* Handle extra junk on the stack. For example,
@@ -2473,6 +2475,8 @@ PP(pp_return)
else
PL_stack_sp = oldsp;
}
+ if (CxTYPE(cx) == CXt_EVAL)
+ return Perl_pp_leavetry(aTHX);
/* fall through to a normal sub exit */
return CvLVALUE(cx->blk_sub.cv)
? Perl_pp_leavesublv(aTHX)
@@ -2487,8 +2491,6 @@ PP(pp_return)
POPEVAL(cx);
namesv = cx->blk_eval.old_namesv;
retop = cx->blk_eval.retop;
- if (CxTRYBLOCK(cx))
- break;
if (optype == OP_REQUIRE &&
(MARK == SP || (gimme == G_SCALAR && !SvTRUE(*SP))) )
{
@@ -4379,9 +4381,11 @@ PP(pp_leavetry)
I32 gimme;
PERL_CONTEXT *cx;
I32 optype;
+ OP *retop;
PERL_ASYNC_CHECK();
POPBLOCK(cx,newpm);
+ retop = cx->blk_eval.retop;
POPEVAL(cx);
PERL_UNUSED_VAR(optype);
@@ -4391,7 +4395,7 @@ PP(pp_leavetry)
LEAVE_with_name("eval_scope");
CLEAR_ERRSV();
- RETURN;
+ RETURNOP(retop);
}
PP(pp_entergiven)