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 )