summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2015-05-24 09:48:53 +0100
committerDavid Mitchell <davem@iabyn.com>2015-06-19 08:44:17 +0100
commit57486a97716ab2f9c98c7bd4353b3c1974a40db9 (patch)
tree7d6e72e58c0f15787659549164b8daebdefe16db /pp_ctl.c
parent6228a1e1a04e2002bf9e76fea0f52a87b43f841a (diff)
downloadperl-57486a97716ab2f9c98c7bd4353b3c1974a40db9.tar.gz
handle most of lvalue return in single place
Currently about half the work involved in returning from an lvalue sub call is done by the shared sub S_return_lvalues() function, while the other half is duplicated in pp_leavesublv() and pp_return(). Move most of that duplicated code into S_return_lvalues().
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c92
1 files changed, 46 insertions, 46 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 71d18b2a1a..5804f47ca0 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2279,11 +2279,31 @@ PP(pp_leaveloop)
return NORMAL;
}
-STATIC void
-S_return_lvalues(pTHX_ SV **mark, SV **sp, SV **newsp, I32 gimme,
- PERL_CONTEXT *cx, PMOP *newpm)
+/* handle most of the activity of returning from an lvalue sub.
+ * Called by pp_leavesublv and pp_return.
+ * For pp_leavesublv, base is null; for pp_return, its the base
+ * of the args to be returned (i.e. the mark on entry to pp_return)
+ */
+
+STATIC OP*
+S_return_lvalues(pTHX_ SV **base)
{
- const bool ref = !!(CxLVAL(cx) & OPpENTERSUB_INARGS);
+ dSP;
+ SV **newsp;
+ SV **mark;
+ PMOP *newpm;
+ I32 gimme;
+ PERL_CONTEXT *cx;
+ SV *sv;
+ bool ref;
+
+ POPBLOCK(cx,newpm);
+ cxstack_ix++; /* preserve cx entry on stack for use by POPSUB */
+ TAINT_NOT;
+
+ mark = base ? base : newsp;
+
+ ref = !!(CxLVAL(cx) & OPpENTERSUB_INARGS);
if (gimme == G_SCALAR) {
if (CxLVAL(cx) && !ref) { /* Leave it as it is if we can. */
SV *sv;
@@ -2382,21 +2402,34 @@ S_return_lvalues(pTHX_ SV **mark, SV **sp, SV **newsp, I32 gimme,
}
}
PL_stack_sp = newsp;
+
+ LEAVE;
+ /* Stack values are safe: */
+ if (base) {
+ cxstack_ix--;
+ POPSUB(cx,sv); /* release CV and @_ ... */
+ }
+ else {
+ POPSUB(cx,sv); /* Stack values are safe: release CV and @_ ... */
+ cxstack_ix--;
+ }
+ PL_curpm = newpm; /* ... and pop $1 et al */
+ LEAVESUB(sv);
+
+ return cx->blk_sub.retop;
}
+
PP(pp_return)
{
dSP; dMARK;
PERL_CONTEXT *cx;
- bool popsub2 = FALSE;
bool clear_errsv = FALSE;
- bool lval = FALSE;
I32 gimme;
SV **newsp;
PMOP *newpm;
I32 optype = 0;
SV *namesv;
- SV *sv;
OP *retop = NULL;
const I32 cxix = dopoptosub(cxstack_ix);
@@ -2428,7 +2461,10 @@ PP(pp_return)
return 0;
}
- if (CxTYPE(cx) == CXt_SUB && !CvLVALUE(cx->blk_sub.cv)) {
+ if (CxTYPE(cx) == CXt_SUB) {
+ if (CvLVALUE(cx->blk_sub.cv))
+ return S_return_lvalues(aTHX_ MARK);
+ else {
SV **oldsp = PL_stack_base + cx->blk_oldsp;
if (oldsp != MARK) {
/* shift return args to base of call stack frame */
@@ -2443,17 +2479,11 @@ PP(pp_return)
}
/* fall through to a normal sub exit */
return Perl_pp_leavesub(aTHX);
+ }
}
POPBLOCK(cx,newpm);
switch (CxTYPE(cx)) {
- case CXt_SUB:
- popsub2 = TRUE;
- assert(CvLVALUE(cx->blk_sub.cv));
- lval = TRUE;
- retop = cx->blk_sub.retop;
- cxstack_ix++; /* preserve cx entry on stack for use by POPSUB */
- break;
case CXt_EVAL:
if (!(PL_in_eval & EVAL_KEEPERR))
clear_errsv = TRUE;
@@ -2482,8 +2512,6 @@ PP(pp_return)
}
TAINT_NOT;
- if (lval) S_return_lvalues(aTHX_ MARK, SP, newsp, gimme, cx, newpm);
- else {
if (gimme == G_SCALAR)
*++newsp = (MARK < SP) ? sv_mortalcopy(*SP) : &PL_sv_undef;
else if (gimme == G_ARRAY) {
@@ -2493,19 +2521,10 @@ PP(pp_return)
}
}
PL_stack_sp = newsp;
- }
LEAVE;
- /* Stack values are safe: */
- if (popsub2) {
- cxstack_ix--;
- POPSUB(cx,sv); /* release CV and @_ ... */
- }
- else
- sv = NULL;
PL_curpm = newpm; /* ... and pop $1 et al */
- LEAVESUB(sv);
if (clear_errsv) {
CLEAR_ERRSV();
}
@@ -2516,30 +2535,11 @@ PP(pp_return)
* pp_return */
PP(pp_leavesublv)
{
- dSP;
- SV **newsp;
- PMOP *newpm;
- I32 gimme;
- PERL_CONTEXT *cx;
- SV *sv;
-
if (CxMULTICALL(&cxstack[cxstack_ix]))
return 0;
+ return S_return_lvalues(aTHX_ NULL);
- POPBLOCK(cx,newpm);
- cxstack_ix++; /* temporarily protect top context */
-
- TAINT_NOT;
-
- S_return_lvalues(aTHX_ newsp, SP, newsp, gimme, cx, newpm);
- LEAVE;
- POPSUB(cx,sv); /* Stack values are safe: release CV and @_ ... */
- cxstack_ix--;
- PL_curpm = newpm; /* ... and pop $1 et al */
-
- LEAVESUB(sv);
- return cx->blk_sub.retop;
}
static I32