X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/d056e33c1ea02abb0c031adb18b181624282ba3c..6d816fb80d2076797e96806cab8abe80afb883a1:/sv.c diff --git a/sv.c b/sv.c index e51b66a..def677b 100644 --- a/sv.c +++ b/sv.c @@ -32,6 +32,15 @@ #include "perl.h" #include "regcomp.h" +#ifndef HAS_C99 +# if __STDC_VERSION__ >= 199901L && !defined(VMS) +# define HAS_C99 1 +# endif +#endif +#if HAS_C99 +# include +#endif + #define FCALL *f #ifdef __Lynx__ @@ -71,7 +80,7 @@ many types, a pointer to the body (struct xrv, xpv, xpviv...), which contains fields specific to each type. Some types store all they need in the head, so don't have a body. -In all but the most memory-paranoid configuations (ex: PURIFY), heads +In all but the most memory-paranoid configurations (ex: PURIFY), heads and bodies are allocated out of arenas, which by default are approximately 4K chunks of memory parcelled up into N heads or bodies. Sv-bodies are allocated by their sv-type, guaranteeing size @@ -126,8 +135,7 @@ called by visit() for each SV]): sv_clean_objs() / do_clean_objs(),do_clean_named_objs(), do_clean_named_io_objs() Attempt to free all objects pointed to by RVs, - and, unless DISABLE_DESTRUCTOR_KLUDGE is defined, - try to do the same for all objects indirectly + and try to do the same for all objects indirectly referenced by typeglobs too. Called once from perl_destruct(), prior to calling sv_clean_all() below. @@ -476,8 +484,6 @@ do_clean_objs(pTHX_ SV *const ref) } -#ifndef DISABLE_DESTRUCTOR_KLUDGE - /* clear any slots in a GV which hold objects - except IO; * called by sv_clean_objs() for each live GV */ @@ -544,7 +550,15 @@ do_clean_named_io_objs(pTHX_ SV *const sv) } SvREFCNT_dec(sv); /* undo the inc above */ } -#endif + +/* Void wrapper to pass to visit() */ +static void +do_curse(pTHX_ SV * const sv) { + if ((PL_stderrgv && GvGP(PL_stderrgv) && (SV*)GvIO(PL_stderrgv) == sv) + || (PL_defoutgv && GvGP(PL_defoutgv) && (SV*)GvIO(PL_defoutgv) == sv)) + return; + (void)curse(sv, 0); +} /* =for apidoc sv_clean_objs @@ -561,12 +575,14 @@ Perl_sv_clean_objs(pTHX) GV *olddef, *olderr; PL_in_clean_objs = TRUE; visit(do_clean_objs, SVf_ROK, SVf_ROK); -#ifndef DISABLE_DESTRUCTOR_KLUDGE /* Some barnacles may yet remain, clinging to typeglobs. * Run the non-IO destructors first: they may want to output * error messages, close files etc */ visit(do_clean_named_objs, SVt_PVGV|SVpgv_GP, SVTYPEMASK|SVp_POK|SVpgv_GP); visit(do_clean_named_io_objs, SVt_PVGV|SVpgv_GP, SVTYPEMASK|SVp_POK|SVpgv_GP); + /* And if there are some very tenacious barnacles clinging to arrays, + closures, or what have you.... */ + visit(do_curse, SVs_OBJECT, SVs_OBJECT); olddef = PL_defoutgv; PL_defoutgv = NULL; /* disable skip of PL_defoutgv */ if (olddef && isGV_with_GP(olddef)) @@ -576,7 +592,6 @@ Perl_sv_clean_objs(pTHX) if (olderr && isGV_with_GP(olderr)) do_clean_named_io_objs(aTHX_ MUTABLE_SV(olderr)); SvREFCNT_dec(olddef); -#endif PL_in_clean_objs = FALSE; } @@ -1053,7 +1068,7 @@ Perl_more_bodies (pTHX_ const svtype sv_type, const size_t body_size, Remember, this is integer division: */ end = start + good_arena_size / body_size * body_size; - /* computed count doesnt reflect the 1st slot reservation */ + /* computed count doesn't reflect the 1st slot reservation */ #if defined(MYMALLOC) || defined(HAS_MALLOC_GOOD_SIZE) DEBUG_m(PerlIO_printf(Perl_debug_log, "arena %p end %p arena-size %d (from %d) type %d " @@ -2296,7 +2311,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *const sv, const I32 flags) SV * tmpstr; if (flags & SV_SKIP_OVERLOAD) return 0; - tmpstr=AMG_CALLun(sv,numer); + tmpstr = AMG_CALLunary(sv, numer_amg); if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) { return SvIV(tmpstr); } @@ -2375,7 +2390,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *const sv, const I32 flags) SV *tmpstr; if (flags & SV_SKIP_OVERLOAD) return 0; - tmpstr = AMG_CALLun(sv,numer); + tmpstr = AMG_CALLunary(sv, numer_amg); if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) { return SvUV(tmpstr); } @@ -2449,7 +2464,7 @@ Perl_sv_2nv_flags(pTHX_ register SV *const sv, const I32 flags) SV *tmpstr; if (flags & SV_SKIP_OVERLOAD) return 0; - tmpstr = AMG_CALLun(sv,numer); + tmpstr = AMG_CALLunary(sv, numer_amg); if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) { return SvNV(tmpstr); } @@ -2648,7 +2663,7 @@ Perl_sv_2num(pTHX_ register SV *const sv) if (!SvROK(sv)) return sv; if (SvAMAGIC(sv)) { - SV * const tmpsv = AMG_CALLun(sv,numer); + SV * const tmpsv = AMG_CALLunary(sv, numer_amg); TAINT_IF(tmpsv && SvTAINTED(tmpsv)); if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv)))) return sv_2num(tmpsv); @@ -2767,7 +2782,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags SV *tmpstr; if (flags & SV_SKIP_OVERLOAD) return NULL; - tmpstr = AMG_CALLun(sv,string); + tmpstr = AMG_CALLunary(sv, string_amg); TAINT_IF(tmpstr && SvTAINTED(tmpstr)); if (tmpstr && (!SvROK(tmpstr) || (SvRV(tmpstr) != SvRV(sv)))) { /* Unwrap this: */ @@ -2875,7 +2890,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags retval -= stashnamelen; memcpy(retval, stashname, stashnamelen); } - /* retval may not neccesarily have reached the start of the + /* retval may not necessarily have reached the start of the buffer here. */ assert (retval >= buffer); @@ -3034,8 +3049,9 @@ Perl_sv_2pvbyte(pTHX_ register SV *const sv, STRLEN *const lp) { PERL_ARGS_ASSERT_SV_2PVBYTE; + SvGETMAGIC(sv); sv_utf8_downgrade(sv,0); - return lp ? SvPV(sv,*lp) : SvPV_nolen(sv); + return lp ? SvPV_nomg(sv,*lp) : SvPV_nomg_nolen(sv); } /* @@ -3089,7 +3105,7 @@ Perl_sv_2bool_flags(pTHX_ register SV *const sv, const I32 flags) return 0; if (SvROK(sv)) { if (SvAMAGIC(sv)) { - SV * const tmpsv = AMG_CALLun(sv,bool_); + SV * const tmpsv = AMG_CALLunary(sv, bool__amg); if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv)))) return cBOOL(SvTRUE(tmpsv)); } @@ -3612,13 +3628,18 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype) } /* If source has a real method, then a method is going to change */ - else if(GvCV((const GV *)sstr)) { + else if( + GvCV((const GV *)sstr) && GvSTASH(dstr) && HvENAME(GvSTASH(dstr)) + ) { mro_changes = 1; } } /* If dest already had a real method, that's a change as well */ - if(!mro_changes && GvGP(MUTABLE_GV(dstr)) && GvCVu((const GV *)dstr)) { + if( + !mro_changes && GvGP(MUTABLE_GV(dstr)) && GvCVu((const GV *)dstr) + && GvSTASH(dstr) && HvENAME(GvSTASH(dstr)) + ) { mro_changes = 1; } @@ -3626,7 +3647,13 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype) glob to begin with. */ if(dtype == SVt_PVGV) { const char * const name = GvNAME((const GV *)dstr); - if(strEQ(name,"ISA")) + if( + strEQ(name,"ISA") + /* The stash may have been detached from the symbol table, so + check its name. */ + && GvSTASH(dstr) && HvENAME(GvSTASH(dstr)) + && GvAV((const GV *)sstr) + ) mro_changes = 2; else { const STRLEN len = GvNAMELEN(dstr); @@ -3635,7 +3662,11 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype) /* Set aside the old stash, so we can reset isa caches on its subclasses. */ - old_stash = GvHV(dstr); + if((old_stash = GvHV(dstr))) + /* Make sure we do not lose it early. */ + SvREFCNT_inc_simple_void_NN( + sv_2mortal((SV *)old_stash) + ); } } } @@ -3654,14 +3685,26 @@ S_glob_assign_glob(pTHX_ SV *const dstr, SV *const sstr, const int dtype) GvIMPORTED_on(dstr); } GvMULTI_on(dstr); - if(mro_changes == 2) mro_isa_changed_in(GvSTASH(dstr)); + if(mro_changes == 2) { + MAGIC *mg; + SV * const sref = (SV *)GvAV((const GV *)dstr); + if (SvSMAGICAL(sref) && (mg = mg_find(sref, PERL_MAGIC_isa))) { + if (SvTYPE(mg->mg_obj) != SVt_PVAV) { + AV * const ary = newAV(); + av_push(ary, mg->mg_obj); /* takes the refcount */ + mg->mg_obj = (SV *)ary; + } + av_push((AV *)mg->mg_obj, SvREFCNT_inc_simple_NN(dstr)); + } + else sv_magic(sref, dstr, PERL_MAGIC_isa, NULL, 0); + mro_isa_changed_in(GvSTASH(dstr)); + } else if(mro_changes == 3) { HV * const stash = GvHV(dstr); - if((stash && HvNAME(stash)) || (old_stash && HvNAME(old_stash))) + if(old_stash ? (HV *)HvENAME_get(old_stash) : stash) mro_package_moved( - stash && HvNAME(stash) ? stash : NULL, - old_stash && HvNAME(old_stash) ? old_stash : NULL, - (GV *)dstr, NULL, 0 + stash, old_stash, + (GV *)dstr, 0 ); } else if(mro_changes) mro_method_changed_in(GvSTASH(dstr)); @@ -3775,18 +3818,63 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr) const STRLEN len = GvNAMELEN(dstr); if ( len > 1 && name[len-2] == ':' && name[len-1] == ':' - && (HvNAME(dref) || HvNAME(sref)) + && (!dref || HvENAME_get(dref)) ) { mro_package_moved( - HvNAME(sref) ? (HV *)sref : NULL, - HvNAME(dref) ? (HV *)dref : NULL, - (GV *)dstr, NULL, 0 + (HV *)sref, (HV *)dref, + (GV *)dstr, 0 ); } } - else if (stype == SVt_PVAV && strEQ(GvNAME((GV*)dstr), "ISA")) { - sv_magic(sref, dstr, PERL_MAGIC_isa, NULL, 0); - mro_isa_changed_in(GvSTASH(dstr)); + else if ( + stype == SVt_PVAV && sref != dref + && strEQ(GvNAME((GV*)dstr), "ISA") + /* The stash may have been detached from the symbol table, so + check its name before doing anything. */ + && GvSTASH(dstr) && HvENAME(GvSTASH(dstr)) + ) { + MAGIC *mg; + MAGIC * const omg = dref && SvSMAGICAL(dref) + ? mg_find(dref, PERL_MAGIC_isa) + : NULL; + if (SvSMAGICAL(sref) && (mg = mg_find(sref, PERL_MAGIC_isa))) { + if (SvTYPE(mg->mg_obj) != SVt_PVAV) { + AV * const ary = newAV(); + av_push(ary, mg->mg_obj); /* takes the refcount */ + mg->mg_obj = (SV *)ary; + } + if (omg) { + if (SvTYPE(omg->mg_obj) == SVt_PVAV) { + SV **svp = AvARRAY((AV *)omg->mg_obj); + I32 items = AvFILLp((AV *)omg->mg_obj) + 1; + while (items--) + av_push( + (AV *)mg->mg_obj, + SvREFCNT_inc_simple_NN(*svp++) + ); + } + else + av_push( + (AV *)mg->mg_obj, + SvREFCNT_inc_simple_NN(omg->mg_obj) + ); + } + else + av_push((AV *)mg->mg_obj,SvREFCNT_inc_simple_NN(dstr)); + } + else + { + sv_magic( + sref, omg ? omg->mg_obj : dstr, PERL_MAGIC_isa, NULL, 0 + ); + mg = mg_find(sref, PERL_MAGIC_isa); + } + /* Since the *ISA assignment could have affected more than + one stash, don’t call mro_isa_changed_in directly, but let + magic_clearisa do it for us, as it already has the logic for + dealing with globs vs arrays of globs. */ + assert(mg); + Perl_magic_clearisa(aTHX_ NULL, mg); } break; } @@ -3936,22 +4024,17 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags) /* case SVt_BIND: */ case SVt_PVLV: case SVt_PVGV: - if (isGV_with_GP(sstr) && dtype <= SVt_PVLV) { - glob_assign_glob(dstr, sstr, dtype); - return; - } /* SvVALID means that this PVGV is playing at being an FBM. */ - /*FALLTHROUGH*/ case SVt_PVMG: if (SvGMAGICAL(sstr) && (flags & SV_GMAGIC)) { mg_get(sstr); if (SvTYPE(sstr) != stype) stype = SvTYPE(sstr); - if (isGV_with_GP(sstr) && dtype <= SVt_PVLV) { + } + if (isGV_with_GP(sstr) && dtype <= SVt_PVLV) { glob_assign_glob(dstr, sstr, dtype); return; - } } if (stype == SVt_PVLV) SvUPGRADE(dstr, SVt_PVNV); @@ -4035,7 +4118,12 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags) if (len > 1 && name[len-2] == ':' && name[len-1] == ':') { /* Set aside the old stash, so we can reset isa caches on its subclasses. */ - old_stash = GvHV(dstr); + if((old_stash = GvHV(dstr))) { + /* Make sure we do not lose it early. */ + SvREFCNT_inc_simple_void_NN( + sv_2mortal((SV *)old_stash) + ); + } reset_isa = TRUE; } @@ -4046,13 +4134,11 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags) if (reset_isa) { HV * const stash = GvHV(dstr); if( - (stash && HvNAME(stash)) - || (old_stash && HvNAME(old_stash)) + old_stash ? (HV *)HvENAME_get(old_stash) : stash ) mro_package_moved( - stash && HvNAME(stash) ? stash : NULL, - old_stash && HvNAME(old_stash) ? old_stash : NULL, - (GV *)dstr, NULL, 0 + stash, old_stash, + (GV *)dstr, 0 ); } } @@ -4492,7 +4578,7 @@ Perl_sv_usepvn_flags(pTHX_ SV *const sv, char *ptr, const STRLEN len, const U32 #endif if (flags & SV_HAS_TRAILING_NUL) { /* It's long enough - do nothing. - Specfically Perl_newCONSTSUB is relying on this. */ + Specifically Perl_newCONSTSUB is relying on this. */ } else { #ifdef DEBUGGING /* Force a move to shake out bugs in callers. */ @@ -4648,7 +4734,7 @@ Perl_sv_force_normal_flags(pTHX_ register SV *const sv, const U32 flags) else if (SvFAKE(sv) && isGV_with_GP(sv)) sv_unglob(sv); else if (SvFAKE(sv) && SvTYPE(sv) == SVt_REGEXP) { - /* Need to downgrade the REGEXP to a simple(r) scalar. This is analagous + /* Need to downgrade the REGEXP to a simple(r) scalar. This is analogous 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); @@ -4922,7 +5008,7 @@ on the SVs if appropriate, else not. */ void -Perl_sv_catpv_flags(pTHX_ SV *dstr, const char *sstr, I32 flags) +Perl_sv_catpv_flags(pTHX_ SV *dstr, const char *sstr, const I32 flags) { PERL_ARGS_ASSERT_SV_CATPV_FLAGS; sv_catpvn_flags(dstr, sstr, strlen(sstr), flags); @@ -5053,7 +5139,7 @@ Perl_sv_magicext(pTHX_ SV *const sv, SV *const obj, const int how, mg->mg_ptr = savepvn(name, namlen); else if (namlen == HEf_SVKEY) { /* Yes, this is casting away const. This is only for the case of - HEf_SVKEY. I think we need to document this abberation of the + HEf_SVKEY. I think we need to document this aberation of the constness of the API, rather than making name non-const, as that change propagating outwards a long way. */ mg->mg_ptr = (char*)SvREFCNT_inc_simple_NN((SV *)name); @@ -5265,31 +5351,23 @@ Perl_sv_magic(pTHX_ register SV *const sv, SV *const obj, const int how, } } -/* -=for apidoc sv_unmagic - -Removes all magic of type C from an SV. - -=cut -*/ - int -Perl_sv_unmagic(pTHX_ SV *const sv, const int type) +S_sv_unmagicext_flags(pTHX_ SV *const sv, const int type, MGVTBL *vtbl, const U32 flags) { MAGIC* mg; MAGIC** mgp; - PERL_ARGS_ASSERT_SV_UNMAGIC; + assert(flags <= 1); if (SvTYPE(sv) < SVt_PVMG || !SvMAGIC(sv)) return 0; mgp = &(((XPVMG*) SvANY(sv))->xmg_u.xmg_magic); for (mg = *mgp; mg; mg = *mgp) { - if (mg->mg_type == type) { - const MGVTBL* const vtbl = mg->mg_virtual; + const MGVTBL* const virt = mg->mg_virtual; + if (mg->mg_type == type && (!flags || virt == vtbl)) { *mgp = mg->mg_moremagic; - if (vtbl && vtbl->svt_free) - vtbl->svt_free(aTHX_ sv, mg); + if (virt && virt->svt_free) + virt->svt_free(aTHX_ sv, mg); if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) { if (mg->mg_len > 0) Safefree(mg->mg_ptr); @@ -5317,6 +5395,36 @@ Perl_sv_unmagic(pTHX_ SV *const sv, const int type) } /* +=for apidoc sv_unmagic + +Removes all magic of type C from an SV. + +=cut +*/ + +int +Perl_sv_unmagic(pTHX_ SV *const sv, const int type) +{ + PERL_ARGS_ASSERT_SV_UNMAGIC; + return S_sv_unmagicext_flags(aTHX_ sv, type, NULL, 0); +} + +/* +=for apidoc sv_unmagicext + +Removes all magic of type C with the specified C from an SV. + +=cut +*/ + +int +Perl_sv_unmagicext(pTHX_ SV *const sv, const int type, MGVTBL *vtbl) +{ + PERL_ARGS_ASSERT_SV_UNMAGICEXT; + return S_sv_unmagicext_flags(aTHX_ sv, type, vtbl, 1); +} + +/* =for apidoc sv_rvweaken Weaken a reference: set the C flag on this RV; give the @@ -5463,7 +5571,6 @@ Perl_sv_del_backref(pTHX_ SV *const tsv, SV *const sv) { dVAR; SV **svp = NULL; - I32 i; PERL_ARGS_ASSERT_SV_DEL_BACKREF; @@ -5480,30 +5587,54 @@ Perl_sv_del_backref(pTHX_ SV *const tsv, SV *const sv) Perl_croak(aTHX_ "panic: del_backref"); if (SvTYPE(*svp) == SVt_PVAV) { - int count = 0; +#ifdef DEBUGGING + int count = 1; +#endif AV * const av = (AV*)*svp; + SSize_t fill; assert(!SvIS_FREED(av)); + fill = AvFILLp(av); + assert(fill > -1); svp = AvARRAY(av); - for (i = AvFILLp(av); i >= 0; i--) { - if (svp[i] == sv) { - const SSize_t fill = AvFILLp(av); - if (i != fill) { - /* We weren't the last entry. - An unordered list has this property that you can take the - last element off the end to fill the hole, and it's still - an unordered list :-) - */ - svp[i] = svp[fill]; - } - svp[fill] = NULL; - AvFILLp(av) = fill - 1; - count++; -#ifndef DEBUGGING - break; /* should only be one */ + /* for an SV with N weak references to it, if all those + * weak refs are deleted, then sv_del_backref will be called + * N times and O(N^2) compares will be done within the backref + * array. To ameliorate this potential slowness, we: + * 1) make sure this code is as tight as possible; + * 2) when looking for SV, look for it at both the head and tail of the + * array first before searching the rest, since some create/destroy + * patterns will cause the backrefs to be freed in order. + */ + if (*svp == sv) { + AvARRAY(av)++; + AvMAX(av)--; + } + else { + SV **p = &svp[fill]; + SV *const topsv = *p; + if (topsv != sv) { +#ifdef DEBUGGING + count = 0; #endif + while (--p > svp) { + if (*p == sv) { + /* We weren't the last entry. + An unordered list has this property that you + can take the last element off the end to fill + the hole, and it's still an unordered list :-) + */ + *p = topsv; +#ifdef DEBUGGING + count++; +#else + break; /* should only be one */ +#endif + } + } } } - assert(count == 1); + assert(count ==1); + AvFILLp(av) = fill-1; } else { /* optimisation: only a single backref, stored directly */ @@ -5563,7 +5694,7 @@ Perl_sv_kill_backrefs(pTHX_ SV *const sv, AV *const av) /* You lookin' at me? */ assert(CvSTASH(referrer)); assert(CvSTASH(referrer) == (const HV *)sv); - CvSTASH(referrer) = 0; + SvANY(MUTABLE_CV(referrer))->xcv_stash = 0; } else { assert(SvTYPE(sv) == SVt_PVGV); @@ -5860,65 +5991,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv) } if (SvOBJECT(sv)) { - if (PL_defstash && /* Still have a symbol table? */ - SvDESTROYABLE(sv)) - { - dSP; - HV* stash; - do { - CV* destructor; - stash = SvSTASH(sv); - destructor = StashHANDLER(stash,DESTROY); - if (destructor - /* A constant subroutine can have no side effects, so - don't bother calling it. */ - && !CvCONST(destructor) - /* Don't bother calling an empty destructor */ - && (CvISXSUB(destructor) - || (CvSTART(destructor) - && (CvSTART(destructor)->op_next->op_type - != OP_LEAVESUB)))) - { - SV* const tmpref = newRV(sv); - SvREADONLY_on(tmpref); /* DESTROY() could be naughty */ - ENTER; - PUSHSTACKi(PERLSI_DESTROY); - EXTEND(SP, 2); - PUSHMARK(SP); - PUSHs(tmpref); - PUTBACK; - call_sv(MUTABLE_SV(destructor), - G_DISCARD|G_EVAL|G_KEEPERR|G_VOID); - POPSTACK; - SPAGAIN; - LEAVE; - if(SvREFCNT(tmpref) < 2) { - /* tmpref is not kept alive! */ - SvREFCNT(sv)--; - SvRV_set(tmpref, NULL); - SvROK_off(tmpref); - } - SvREFCNT_dec(tmpref); - } - } while (SvOBJECT(sv) && SvSTASH(sv) != stash); - - - if (SvREFCNT(sv)) { - if (PL_in_clean_objs) - Perl_croak(aTHX_ - "DESTROY created new reference to dead object '%s'", - HvNAME_get(stash)); - /* DESTROY gave object new lease on life */ - goto get_next_sv; - } - } - - if (SvOBJECT(sv)) { - SvREFCNT_dec(SvSTASH(sv)); /* possibly of changed persuasion */ - SvOBJECT_off(sv); /* Curse the object. */ - if (type != SVt_PVIO) - --PL_sv_objcount;/* XXX Might want something more general */ - } + if (!curse(sv, 1)) goto get_next_sv; } if (type >= SVt_PVMG) { if (type == SVt_PVMG && SvPAD_OUR(sv)) { @@ -5964,7 +6037,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv) PL_last_swash_hv = NULL; } Perl_hv_kill_backrefs(aTHX_ MUTABLE_HV(sv)); - hv_undef(MUTABLE_HV(sv)); + Perl_hv_undef_flags(aTHX_ MUTABLE_HV(sv), HV_NAME_SETALL); break; case SVt_PVAV: { @@ -5996,7 +6069,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv) case SVt_PVGV: if (isGV_with_GP(sv)) { if(GvCVu((const GV *)sv) && (stash = GvSTASH(MUTABLE_GV(sv))) - && HvNAME_get(stash)) + && HvENAME_get(stash)) mro_method_changed_in(stash); gp_free(MUTABLE_GV(sv)); if (GvNAME_HEK(sv)) @@ -6144,6 +6217,78 @@ Perl_sv_clear(pTHX_ SV *const orig_sv) } /* while sv */ } +/* This routine curses the sv itself, not the object referenced by sv. So + sv does not have to be ROK. */ + +static bool +S_curse(pTHX_ SV * const sv, const bool check_refcnt) { + dVAR; + + PERL_ARGS_ASSERT_CURSE; + assert(SvOBJECT(sv)); + + if (PL_defstash && /* Still have a symbol table? */ + SvDESTROYABLE(sv)) + { + dSP; + HV* stash; + do { + CV* destructor; + stash = SvSTASH(sv); + destructor = StashHANDLER(stash,DESTROY); + if (destructor + /* A constant subroutine can have no side effects, so + don't bother calling it. */ + && !CvCONST(destructor) + /* Don't bother calling an empty destructor */ + && (CvISXSUB(destructor) + || (CvSTART(destructor) + && (CvSTART(destructor)->op_next->op_type + != OP_LEAVESUB)))) + { + SV* const tmpref = newRV(sv); + SvREADONLY_on(tmpref); /* DESTROY() could be naughty */ + ENTER; + PUSHSTACKi(PERLSI_DESTROY); + EXTEND(SP, 2); + PUSHMARK(SP); + PUSHs(tmpref); + PUTBACK; + call_sv(MUTABLE_SV(destructor), + G_DISCARD|G_EVAL|G_KEEPERR|G_VOID); + POPSTACK; + SPAGAIN; + LEAVE; + if(SvREFCNT(tmpref) < 2) { + /* tmpref is not kept alive! */ + SvREFCNT(sv)--; + SvRV_set(tmpref, NULL); + SvROK_off(tmpref); + } + SvREFCNT_dec(tmpref); + } + } while (SvOBJECT(sv) && SvSTASH(sv) != stash); + + + if (check_refcnt && SvREFCNT(sv)) { + if (PL_in_clean_objs) + Perl_croak(aTHX_ + "DESTROY created new reference to dead object '%s'", + HvNAME_get(stash)); + /* DESTROY gave object new lease on life */ + return FALSE; + } + } + + if (SvOBJECT(sv)) { + SvREFCNT_dec(SvSTASH(sv)); /* possibly of changed persuasion */ + SvOBJECT_off(sv); /* Curse the object. */ + if (SvTYPE(sv) != SVt_PVIO) + --PL_sv_objcount;/* XXX Might want something more general */ + } + return TRUE; +} + /* =for apidoc sv_newref @@ -6715,7 +6860,7 @@ S_utf8_mg_pos_cache_update(pTHX_ SV *const sv, MAGIC **const mgp, const STRLEN b /* Cache has 2 slots in use, and we know three potential pairs. Keep the two that give the lowest RMS distance. Do the - calcualation in bytes simply because we always know the byte + calculation in bytes simply because we always know the byte length. squareroot has the same ordering as the positive value, so don't bother with the actual square root. */ const float existing = THREEWAY_SQUARE(0, cache[3], cache[1], blen); @@ -6956,7 +7101,7 @@ if necessary. If the flags include SV_GMAGIC, it handles get-magic, too. */ I32 -Perl_sv_eq_flags(pTHX_ register SV *sv1, register SV *sv2, const I32 flags) +Perl_sv_eq_flags(pTHX_ register SV *sv1, register SV *sv2, const U32 flags) { dVAR; const char *pv1; @@ -7011,28 +7156,15 @@ Perl_sv_eq_flags(pTHX_ register SV *sv1, register SV *sv2, const I32 flags) } } else { - bool is_utf8 = TRUE; - if (SvUTF8(sv1)) { - /* sv1 is the UTF-8 one, - * if is equal it must be downgrade-able */ - char * const pv = (char*)bytes_from_utf8((const U8*)pv1, - &cur1, &is_utf8); - if (pv != pv1) - pv1 = tpv = pv; + /* sv1 is the UTF-8 one */ + return bytes_cmp_utf8((const U8*)pv2, cur2, + (const U8*)pv1, cur1) == 0; } else { - /* sv2 is the UTF-8 one, - * if is equal it must be downgrade-able */ - char * const pv = (char *)bytes_from_utf8((const U8*)pv2, - &cur2, &is_utf8); - if (pv != pv2) - pv2 = tpv = pv; - } - if (is_utf8) { - /* Downgrade not possible - cannot be eq */ - assert (tpv == 0); - return FALSE; + /* sv2 is the UTF-8 one */ + return bytes_cmp_utf8((const U8*)pv1, cur1, + (const U8*)pv2, cur2) == 0; } } } @@ -7073,7 +7205,8 @@ Perl_sv_cmp(pTHX_ register SV *const sv1, register SV *const sv2) } I32 -Perl_sv_cmp_flags(pTHX_ register SV *const sv1, register SV *const sv2, const I32 flags) +Perl_sv_cmp_flags(pTHX_ register SV *const sv1, register SV *const sv2, + const U32 flags) { dVAR; STRLEN cur1, cur2; @@ -7106,7 +7239,9 @@ Perl_sv_cmp_flags(pTHX_ register SV *const sv1, register SV *const sv2, const I3 pv2 = SvPV_const(svrecode, cur2); } else { - pv2 = tpv = (char*)bytes_to_utf8((const U8*)pv2, &cur2); + const int retval = -bytes_cmp_utf8((const U8*)pv2, cur2, + (const U8*)pv1, cur1); + return retval ? retval < 0 ? -1 : +1 : 0; } } else { @@ -7116,7 +7251,9 @@ Perl_sv_cmp_flags(pTHX_ register SV *const sv1, register SV *const sv2, const I3 pv1 = SvPV_const(svrecode, cur1); } else { - pv1 = tpv = (char*)bytes_to_utf8((const U8*)pv1, &cur1); + const int retval = bytes_cmp_utf8((const U8*)pv1, cur1, + (const U8*)pv2, cur2); + return retval ? retval < 0 ? -1 : +1 : 0; } } } @@ -7167,7 +7304,8 @@ Perl_sv_cmp_locale(pTHX_ register SV *const sv1, register SV *const sv2) } I32 -Perl_sv_cmp_locale_flags(pTHX_ register SV *const sv1, register SV *const sv2, const I32 flags) +Perl_sv_cmp_locale_flags(pTHX_ register SV *const sv1, register SV *const sv2, + const U32 flags) { dVAR; #ifdef USE_LOCALE_COLLATE @@ -7286,6 +7424,55 @@ Perl_sv_collxfrm_flags(pTHX_ SV *const sv, STRLEN *const nxp, const I32 flags) #endif /* USE_LOCALE_COLLATE */ +static char * +S_sv_gets_append_to_utf8(pTHX_ SV *const sv, PerlIO *const fp, I32 append) +{ + SV * const tsv = newSV(0); + ENTER; + SAVEFREESV(tsv); + sv_gets(tsv, fp, 0); + sv_utf8_upgrade_nomg(tsv); + SvCUR_set(sv,append); + sv_catsv(sv,tsv); + LEAVE; + return (SvCUR(sv) - append) ? SvPVX(sv) : NULL; +} + +static char * +S_sv_gets_read_record(pTHX_ SV *const sv, PerlIO *const fp, I32 append) +{ + I32 bytesread; + const U32 recsize = SvUV(SvRV(PL_rs)); /* RsRECORD() guarantees > 0. */ + /* Grab the size of the record we're getting */ + char *const buffer = SvGROW(sv, (STRLEN)(recsize + append + 1)) + append; +#ifdef VMS + int fd; +#endif + + /* Go yank in */ +#ifdef VMS + /* VMS wants read instead of fread, because fread doesn't respect */ + /* RMS record boundaries. This is not necessarily a good thing to be */ + /* doing, but we've got no other real choice - except avoid stdio + as implementation - perhaps write a :vms layer ? + */ + fd = PerlIO_fileno(fp); + if (fd != -1) { + bytesread = PerlLIO_read(fd, buffer, recsize); + } + else /* in-memory file from PerlIO::Scalar */ +#endif + { + bytesread = PerlIO_read(fp, buffer, recsize); + } + + if (bytesread < 0) + bytesread = 0; + SvCUR_set(sv, bytesread + append); + buffer[bytesread] = '\0'; + return (SvCUR(sv) - append) ? SvPVX(sv) : NULL; +} + /* =for apidoc sv_gets @@ -7327,13 +7514,7 @@ Perl_sv_gets(pTHX_ register SV *const sv, register PerlIO *const fp, I32 append) sv_pos_u2b(sv,&append,0); } } else if (SvUTF8(sv)) { - SV * const tsv = newSV(0); - sv_gets(tsv, fp, 0); - sv_utf8_upgrade_nomg(tsv); - SvCUR_set(sv,append); - sv_catsv(sv,tsv); - sv_free(tsv); - goto return_string_or_null; + return S_sv_gets_append_to_utf8(aTHX_ sv, fp, append); } } @@ -7366,38 +7547,7 @@ Perl_sv_gets(pTHX_ register SV *const sv, register PerlIO *const fp, I32 append) rslen = 0; } else if (RsRECORD(PL_rs)) { - I32 bytesread; - char *buffer; - U32 recsize; -#ifdef VMS - int fd; -#endif - - /* Grab the size of the record we're getting */ - recsize = SvUV(SvRV(PL_rs)); /* RsRECORD() guarantees > 0. */ - buffer = SvGROW(sv, (STRLEN)(recsize + append + 1)) + append; - /* Go yank in */ -#ifdef VMS - /* VMS wants read instead of fread, because fread doesn't respect */ - /* RMS record boundaries. This is not necessarily a good thing to be */ - /* doing, but we've got no other real choice - except avoid stdio - as implementation - perhaps write a :vms layer ? - */ - fd = PerlIO_fileno(fp); - if (fd == -1) { /* in-memory file from PerlIO::Scalar */ - bytesread = PerlIO_read(fp, buffer, recsize); - } - else { - bytesread = PerlLIO_read(fd, buffer, recsize); - } -#else - bytesread = PerlIO_read(fp, buffer, recsize); -#endif - if (bytesread < 0) - bytesread = 0; - SvCUR_set(sv, bytesread + append); - buffer[bytesread] = '\0'; - goto return_string_or_null; + return S_sv_gets_read_record(aTHX_ sv, fp, append); } else if (RsPARA(PL_rs)) { rsptr = "\n\n"; @@ -7507,6 +7657,8 @@ Perl_sv_gets(pTHX_ register SV *const sv, register PerlIO *const fp, I32 append) bp += cnt; /* screams | dust */ ptr += cnt; /* louder | sed :-) */ cnt = 0; + assert (!shortbuffered); + goto cannot_be_shortbuffered; } } @@ -7520,26 +7672,27 @@ Perl_sv_gets(pTHX_ register SV *const sv, register PerlIO *const fp, I32 append) continue; } + cannot_be_shortbuffered: DEBUG_P(PerlIO_printf(Perl_debug_log, "Screamer: going to getc, ptr=%"UVuf", cnt=%ld\n", PTR2UV(ptr),(long)cnt)); PerlIO_set_ptrcnt(fp, (STDCHAR*)ptr, cnt); /* deregisterize cnt and ptr */ -#if 0 - DEBUG_P(PerlIO_printf(Perl_debug_log, + + DEBUG_Pv(PerlIO_printf(Perl_debug_log, "Screamer: pre: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n", PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp), PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0))); -#endif + /* This used to call 'filbuf' in stdio form, but as that behaves like getc when cnt <= 0 we use PerlIO_getc here to avoid introducing another abstraction. */ i = PerlIO_getc(fp); /* get more characters */ -#if 0 - DEBUG_P(PerlIO_printf(Perl_debug_log, + + DEBUG_Pv(PerlIO_printf(Perl_debug_log, "Screamer: post: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n", PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp), PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0))); -#endif + cnt = PerlIO_get_cnt(fp); ptr = (STDCHAR*)PerlIO_get_ptr(fp); /* reregisterize cnt and ptr */ DEBUG_P(PerlIO_printf(Perl_debug_log, @@ -7600,7 +7753,7 @@ screamer2: } else { cnt = PerlIO_read(fp,(char*)buf, sizeof(buf)); - /* Accomodate broken VAXC compiler, which applies U8 cast to + /* Accommodate broken VAXC compiler, which applies U8 cast to * both args of ?: operator, causing EOF to change into 255 */ if (cnt > 0) @@ -7652,7 +7805,6 @@ screamer2: } } -return_string_or_null: return (SvCUR(sv) - append) ? SvPVX(sv) : NULL; } @@ -7701,7 +7853,7 @@ Perl_sv_inc_nomg(pTHX_ register SV *const sv) } if (SvROK(sv)) { IV i; - if (SvAMAGIC(sv) && AMG_CALLun(sv,inc)) + if (SvAMAGIC(sv) && AMG_CALLunary(sv, inc_amg)) return; i = PTR2IV(SvRV(sv)); sv_unref(sv); @@ -7882,7 +8034,7 @@ Perl_sv_dec_nomg(pTHX_ register SV *const sv) } if (SvROK(sv)) { IV i; - if (SvAMAGIC(sv) && AMG_CALLun(sv,dec)) + if (SvAMAGIC(sv) && AMG_CALLunary(sv, dec_amg)) return; i = PTR2IV(SvRV(sv)); sv_unref(sv); @@ -8072,11 +8224,11 @@ Perl_newSVpvn_flags(pTHX_ const char *const s, const STRLEN len, const U32 flags 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. + * and do what it does ourselves 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) + * eliminate quite a few steps than it looks - Yves (explaining patch by gfx) */ SvFLAGS(sv) |= flags; @@ -8186,11 +8338,11 @@ Perl_newSVhek(pTHX_ const HEK *const hek) Andreas would like keys he put in as utf8 to come back as utf8 */ STRLEN utf8_len = HEK_LEN(hek); - const U8 *as_utf8 = bytes_to_utf8 ((U8*)HEK_KEY(hek), &utf8_len); - SV * const sv = newSVpvn ((const char*)as_utf8, utf8_len); - + SV * const sv = newSV_type(SVt_PV); + char *as_utf8 = (char *)bytes_to_utf8 ((U8*)HEK_KEY(hek), &utf8_len); + /* bytes_to_utf8() allocates a new string, which we can repurpose: */ + sv_usepvn_flags(sv, as_utf8, utf8_len, SV_HAS_TRAILING_NUL); SvUTF8_on (sv); - Safefree (as_utf8); /* bytes_to_utf8() allocates a new string */ return sv; } else if (flags & (HVhek_REHASH|HVhek_UNSHARED)) { /* We don't have a pointer to the hv, so we have to replicate the @@ -8694,9 +8846,11 @@ Perl_sv_2cv(pTHX_ SV *sv, HV **const st, GV **const gvp, const I32 lref) default: if (SvROK(sv)) { - SV * const *sp = &sv; /* Used in tryAMAGICunDEREF macro. */ SvGETMAGIC(sv); - tryAMAGICunDEREF(to_cv); + if (SvAMAGIC(sv)) + sv = amagic_deref_call(sv, to_cv_amg); + /* At this point I'd like to do SPAGAIN, but really I need to + force it upon my callers. Hmmm. This is a mess... */ sv = SvRV(sv); if (SvTYPE(sv) == SVt_PVCV) { @@ -8931,7 +9085,7 @@ Perl_sv_reftype(pTHX_ const SV *const sv, const int ob) case SVt_PVLV: return (char *) (SvROK(sv) ? "REF" /* tied lvalues should appear to be - * scalars for backwards compatitbility */ + * scalars for backwards compatibility */ : (LvTYPE(sv) == 't' || LvTYPE(sv) == 'T') ? "SCALAR" : "LVALUE"); case SVt_PVAV: return "ARRAY"; @@ -10151,16 +10305,28 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, #endif case 'l': #if defined(HAS_QUAD) || defined(HAS_LONG_DOUBLE) - if (*(q + 1) == 'l') { /* lld, llf */ + if (*++q == 'l') { /* lld, llf */ intsize = 'q'; - q += 2; - break; - } + ++q; + } + else #endif - /*FALLTHROUGH*/ + intsize = 'l'; + break; case 'h': - /*FALLTHROUGH*/ + if (*++q == 'h') { /* hhd, hhu */ + intsize = 'c'; + ++q; + } + else + intsize = 'h'; + break; case 'V': + case 'z': + case 't': +#if HAS_C99 + case 'j': +#endif intsize = *q++; break; } @@ -10286,10 +10452,16 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, } else if (args) { switch (intsize) { + case 'c': iv = (char)va_arg(*args, int); break; case 'h': iv = (short)va_arg(*args, int); break; case 'l': iv = va_arg(*args, long); break; case 'V': iv = va_arg(*args, IV); break; + case 'z': iv = va_arg(*args, SSize_t); break; + case 't': iv = va_arg(*args, ptrdiff_t); break; default: iv = va_arg(*args, int); break; +#if HAS_C99 + case 'j': iv = va_arg(*args, intmax_t); break; +#endif case 'q': #ifdef HAS_QUAD iv = va_arg(*args, Quad_t); break; @@ -10301,6 +10473,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, else { IV tiv = SvIV(argsv); /* work around GCC bug #13488 */ switch (intsize) { + case 'c': iv = (char)tiv; break; case 'h': iv = (short)tiv; break; case 'l': iv = (long)tiv; break; case 'V': @@ -10377,9 +10550,15 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, } else if (args) { switch (intsize) { + case 'c': uv = (unsigned char)va_arg(*args, unsigned); break; case 'h': uv = (unsigned short)va_arg(*args, unsigned); break; case 'l': uv = va_arg(*args, unsigned long); break; case 'V': uv = va_arg(*args, UV); break; + case 'z': uv = va_arg(*args, Size_t); break; + case 't': uv = va_arg(*args, ptrdiff_t); break; /* will sign extend, but there is no uptrdiff_t, so oh well */ +#if HAS_C99 + case 'j': uv = va_arg(*args, uintmax_t); break; +#endif default: uv = va_arg(*args, unsigned); break; case 'q': #ifdef HAS_QUAD @@ -10392,6 +10571,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, else { UV tuv = SvUV(argsv); /* work around GCC bug #13488 */ switch (intsize) { + case 'c': uv = (unsigned char)tuv; break; case 'h': uv = (unsigned short)tuv; break; case 'l': uv = (unsigned long)tuv; break; case 'V': @@ -10502,7 +10682,11 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, #else /*FALLTHROUGH*/ #endif + case 'c': case 'h': + case 'z': + case 't': + case 'j': goto unknown; } @@ -10682,10 +10866,16 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, i = SvCUR(sv) - origlen; if (args) { switch (intsize) { + case 'c': *(va_arg(*args, char*)) = i; break; case 'h': *(va_arg(*args, short*)) = i; break; default: *(va_arg(*args, int*)) = i; break; case 'l': *(va_arg(*args, long*)) = i; break; case 'V': *(va_arg(*args, IV*)) = i; break; + case 'z': *(va_arg(*args, SSize_t*)) = i; break; + case 't': *(va_arg(*args, ptrdiff_t*)) = i; break; +#if HAS_C99 + case 'j': *(va_arg(*args, intmax_t*)) = i; break; +#endif case 'q': #ifdef HAS_QUAD *(va_arg(*args, Quad_t*)) = i; break; @@ -11014,10 +11204,11 @@ Perl_fp_dup(pTHX_ PerlIO *const fp, const char type, CLONE_PARAMS *const param) /* duplicate a directory handle */ DIR * -Perl_dirp_dup(pTHX_ DIR *const dp) +Perl_dirp_dup(pTHX_ DIR *const dp, CLONE_PARAMS *const param) { -#ifdef HAS_FCHDIR DIR *ret; + +#ifdef HAS_FCHDIR DIR *pwd; register const Direntry_t *dirent; char smallbuf[256]; @@ -11027,15 +11218,20 @@ Perl_dirp_dup(pTHX_ DIR *const dp) #endif PERL_UNUSED_CONTEXT; + PERL_ARGS_ASSERT_DIRP_DUP; -#ifdef HAS_FCHDIR if (!dp) return (DIR*)NULL; + /* look for it in the table first */ ret = (DIR*)ptr_table_fetch(PL_ptr_table, dp); if (ret) return ret; +#ifdef HAS_FCHDIR + + PERL_UNUSED_ARG(param); + /* create anew */ /* open the current directory (so we can switch back) */ @@ -11103,14 +11299,17 @@ Perl_dirp_dup(pTHX_ DIR *const dp) if (name && name != smallbuf) Safefree(name); +#endif + +#ifdef WIN32 + ret = win32_dirp_dup(dp, param); +#endif /* pop it in the pointer table */ - ptr_table_store(PL_ptr_table, dp, ret); + if (ret) + ptr_table_store(PL_ptr_table, dp, ret); return ret; -#else - return (DIR*)NULL; -#endif } /* duplicate a typeglob */ @@ -11422,7 +11621,7 @@ Perl_rvpv_dup(pTHX_ SV *const dstr, const SV *const sstr, CLONE_PARAMS *const pa SvPV_set(dstr, SAVEPVN(SvPVX_const(sstr), SvLEN(sstr)-1)); if (SvREADONLY(sstr) && SvFAKE(sstr)) { /* Not that normal - actually sstr is copy on write. - But we are a true, independant SV, so: */ + But we are a true, independent SV, so: */ SvREADONLY_off(dstr); SvFAKE_off(dstr); } @@ -11666,7 +11865,7 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) IoFMT_GV(dstr) = gv_dup(IoFMT_GV(dstr), param); IoBOTTOM_GV(dstr) = gv_dup(IoBOTTOM_GV(dstr), param); if (IoDIRP(dstr)) { - IoDIRP(dstr) = dirp_dup(IoDIRP(dstr)); + IoDIRP(dstr) = dirp_dup(IoDIRP(dstr), param); } else { NOOP; /* IoDIRP(dstr) is already a copy of IoDIRP(sstr) */ @@ -11730,15 +11929,33 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) ++i; } if (SvOOK(sstr)) { - HEK *hvname; const struct xpvhv_aux * const saux = HvAUX(sstr); struct xpvhv_aux * const daux = HvAUX(dstr); /* This flag isn't copied. */ /* SvOOK_on(hv) attacks the IV flags. */ SvFLAGS(dstr) |= SVf_OOK; - hvname = saux->xhv_name; - daux->xhv_name = hek_dup(hvname, param); + if (saux->xhv_name_count) { + HEK ** const sname = saux->xhv_name_u.xhvnameu_names; + const I32 count + = saux->xhv_name_count < 0 + ? -saux->xhv_name_count + : saux->xhv_name_count; + HEK **shekp = sname + count; + HEK **dhekp; + Newx(daux->xhv_name_u.xhvnameu_names, count, HEK *); + dhekp = daux->xhv_name_u.xhvnameu_names + count; + while (shekp-- > sname) { + dhekp--; + *dhekp = hek_dup(*shekp, param); + } + } + else { + daux->xhv_name_u.xhvnameu_name + = hek_dup(saux->xhv_name_u.xhvnameu_name, + param); + } + daux->xhv_name_count = saux->xhv_name_count; daux->xhv_riter = saux->xhv_riter; daux->xhv_eiter = saux->xhv_eiter @@ -11769,7 +11986,7 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) : 0; /* Record stashes for possible cloning in Perl_clone(). */ - if (hvname) + if (HvNAME(sstr)) av_push(param->stashes, dstr); } } @@ -11783,14 +12000,16 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) /*FALLTHROUGH*/ case SVt_PVFM: /* NOTE: not refcounted */ - CvSTASH(dstr) = hv_dup(CvSTASH(dstr), param); + SvANY(MUTABLE_CV(dstr))->xcv_stash = + hv_dup(CvSTASH(dstr), param); if ((param->flags & CLONEf_JOIN_IN) && CvSTASH(dstr)) Perl_sv_add_backref(aTHX_ MUTABLE_SV(CvSTASH(dstr)), dstr); - OP_REFCNT_LOCK; - if (!CvISXSUB(dstr)) + if (!CvISXSUB(dstr)) { + OP_REFCNT_LOCK; CvROOT(dstr) = OpREFCNT_inc(CvROOT(dstr)); - OP_REFCNT_UNLOCK; - if (CvCONST(dstr) && CvISXSUB(dstr)) { + OP_REFCNT_UNLOCK; + CvFILE(dstr) = SAVEPV(CvFILE(dstr)); + } else if (CvCONST(dstr)) { CvXSUBANY(dstr).any_ptr = sv_dup_inc((const SV *)CvXSUBANY(dstr).any_ptr, param); } @@ -11808,8 +12027,6 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) CvWEAKOUTSIDE(sstr) ? cv_dup( CvOUTSIDE(dstr), param) : cv_dup_inc(CvOUTSIDE(dstr), param); - if (!CvISXSUB(dstr)) - CvFILE(dstr) = SAVEPV(CvFILE(dstr)); break; } } @@ -11907,7 +12124,7 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param) ncx->blk_loop.state_u.lazysv.end = sv_dup_inc(ncx->blk_loop.state_u.lazysv.end, param); /* We are taking advantage of av_dup_inc and sv_dup_inc - actually being the same function, and order equivalance of + actually being the same function, and order equivalence of the two unions. We can assert the later [but only at run time :-(] */ assert ((void *) &ncx->blk_loop.state_u.ary.ary == @@ -12154,13 +12371,11 @@ 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); - i = POPINT(ss,ix); - TOPINT(nss,ix) = i; + gv = (const GV *)POPPTR(ss,ix); + TOPPTR(nss,ix) = gv_dup_inc(gv, param); break; case SAVEt_FREEOP: ptr = POPPTR(ss,ix); @@ -12188,6 +12403,10 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param) else TOPPTR(nss,ix) = NULL; break; + case SAVEt_FREECOPHH: + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = cophh_copy((COPHH *)ptr); + break; case SAVEt_DELETE: hv = (const HV *)POPPTR(ss,ix); TOPPTR(nss,ix) = hv_dup_inc(hv, param); @@ -12236,11 +12455,7 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param) break; case SAVEt_HINTS: ptr = POPPTR(ss,ix); - if (ptr) { - HINTS_REFCNT_LOCK; - ((struct refcounted_he *)ptr)->refcounted_he_refcnt++; - HINTS_REFCNT_UNLOCK; - } + ptr = cophh_copy((COPHH*)ptr); TOPPTR(nss,ix) = ptr; i = POPINT(ss,ix); TOPINT(nss,ix) = i; @@ -12516,7 +12731,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, param->proto_perl = proto_perl; /* Likely nothing will use this, but it is initialised to be consistent with Perl_clone_params_new(). */ - param->proto_perl = my_perl; + param->new_perl = my_perl; param->unreferenced = NULL; INIT_TRACK_MEMPOOL(my_perl->Imemory_debug_header, my_perl); @@ -12593,11 +12808,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, ptr_table_store(PL_ptr_table, &proto_perl->Icompiling, &PL_compiling); PL_compiling.cop_warnings = DUP_WARNINGS(PL_compiling.cop_warnings); - if (PL_compiling.cop_hints_hash) { - HINTS_REFCNT_LOCK; - PL_compiling.cop_hints_hash->refcounted_he_refcnt++; - HINTS_REFCNT_UNLOCK; - } + CopHINTHASH_set(&PL_compiling, cophh_copy(CopHINTHASH_get(&PL_compiling))); PL_curcop = (COP*)any_dup(proto_perl->Icurcop, proto_perl); #ifdef PERL_DEBUG_READONLY_OPS PL_slabs = NULL; @@ -12651,7 +12862,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_minus_F = proto_perl->Iminus_F; PL_doswitches = proto_perl->Idoswitches; PL_dowarn = proto_perl->Idowarn; - PL_doextract = proto_perl->Idoextract; PL_sawampersand = proto_perl->Isawampersand; PL_unsafe = proto_perl->Iunsafe; PL_inplace = SAVEPV(proto_perl->Iinplace); @@ -12800,6 +13010,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_modglobal = hv_dup_inc(proto_perl->Imodglobal, param); PL_custom_op_names = hv_dup_inc(proto_perl->Icustom_op_names,param); PL_custom_op_descs = hv_dup_inc(proto_perl->Icustom_op_descs,param); + PL_custom_ops = hv_dup_inc(proto_perl->Icustom_ops, param); PL_profiledata = NULL; @@ -13050,7 +13261,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_restartop = proto_perl->Irestartop; PL_in_eval = proto_perl->Iin_eval; PL_delaymagic = proto_perl->Idelaymagic; - PL_dirty = proto_perl->Idirty; + PL_phase = proto_perl->Iphase; PL_localizing = proto_perl->Ilocalizing; PL_errors = sv_dup_inc(proto_perl->Ierrors, param); @@ -13100,6 +13311,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_registered_mros = hv_dup_inc(proto_perl->Iregistered_mros, param); PL_blockhooks = av_dup_inc(proto_perl->Iblockhooks, param); + PL_utf8_foldclosures = hv_dup_inc(proto_perl->Iutf8_foldclosures, param); /* Call the ->CLONE method, if it exists, for each of the stashes identified by sv_dup() above. @@ -13592,7 +13804,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, case OP_GVSV: gv = cGVOPx_gv(obase); - if (!gv || (match && GvSV(gv) != uninit_sv)) + if (!gv || (match && GvSV(gv) != uninit_sv) || !GvSTASH(gv)) break; return varname(gv, '$', 0, NULL, 0, FUV_SUBSCRIPT_NONE); @@ -13891,6 +14103,12 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, if ( (type == OP_CONST && SvOK(cSVOPx_sv(kid))) || (type == OP_NULL && ! (kid->op_flags & OPf_KIDS)) || (type == OP_PUSHMARK) + || ( + /* @$a and %$a, but not @a or %a */ + (type == OP_RV2AV || type == OP_RV2HV) + && cUNOPx(kid)->op_first + && cUNOPx(kid)->op_first->op_type != OP_GV + ) ) continue; }