/* S_leave_common: Common code that many functions in this file use on
scope exit.
- Process the return args on the stack in the range (mark..sp) based on
- context, with any final args starting at newsp.
+ Process the return args on the stack in the range (mark+1..sp) based on
+ context, with any final args starting at newsp+1. Returns the new
+ top-of-stack position
Args are mortal copied (or mortalied if lvalue) unless its safe to use
- as-is, based on whether it the specified flags
+ as-is, based on whether it has the specified flags. Note that most
+ callers specify flags as (SVs_PADTMP|SVs_TEMP), while leaveeval skips
+ SVs_PADTMP since its optree gets immediately freed, freeing its padtmps
+ at the same time.
Also, taintedness is cleared.
*/
dSP; dMARK;
PERL_CONTEXT *cx;
const I32 gimme = GIMME_V;
- void *itervar; /* location of the iteration variable */
+ void *itervarp; /* GV or pad slot of the iteration variable */
+ SV *itersave; /* the old var in the iterator var slot */
U8 cxtype = CXt_LOOP_FOR;
ENTER_with_name("loop1");
SAVETMPS;
if (PL_op->op_targ) { /* "my" variable */
+ itervarp = &PAD_SVl(PL_op->op_targ);
+ itersave = *(SV**)itervarp;
+ assert(itersave);
if (PL_op->op_private & OPpLVAL_INTRO) { /* for my $x (...) */
/* the SV currently in the pad slot is never live during
* iteration (the slot is always aliased to one of the items)
* so it's always stale */
- SvPADSTALE_on(PAD_SVl(PL_op->op_targ));
+ SvPADSTALE_on(itersave);
}
- SAVEPADSVANDMORTALIZE(PL_op->op_targ);
- itervar = &PAD_SVl(PL_op->op_targ);
+ SvREFCNT_inc_simple_void_NN(itersave);
+ cxtype |= CXp_FOR_PAD;
}
else if (LIKELY(isGV(TOPs))) { /* symbol table variable */
GV * const gv = MUTABLE_GV(POPs);
SV** svp = &GvSV(gv);
- save_pushptrptr(gv, SvREFCNT_inc(*svp), SAVEt_GVSV);
+ itervarp = (void *)gv;
+ itersave = *svp;
*svp = newSV(0);
- itervar = (void *)gv;
+ cxtype |= CXp_FOR_GV;
}
else {
SV * const sv = POPs;
assert(SvTYPE(sv) == SVt_PVMG);
assert(SvMAGIC(sv));
assert(SvMAGIC(sv)->mg_type == PERL_MAGIC_lvref);
- itervar = (void *)sv;
+ itervarp = (void *)sv;
cxtype |= CXp_FOR_LVREF;
+ itersave = NULL;
}
if (PL_op->op_private & OPpITER_DEF)
ENTER_with_name("loop2");
PUSHBLOCK(cx, cxtype, SP);
- PUSHLOOP_FOR(cx, itervar, MARK);
+ PUSHLOOP_FOR(cx, itervarp, itersave, MARK);
if (PL_op->op_flags & OPf_STACKED) {
SV *maybe_ary = POPs;
if (SvTYPE(maybe_ary) != SVt_PVAV) {
SP = (gimme == G_VOID)
? newsp
- : leave_common(newsp, SP, MARK, gimme, 0,
+ : leave_common(newsp, SP, MARK, gimme, SVs_PADTMP|SVs_TEMP,
PL_op->op_private & OPpLVALUE);
PUTBACK;
if (CxLVAL(cx) && !ref) { /* Leave it as it is if we can. */
SV *sv;
if (MARK <= SP) {
- assert(MARK == SP);
if ((SvPADTMP(TOPs) || SvREADONLY(TOPs)) &&
!SvSMAGICAL(TOPs)) {
what =
{
dSP; dMARK;
PERL_CONTEXT *cx;
- SV **oldsp;
const I32 cxix = dopoptosub(cxstack_ix);
assert(cxstack_ix >= 0);
if (cxix < cxstack_ix) {
if (cxix < 0) {
- if (CxMULTICALL(cxstack)) { /* In this case we must be in a
- * sort block, which is a CXt_NULL
- * not a CXt_SUB */
- dounwind(0);
- /* if we were in list context, we would have to splice out
- * any junk before the return args, like we do in the general
- * pp_return case, e.g.
- * sub f { for (junk1, junk2) { return arg1, arg2 }}
- */
+ if (!CxMULTICALL(cxstack))
+ DIE(aTHX_ "Can't return outside a subroutine");
+ /* We must be in a sort block, which is a CXt_NULL not a
+ * CXt_SUB. Handle specially. */
+ if (cxstack_ix > 0) {
+ /* See comment below about context popping. Since we know
+ * we're scalar and not lvalue, we can preserve the return
+ * value in a simpler fashion than there. */
+ SV *sv = *SP;
assert(cxstack[0].blk_gimme == G_SCALAR);
- return 0;
+ if ( (sp != PL_stack_base)
+ && !(SvFLAGS(sv) & (SVs_TEMP|SVs_PADTMP))
+ )
+ *SP = sv_mortalcopy(sv);
+ dounwind(0);
}
- else
- DIE(aTHX_ "Can't return outside a subroutine");
+ /* caller responsible for popping cxstack[0] */
+ return 0;
}
- dounwind(cxix);
- }
-
- cx = &cxstack[cxix];
- oldsp = PL_stack_base + cx->blk_oldsp;
- if (oldsp != MARK) {
- /* Handle extra junk on the stack. For example,
+ /* There are contexts that need popping. Doing this may free the
+ * return value(s), so preserve them first, e.g. popping the plain
+ * loop here would free $x:
+ * sub f { { my $x = 1; return $x } }
+ * We may also need to shift the args down; for example,
* for (1,2) { return 3,4 }
- * leaves 1,2,3,4 on the stack. In list context we
- * have to splice out the 1,2; In scalar context for
+ * leaves 1,2,3,4 on the stack. Both these actions can be done by
+ * leave_common(). By calling it with lvalue=TRUE, we just bump
+ * the ref count and mortalise the args that need it. The "scan
+ * the args and maybe copy them" process will be repeated by
+ * whoever we tail-call (e.g. pp_leaveeval), where any copying etc
+ * will be done. That is to say, in this code path two scans of
+ * the args will be done; the first just shifts and preserves; the
+ * second is the "real" arg processing, based on the type of
+ * return.
+ */
+ cx = &cxstack[cxix];
+ SP = leave_common(PL_stack_base + cx->blk_oldsp, SP, MARK,
+ cx->blk_gimme, SVs_TEMP|SVs_PADTMP, TRUE);
+ PUTBACK;
+ dounwind(cxix);
+ }
+ else {
+ /* Like in the branch above, we need to handle any extra junk on
+ * the stack. But because we're not also popping extra contexts, we
+ * don't have to worry about prematurely freeing args. So we just
+ * need to do the bare minimum to handle junk, and leave the main
+ * arg processing in the function we tail call, e.g. pp_leavesub.
+ * In list context we have to splice out the junk; in scalar
+ * context we can leave as-is (pp_leavesub will later return the
+ * top stack element). But for an empty arg list, e.g.
* for (1,2) { return }
- * we need to set sp = oldsp so that pp_leavesub knows
- * to push &PL_sv_undef onto the stack.
- * Note that in pp_return we only do the extra processing
- * required to handle junk; everything else we leave to
- * pp_leavesub.
+ * we need to set sp = oldsp so that pp_leavesub knows to push
+ * &PL_sv_undef onto the stack.
*/
- SSize_t nargs = SP - MARK;
- if (nargs) {
- if (cx->blk_gimme == G_ARRAY) {
- /* shift return args to base of call stack frame */
- Move(MARK + 1, oldsp + 1, nargs, SV*);
- PL_stack_sp = oldsp + nargs;
+ SV **oldsp;
+ cx = &cxstack[cxix];
+ oldsp = PL_stack_base + cx->blk_oldsp;
+ if (oldsp != MARK) {
+ SSize_t nargs = SP - MARK;
+ if (nargs) {
+ if (cx->blk_gimme == G_ARRAY) {
+ /* shift return args to base of call stack frame */
+ Move(MARK + 1, oldsp + 1, nargs, SV*);
+ PL_stack_sp = oldsp + nargs;
+ }
}
+ else
+ PL_stack_sp = oldsp;
}
- else
- PL_stack_sp = oldsp;
}
/* fall through to a normal exit */