#define CVf_CLONED 0x02 /* a clone of one of those */
#define CVf_ANON 0x04 /* CvGV() can't be trusted */
#define CVf_OLDSTYLE 0x08
+#define CVf_UNIQUE 0x10 /* can't be cloned */
#define CvCLONE(cv) (CvFLAGS(cv) & CVf_CLONE)
#define CvCLONE_on(cv) (CvFLAGS(cv) |= CVf_CLONE)
#define CvOLDSTYLE(cv) (CvFLAGS(cv) & CVf_OLDSTYLE)
#define CvOLDSTYLE_on(cv) (CvFLAGS(cv) |= CVf_OLDSTYLE)
#define CvOLDSTYLE_off(cv) (CvFLAGS(cv) &= ~CVf_OLDSTYLE)
+
+#define CvUNIQUE(cv) (CvFLAGS(cv) & CVf_UNIQUE)
+#define CvUNIQUE_on(cv) (CvFLAGS(cv) |= CVf_UNIQUE)
+#define CvUNIQUE_off(cv) (CvFLAGS(cv) &= ~CVf_UNIQUE)
depth = CvDEPTH(cv);
if (!depth) {
- if (newoff && (CvANON(cv) || CvGV(cv)))
+ if (newoff && !CvUNIQUE(cv))
return 0; /* don't clone inactive sub's stack frame */
depth = 1;
}
SvNVX(sv) = (double)curcop->cop_seq;
SvIVX(sv) = 999999999; /* A ref, intro immediately */
SvFLAGS(sv) |= SVf_FAKE;
- /* "It's closures all the way down." */
- CvCLONE_on(compcv);
- if (cv != startcv) {
- CV *bcv;
- for (bcv = startcv;
- bcv && bcv != cv && !CvCLONE(bcv);
- bcv = CvOUTSIDE(bcv))
- CvCLONE_on(bcv);
+ if (!CvUNIQUE(cv)) {
+ /* "It's closures all the way down." */
+ CvCLONE_on(compcv);
+ if (cv != startcv) {
+ CV *bcv;
+ for (bcv = startcv;
+ bcv && bcv != cv && !CvCLONE(bcv);
+ bcv = CvOUTSIDE(bcv))
+ CvCLONE_on(bcv);
+ }
}
}
av_store(comppad, newoff, SvREFCNT_inc(oldsv));
cv,
(CvANON(cv) ? "ANON"
: (cv == main_cv) ? "MAIN"
+ : CvUNIQUE(outside) ? "UNIQUE"
: CvGV(cv) ? GvNAME(CvGV(cv)) : "?mystery?"),
outside,
(!outside ? "null"
: CvANON(outside) ? "ANON"
: (outside == main_cv) ? "MAIN"
+ : CvUNIQUE(outside) ? "UNIQUE"
: CvGV(outside) ? GvNAME(CvGV(outside)) : "?mystery?"));
for (ix = 1; ix <= AvFILL(pad); ix++) {
AV* comppadlist;
CV* cv;
+ assert(!CvUNIQUE(proto));
+
ENTER;
SAVESPTR(curpad);
SAVESPTR(comppad);
compcv = (CV*)NEWSV(1104,0);
sv_upgrade((SV *)compcv, SVt_PVCV);
+ CvUNIQUE_on(compcv);
comppad = newAV();
av_push(comppad, Nullsv);
/* We usually try to add a non-existent subroutine in case of AUTOLOAD. */
/* (But not in defined().) */
CV *cv = sv_2cv(TOPs, &stash, &gv, !(op->op_flags & OPf_SPECIAL));
-
- if (!cv)
+ if (cv) {
+ if (CvCLONE(cv))
+ cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
+ }
+ else
cv = (CV*)&sv_undef;
SETs((SV*)cv);
RETURN;
SAVESPTR(compcv);
compcv = (CV*)NEWSV(1104,0);
sv_upgrade((SV *)compcv, SVt_PVCV);
- CvOUTSIDE(compcv) = (CV*)SvREFCNT_inc(caller);
+ CvUNIQUE_on(compcv);
comppad = newAV();
comppad_name = newAV();
av_store(comppadlist, 0, (SV*)comppad_name);
av_store(comppadlist, 1, (SV*)comppad);
CvPADLIST(compcv) = comppadlist;
+ CvOUTSIDE(compcv) = (CV*)SvREFCNT_inc(caller);
+
SAVEFREESV(compcv);
/* make sure we compile in the right package */
register CV *cv;
register CONTEXT *cx;
I32 gimme;
- I32 hasargs = (op->op_flags & OPf_STACKED) != 0;
+ bool hasargs = (op->op_flags & OPf_STACKED) != 0;
+ bool may_clone = TRUE;
if (!sv)
DIE("Not a CODE reference");
break;
}
cv = (CV*)SvRV(sv);
- if (SvTYPE(cv) == SVt_PVCV)
+ if (SvTYPE(cv) == SVt_PVCV) {
+ may_clone = FALSE;
break;
+ }
/* FALL THROUGH */
case SVt_PVHV:
case SVt_PVAV:
DIE("Not a CODE reference");
case SVt_PVCV:
cv = (CV*)sv;
+ may_clone = FALSE;
break;
case SVt_PVGV:
if (!(cv = GvCV((GV*)sv)))
ENTER;
SAVETMPS;
+ if (may_clone && cv && CvCLONE(cv))
+ cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
+
retry:
if (!cv)
DIE("Not a CODE reference");