X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/6dfeccca7d595e9c94766acdd058cec56fa67315..5c5ade3ee4e783409153da7ec47110c6bb74a89b:/sv.c diff --git a/sv.c b/sv.c index cf9a6ff..2e3ba69 100644 --- a/sv.c +++ b/sv.c @@ -353,10 +353,9 @@ S_del_sv(pTHX_ SV *p) } } if (!ok) { - if (ckWARN_d(WARN_INTERNAL)) - Perl_warner(aTHX_ packWARN(WARN_INTERNAL), - "Attempt to free non-arena SV: 0x%"UVxf - pTHX__FORMAT, PTR2UV(p) pTHX__VALUE); + Perl_ck_warner_d(aTHX_ packWARN(WARN_INTERNAL), + "Attempt to free non-arena SV: 0x%"UVxf + pTHX__FORMAT, PTR2UV(p) pTHX__VALUE); return; } } @@ -608,7 +607,7 @@ Perl_sv_clean_all(pTHX) struct arena_desc { char *arena; /* the raw storage, allocated aligned */ size_t size; /* its size ~4k typ */ - U32 misc; /* type, and in future other things. */ + svtype utype; /* bodytype stored in arena */ }; struct arena_set; @@ -690,7 +689,6 @@ Perl_sv_free_arenas(pTHX) 2. regular body arenas 3. arenas for reduced-size bodies 4. Hash-Entry arenas - 5. pte arenas (thread related) Arena types 2 & 3 are chained by body-type off an array of arena-root pointers, which is indexed by svtype. Some of the @@ -709,19 +707,13 @@ Perl_sv_free_arenas(pTHX) HE, HEK arenas are managed separately, with separate code, but may be merge-able later.. - - PTE arenas are not sv-bodies, but they share these mid-level - mechanics, so are considered here. The new mid-level mechanics rely - on the sv_type of the body being allocated, so we just reserve one - of the unused body-slots for PTEs, then use it in those (2) PTE - contexts below (line ~10k) */ /* get_arena(size): this creates custom-sized arenas TBD: export properly for hv.c: S_more_he(). */ void* -Perl_get_arena(pTHX_ const size_t arena_size, const U32 misc) +Perl_get_arena(pTHX_ const size_t arena_size, const svtype bodytype) { dVAR; struct arena_desc* adesc; @@ -750,7 +742,7 @@ Perl_get_arena(pTHX_ const size_t arena_size, const U32 misc) Newx(adesc->arena, arena_size, char); adesc->size = arena_size; - adesc->misc = misc; + adesc->utype = bodytype; DEBUG_m(PerlIO_printf(Perl_debug_log, "arena %d added: %p size %"UVuf"\n", curr, (void*)adesc->arena, (UV)arena_size)); @@ -853,13 +845,6 @@ PL_body_roots[HE_SVSLOT=SVt_NULL] is filled by S_more_he, but the bodies_by_type[SVt_NULL] slot is not used, as the table is not available in hv.c. -PTEs also use arenas, but are never seen in Perl_sv_upgrade. Nonetheless, -they get their own slot in bodies_by_type[PTE_SVSLOT =SVt_IV], so they can -just use the same allocation semantics. At first, PTEs were also -overloaded to a non-body sv-type, but this yielded hard-to-find malloc -bugs, so was simplified by claiming a new slot. This choice has no -consequence at this time. - */ struct body_details { @@ -922,14 +907,11 @@ static const struct body_details bodies_by_type[] = { implemented. */ { 0, 0, 0, SVt_BIND, TRUE, NONV, NOARENA, 0 }, - /* IVs are in the head, so the allocation size is 0. - However, the slot is overloaded for PTEs. */ - { sizeof(struct ptr_tbl_ent), /* This is used for PTEs. */ + /* IVs are in the head, so the allocation size is 0. */ + { 0, sizeof(IV), /* This is used to copy out the IV body. */ STRUCT_OFFSET(XPVIV, xiv_iv), SVt_IV, FALSE, NONV, - NOARENA /* IVS don't need an arena */, - /* But PTEs need to know the size of their arena */ - FIT_ARENA(0, sizeof(struct ptr_tbl_ent)) + NOARENA /* IVS don't need an arena */, 0 }, /* 8 bytes on most ILP32 with IEEE doubles */ @@ -1373,6 +1355,10 @@ Perl_sv_upgrade(pTHX_ register SV *const sv, svtype new_type) break; + case SVt_REGEXP: + /* This ensures that SvTHINKFIRST(sv) is true, and hence that + sv_force_normal_flags(sv) is called. */ + SvFAKE_on(sv); case SVt_PVIV: /* XXX Is this still needed? Was it ever needed? Surely as there is no route from NV to PVIV, NOK can never be true */ @@ -1383,7 +1369,6 @@ Perl_sv_upgrade(pTHX_ register SV *const sv, svtype new_type) case SVt_PVGV: case SVt_PVCV: case SVt_PVLV: - case SVt_REGEXP: case SVt_PVMG: case SVt_PVNV: case SVt_PV: @@ -1432,17 +1417,13 @@ Perl_sv_upgrade(pTHX_ register SV *const sv, svtype new_type) if (new_type == SVt_PVIO) { IO * const io = MUTABLE_IO(sv); - GV *iogv = gv_fetchpvs("FileHandle::", 0, SVt_PVHV); + GV *iogv = gv_fetchpvs("IO::File::", GV_ADD, SVt_PVHV); SvOBJECT_on(io); /* Clear the stashcache because a new IO could overrule a package name */ hv_clear(PL_stashcache); - /* unless exists($main::{FileHandle}) and - defined(%main::FileHandle::) */ - if (!(iogv && GvHV(iogv) && HvARRAY(GvHV(iogv)))) - iogv = gv_fetchpvs("IO::Handle::", GV_ADD, SVt_PVHV); SvSTASH_set(io, MUTABLE_HV(SvREFCNT_inc(GvHV(iogv)))); IoPAGE_LEN(sv) = 60; } @@ -1457,14 +1438,14 @@ Perl_sv_upgrade(pTHX_ register SV *const sv, svtype new_type) (unsigned long)new_type); } - if (old_type_details->arena) { - /* If there was an old body, then we need to free it. - Note that there is an assumption that all bodies of types that - can be upgraded came from arenas. Only the more complex non- - upgradable types are allowed to be directly malloc()ed. */ + if (old_type > SVt_IV) { #ifdef PURIFY my_safefree(old_body); #else + /* Note that there is an assumption that all bodies of types that + can be upgraded came from arenas. Only the more complex non- + upgradable types are allowed to be directly malloc()ed. */ + assert(old_type_details->arena); del_body((void*)((char*)old_body + old_type_details->offset), &PL_body_roots[old_type]); #endif @@ -1719,7 +1700,7 @@ Perl_sv_setnv(pTHX_ register SV *const sv, const NV num) case SVt_PVFM: case SVt_PVIO: Perl_croak(aTHX_ "Can't coerce %s to number in %s", sv_reftype(sv,0), - OP_NAME(PL_op)); + OP_DESC(PL_op)); default: NOOP; } SvNV_set(sv, num); @@ -2991,11 +2972,17 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags gv_efullname3(buffer, gv, "*"); SvFLAGS(gv) |= wasfake; - assert(SvPOK(buffer)); - if (lp) { - *lp = SvCUR(buffer); + if (SvPOK(buffer)) { + if (lp) { + *lp = SvCUR(buffer); + } + return SvPVX(buffer); + } + else { + if (lp) + *lp = 0; + return (char *)""; } - return SvPVX(buffer); } if (lp) @@ -3120,7 +3107,7 @@ Perl_sv_2bool(pTHX_ register SV *const sv) if (SvAMAGIC(sv)) { SV * const tmpsv = AMG_CALLun(sv,bool_); if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv)))) - return (bool)SvTRUE(tmpsv); + return cBOOL(SvTRUE(tmpsv)); } return SvRV(sv) != 0; } @@ -3251,7 +3238,9 @@ Perl_sv_utf8_upgrade_flags_grow(pTHX_ register SV *const sv, const I32 flags, ST return SvCUR(sv); } - if (SvCUR(sv) > 0) { /* Assume Latin-1/EBCDIC */ + if (SvCUR(sv) == 0) { + if (extra) SvGROW(sv, extra); + } else { /* Assume Latin-1/EBCDIC */ /* This function could be much more efficient if we * had a FLAG in SVs to signal if there are any variant * chars in the PV. Given that there isn't such a flag @@ -3679,7 +3668,6 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr) SV **location; U8 import_flag = 0; const U32 stype = SvTYPE(sref); - bool mro_changes = FALSE; PERL_ARGS_ASSERT_GLOB_ASSIGN_REF; @@ -3700,8 +3688,6 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr) goto common; case SVt_PVAV: location = (SV **) &GvAV(dstr); - if (strEQ(GvNAME((GV*)dstr), "ISA")) - mro_changes = TRUE; import_flag = GVf_IMPORTED_AV; goto common; case SVt_PVIO: @@ -3775,12 +3761,15 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr) && CopSTASH_ne(PL_curcop, GvSTASH(dstr))) { GvFLAGS(dstr) |= import_flag; } + if (stype == SVt_PVAV && strEQ(GvNAME((GV*)dstr), "ISA")) { + sv_magic(sref, dstr, PERL_MAGIC_isa, NULL, 0); + mro_isa_changed_in(GvSTASH(dstr)); + } break; } SvREFCNT_dec(dref); if (SvTAINTED(sstr)) SvTAINT(dstr); - if (mro_changes) mro_isa_changed_in(GvSTASH(dstr)); return; } @@ -3892,7 +3881,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags) } /* Fall through */ #endif - case SVt_REGEXP: case SVt_PV: if (dtype < SVt_PV) sv_upgrade(dstr, SVt_PV); @@ -3909,12 +3897,17 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags) { const char * const type = sv_reftype(sstr,0); if (PL_op) - Perl_croak(aTHX_ "Bizarre copy of %s in %s", type, OP_NAME(PL_op)); + Perl_croak(aTHX_ "Bizarre copy of %s in %s", type, OP_DESC(PL_op)); else Perl_croak(aTHX_ "Bizarre copy of %s", type); } break; + case SVt_REGEXP: + if (dtype < SVt_REGEXP) + sv_upgrade(dstr, SVt_REGEXP); + break; + /* case SVt_BIND: */ case SVt_PVLV: case SVt_PVGV: @@ -3964,7 +3957,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags) } else if (dtype == SVt_PVAV || dtype == SVt_PVHV) { const char * const type = sv_reftype(dstr,0); if (PL_op) - Perl_croak(aTHX_ "Cannot copy to %s in %s", type, OP_NAME(PL_op)); + Perl_croak(aTHX_ "Cannot copy to %s in %s", type, OP_DESC(PL_op)); else Perl_croak(aTHX_ "Cannot copy to %s", type); } else if (sflags & SVf_ROK) { @@ -4005,9 +3998,8 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags) } else if (dtype == SVt_PVGV && isGV_with_GP(dstr)) { if (!(sflags & SVf_OK)) { - if (ckWARN(WARN_MISC)) - Perl_warner(aTHX_ packWARN(WARN_MISC), - "Undefined value assigned to typeglob"); + Perl_ck_warner(aTHX_ packWARN(WARN_MISC), + "Undefined value assigned to typeglob"); } else { GV *gv = gv_fetchsv(sstr, GV_ADD, SVt_PVGV); @@ -4018,6 +4010,9 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags) } } } + else if (dtype == SVt_REGEXP && stype == SVt_REGEXP) { + reg_temp_copy((REGEXP*)dstr, (REGEXP*)sstr); + } else if (sflags & SVp_POK) { bool isSwipe = 0; @@ -4606,6 +4601,45 @@ Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags) sv_unref_flags(sv, flags); else if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV) sv_unglob(sv); + else if (SvFAKE(sv) && SvTYPE(sv) == SVt_REGEXP) { + /* Need to downgrade the REGEXP to a simple(r) scalar. This is analagous + to sv_unglob. We only need it here, so inline it. */ + const svtype new_type = SvMAGIC(sv) || SvSTASH(sv) ? SVt_PVMG : SVt_PV; + SV *const temp = newSV_type(new_type); + void *const temp_p = SvANY(sv); + + if (new_type == SVt_PVMG) { + SvMAGIC_set(temp, SvMAGIC(sv)); + SvMAGIC_set(sv, NULL); + SvSTASH_set(temp, SvSTASH(sv)); + SvSTASH_set(sv, NULL); + } + SvCUR_set(temp, SvCUR(sv)); + /* Remember that SvPVX is in the head, not the body. */ + if (SvLEN(temp)) { + SvLEN_set(temp, SvLEN(sv)); + /* This signals "buffer is owned by someone else" in sv_clear, + which is the least effort way to stop it freeing the buffer. + */ + SvLEN_set(sv, SvLEN(sv)+1); + } else { + /* Their buffer is already owned by someone else. */ + SvPVX(sv) = savepvn(SvPVX(sv), SvCUR(sv)); + SvLEN_set(temp, SvCUR(sv)+1); + } + + /* Now swap the rest of the bodies. */ + + SvFLAGS(sv) &= ~(SVf_FAKE|SVTYPEMASK); + SvFLAGS(sv) |= new_type; + SvANY(sv) = SvANY(temp); + + SvFLAGS(temp) &= ~(SVTYPEMASK); + SvFLAGS(temp) |= SVt_REGEXP|SVf_FAKE; + SvANY(temp) = temp_p; + + SvREFCNT_dec(temp); + } } /* @@ -5206,12 +5240,14 @@ Perl_sv_unmagic(pTHX_ SV *const sv, const int type) else mgp = &mg->mg_moremagic; } - if (!SvMAGIC(sv)) { + if (SvMAGIC(sv)) { + if (SvMAGICAL(sv)) /* if we're under save_magic, wait for restore_magic; */ + mg_magical(sv); /* else fix the flags now */ + } + else { SvMAGICAL_off(sv); SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT; - SvMAGIC_set(sv, NULL); } - return 0; } @@ -5239,8 +5275,7 @@ Perl_sv_rvweaken(pTHX_ SV *const sv) if (!SvROK(sv)) Perl_croak(aTHX_ "Can't weaken a nonreference"); else if (SvWEAKREF(sv)) { - if (ckWARN(WARN_MISC)) - Perl_warner(aTHX_ packWARN(WARN_MISC), "Reference is already weak"); + Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Reference is already weak"); return sv; } tsv = SvRV(sv); @@ -5624,15 +5659,9 @@ Perl_sv_clear(pTHX_ register SV *const sv) if (type <= SVt_IV) { /* See the comment in sv.h about the collusion between this early - return and the overloading of the NULL and IV slots in the size - table. */ - if (SvROK(sv)) { - SV * const target = SvRV(sv); - if (SvWEAKREF(sv)) - sv_del_backref(target, sv); - else - SvREFCNT_dec(target); - } + return and the overloading of the NULL slots in the size table. */ + if (SvROK(sv)) + goto free_rv; SvFLAGS(sv) &= SVf_BREAK; SvFLAGS(sv) |= SVTYPEMASK; return; @@ -5654,7 +5683,8 @@ Perl_sv_clear(pTHX_ register SV *const sv) && !CvCONST(destructor) /* Don't bother calling an empty destructor */ && (CvISXSUB(destructor) - || CvSTART(destructor)->op_next->op_type != OP_LEAVESUB)) + || (CvSTART(destructor) + && (CvSTART(destructor)->op_next->op_type != OP_LEAVESUB)))) { SV* const tmpref = newRV(sv); SvREADONLY_on(tmpref); /* DESTROY() could be naughty */ @@ -5783,11 +5813,14 @@ Perl_sv_clear(pTHX_ register SV *const sv) /* Don't even bother with turning off the OOK flag. */ } if (SvROK(sv)) { - SV * const target = SvRV(sv); - if (SvWEAKREF(sv)) - sv_del_backref(target, sv); - else - SvREFCNT_dec(target); + free_rv: + { + SV * const target = SvRV(sv); + if (SvWEAKREF(sv)) + sv_del_backref(target, sv); + else + SvREFCNT_dec(target); + } } #ifdef PERL_OLD_COPY_ON_WRITE else if (SvPVX_const(sv)) { @@ -5918,10 +5951,9 @@ Perl_sv_free2(pTHX_ SV *const sv) #ifdef DEBUGGING if (SvTEMP(sv)) { - if (ckWARN_d(WARN_DEBUGGING)) - Perl_warner(aTHX_ packWARN(WARN_DEBUGGING), - "Attempt to free temp prematurely: SV 0x%"UVxf - pTHX__FORMAT, PTR2UV(sv) pTHX__VALUE); + Perl_ck_warner_d(aTHX_ packWARN(WARN_DEBUGGING), + "Attempt to free temp prematurely: SV 0x%"UVxf + pTHX__FORMAT, PTR2UV(sv) pTHX__VALUE); return; } #endif @@ -6013,12 +6045,17 @@ Perl_sv_len_utf8(pTHX_ register SV *const sv) else { ulen = Perl_utf8_length(aTHX_ s, s + len); if (!SvREADONLY(sv)) { - if (!mg) { + if (!mg && (SvTYPE(sv) < SVt_PVMG || + !(mg = mg_find(sv, PERL_MAGIC_utf8)))) { mg = sv_magicext(sv, 0, PERL_MAGIC_utf8, &PL_vtbl_utf8, 0, 0); } assert(mg); mg->mg_len = ulen; + /* For now, treat "overflowed" as "still unknown". + See RT #72924. */ + if (ulen != (STRLEN) mg->mg_len) + mg->mg_len = -1; } } return ulen; @@ -6093,8 +6130,10 @@ S_sv_pos_u2b_cached(pTHX_ SV *const sv, MAGIC **const mgp, const U8 *const start assert (uoffset >= uoffset0); - if (SvMAGICAL(sv) && !SvREADONLY(sv) && PL_utf8cache - && (*mgp || (*mgp = mg_find(sv, PERL_MAGIC_utf8)))) { + if (!SvREADONLY(sv) + && PL_utf8cache + && (*mgp || (SvTYPE(sv) >= SVt_PVMG && + (*mgp = mg_find(sv, PERL_MAGIC_utf8))))) { if ((*mgp)->mg_ptr) { STRLEN *cache = (STRLEN *) (*mgp)->mg_ptr; if (cache[0] == uoffset) { @@ -6185,62 +6224,97 @@ S_sv_pos_u2b_cached(pTHX_ SV *const sv, MAGIC **const mgp, const U8 *const start /* -=for apidoc sv_pos_u2b +=for apidoc sv_pos_u2b_flags Converts the value pointed to by offsetp from a count of UTF-8 chars from the start of the string, to a count of the equivalent number of bytes; if lenp is non-zero, it does the same to lenp, but this time starting from -the offset, rather than from the start of the string. Handles magic and -type coercion. +the offset, rather than from the start of the string. Handles type coercion. +I is passed to C, and usually should be +C to handle magic. =cut */ /* - * sv_pos_u2b() uses, like sv_pos_b2u(), the mg_ptr of the potential + * sv_pos_u2b_flags() uses, like sv_pos_b2u(), the mg_ptr of the potential * PERL_MAGIC_utf8 of the sv to store the mapping between UTF-8 and * byte offsets. See also the comments of S_utf8_mg_pos_cache_update(). * */ -void -Perl_sv_pos_u2b(pTHX_ register SV *const sv, I32 *const offsetp, I32 *const lenp) +STRLEN +Perl_sv_pos_u2b_flags(pTHX_ SV *const sv, STRLEN uoffset, STRLEN *const lenp, + U32 flags) { const U8 *start; STRLEN len; + STRLEN boffset; - PERL_ARGS_ASSERT_SV_POS_U2B; + PERL_ARGS_ASSERT_SV_POS_U2B_FLAGS; - if (!sv) - return; - - start = (U8*)SvPV_const(sv, len); + start = (U8*)SvPV_flags(sv, len, flags); if (len) { - STRLEN uoffset = (STRLEN) *offsetp; const U8 * const send = start + len; MAGIC *mg = NULL; - const STRLEN boffset = sv_pos_u2b_cached(sv, &mg, start, send, - uoffset, 0, 0); - - *offsetp = (I32) boffset; + boffset = sv_pos_u2b_cached(sv, &mg, start, send, uoffset, 0, 0); if (lenp) { /* Convert the relative offset to absolute. */ - const STRLEN uoffset2 = uoffset + (STRLEN) *lenp; + const STRLEN uoffset2 = uoffset + *lenp; const STRLEN boffset2 = sv_pos_u2b_cached(sv, &mg, start, send, uoffset2, uoffset, boffset) - boffset; *lenp = boffset2; } - } - else { - *offsetp = 0; - if (lenp) - *lenp = 0; + } else { + if (lenp) + *lenp = 0; + boffset = 0; } - return; + return boffset; +} + +/* +=for apidoc sv_pos_u2b + +Converts the value pointed to by offsetp from a count of UTF-8 chars from +the start of the string, to a count of the equivalent number of bytes; if +lenp is non-zero, it does the same to lenp, but this time starting from +the offset, rather than from the start of the string. Handles magic and +type coercion. + +Use C in preference, which correctly handles strings longer +than 2Gb. + +=cut +*/ + +/* + * sv_pos_u2b() uses, like sv_pos_b2u(), the mg_ptr of the potential + * PERL_MAGIC_utf8 of the sv to store the mapping between UTF-8 and + * byte offsets. See also the comments of S_utf8_mg_pos_cache_update(). + * + */ + +/* This function is subject to size and sign problems */ + +void +Perl_sv_pos_u2b(pTHX_ register SV *const sv, I32 *const offsetp, I32 *const lenp) +{ + PERL_ARGS_ASSERT_SV_POS_U2B; + + if (lenp) { + STRLEN ulen = (STRLEN)*lenp; + *offsetp = (I32)sv_pos_u2b_flags(sv, (STRLEN)*offsetp, &ulen, + SV_GMAGIC|SV_CONST_RETURN); + *lenp = (I32)ulen; + } else { + *offsetp = (I32)sv_pos_u2b_flags(sv, (STRLEN)*offsetp, NULL, + SV_GMAGIC|SV_CONST_RETURN); + } } /* Create and update the UTF8 magic offset cache, with the proffered utf8/ @@ -6277,7 +6351,8 @@ S_utf8_mg_pos_cache_update(pTHX_ SV *const sv, MAGIC **const mgp, const STRLEN b if (SvREADONLY(sv)) return; - if (!*mgp) { + if (!*mgp && (SvTYPE(sv) < SVt_PVMG || + !(*mgp = mg_find(sv, PERL_MAGIC_utf8)))) { *mgp = sv_magicext(sv, 0, PERL_MAGIC_utf8, (MGVTBL*)&PL_vtbl_utf8, 0, 0); (*mgp)->mg_len = -1; @@ -6290,7 +6365,13 @@ S_utf8_mg_pos_cache_update(pTHX_ SV *const sv, MAGIC **const mgp, const STRLEN b } assert(cache); - if (PL_utf8cache < 0) { + if (PL_utf8cache < 0 && SvPOKp(sv)) { + /* SvPOKp() because it's possible that sv has string overloading, and + therefore is a reference, hence SvPVX() is actually a pointer. + This cures the (very real) symptoms of RT 69422, but I'm not actually + sure whether we should even be caching the results of UTF-8 + operations on overloading, given that nothing stops overloading + returning a different value every time it's called. */ const U8 *start = (const U8 *) SvPVX_const(sv); const STRLEN realutf8 = utf8_length(start, start + byte); @@ -6468,8 +6549,11 @@ Perl_sv_pos_b2u(pTHX_ register SV *const sv, I32 *const offsetp) send = s + byte; - if (SvMAGICAL(sv) && !SvREADONLY(sv) && PL_utf8cache - && (mg = mg_find(sv, PERL_MAGIC_utf8))) { + if (!SvREADONLY(sv) + && PL_utf8cache + && SvTYPE(sv) >= SVt_PVMG + && (mg = mg_find(sv, PERL_MAGIC_utf8))) + { if (mg->mg_ptr) { STRLEN * const cache = (STRLEN *) mg->mg_ptr; if (cache[1] == byte) { @@ -7278,10 +7362,10 @@ Perl_sv_inc(pTHX_ register SV *const sv) if (flags & SVp_NOK) { const NV was = SvNVX(sv); if (NV_OVERFLOWS_INTEGERS_AT && - was >= NV_OVERFLOWS_INTEGERS_AT && ckWARN(WARN_IMPRECISION)) { - Perl_warner(aTHX_ packWARN(WARN_IMPRECISION), - "Lost precision when incrementing %" NVff " by 1", - was); + was >= NV_OVERFLOWS_INTEGERS_AT) { + Perl_ck_warner(aTHX_ packWARN(WARN_IMPRECISION), + "Lost precision when incrementing %" NVff " by 1", + was); } (void)SvNOK_only(sv); SvNV_set(sv, was + 1.0); @@ -7444,10 +7528,10 @@ Perl_sv_dec(pTHX_ register SV *const sv) { const NV was = SvNVX(sv); if (NV_OVERFLOWS_INTEGERS_AT && - was <= -NV_OVERFLOWS_INTEGERS_AT && ckWARN(WARN_IMPRECISION)) { - Perl_warner(aTHX_ packWARN(WARN_IMPRECISION), - "Lost precision when decrementing %" NVff " by 1", - was); + was <= -NV_OVERFLOWS_INTEGERS_AT) { + Perl_ck_warner(aTHX_ packWARN(WARN_IMPRECISION), + "Lost precision when decrementing %" NVff " by 1", + was); } (void)SvNOK_only(sv); SvNV_set(sv, was - 1.0); @@ -7498,6 +7582,16 @@ Perl_sv_dec(pTHX_ register SV *const sv) sv_setnv(sv,Atof(SvPVX_const(sv)) - 1.0); /* punt */ } +/* this define is used to eliminate a chunk of duplicated but shared logic + * it has the suffix __SV_C to signal that it isnt API, and isnt meant to be + * used anywhere but here - yves + */ +#define PUSH_EXTEND_MORTAL__SV_C(AnSv) \ + STMT_START { \ + EXTEND_MORTAL(1); \ + PL_tmps_stack[++PL_tmps_ix] = (AnSv); \ + } STMT_END + /* =for apidoc sv_mortalcopy @@ -7522,8 +7616,7 @@ Perl_sv_mortalcopy(pTHX_ SV *const oldstr) new_SV(sv); sv_setsv(sv,oldstr); - EXTEND_MORTAL(1); - PL_tmps_stack[++PL_tmps_ix] = sv; + PUSH_EXTEND_MORTAL__SV_C(sv); SvTEMP_on(sv); return sv; } @@ -7547,8 +7640,7 @@ Perl_sv_newmortal(pTHX) new_SV(sv); SvFLAGS(sv) = SVs_TEMP; - EXTEND_MORTAL(1); - PL_tmps_stack[++PL_tmps_ix] = sv; + PUSH_EXTEND_MORTAL__SV_C(sv); return sv; } @@ -7562,7 +7654,8 @@ string. You are responsible for ensuring that the source string is at least C bytes long. If the C argument is NULL the new SV will be undefined. Currently the only flag bits accepted are C and C. If C is set, then C is called on the result before -returning. If C is set, then it will be set on the new SV. +returning. If C is set, C is considered to be in UTF-8 and the +C flag will be set on the new SV. C is a convenience wrapper for this function, defined as #define newSVpvn_utf8(s, len, u) \ @@ -7582,11 +7675,19 @@ Perl_newSVpvn_flags(pTHX_ const char *const s, const STRLEN len, const U32 flags assert(!(flags & ~(SVf_UTF8|SVs_TEMP))); new_SV(sv); sv_setpvn(sv,s,len); + + /* This code used to a sv_2mortal(), however we now unroll the call to sv_2mortal() + * and do what it does outselves here. + * Since we have asserted that flags can only have the SVf_UTF8 and/or SVs_TEMP flags + * set above we can use it to enable the sv flags directly (bypassing SvTEMP_on), which + * in turn means we dont need to mask out the SVf_UTF8 flag below, which means that we + * eleminate quite a few steps than it looks - Yves (explaining patch by gfx) + */ + SvFLAGS(sv) |= flags; if(flags & SVs_TEMP){ - EXTEND_MORTAL(1); - PL_tmps_stack[++PL_tmps_ix] = sv; + PUSH_EXTEND_MORTAL__SV_C(sv); } return sv; @@ -7612,8 +7713,7 @@ Perl_sv_2mortal(pTHX_ register SV *const sv) return NULL; if (SvREADONLY(sv) && SvIMMORTAL(sv)) return sv; - EXTEND_MORTAL(1); - PL_tmps_stack[++PL_tmps_ix] = sv; + PUSH_EXTEND_MORTAL__SV_C(sv); SvTEMP_on(sv); return sv; } @@ -7977,8 +8077,7 @@ Perl_newSVsv(pTHX_ register SV *const old) if (!old) return NULL; if (SvTYPE(old) == SVTYPEMASK) { - if (ckWARN_d(WARN_INTERNAL)) - Perl_warner(aTHX_ packWARN(WARN_INTERNAL), "semi-panic: attempt to dup freed string"); + Perl_ck_warner_d(aTHX_ packWARN(WARN_INTERNAL), "semi-panic: attempt to dup freed string"); return NULL; } new_SV(sv); @@ -8145,7 +8244,7 @@ Perl_sv_2io(pTHX_ SV *const sv) Using various gambits, try to get a CV from an SV; in addition, try if possible to set C<*st> and C<*gvp> to the stash and GV associated with it. -The flags in C are passed to sv_fetchsv. +The flags in C are passed to gv_fetchsv. =cut */ @@ -8316,14 +8415,14 @@ Perl_sv_pvn_force_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags) const char * const ref = sv_reftype(sv,0); if (PL_op) Perl_croak(aTHX_ "Can't coerce readonly %s to string in %s", - ref, OP_NAME(PL_op)); + ref, OP_DESC(PL_op)); else Perl_croak(aTHX_ "Can't coerce readonly %s to string", ref); } if ((SvTYPE(sv) > SVt_PVLV && SvTYPE(sv) != SVt_PVFM) || isGV_with_GP(sv)) Perl_croak(aTHX_ "Can't coerce %s to string in %s", sv_reftype(sv,0), - OP_NAME(PL_op)); + OP_DESC(PL_op)); s = sv_2pv_flags(sv, &len, flags); if (lp) *lp = len; @@ -9140,6 +9239,22 @@ Perl_sv_vsetpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, sv_vcatpvfn(sv, pat, patlen, args, svargs, svmax, maybe_tainted); } + +/* + * Warn of missing argument to sprintf, and then return a defined value + * to avoid inappropriate "use of uninit" warnings [perl #71000]. + */ +#define WARN_MISSING WARN_UNINITIALIZED /* Not sure we want a new category */ +STATIC SV* +S_vcatpvfn_missing_argument(pTHX) { + if (ckWARN(WARN_MISSING)) { + Perl_warner(aTHX_ packWARN(WARN_MISSING), "Missing argument in %s", + PL_op ? OP_DESC(PL_op) : "sv_vcatpvfn()"); + } + return &PL_sv_no; +} + + STATIC I32 S_expect_number(pTHX_ char **const pattern) { @@ -9156,7 +9271,7 @@ S_expect_number(pTHX_ char **const pattern) while (isDIGIT(**pattern)) { const I32 tmp = var * 10 + (*(*pattern)++ - '0'); if (tmp < var) - Perl_croak(aTHX_ "Integer overflow in format string for %s", (PL_op ? OP_NAME(PL_op) : "sv_vcatpvfn")); + Perl_croak(aTHX_ "Integer overflow in format string for %s", (PL_op ? OP_DESC(PL_op) : "sv_vcatpvfn")); var = tmp; } } @@ -9423,9 +9538,8 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, goto string; } else if (n) { - if (ckWARN_d(WARN_INTERNAL)) - Perl_warner(aTHX_ packWARN(WARN_INTERNAL), - "internal %%p might conflict with future printf extensions"); + Perl_ck_warner_d(aTHX_ packWARN(WARN_INTERNAL), + "internal %%p might conflict with future printf extensions"); } } q = r; @@ -9506,9 +9620,10 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, vecsv = va_arg(*args, SV*); else if (evix) { vecsv = (evix > 0 && evix <= svmax) - ? svargs[evix-1] : &PL_sv_undef; + ? svargs[evix-1] : S_vcatpvfn_missing_argument(aTHX); } else { - vecsv = svix < svmax ? svargs[svix++] : &PL_sv_undef; + vecsv = svix < svmax + ? svargs[svix++] : S_vcatpvfn_missing_argument(aTHX); } dotstr = SvPV_const(vecsv, dotstrlen); /* Keep the DO_UTF8 test *after* the SvPV call, else things go @@ -9655,10 +9770,11 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, if (!vectorize && !args) { if (efix) { const I32 i = efix-1; - argsv = (i >= 0 && i < svmax) ? svargs[i] : &PL_sv_undef; + argsv = (i >= 0 && i < svmax) + ? svargs[i] : S_vcatpvfn_missing_argument(aTHX); } else { argsv = (svix >= 0 && svix < svmax) - ? svargs[svix++] : &PL_sv_undef; + ? svargs[svix++] : S_vcatpvfn_missing_argument(aTHX); } } @@ -10295,6 +10411,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, goto vector; } } + SvTAINT(sv); } /* ========================================================================= @@ -10600,6 +10717,11 @@ Perl_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *const param) #endif /* USE_ITHREADS */ +struct ptr_tbl_arena { + struct ptr_tbl_arena *next; + struct ptr_tbl_ent array[1023/3]; /* as ptr_tbl_ent has 3 pointers. */ +}; + /* create a new pointer-mapping table */ PTR_TBL_t * @@ -10611,6 +10733,9 @@ Perl_ptr_table_new(pTHX) Newx(tbl, 1, PTR_TBL_t); tbl->tbl_max = 511; tbl->tbl_items = 0; + tbl->tbl_arena = NULL; + tbl->tbl_arena_next = NULL; + tbl->tbl_arena_end = NULL; Newxz(tbl->tbl_ary, tbl->tbl_max + 1, PTR_TBL_ENT_t*); return tbl; } @@ -10618,14 +10743,6 @@ Perl_ptr_table_new(pTHX) #define PTR_TABLE_HASH(ptr) \ ((PTR2UV(ptr) >> 3) ^ (PTR2UV(ptr) >> (3 + 7)) ^ (PTR2UV(ptr) >> (3 + 17))) -/* - we use the PTE_SVSLOT 'reservation' made above, both here (in the - following define) and at call to new_body_inline made below in - Perl_ptr_table_store() - */ - -#define del_pte(p) del_body_type(p, PTE_SVSLOT) - /* map an existing pointer using a table */ STATIC PTR_TBL_ENT_t * @@ -10670,7 +10787,18 @@ Perl_ptr_table_store(pTHX_ PTR_TBL_t *const tbl, const void *const oldsv, void * } else { const UV entry = PTR_TABLE_HASH(oldsv) & tbl->tbl_max; - new_body_inline(tblent, PTE_SVSLOT); + if (tbl->tbl_arena_next == tbl->tbl_arena_end) { + struct ptr_tbl_arena *new_arena; + + Newx(new_arena, 1, struct ptr_tbl_arena); + new_arena->next = tbl->tbl_arena; + tbl->tbl_arena = new_arena; + tbl->tbl_arena_next = new_arena->array; + tbl->tbl_arena_end = new_arena->array + + sizeof(new_arena->array) / sizeof(new_arena->array[0]); + } + + tblent = tbl->tbl_arena_next++; tblent->oldval = oldsv; tblent->newval = newsv; @@ -10718,25 +10846,27 @@ Perl_ptr_table_split(pTHX_ PTR_TBL_t *const tbl) } /* remove all the entries from a ptr table */ +/* Deprecated - will be removed post 5.14 */ void Perl_ptr_table_clear(pTHX_ PTR_TBL_t *const tbl) { if (tbl && tbl->tbl_items) { - register PTR_TBL_ENT_t * const * const array = tbl->tbl_ary; - UV riter = tbl->tbl_max; + struct ptr_tbl_arena *arena = tbl->tbl_arena; - do { - PTR_TBL_ENT_t *entry = array[riter]; + Zero(tbl->tbl_ary, tbl->tbl_max + 1, struct ptr_tbl_ent **); - while (entry) { - PTR_TBL_ENT_t * const oentry = entry; - entry = entry->next; - del_pte(oentry); - } - } while (riter--); + while (arena) { + struct ptr_tbl_arena *next = arena->next; + + Safefree(arena); + arena = next; + }; tbl->tbl_items = 0; + tbl->tbl_arena = NULL; + tbl->tbl_arena_next = NULL; + tbl->tbl_arena_end = NULL; } } @@ -10745,10 +10875,21 @@ Perl_ptr_table_clear(pTHX_ PTR_TBL_t *const tbl) void Perl_ptr_table_free(pTHX_ PTR_TBL_t *const tbl) { + struct ptr_tbl_arena *arena; + if (!tbl) { return; } - ptr_table_clear(tbl); + + arena = tbl->tbl_arena; + + while (arena) { + struct ptr_tbl_arena *next = arena->next; + + Safefree(arena); + arena = next; + } + Safefree(tbl->tbl_ary); Safefree(tbl); } @@ -10988,10 +11129,23 @@ Perl_sv_dup(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) GvNAME_HEK(dstr) = hek_dup(GvNAME_HEK(dstr), param); /* Don't call sv_add_backref here as it's going to be created as part of the magic cloning of the symbol - table. */ + table--unless this is during a join and the stash + is not actually being cloned. */ /* Danger Will Robinson - GvGP(dstr) isn't initialised at the point of this comment. */ GvSTASH(dstr) = hv_dup(GvSTASH(dstr), param); + if(param->flags & CLONEf_JOIN_IN) { + const HEK * const hvname + = HvNAME_HEK(GvSTASH(dstr)); + if( hvname + && GvSTASH(dstr) == gv_stashpvn( + HEK_KEY(hvname), HEK_LEN(hvname), 0 + ) + ) + Perl_sv_add_backref( + aTHX_ MUTABLE_SV(GvSTASH(dstr)), dstr + ); + } GvGP(dstr) = gp_dup(GvGP(sstr), param); (void)GpREFCNT_inc(GvGP(dstr)); } else @@ -11044,6 +11198,11 @@ Perl_sv_dup(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) else { while (items-- > 0) *dst_ary++ = sv_dup(*src_ary++, param); + if (!(param->flags & CLONEf_COPY_STACKS) + && AvREIFY(sstr)) + { + av_reify(MUTABLE_AV(dstr)); /* #41138 */ + } } items = AvMAX((const AV *)sstr) - AvFILLp((const AV *)sstr); while (items-- > 0) { @@ -11088,7 +11247,7 @@ Perl_sv_dup(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) daux->xhv_riter = saux->xhv_riter; daux->xhv_eiter = saux->xhv_eiter ? he_dup(saux->xhv_eiter, - (bool)!!HvSHAREKEYS(sstr), param) : 0; + cBOOL(HvSHAREKEYS(sstr)), param) : 0; /* backref array needs refcnt=2; see sv_add_backref */ daux->xhv_backreferences = saux->xhv_backreferences @@ -11434,12 +11593,14 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param) TOPPTR(nss,ix) = pv_dup(c); break; case SAVEt_GP: /* scalar reference */ + gv = (const GV *)POPPTR(ss,ix); + TOPPTR(nss,ix) = gv_dup_inc(gv, param); gp = (GP*)POPPTR(ss,ix); TOPPTR(nss,ix) = gp = gp_dup(gp, param); (void)GpREFCNT_inc(gp); - gv = (const GV *)POPPTR(ss,ix); - TOPPTR(nss,ix) = gv_dup_inc(gv, param); - break; + i = POPINT(ss,ix); + TOPINT(nss,ix) = i; + break; case SAVEt_FREEOP: ptr = POPPTR(ss,ix); if (ptr && (((OP*)ptr)->op_private & OPpREFCOUNTED)) { @@ -11541,7 +11702,7 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param) ptr = POPPTR(ss,ix); TOPPTR(nss,ix) = any_dup(ptr, proto_perl); longval = (long)POPBOOL(ss,ix); - TOPBOOL(nss,ix) = (bool)longval; + TOPBOOL(nss,ix) = cBOOL(longval); break; case SAVEt_SET_SVFLAGS: i = POPINT(ss,ix); @@ -11750,27 +11911,40 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PerlInterpreter * const my_perl = (PerlInterpreter*)(*ipM->pMalloc)(ipM, sizeof(PerlInterpreter)); PERL_ARGS_ASSERT_PERL_CLONE_USING; +#else /* !PERL_IMPLICIT_SYS */ + IV i; + CLONE_PARAMS clone_params; + CLONE_PARAMS* param = &clone_params; + PerlInterpreter * const my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter)); + + PERL_ARGS_ASSERT_PERL_CLONE; +#endif /* PERL_IMPLICIT_SYS */ /* for each stash, determine whether its objects should be cloned */ S_visit(proto_perl, do_mark_cloneable_stash, SVt_PVHV, SVTYPEMASK); PERL_SET_THX(my_perl); -# ifdef DEBUGGING +#ifdef DEBUGGING PoisonNew(my_perl, 1, PerlInterpreter); PL_op = NULL; PL_curcop = NULL; PL_markstack = 0; PL_scopestack = 0; + PL_scopestack_name = 0; PL_savestack = 0; PL_savestack_ix = 0; PL_savestack_max = -1; PL_sig_pending = 0; PL_parser = NULL; Zero(&PL_debug_pad, 1, struct perl_debug_pad); -# else /* !DEBUGGING */ +# ifdef DEBUG_LEAKING_SCALARS + PL_sv_serial = (((U32)my_perl >> 2) & 0xfff) * 1000000; +# endif +#else /* !DEBUGGING */ Zero(my_perl, 1, PerlInterpreter); -# endif /* DEBUGGING */ +#endif /* DEBUGGING */ +#ifdef PERL_IMPLICIT_SYS /* host pointers */ PL_Mem = ipM; PL_MemShared = ipMS; @@ -11781,34 +11955,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_Dir = ipD; PL_Sock = ipS; PL_Proc = ipP; -#else /* !PERL_IMPLICIT_SYS */ - IV i; - CLONE_PARAMS clone_params; - CLONE_PARAMS* param = &clone_params; - PerlInterpreter * const my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter)); - - PERL_ARGS_ASSERT_PERL_CLONE; - - /* for each stash, determine whether its objects should be cloned */ - S_visit(proto_perl, do_mark_cloneable_stash, SVt_PVHV, SVTYPEMASK); - PERL_SET_THX(my_perl); - -# ifdef DEBUGGING - PoisonNew(my_perl, 1, PerlInterpreter); - PL_op = NULL; - PL_curcop = NULL; - PL_markstack = 0; - PL_scopestack = 0; - PL_savestack = 0; - PL_savestack_ix = 0; - PL_savestack_max = -1; - PL_sig_pending = 0; - PL_parser = NULL; - Zero(&PL_debug_pad, 1, struct perl_debug_pad); -# else /* !DEBUGGING */ - Zero(my_perl, 1, PerlInterpreter); -# endif /* DEBUGGING */ #endif /* PERL_IMPLICIT_SYS */ + param->flags = flags; param->proto_perl = proto_perl; @@ -11868,6 +12016,9 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, SvNV_set(&PL_sv_yes, 1); ptr_table_store(PL_ptr_table, &proto_perl->Isv_yes, &PL_sv_yes); + /* dbargs array probably holds garbage */ + PL_dbargs = NULL; + /* create (a non-shared!) shared string table */ PL_strtab = newHV(); HvSHAREKEYS_off(PL_strtab); @@ -11994,7 +12145,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_DBsingle = sv_dup(proto_perl->IDBsingle, param); PL_DBtrace = sv_dup(proto_perl->IDBtrace, param); PL_DBsignal = sv_dup(proto_perl->IDBsignal, param); - PL_dbargs = av_dup(proto_perl->Idbargs, param); /* symbol tables */ PL_defstash = hv_dup_inc(proto_perl->Idefstash, param); @@ -12153,7 +12303,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, /* utf8 character classes */ PL_utf8_alnum = sv_dup_inc(proto_perl->Iutf8_alnum, param); - PL_utf8_alnumc = sv_dup_inc(proto_perl->Iutf8_alnumc, param); PL_utf8_ascii = sv_dup_inc(proto_perl->Iutf8_ascii, param); PL_utf8_alpha = sv_dup_inc(proto_perl->Iutf8_alpha, param); PL_utf8_space = sv_dup_inc(proto_perl->Iutf8_space, param); @@ -12166,6 +12315,16 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_utf8_punct = sv_dup_inc(proto_perl->Iutf8_punct, param); PL_utf8_xdigit = sv_dup_inc(proto_perl->Iutf8_xdigit, param); PL_utf8_mark = sv_dup_inc(proto_perl->Iutf8_mark, param); + PL_utf8_X_begin = sv_dup_inc(proto_perl->Iutf8_X_begin, param); + PL_utf8_X_extend = sv_dup_inc(proto_perl->Iutf8_X_extend, param); + PL_utf8_X_prepend = sv_dup_inc(proto_perl->Iutf8_X_prepend, param); + PL_utf8_X_non_hangul = sv_dup_inc(proto_perl->Iutf8_X_non_hangul, param); + PL_utf8_X_L = sv_dup_inc(proto_perl->Iutf8_X_L, param); + PL_utf8_X_LV = sv_dup_inc(proto_perl->Iutf8_X_LV, param); + PL_utf8_X_LVT = sv_dup_inc(proto_perl->Iutf8_X_LVT, param); + PL_utf8_X_T = sv_dup_inc(proto_perl->Iutf8_X_T, param); + PL_utf8_X_V = sv_dup_inc(proto_perl->Iutf8_X_V, param); + PL_utf8_X_LV_LVT_V = sv_dup_inc(proto_perl->Iutf8_X_LV_LVT_V, param); PL_utf8_toupper = sv_dup_inc(proto_perl->Iutf8_toupper, param); PL_utf8_totitle = sv_dup_inc(proto_perl->Iutf8_totitle, param); PL_utf8_tolower = sv_dup_inc(proto_perl->Iutf8_tolower, param); @@ -12241,8 +12400,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_tmps_max = proto_perl->Itmps_max; PL_tmps_floor = proto_perl->Itmps_floor; Newx(PL_tmps_stack, PL_tmps_max, SV*); - sv_dup_inc_multiple(proto_perl->Itmps_stack, PL_tmps_stack, PL_tmps_ix, - param); + sv_dup_inc_multiple(proto_perl->Itmps_stack, PL_tmps_stack, + PL_tmps_ix+1, param); /* next PUSHMARK() sets *(PL_markstack_ptr+1) */ i = proto_perl->Imarkstack_max - proto_perl->Imarkstack; @@ -12261,6 +12420,10 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, Newxz(PL_scopestack, PL_scopestack_max, I32); Copy(proto_perl->Iscopestack, PL_scopestack, PL_scopestack_ix, I32); +#ifdef DEBUGGING + Newxz(PL_scopestack_name, PL_scopestack_max, const char *); + Copy(proto_perl->Iscopestack_name, PL_scopestack_name, PL_scopestack_ix, const char *); +#endif /* NOTE: si_dup() looks at PL_markstack */ PL_curstackinfo = si_dup(proto_perl->Icurstackinfo, param); @@ -12294,8 +12457,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, SV * const nsv = MUTABLE_SV(ptr_table_fetch(PL_ptr_table, proto_perl->Itmps_stack[i])); if (nsv && !SvREFCNT(nsv)) { - EXTEND_MORTAL(1); - PL_tmps_stack[++PL_tmps_ix] = SvREFCNT_inc_simple(nsv); + PUSH_EXTEND_MORTAL__SV_C(SvREFCNT_inc_simple(nsv)); } } } @@ -12327,6 +12489,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_bodytarget = sv_dup_inc(proto_perl->Ibodytarget, param); PL_formtarget = sv_dup(proto_perl->Iformtarget, param); + PL_restartjmpenv = proto_perl->Irestartjmpenv; PL_restartop = proto_perl->Irestartop; PL_in_eval = proto_perl->Iin_eval; PL_delaymagic = proto_perl->Idelaymagic;