Clone-Closure
view release on metacpan or search on metacpan
lib/Clone/Closure.xs view on Meta::CPAN
clone = (CV *)newSV_type(SvTYPE(ref));
CvFLAGS(clone) = CvFLAGS(ref) & ~CVf_CVGV_RC;
#ifdef USE_ITHREADS
CvFILE(clone) = CvISXSUB(ref) ? CvFILE(ref)
: savepv(CvFILE(ref));
#else
CvFILE(clone) = CvFILE(ref);
#endif
CvGV_set(clone, CvGV(ref));
CvSTASH_set(clone, CvSTASH(ref));
OP_REFCNT_LOCK;
CvROOT(clone) = OpREFCNT_inc(CvROOT(ref));
OP_REFCNT_UNLOCK;
CvSTART(clone) = CvSTART(ref);
CvOUTSIDE(clone) = outside;
if (!CvWEAKOUTSIDE(clone)) SvREFCNT_inc(outside);
#ifdef CvOUTSIDE_SEQ
CvOUTSIDE_SEQ(clone) = CvOUTSIDE_SEQ(ref);
#endif
if (SvPOK(ref))
sv_setpvn((SV *)clone, SvPVX_const(ref), SvCUR(ref));
/* create a new padlist, and initial pad */
cname = newAV();
av_fill(cname, fname);
/* fill in the names of the lexicals */
for (ix = fname; ix >= 0; ix--) {
av_store(cname, ix, SvREFCNT_inc(prname[ix]));
}
cpad = newAV();
av_fill(cpad, fpad);
/* create @_ */
a0 = newAV();
av_extend(a0, 0);
av_store(cpad, 0, (SV *)a0);
AvREIFY_only(a0);
/* the pad is filled in later, by pad_clone */
cpadlist = newAV();
AvREAL_off(cpadlist);
av_store(cpadlist, 0, (SV *)cname);
av_store(cpadlist, 1, (SV *)cpad);
CvPADLIST(clone) = cpadlist;
TRACE_SV("clone", "CV", clone);
return clone;
}
/* mostly stolen from PadWalker */
static void
pad_clone(HV *SEEN, CV *ref, CV *clone)
{
U32 vdepth = CvDEPTH(clone) ? CvDEPTH(clone) : 1;
U32 rdepth = CvDEPTH(ref) ? CvDEPTH(ref) : 1;
AV *padn = (AV *) *av_fetch(CvPADLIST(clone), 0, FALSE);
AV *padv = (AV *) *av_fetch(CvPADLIST(clone), vdepth, FALSE);
AV *padr = (AV *) *av_fetch(CvPADLIST(ref), rdepth, FALSE);
I32 i;
TRACE_SV("ref", "pad", ref);
for (i = av_len(padn); i >= 0; --i) {
SV **name_p, *name_sv, **val_p, *val_sv;
SV **old_p, *old_sv, *new_sv;
const char *name;
bool can_copy;
bool is_proto;
name_p = av_fetch(padn, i, 0);
name_sv = name_p ? *name_p : &PL_sv_undef;
name = (name_p && SvPOKp(name_sv))
? SvPVX_const(name_sv)
: "???";
val_p = av_fetch(padr, i, 0);
val_sv = val_p ? *val_p : &PL_sv_undef;
is_proto = 0;
/* The following types of entries exist in pads... */
/* @_ must be cloned */
if (i == 0) {
name = "@_";
can_copy = 0;
}
/* 'our' entries have everything in the name, and need no pad
* entry */
else if (SvFLAGS(name_sv) & SVpad_OUR) {
can_copy = 1;
}
/* PADTMP entries are targs/GVs/constants, and need copying.
* PADGV/CONST are used by ithreads */
else if (
SvPADTMP(val_sv) ||
IS_PADGV(val_sv) ||
IS_PADCONST(val_sv)
) {
name = "PADTMP";
can_copy = 1;
}
/* entries with names are lexicals */
else if (name_sv != &PL_sv_undef) {
/* closure prototypes must be copied */
( run in 1.868 second using v1.01-cache-2.11-cpan-39bf76dae61 )