diff --git a/MANIFEST b/MANIFEST index d276691d8b21..0ab0da637873 100644 --- a/MANIFEST +++ b/MANIFEST @@ -5551,6 +5551,7 @@ scope.h Scope entry and exit header SECURITY.md Add Security Policy for GitHub sv.c Scalar value code sv.h Scalar value header +sv_inline.h Perl_newSV_type and required defs t/base/cond.t See if conditionals work t/base/if.t See if if works t/base/lex.t See if lexical items work diff --git a/av.c b/av.c index d2f0e0db45d3..335121a951d6 100644 --- a/av.c +++ b/av.c @@ -267,8 +267,7 @@ Perl_av_fetch(pTHX_ AV *av, SSize_t key, I32 lval) return NULL; } - sv = sv_newmortal(); - sv_upgrade(sv, SVt_PVLV); + sv = newSV_type_mortal(SVt_PVLV); mg_copy(MUTABLE_SV(av), sv, 0, key); if (!tied_magic) /* for regdata, force leavesub to make copies */ SvTEMP_off(sv); @@ -292,7 +291,7 @@ Perl_av_fetch(pTHX_ AV *av, SSize_t key, I32 lval) if (!AvARRAY(av)[key]) { emptyness: - return lval ? av_store(av,key,newSV(0)) : NULL; + return lval ? av_store(av,key,newSV_type(SVt_NULL)) : NULL; } return &AvARRAY(av)[key]; @@ -473,7 +472,7 @@ Perl_av_make(pTHX_ SSize_t size, SV **strp) SvGETMAGIC(*strp); /* before newSV, in case it dies */ AvFILLp(av)++; - ary[i] = newSV(0); + ary[i] = newSV_type(SVt_NULL); sv_setsv_flags(ary[i], *strp, SV_DO_COW_SVSETSV|SV_NOSTEAL); strp++; @@ -1124,7 +1123,7 @@ Perl_av_iter_p(pTHX_ AV *av) { SV * Perl_av_nonelem(pTHX_ AV *av, SSize_t ix) { - SV * const sv = newSV(0); + SV * const sv = newSV_type(SVt_NULL); PERL_ARGS_ASSERT_AV_NONELEM; if (!av_store(av,ix,sv)) return sv_2mortal(sv); /* has tie magic */ diff --git a/doop.c b/doop.c index 5a9c0d8f467f..ede537723ce2 100644 --- a/doop.c +++ b/doop.c @@ -1176,7 +1176,7 @@ Perl_do_kv(pTHX) if (gimme == G_SCALAR) { if (PL_op->op_flags & OPf_MOD || LVRET) { /* lvalue */ - SV * const ret = sv_2mortal(newSV_type(SVt_PVLV)); /* Not TARG RT#67838 */ + SV * const ret = newSV_type_mortal(SVt_PVLV); /* Not TARG RT#67838 */ sv_magic(ret, NULL, PERL_MAGIC_nkeys, NULL, 0); LvTYPE(ret) = 'k'; LvTARG(ret) = SvREFCNT_inc_simple(keys); diff --git a/dump.c b/dump.c index b2c6a075fd99..d48f58238135 100644 --- a/dump.c +++ b/dump.c @@ -2674,7 +2674,7 @@ S_append_gv_name(pTHX_ GV *gv, SV *out) sv_catpvs_nomg(out, ""); return; } - sv = newSV(0); + sv = newSV_type(SVt_NULL); gv_fullname4(sv, gv, NULL, FALSE); Perl_sv_catpvf(aTHX_ out, "$%" SVf, SVfARG(sv)); SvREFCNT_dec_NN(sv); diff --git a/embed.fnc b/embed.fnc index 45c6fd2b2648..32ca60e26d24 100644 --- a/embed.fnc +++ b/embed.fnc @@ -1519,7 +1519,8 @@ Apd |SV* |newSVrv |NN SV *const rv|NULLOK const char *const classname ApMbdR |SV* |newSVsv |NULLOK SV *const old AmdR |SV* |newSVsv_nomg |NULLOK SV *const old AdpR |SV* |newSVsv_flags |NULLOK SV *const old|I32 flags -ApdR |SV* |newSV_type |const svtype type +ApdiR |SV* |newSV_type |const svtype type +ApdIR |SV* |newSV_type_mortal|const svtype type ApdR |OP* |newUNOP |I32 type|I32 flags|NULLOK OP* first ApdR |OP* |newUNOP_AUX |I32 type|I32 flags|NULLOK OP* first \ |NULLOK UNOP_AUX_item *aux @@ -3165,7 +3166,7 @@ S |STRLEN |sv_pos_b2u_midway|NN const U8 *const s|NN const U8 *const target \ S |void |assert_uft8_cache_coherent|NN const char *const func \ |STRLEN from_cache|STRLEN real|NN SV *const sv ST |char * |F0convert |NV nv|NN char *const endbuf|NN STRLEN *const len -S |SV * |more_sv +Cp |SV * |more_sv S |bool |sv_2iuv_common |NN SV *const sv S |void |glob_assign_glob|NN SV *const dsv|NN SV *const ssv \ |const int dtype @@ -3174,7 +3175,7 @@ S |void |anonymise_cv_maybe |NN GV *gv|NN CV *cv #endif : Used in sv.c and hv.c -po |void * |more_bodies |const svtype sv_type|const size_t body_size \ +Cpo |void * |more_bodies |const svtype sv_type|const size_t body_size \ |const size_t arena_size EXpR |SV* |get_and_check_backslash_N_name|NN const char* s \ |NN const char* e \ diff --git a/embed.h b/embed.h index c08806128c94..60dfd52b8218 100644 --- a/embed.h +++ b/embed.h @@ -386,6 +386,7 @@ #define newSVOP(a,b,c) Perl_newSVOP(aTHX_ a,b,c) #define newSVREF(a) Perl_newSVREF(aTHX_ a) #define newSV_type(a) Perl_newSV_type(aTHX_ a) +#define newSV_type_mortal(a) Perl_newSV_type_mortal(aTHX_ a) #define newSVhek(a) Perl_newSVhek(aTHX_ a) #define newSViv(a) Perl_newSViv(aTHX_ a) #define newSVnv(a) Perl_newSVnv(aTHX_ a) @@ -880,6 +881,9 @@ #define dump_mstats(a) Perl_dump_mstats(aTHX_ a) #define get_mstats(a,b,c) Perl_get_mstats(aTHX_ a,b,c) #endif +#if defined(PERL_IN_SV_C) +#define more_sv() Perl_more_sv(aTHX) +#endif #if defined(PERL_USE_3ARG_SIGHANDLER) #define csighandler Perl_csighandler #endif @@ -1929,7 +1933,6 @@ #define find_uninit_var(a,b,c,d) S_find_uninit_var(aTHX_ a,b,c,d) #define glob_2number(a) S_glob_2number(aTHX_ a) #define glob_assign_glob(a,b,c) S_glob_assign_glob(aTHX_ a,b,c) -#define more_sv() S_more_sv(aTHX) #define not_a_number(a) S_not_a_number(aTHX_ a) #define not_incrementable(a) S_not_incrementable(aTHX_ a) #define ptr_table_find S_ptr_table_find diff --git a/gv.c b/gv.c index 1f06833e1a9b..6792a0f69fda 100644 --- a/gv.c +++ b/gv.c @@ -202,7 +202,7 @@ Perl_newGP(pTHX_ GV *const gv) Newxz(gp, 1, GP); gp->gp_egv = gv; /* allow compiler to reuse gv after this */ #ifndef PERL_DONT_CREATE_GVSV - gp->gp_sv = newSV(0); + gp->gp_sv = newSV_type(SVt_NULL); #endif /* PL_curcop may be null here. E.g., @@ -294,7 +294,7 @@ Perl_cvgv_from_hek(pTHX_ CV *cv) if (!CvSTASH(cv)) return NULL; ASSUME(CvNAME_HEK(cv)); svp = hv_fetchhek(CvSTASH(cv), CvNAME_HEK(cv), 0); - gv = MUTABLE_GV(svp && *svp ? *svp : newSV(0)); + gv = MUTABLE_GV(svp && *svp ? *svp : newSV_type(SVt_NULL)); if (!isGV(gv)) gv_init_pvn(gv, CvSTASH(cv), HEK_KEY(CvNAME_HEK(cv)), HEK_LEN(CvNAME_HEK(cv)), @@ -580,7 +580,7 @@ S_maybe_add_coresub(pTHX_ HV * const stash, GV *gv, ampable = FALSE; } if (!gv) { - gv = (GV *)newSV(0); + gv = (GV *)newSV_type(SVt_NULL); gv_init(gv, stash, name, len, TRUE); } GvMULTI_on(gv); @@ -1359,7 +1359,7 @@ Perl_gv_autoload_pvn(pTHX_ HV *stash, const char *name, STRLEN len, U32 flags) if (!isGV(vargv)) { gv_init_pvn(vargv, varstash, S_autoload, S_autolen, 0); #ifdef PERL_DONT_CREATE_GVSV - GvSV(vargv) = newSV(0); + GvSV(vargv) = newSV_type(SVt_NULL); #endif } LEAVE; @@ -2516,7 +2516,7 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags, /* By this point we should have a stash and a name */ gvp = (GV**)hv_fetch(stash,name,is_utf8 ? -(I32)len : (I32)len,add); if (!gvp || *gvp == (const GV *)&PL_sv_undef) { - if (addmg) gv = (GV *)newSV(0); /* tentatively */ + if (addmg) gv = (GV *)newSV_type(SVt_NULL); /* tentatively */ else return NULL; } else gv = *gvp, addmg = 0; @@ -3801,7 +3801,7 @@ Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags) break; case G_LIST: if (flags & AMGf_want_list) { - res = sv_2mortal((SV *)newAV()); + res = newSV_type_mortal(SVt_PVAV); av_extend((AV *)res, nret); while (nret--) av_store((AV *)res, nret, POPs); diff --git a/hv.c b/hv.c index 34b722809d2c..ab17badbf235 100644 --- a/hv.c +++ b/hv.c @@ -200,12 +200,12 @@ static void S_hv_notallowed(pTHX_ int flags, const char *key, I32 klen, const char *msg) { - SV * const sv = sv_newmortal(); + /* Straight to SVt_PVN here, as needed by sv_setpvn_fresh and + * sv_usepvn would otherwise call it */ + SV * const sv = newSV_type_mortal(SVt_PV); PERL_ARGS_ASSERT_HV_NOTALLOWED; - sv_upgrade(sv, SVt_PV); /* Needed by sv_setpvn_fresh and - * sv_usepvn would otherwise call it */ if (!(flags & HVhek_FREEKEY)) { sv_setpvn_fresh(sv, key, klen); } @@ -480,7 +480,7 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, HV_FETCH_ISSTORE | HV_DISABLE_UVAR_XKEY | return_svp, - newSV(0), hash); + newSV_type(SVt_NULL), hash); } else { if (flags & HVhek_FREEKEY) Safefree(key); @@ -739,7 +739,7 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, break; } /* LVAL fetch which actually needs a store. */ - val = newSV(0); + val = newSV_type(SVt_NULL); HvPLACEHOLDERS(hv)--; } else { /* store */ @@ -793,7 +793,7 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, return NULL; } if (action & HV_FETCH_LVALUE) { - val = action & HV_FETCH_EMPTY_HE ? NULL : newSV(0); + val = action & HV_FETCH_EMPTY_HE ? NULL : newSV_type(SVt_NULL); if (SvMAGICAL(hv)) { /* At this point the old hv_fetch code would call to hv_store, which in turn might do some tied magic. So we need to make that @@ -968,6 +968,7 @@ SV * Perl_hv_scalar(pTHX_ HV *hv) { SV *sv; + UV u; PERL_ARGS_ASSERT_HV_SCALAR; @@ -977,8 +978,21 @@ Perl_hv_scalar(pTHX_ HV *hv) return magic_scalarpack(hv, mg); } - sv = sv_newmortal(); - sv_setuv(sv, HvUSEDKEYS(hv)); + sv = newSV_type_mortal(SVt_IV); + + /* Inlined sv_setuv(sv, HvUSEDKEYS(hv)) follows:*/ + u = HvUSEDKEYS(hv); + + if (u <= (UV)IV_MAX) { + SvIV_set(sv, (IV)u); + (void)SvIOK_only(sv); + SvTAINT(sv); + } else { + SvIV_set(sv, 0); + SvUV_set(sv, u); + (void)SvIOK_only_UV(sv); + SvTAINT(sv); + } return sv; } @@ -3247,7 +3261,7 @@ S_refcounted_he_value(pTHX_ const struct refcounted_he *he) switch(he->refcounted_he_data[0] & HVrhek_typemask) { case HVrhek_undef: - value = newSV(0); + value = newSV_type(SVt_NULL); break; case HVrhek_delete: value = &PL_sv_placeholder; diff --git a/inline.h b/inline.h index 7ff7d799a23a..e664d25f6d52 100644 --- a/inline.h +++ b/inline.h @@ -134,7 +134,7 @@ Perl_av_fetch_simple(pTHX_ AV *av, SSize_t key, I32 lval) assert(key > -1); if ( (key > AvFILLp(av)) || !AvARRAY(av)[key]) { - return lval ? av_store_simple(av,key,newSV(0)) : NULL; + return lval ? av_store_simple(av,key,newSV_type(SVt_NULL)) : NULL; } else { return &AvARRAY(av)[key]; } diff --git a/mg.c b/mg.c index 10813a73165c..83b7581a4c9a 100644 --- a/mg.c +++ b/mg.c @@ -877,7 +877,7 @@ Perl_sv_string_from_errnum(pTHX_ int errnum, SV *tgtsv) { char const *errstr; if(!tgtsv) - tgtsv = sv_newmortal(); + tgtsv = newSV_type_mortal(SVt_PV); errstr = my_strerror(errnum); if(errstr) { sv_setpv(tgtsv, errstr); diff --git a/mro_core.c b/mro_core.c index 947326eb0f43..85c40db2b5e1 100644 --- a/mro_core.c +++ b/mro_core.c @@ -255,7 +255,7 @@ S_mro_get_linear_isa_dfs(pTHX_ HV *stash, U32 level) /* not in cache, make a new one */ - retval = MUTABLE_AV(sv_2mortal(MUTABLE_SV(newAV()))); + retval = MUTABLE_AV(newSV_type_mortal(SVt_PVAV)); /* We use this later in this function, but don't need a reference to it beyond the end of this function, so reference count is fine. */ our_name = newSVhek(stashhek); @@ -347,7 +347,7 @@ S_mro_get_linear_isa_dfs(pTHX_ HV *stash, U32 level) } else { /* They have no stash. So create ourselves an ->isa cache as if we'd copied it from what theirs should be. */ - stored = MUTABLE_HV(sv_2mortal(MUTABLE_SV(newHV()))); + stored = MUTABLE_HV(newSV_type_mortal(SVt_PVHV)); (void) hv_stores(stored, "UNIVERSAL", &PL_sv_undef); av_push(retval, newSVhek(HeKEY_hek(hv_store_ent(stored, sv, @@ -357,7 +357,7 @@ S_mro_get_linear_isa_dfs(pTHX_ HV *stash, U32 level) } } else { /* We have no parents. */ - stored = MUTABLE_HV(sv_2mortal(MUTABLE_SV(newHV()))); + stored = MUTABLE_HV(newSV_type_mortal(SVt_PVHV)); (void) hv_stores(stored, "UNIVERSAL", &PL_sv_undef); } @@ -428,7 +428,7 @@ Perl_mro_get_linear_isa(pTHX_ HV *stash) SV **svp; SV **ovp = AvARRAY(old); SV * const * const oend = ovp + AvFILLp(old) + 1; - isa = (AV *)sv_2mortal((SV *)newAV()); + isa = (AV *)newSV_type_mortal(SVt_PVAV); av_extend(isa, AvFILLp(isa) = AvFILLp(old)+1); *AvARRAY(isa) = namesv; svp = AvARRAY(isa)+1; @@ -570,7 +570,7 @@ Perl_mro_isa_changed_in(pTHX_ HV* stash) if(hv_iterinit(isarev)) { /* Only create the hash if we need it; i.e., if isarev has any elements. */ - isa_hashes = (HV *)sv_2mortal((SV *)newHV()); + isa_hashes = (HV *)newSV_type_mortal(SVt_PVHV); } while((iter = hv_iternext(isarev))) { HV* revstash = gv_stashsv(hv_iterkeysv(iter), 0); @@ -817,7 +817,7 @@ Perl_mro_package_moved(pTHX_ HV * const stash, HV * const oldstash, } else { SV *aname; - namesv = sv_2mortal((SV *)newAV()); + namesv = newSV_type_mortal(SVt_PVAV); while (name_count--) { if(memEQs(HEK_KEY(*namep), HEK_LEN(*namep), "main")){ aname = GvNAMELEN(gv) == 1 @@ -854,9 +854,9 @@ Perl_mro_package_moved(pTHX_ HV * const stash, HV * const oldstash, wrong name. The names must be set on *all* affected stashes before we do anything else. (And linearisations must be cleared, too.) */ - stashes = (HV *) sv_2mortal((SV *)newHV()); + stashes = (HV *) newSV_type_mortal(SVt_PVHV); mro_gather_and_rename( - stashes, (HV *) sv_2mortal((SV *)newHV()), + stashes, (HV *) newSV_type_mortal(SVt_PVHV), stash, oldstash, namesv ); @@ -1119,7 +1119,7 @@ S_mro_gather_and_rename(pTHX_ HV * const stashes, HV * const seen_stashes, /* Skip the entire loop if the hash is empty. */ if(oldstash && HvTOTALKEYS(oldstash)) { xhv = (XPVHV*)SvANY(oldstash); - seen = (HV *) sv_2mortal((SV *)newHV()); + seen = (HV *) newSV_type_mortal(SVt_PVHV); /* Iterate through entries in the oldstash, adding them to the list, meanwhile doing the equivalent of $seen{$key} = 1. @@ -1164,7 +1164,7 @@ S_mro_gather_and_rename(pTHX_ HV * const stashes, HV * const seen_stashes, SV *aname; items = AvFILLp((AV *)namesv) + 1; svp = AvARRAY((AV *)namesv); - subname = sv_2mortal((SV *)newAV()); + subname = newSV_type_mortal(SVt_PVAV); while (items--) { aname = newSVsv(*svp++); if (len == 1) @@ -1247,7 +1247,7 @@ S_mro_gather_and_rename(pTHX_ HV * const stashes, HV * const seen_stashes, SV *aname; items = AvFILLp((AV *)namesv) + 1; svp = AvARRAY((AV *)namesv); - subname = sv_2mortal((SV *)newAV()); + subname = newSV_type_mortal(SVt_PVAV); while (items--) { aname = newSVsv(*svp++); if (len == 1) diff --git a/op.c b/op.c index 6b7bb5b87d32..bb543b3611bf 100644 --- a/op.c +++ b/op.c @@ -10964,7 +10964,7 @@ S_op_const_sv(pTHX_ const OP *o, CV *cv, bool allow_lex) if (type == OP_CONST && cSVOPo->op_sv) sv = cSVOPo->op_sv; else if (type == OP_UNDEF && !o->op_private) { - sv = newSV(0); + sv = newSV_type(SVt_NULL); SAVEFREESV(sv); } else if (allow_lex && type == OP_PADSV) { @@ -13623,7 +13623,7 @@ Perl_ck_glob(pTHX_ OP *o) LEAVE; } #endif /* !PERL_EXTERNAL_GLOB */ - gv = (GV *)newSV(0); + gv = (GV *)newSV_type(SVt_NULL); gv_init(gv, 0, "", 0, 0); gv_IOadd(gv); op_append_elem(OP_GLOB, o, newGVOP(OP_GV, 0, gv)); @@ -13689,7 +13689,7 @@ Perl_ck_index(pTHX_ OP *o) if ( (!SvPOK(sv) || SvNIOKp(sv) || isREGEXP(sv)) && SvOK(sv) && !SvROK(sv)) { - sv = newSV(0); + sv = newSV_type(SVt_NULL); sv_copypv(sv, kSVOP->op_sv); SvREFCNT_dec_NN(kSVOP->op_sv); kSVOP->op_sv = sv; diff --git a/pad.c b/pad.c index bc41a475bb48..b1ea097ebd83 100644 --- a/pad.c +++ b/pad.c @@ -719,7 +719,7 @@ Perl_pad_alloc(pTHX_ I32 optype, U32 tmptype) pad_reset(); if (tmptype == SVs_PADMY) { /* Not & because this ‘flag’ is 0. */ /* For a my, simply push a null SV onto the end of PL_comppad. */ - sv = *av_store_simple(PL_comppad, AvFILLp(PL_comppad) + 1, newSV(0)); + sv = *av_store_simple(PL_comppad, AvFILLp(PL_comppad) + 1, newSV_type(SVt_NULL)); retval = (PADOFFSET)AvFILLp(PL_comppad); } else { @@ -1252,13 +1252,13 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv, } if (!*out_capture) { if (namelen != 0 && *namepv == '@') - *out_capture = sv_2mortal(MUTABLE_SV(newAV())); + *out_capture = newSV_type_mortal(SVt_PVAV); else if (namelen != 0 && *namepv == '%') - *out_capture = sv_2mortal(MUTABLE_SV(newHV())); + *out_capture = newSV_type_mortal(SVt_PVHV); else if (namelen != 0 && *namepv == '&') - *out_capture = sv_2mortal(newSV_type(SVt_PVCV)); + *out_capture = newSV_type_mortal(SVt_PVCV); else - *out_capture = sv_newmortal(); + *out_capture = newSV_type_mortal(SVt_NULL); } } @@ -1565,7 +1565,7 @@ Perl_pad_swipe(pTHX_ PADOFFSET po, bool refadjust) /* if pad tmps aren't shared between ops, then there's no need to * create a new tmp when an existing op is freed */ #ifdef USE_PAD_RESET - PL_curpad[po] = newSV(0); + PL_curpad[po] = newSV_type(SVt_NULL); SvPADTMP_on(PL_curpad[po]); #else PL_curpad[po] = NULL; @@ -2030,7 +2030,7 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned, else if (sigil == '%') sv = MUTABLE_SV(newHV()); else - sv = newSV(0); + sv = newSV_type(SVt_NULL); /* reset the 'assign only once' flag on each state var */ if (sigil != '&' && SvPAD_STATE(namesv)) SvPADSTALE_on(sv); @@ -2041,7 +2041,7 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned, sv = SvREFCNT_inc_NN(ppad[ix]); } else { - sv = newSV(0); + sv = newSV_type(SVt_NULL); SvPADTMP_on(sv); } PL_curpad[ix] = sv; @@ -2063,7 +2063,7 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned, */ bool cloned_in_this_pass; if (!cloned) - cloned = (HV *)sv_2mortal((SV *)newHV()); + cloned = (HV *)newSV_type_mortal(SVt_PVHV); do { cloned_in_this_pass = FALSE; for (ix = fpad; ix > 0; ix--) { @@ -2435,7 +2435,7 @@ Perl_pad_push(pTHX_ PADLIST *padlist, int depth) else if (sigil == '%') sv = MUTABLE_SV(newHV()); else - sv = newSV(0); + sv = newSV_type(SVt_NULL); } } else if (PadnamePV(names[ix])) { @@ -2443,7 +2443,7 @@ Perl_pad_push(pTHX_ PADLIST *padlist, int depth) } else { /* save temporaries on recursion? */ - sv = newSV(0); + sv = newSV_type(SVt_NULL); SvPADTMP_on(sv); } AvARRAY(newpad)[ix] = sv; @@ -2543,7 +2543,7 @@ Perl_padlist_dup(pTHX_ PADLIST *srcpad, CLONE_PARAMS *param) else if (sigil == '%') sv = MUTABLE_SV(newHV()); else - sv = newSV(0); + sv = newSV_type(SVt_NULL); pad1a[ix] = sv; } } @@ -2554,7 +2554,7 @@ Perl_padlist_dup(pTHX_ PADLIST *srcpad, CLONE_PARAMS *param) } else { /* save temporaries on recursion? */ - SV * const sv = newSV(0); + SV * const sv = newSV_type(SVt_NULL); pad1a[ix] = sv; /* SvREFCNT(oldpad[ix]) != 1 for some code in threads.xs diff --git a/perl.h b/perl.h index d05cc2928c1e..32c7afa5cd84 100644 --- a/perl.h +++ b/perl.h @@ -1252,12 +1252,6 @@ Use L to declare variables of the maximum usable size on this platform. (((U64)(x) & UINT64_C(0xff00000000000000)) >> 56) )) # endif -/* The old value was hard coded at 1008. (4096-16) seems to be a bit faster, - at least on FreeBSD. YMMV, so experiment. */ -#ifndef PERL_ARENA_SIZE -#define PERL_ARENA_SIZE 4080 -#endif - /* Maximum level of recursion */ #ifndef PERL_SUB_DEPTH_WARN #define PERL_SUB_DEPTH_WARN 100 @@ -7160,6 +7154,7 @@ cannot have changed since the precalculation. START_EXTERN_C # include "inline.h" +# include "sv_inline.h" END_EXTERN_C diff --git a/pp.c b/pp.c index b53fd8796832..b0c6e42031c0 100644 --- a/pp.c +++ b/pp.c @@ -130,7 +130,7 @@ S_rv2gv(pTHX_ SV *sv, const bool vivify_sv, const bool strict, HV *stash; if (SvREADONLY(sv)) Perl_croak_no_modify(); - gv = MUTABLE_GV(newSV(0)); + gv = MUTABLE_GV(newSV_type(SVt_NULL)); stash = CopSTASH(PL_curcop); if (SvTYPE(stash) != SVt_PVHV) stash = NULL; if (cUNOP->op_targ) { @@ -313,7 +313,7 @@ PP(pp_pos) dSP; dTOPss; if (PL_op->op_flags & OPf_MOD || LVRET) { - SV * const ret = sv_2mortal(newSV_type(SVt_PVLV));/* Not TARG RT#67838 */ + SV * const ret = newSV_type_mortal(SVt_PVLV);/* Not TARG RT#67838 */ sv_magic(ret, NULL, PERL_MAGIC_pos, NULL, 0); LvTYPE(ret) = '.'; LvTARG(ret) = SvREFCNT_inc_simple(sv); @@ -467,7 +467,7 @@ S_refto(pTHX_ SV *sv) SvTEMP_off(sv); SvREFCNT_inc_void_NN(sv); } - rv = sv_newmortal(); + rv = newSV_type_mortal(SVt_IV); sv_setrv_noinc(rv, sv); return rv; } @@ -938,7 +938,7 @@ PP(pp_undef) Newxz(gp, 1, GP); GvGP_set(sv, gp_ref(gp)); #ifndef PERL_DONT_CREATE_GVSV - GvSV(sv) = newSV(0); + GvSV(sv) = newSV_type(SVt_NULL); #endif GvLINE(sv) = CopLINE(PL_curcop); GvEGV(sv) = MUTABLE_GV(sv); @@ -3300,7 +3300,7 @@ PP(pp_substr) } if (lvalue && !repl_sv) { SV * ret; - ret = sv_2mortal(newSV_type(SVt_PVLV)); /* Not TARG RT#67838 */ + ret = newSV_type_mortal(SVt_PVLV); /* Not TARG RT#67838 */ sv_magic(ret, NULL, PERL_MAGIC_substr, NULL, 0); LvTYPE(ret) = 'x'; LvTARG(ret) = SvREFCNT_inc_simple(sv); @@ -3432,7 +3432,7 @@ PP(pp_vec) retuv = errflags ? 0 : do_vecget(src, offset, size); if (lvalue) { /* it's an lvalue! */ - ret = sv_2mortal(newSV_type(SVt_PVLV)); /* Not TARG RT#67838 */ + ret = newSV_type_mortal(SVt_PVLV); /* Not TARG RT#67838 */ sv_magic(ret, NULL, PERL_MAGIC_vec, NULL, 0); LvTYPE(ret) = 'v'; LvTARG(ret) = SvREFCNT_inc_simple(src); @@ -3499,7 +3499,7 @@ PP(pp_index) /* At this point, pv is a malloc()ed string. So donate it to temp to ensure it will get free()d */ - little = temp = newSV(0); + little = temp = newSV_type(SVt_NULL); sv_usepvn(temp, pv, llen); little_p = SvPVX(little); } else { @@ -5534,13 +5534,13 @@ PP(pp_anonhash) { MARK++; SvGETMAGIC(*MARK); - val = newSV(0); + val = newSV_type(SVt_NULL); sv_setsv_nomg(val, *MARK); } else { Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Odd number of elements in anonymous hash"); - val = newSV(0); + val = newSV_type(SVt_NULL); } (void)hv_store_ent(hv,key,val,0); } @@ -5791,7 +5791,7 @@ PP(pp_push) for (++MARK; MARK <= SP; MARK++) { SV *sv; if (*MARK) SvGETMAGIC(*MARK); - sv = newSV(0); + sv = newSV_type(SVt_NULL); if (*MARK) sv_setsv_nomg(sv, *MARK); av_store(ary, AvFILLp(ary)+1, sv); @@ -6830,7 +6830,7 @@ PP(pp_refassign) PP(pp_lvref) { dSP; - SV * const ret = sv_2mortal(newSV_type(SVt_PVMG)); + SV * const ret = newSV_type_mortal(SVt_PVMG); SV * const elem = PL_op->op_private & OPpLVREF_ELEM ? POPs : NULL; SV * const arg = PL_op->op_flags & OPf_STACKED ? POPs : NULL; MAGIC * const mg = sv_magicext(ret, arg, PERL_MAGIC_lvref, @@ -6898,7 +6898,7 @@ PP(pp_lvrefslice) else S_localise_helem_lval(aTHX_ (HV *)av, elemsv, can_preserve); } - *MARK = sv_2mortal(newSV_type(SVt_PVMG)); + *MARK = newSV_type_mortal(SVt_PVMG); sv_magic(*MARK,(SV *)av,PERL_MAGIC_lvref,(char *)elemsv,HEf_SVKEY); } RETURN; @@ -7026,7 +7026,7 @@ PP(pp_argelem) SV *tmpsv; SV **svp = av_fetch(defav, ix + i, FALSE); SV *val = svp ? *svp : &PL_sv_undef; - tmpsv = newSV(0); + tmpsv = newSV_type(SVt_NULL); sv_setsv(tmpsv, val); av_store((AV*)targ, i++, tmpsv); TAINT_NOT; @@ -7042,7 +7042,7 @@ PP(pp_argelem) /* see "target should usually be empty" comment above */ for (i = 0; i < argc; i++) { SV **svp = av_fetch(defav, ix + i, FALSE); - SV *newsv = newSV(0); + SV *newsv = newSV_type(SVt_NULL); sv_setsv_flags(newsv, svp ? *svp : &PL_sv_undef, (SV_DO_COW_SVSETSV|SV_NOSTEAL)); @@ -7071,7 +7071,7 @@ PP(pp_argelem) argc -= 2; if (UNLIKELY(SvGMAGICAL(key))) key = sv_mortalcopy(key); - tmpsv = newSV(0); + tmpsv = newSV_type(SVt_NULL); sv_setsv(tmpsv, val); hv_store_ent((HV*)targ, key, tmpsv, 0); TAINT_NOT; diff --git a/pp_ctl.c b/pp_ctl.c index 44289bbd689d..c28fe258415a 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -4386,7 +4386,7 @@ S_require_file(pTHX_ SV *sv) than hanging another SV from it. In turn, filter_add() optionally takes the SV to use as the filter (or creates a new SV if passed NULL), so simply pass in whatever value filter_cache has. */ - SV * const fc = filter_cache ? newSV(0) : NULL; + SV * const fc = filter_cache ? newSV_type(SVt_NULL) : NULL; SV *datasv; if (fc) sv_copypv(fc, filter_cache); datasv = filter_add(S_run_user_filter, fc); @@ -5169,12 +5169,10 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied) const Size_t other_len = av_count(other_av); if (NULL == seen_this) { - seen_this = newHV(); - (void) sv_2mortal(MUTABLE_SV(seen_this)); + seen_this = (HV*)newSV_type_mortal(SVt_PVHV); } if (NULL == seen_other) { - seen_other = newHV(); - (void) sv_2mortal(MUTABLE_SV(seen_other)); + seen_other = (HV*)newSV_type_mortal(SVt_PVHV); } for(i = 0; i < other_len; ++i) { SV * const * const this_elem = av_fetch(MUTABLE_AV(SvRV(e)), i, FALSE); @@ -5882,7 +5880,7 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) don't want to pass it in a second time. I'm going to use a mortal in case the upstream filter croaks. */ upstream = ((SvOK(buf_sv) && sv_len(buf_sv)) || SvGMAGICAL(buf_sv)) - ? sv_newmortal() : buf_sv; + ? newSV_type_mortal(SVt_PV) : buf_sv; SvUPGRADE(upstream, SVt_PV); if (filter_has_file) { diff --git a/pp_hot.c b/pp_hot.c index 477cdd48b841..67b255e2e760 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -991,7 +991,7 @@ PP(pp_multiconcat) ) ) { - SV *tmp = sv_newmortal(); + SV *tmp = newSV_type_mortal(SVt_PV); sv_copypv(tmp, left); SvSETMAGIC(tmp); left = tmp; @@ -2868,7 +2868,7 @@ PP(pp_qr) REGEXP * rx = PM_GETRE(pm); regexp *prog = ReANY(rx); SV * const pkg = RXp_ENGINE(prog)->qr_package(aTHX_ (rx)); - SV * const rv = sv_newmortal(); + SV * const rv = newSV_type_mortal(SVt_IV); CV **cvp; CV *cv; @@ -3406,8 +3406,7 @@ PP(pp_helem) if (!defer) { DIE(aTHX_ PL_no_helem_sv, SVfARG(keysv)); } - lv = sv_newmortal(); - sv_upgrade(lv, SVt_PVLV); + lv = newSV_type_mortal(SVt_PVLV); LvTYPE(lv) = 'y'; sv_magic(lv, key2 = newSVsv(keysv), PERL_MAGIC_defelem, NULL, 0); SvREFCNT_dec_NN(key2); /* sv_magic() increments refcount */ @@ -3846,8 +3845,7 @@ PP(pp_multideref) SV* key2; if (!defer) DIE(aTHX_ PL_no_helem_sv, SVfARG(keysv)); - lv = sv_newmortal(); - sv_upgrade(lv, SVt_PVLV); + lv = newSV_type_mortal(SVt_PVLV); LvTYPE(lv) = 'y'; sv_magic(lv, key2 = newSVsv(keysv), PERL_MAGIC_defelem, NULL, 0); @@ -4895,7 +4893,7 @@ Perl_leave_adjust_stacks(pTHX_ SV **from_sp, SV **to_sp, U8 gimme, int pass) * ++PL_tmps_ix, moving the previous occupant there * instead. */ - SV *newsv = newSV(0); + SV *newsv = newSV_type(SVt_NULL); PL_tmps_stack[++PL_tmps_ix] = *tmps_basep; /* put it on the tmps stack early so it gets freed if we die */ @@ -5510,7 +5508,7 @@ Perl_vivify_ref(pTHX_ SV *sv, U32 to_what) prepare_SV_for_RV(sv); switch (to_what) { case OPpDEREF_SV: - SvRV_set(sv, newSV(0)); + SvRV_set(sv, newSV_type(SVt_NULL)); break; case OPpDEREF_AV: SvRV_set(sv, MUTABLE_SV(newAV())); diff --git a/proto.h b/proto.h index 2df7f0a30fc5..4bd0d4e39f89 100644 --- a/proto.h +++ b/proto.h @@ -2482,9 +2482,18 @@ PERL_CALLCONV OP* Perl_newSVREF(pTHX_ OP* o) #define PERL_ARGS_ASSERT_NEWSVREF \ assert(o) -PERL_CALLCONV SV* Perl_newSV_type(pTHX_ const svtype type) +#ifndef PERL_NO_INLINE_FUNCTIONS +PERL_STATIC_INLINE SV* Perl_newSV_type(pTHX_ const svtype type) __attribute__warn_unused_result__; #define PERL_ARGS_ASSERT_NEWSV_TYPE +#endif + +#ifndef PERL_NO_INLINE_FUNCTIONS +PERL_STATIC_FORCE_INLINE SV* Perl_newSV_type_mortal(pTHX_ const svtype type) + __attribute__warn_unused_result__ + __attribute__always_inline__; +#define PERL_ARGS_ASSERT_NEWSV_TYPE_MORTAL +#endif PERL_CALLCONV SV* Perl_newSVavdefelem(pTHX_ AV *av, SSize_t ix, bool extendible) __attribute__warn_unused_result__; @@ -6452,7 +6461,7 @@ STATIC bool S_glob_2number(pTHX_ GV* const gv); STATIC void S_glob_assign_glob(pTHX_ SV *const dsv, SV *const ssv, const int dtype); #define PERL_ARGS_ASSERT_GLOB_ASSIGN_GLOB \ assert(dsv); assert(ssv) -STATIC SV * S_more_sv(pTHX); +PERL_CALLCONV SV * Perl_more_sv(pTHX); #define PERL_ARGS_ASSERT_MORE_SV STATIC void S_not_a_number(pTHX_ SV *const sv); #define PERL_ARGS_ASSERT_NOT_A_NUMBER \ diff --git a/regcomp.c b/regcomp.c index cec3194efb7b..9990c074d94f 100644 --- a/regcomp.c +++ b/regcomp.c @@ -16673,8 +16673,8 @@ S_handle_regex_sets(pTHX_ RExC_state_t *pRExC_state, SV** return_invlist, * so that everything gets evaluated down to a single operand, which is the * result */ - sv_2mortal((SV *)(stack = newAV())); - sv_2mortal((SV *)(fence_stack = newAV())); + stack = (AV*)newSV_type_mortal(SVt_PVAV); + fence_stack = (AV*)newSV_type_mortal(SVt_PVAV); while (RExC_parse < RExC_end) { I32 top_index; /* Index of top-most element in 'stack' */ diff --git a/regexec.c b/regexec.c index 47a038580c81..8f9ad6f3ac7c 100644 --- a/regexec.c +++ b/regexec.c @@ -3712,7 +3712,7 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, char *strend, magic belonging to this SV. Not newSVsv, either, as it does not COW. */ - reginfo->sv = newSV(0); + reginfo->sv = newSV_type(SVt_NULL); SvSetSV_nosteal(reginfo->sv, sv); SAVEFREESV(reginfo->sv); } diff --git a/scope.c b/scope.c index 5294e0aa044f..62801c419ad5 100644 --- a/scope.c +++ b/scope.c @@ -232,7 +232,7 @@ S_save_scalar_at(pTHX_ SV **sptr, const U32 flags) if (flags & SAVEf_KEEPOLDELEM) sv = osv; else { - sv = (*sptr = newSV(0)); + sv = (*sptr = newSV_type(SVt_NULL)); if (SvTYPE(osv) >= SVt_PVMG && SvMAGIC(osv)) mg_localize(osv, sv, cBOOL(flags & SAVEf_SETMAGIC)); } @@ -1264,7 +1264,7 @@ Perl_leave_scope(pTHX_ I32 base) CvLEXICAL_on(*svp); break; } - default: *svp = newSV(0); break; + default: *svp = newSV_type(SVt_NULL); break; } SvREFCNT_dec_NN(sv); /* Cast current value to the winds. */ /* preserve pad nature, but also mark as not live diff --git a/sv.c b/sv.c index 0c8958789a7c..0624c49075cb 100644 --- a/sv.c +++ b/sv.c @@ -230,16 +230,6 @@ Public API: * "A time to plant, and a time to uproot what was planted..." */ -#ifdef PERL_MEM_LOG -# define MEM_LOG_NEW_SV(sv, file, line, func) \ - Perl_mem_log_new_sv(sv, file, line, func) -# define MEM_LOG_DEL_SV(sv, file, line, func) \ - Perl_mem_log_del_sv(sv, file, line, func) -#else -# define MEM_LOG_NEW_SV(sv, file, line, func) NOOP -# define MEM_LOG_DEL_SV(sv, file, line, func) NOOP -#endif - #ifdef DEBUG_LEAKING_SCALARS # define FREE_SV_DEBUG_FILE(sv) STMT_START { \ if ((sv)->sv_debug_file) PerlMemShared_free((sv)->sv_debug_file); \ @@ -252,21 +242,6 @@ Public API: # define DEBUG_SV_SERIAL(sv) NOOP #endif -#ifdef PERL_POISON -# define SvARENA_CHAIN(sv) ((sv)->sv_u.svu_rv) -# define SvARENA_CHAIN_SET(sv,val) (sv)->sv_u.svu_rv = MUTABLE_SV((val)) -/* Whilst I'd love to do this, it seems that things like to check on - unreferenced scalars -# define POISON_SV_HEAD(sv) PoisonNew(sv, 1, struct STRUCT_SV) -*/ -# define POISON_SV_HEAD(sv) PoisonNew(&SvANY(sv), 1, void *), \ - PoisonNew(&SvREFCNT(sv), 1, U32) -#else -# define SvARENA_CHAIN(sv) SvANY(sv) -# define SvARENA_CHAIN_SET(sv,val) SvANY(sv) = (void *)(val) -# define POISON_SV_HEAD(sv) -#endif - /* Mark an SV head as unused, and add to free list. * * If SVf_BREAK is set, skip adding it to the free list, as this SV had @@ -289,18 +264,11 @@ Public API: --PL_sv_count; \ } STMT_END -#define uproot_SV(p) \ - STMT_START { \ - (p) = PL_sv_root; \ - PL_sv_root = MUTABLE_SV(SvARENA_CHAIN(p)); \ - ++PL_sv_count; \ - } STMT_END - /* make some more SVs by adding another arena */ -STATIC SV* -S_more_sv(pTHX) +SV* +Perl_more_sv(pTHX) { SV* sv; char *chunk; /* must use New here to match call to */ @@ -310,58 +278,6 @@ S_more_sv(pTHX) return sv; } -/* new_SV(): return a new, empty SV head */ - -#ifdef DEBUG_LEAKING_SCALARS -/* provide a real function for a debugger to play with */ -STATIC SV* -S_new_SV(pTHX_ const char *file, int line, const char *func) -{ - SV* sv; - - if (PL_sv_root) - uproot_SV(sv); - else - sv = S_more_sv(aTHX); - SvANY(sv) = 0; - SvREFCNT(sv) = 1; - SvFLAGS(sv) = 0; - sv->sv_debug_optype = PL_op ? PL_op->op_type : 0; - sv->sv_debug_line = (U16) (PL_parser && PL_parser->copline != NOLINE - ? PL_parser->copline - : PL_curcop - ? CopLINE(PL_curcop) - : 0 - ); - sv->sv_debug_inpad = 0; - sv->sv_debug_parent = NULL; - sv->sv_debug_file = PL_curcop ? savesharedpv(CopFILE(PL_curcop)): NULL; - - sv->sv_debug_serial = PL_sv_serial++; - - MEM_LOG_NEW_SV(sv, file, line, func); - DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%" UVxf ": (%05ld) new_SV (from %s:%d [%s])\n", - PTR2UV(sv), (long)sv->sv_debug_serial, file, line, func)); - - return sv; -} -# define new_SV(p) (p)=S_new_SV(aTHX_ __FILE__, __LINE__, FUNCTION__) - -#else -# define new_SV(p) \ - STMT_START { \ - if (PL_sv_root) \ - uproot_SV(p); \ - else \ - (p) = S_more_sv(aTHX); \ - SvANY(p) = 0; \ - SvREFCNT(p) = 1; \ - SvFLAGS(p) = 0; \ - MEM_LOG_NEW_SV(p, __FILE__, __LINE__, FUNCTION__); \ - } STMT_END -#endif - - /* del_SV(): return an empty SV head to the free list */ #ifdef DEBUGGING @@ -768,8 +684,12 @@ Perl_sv_free_arenas(pTHX) } /* - Here are mid-level routines that manage the allocation of bodies out - of the various arenas. There are 4 kinds of arenas: + Historically, here were mid-level routines that manage the + allocation of bodies out of the various arenas. Some of these + routines and related definitions remain here, but otherse were + moved into sv_inline.h to facilitate inlining of newSV_type(). + + There are 4 kinds of arenas: 1. SV-head arenas, which are discussed and handled above 2. regular body arenas @@ -871,173 +791,6 @@ available in hv.c. Similarly SVt_IV is re-used for HVAUX_ARENA_ROOT_IX. */ -typedef struct xpvhv_with_aux XPVHV_WITH_AUX; - -struct body_details { - U8 body_size; /* Size to allocate */ - U8 copy; /* Size of structure to copy (may be shorter) */ - U8 offset; /* Size of unalloced ghost fields to first alloced field*/ - PERL_BITFIELD8 type : 4; /* We have space for a sanity check. */ - PERL_BITFIELD8 cant_upgrade : 1;/* Cannot upgrade this type */ - PERL_BITFIELD8 zero_nv : 1; /* zero the NV when upgrading from this */ - PERL_BITFIELD8 arena : 1; /* Allocated from an arena */ - U32 arena_size; /* Size of arena to allocate */ -}; - -#define ALIGNED_TYPE_NAME(name) name##_aligned -#define ALIGNED_TYPE(name) \ - typedef union { \ - name align_me; \ - NV nv; \ - IV iv; \ - } ALIGNED_TYPE_NAME(name) - -ALIGNED_TYPE(regexp); -ALIGNED_TYPE(XPVGV); -ALIGNED_TYPE(XPVLV); -ALIGNED_TYPE(XPVAV); -ALIGNED_TYPE(XPVHV); -ALIGNED_TYPE(XPVHV_WITH_AUX); -ALIGNED_TYPE(XPVCV); -ALIGNED_TYPE(XPVFM); -ALIGNED_TYPE(XPVIO); - -#define HADNV FALSE -#define NONV TRUE - - -#ifdef PURIFY -/* With -DPURFIY we allocate everything directly, and don't use arenas. - This seems a rather elegant way to simplify some of the code below. */ -#define HASARENA FALSE -#else -#define HASARENA TRUE -#endif -#define NOARENA FALSE - -/* Size the arenas to exactly fit a given number of bodies. A count - of 0 fits the max number bodies into a PERL_ARENA_SIZE.block, - simplifying the default. If count > 0, the arena is sized to fit - only that many bodies, allowing arenas to be used for large, rare - bodies (XPVFM, XPVIO) without undue waste. The arena size is - limited by PERL_ARENA_SIZE, so we can safely oversize the - declarations. - */ -#define FIT_ARENA0(body_size) \ - ((size_t)(PERL_ARENA_SIZE / body_size) * body_size) -#define FIT_ARENAn(count,body_size) \ - ( count * body_size <= PERL_ARENA_SIZE) \ - ? count * body_size \ - : FIT_ARENA0 (body_size) -#define FIT_ARENA(count,body_size) \ - (U32)(count \ - ? FIT_ARENAn (count, body_size) \ - : FIT_ARENA0 (body_size)) - -/* Calculate the length to copy. Specifically work out the length less any - final padding the compiler needed to add. See the comment in sv_upgrade - for why copying the padding proved to be a bug. */ - -#define copy_length(type, last_member) \ - STRUCT_OFFSET(type, last_member) \ - + sizeof (((type*)SvANY((const SV *)0))->last_member) - -static const struct body_details bodies_by_type[] = { - /* HEs use this offset for their arena. */ - { 0, 0, 0, SVt_NULL, FALSE, NONV, NOARENA, 0 }, - - /* 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 */, 0 - }, - -#if NVSIZE <= IVSIZE - { 0, sizeof(NV), - STRUCT_OFFSET(XPVNV, xnv_u), - SVt_NV, FALSE, HADNV, NOARENA, 0 }, -#else - { sizeof(NV), sizeof(NV), - STRUCT_OFFSET(XPVNV, xnv_u), - SVt_NV, FALSE, HADNV, HASARENA, FIT_ARENA(0, sizeof(NV)) }, -#endif - - { sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur), - copy_length(XPV, xpv_len) - STRUCT_OFFSET(XPV, xpv_cur), - + STRUCT_OFFSET(XPV, xpv_cur), - SVt_PV, FALSE, NONV, HASARENA, - FIT_ARENA(0, sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur)) }, - - { sizeof(XINVLIST) - STRUCT_OFFSET(XPV, xpv_cur), - copy_length(XINVLIST, is_offset) - STRUCT_OFFSET(XPV, xpv_cur), - + STRUCT_OFFSET(XPV, xpv_cur), - SVt_INVLIST, TRUE, NONV, HASARENA, - FIT_ARENA(0, sizeof(XINVLIST) - STRUCT_OFFSET(XPV, xpv_cur)) }, - - { sizeof(XPVIV) - STRUCT_OFFSET(XPV, xpv_cur), - copy_length(XPVIV, xiv_u) - STRUCT_OFFSET(XPV, xpv_cur), - + STRUCT_OFFSET(XPV, xpv_cur), - SVt_PVIV, FALSE, NONV, HASARENA, - FIT_ARENA(0, sizeof(XPVIV) - STRUCT_OFFSET(XPV, xpv_cur)) }, - - { sizeof(XPVNV) - STRUCT_OFFSET(XPV, xpv_cur), - copy_length(XPVNV, xnv_u) - STRUCT_OFFSET(XPV, xpv_cur), - + STRUCT_OFFSET(XPV, xpv_cur), - SVt_PVNV, FALSE, HADNV, HASARENA, - FIT_ARENA(0, sizeof(XPVNV) - STRUCT_OFFSET(XPV, xpv_cur)) }, - - { sizeof(XPVMG), copy_length(XPVMG, xnv_u), 0, SVt_PVMG, FALSE, HADNV, - HASARENA, FIT_ARENA(0, sizeof(XPVMG)) }, - - { sizeof(ALIGNED_TYPE_NAME(regexp)), - sizeof(regexp), - 0, - SVt_REGEXP, TRUE, NONV, HASARENA, - FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(regexp))) - }, - - { sizeof(ALIGNED_TYPE_NAME(XPVGV)), sizeof(XPVGV), 0, SVt_PVGV, TRUE, HADNV, - HASARENA, FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVGV))) }, - - { sizeof(ALIGNED_TYPE_NAME(XPVLV)), sizeof(XPVLV), 0, SVt_PVLV, TRUE, HADNV, - HASARENA, FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVLV))) }, - - { sizeof(ALIGNED_TYPE_NAME(XPVAV)), - copy_length(XPVAV, xav_alloc), - 0, - SVt_PVAV, TRUE, NONV, HASARENA, - FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVAV))) }, - - { sizeof(ALIGNED_TYPE_NAME(XPVHV)), - copy_length(XPVHV, xhv_max), - 0, - SVt_PVHV, TRUE, NONV, HASARENA, - FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVHV))) }, - - { sizeof(ALIGNED_TYPE_NAME(XPVCV)), - sizeof(XPVCV), - 0, - SVt_PVCV, TRUE, NONV, HASARENA, - FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVCV))) }, - - { sizeof(ALIGNED_TYPE_NAME(XPVFM)), - sizeof(XPVFM), - 0, - SVt_PVFM, TRUE, NONV, NOARENA, - FIT_ARENA(20, sizeof(ALIGNED_TYPE_NAME(XPVFM))) }, - - { sizeof(ALIGNED_TYPE_NAME(XPVIO)), - sizeof(XPVIO), - 0, - SVt_PVIO, TRUE, NONV, HASARENA, - FIT_ARENA(24, sizeof(ALIGNED_TYPE_NAME(XPVIO))) }, -}; - -#define new_body_allocated(sv_type) \ - (void *)((char *)S_new_body(aTHX_ sv_type) \ - - bodies_by_type[sv_type].offset) - /* return a thing to the free list */ #define del_body(thing, root) \ @@ -1047,35 +800,6 @@ static const struct body_details bodies_by_type[] = { *root = (void*)thing_copy; \ } STMT_END -#ifdef PURIFY -#if !(NVSIZE <= IVSIZE) -# define new_XNV() safemalloc(sizeof(XPVNV)) -#endif -#define new_XPVNV() safemalloc(sizeof(XPVNV)) -#define new_XPVMG() safemalloc(sizeof(XPVMG)) - -#define del_body_by_type(p, type) safefree(p) - -#else /* !PURIFY */ - -#if !(NVSIZE <= IVSIZE) -# define new_XNV() new_body_allocated(SVt_NV) -#endif -#define new_XPVNV() new_body_allocated(SVt_PVNV) -#define new_XPVMG() new_body_allocated(SVt_PVMG) - -#define del_body_by_type(p, type) \ - del_body(p + bodies_by_type[(type)].offset, \ - &PL_body_roots[(type)]) - -#endif /* PURIFY */ - -/* no arena for you! */ - -#define new_NOARENA(details) \ - safemalloc((details)->body_size + (details)->offset) -#define new_NOARENAZ(details) \ - safecalloc((details)->body_size + (details)->offset, 1) void * Perl_more_bodies (pTHX_ const svtype sv_type, const size_t body_size, @@ -1165,40 +889,6 @@ Perl_more_bodies (pTHX_ const svtype sv_type, const size_t body_size, } } -#ifndef PURIFY - -/* grab a new thing from the arena's free list, allocating more if necessary. */ -#define new_body_from_arena(xpv, root_index, type_meta) \ - STMT_START { \ - void ** const r3wt = &PL_body_roots[root_index]; \ - xpv = (PTR_TBL_ENT_t*) (*((void **)(r3wt)) \ - ? *((void **)(r3wt)) : Perl_more_bodies(aTHX_ root_index, \ - type_meta.body_size,\ - type_meta.arena_size)); \ - *(r3wt) = *(void**)(xpv); \ - } STMT_END - -PERL_STATIC_INLINE void * -S_new_body(pTHX_ const svtype sv_type) -{ - void *xpv; - new_body_from_arena(xpv, sv_type, bodies_by_type[sv_type]); - return xpv; -} - -#endif - -static const struct body_details fake_rv = - { 0, 0, 0, SVt_IV, FALSE, NONV, NOARENA, 0 }; - -static const struct body_details fake_hv_with_aux = - /* The SVt_IV arena is used for (larger) PVHV bodies. */ - { sizeof(ALIGNED_TYPE_NAME(XPVHV_WITH_AUX)), - copy_length(XPVHV, xhv_max), - 0, - SVt_PVHV, TRUE, NONV, HASARENA, - FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVHV_WITH_AUX))) }; - /* =for apidoc sv_upgrade @@ -5868,9 +5558,10 @@ Perl_newSV(pTHX_ const STRLEN len) { SV *sv; - new_SV(sv); - if (len) { - sv_upgrade(sv, SVt_PV); + if (!len) + new_SV(sv); + else { + sv = newSV_type(SVt_PV); sv_grow_fresh(sv, len + 1); } return sv; @@ -8674,7 +8365,7 @@ Perl_sv_collxfrm_flags(pTHX_ SV *const sv, STRLEN *const nxp, const I32 flags) static char * S_sv_gets_append_to_utf8(pTHX_ SV *const sv, PerlIO *const fp, I32 append) { - SV * const tsv = newSV(0); + SV * const tsv = newSV_type(SVt_NULL); ENTER; SAVEFREESV(tsv); sv_gets(tsv, fp, 0); @@ -9681,8 +9372,7 @@ Perl_newSVpvn_flags(pTHX_ const char *const s, const STRLEN len, const U32 flags /* All the flags we don't support must be zero. And we're new code so I'm going to assert this from the start. */ assert(!(flags & ~(SVf_UTF8|SVs_TEMP))); - new_SV(sv); - sv_upgrade(sv, SVt_PV); + sv = newSV_type(SVt_PV); sv_setpvn_fresh(sv,s,len); /* This code used to do a sv_2mortal(), however we now unroll the call to @@ -9750,10 +9440,7 @@ to call C use C instead (calling C yourself). SV * Perl_newSVpv(pTHX_ const char *const s, const STRLEN len) { - SV *sv; - - new_SV(sv); - sv_upgrade(sv, SVt_PV); + SV *sv = newSV_type(SVt_PV); sv_setpvn_fresh(sv, s, len || s == NULL ? len : strlen(s)); return sv; } @@ -9774,9 +9461,7 @@ undefined. SV * Perl_newSVpvn(pTHX_ const char *const buffer, const STRLEN len) { - SV *sv; - new_SV(sv); - sv_upgrade(sv, SVt_PV); + SV *sv = newSV_type(SVt_PV); sv_setpvn_fresh(sv,buffer,len); return sv; } @@ -9830,10 +9515,8 @@ Perl_newSVhek(pTHX_ const HEK *const hek) { /* Inline most of newSVpvn_share(), because share_hek_hek() is far more efficient than sharepvn(). */ - SV *sv; + SV *sv = newSV_type(SVt_PV); - new_SV(sv); - sv_upgrade(sv, SVt_PV); SvPV_set(sv, (char *)HEK_KEY(share_hek_hek(hek))); SvCUR_set(sv, HEK_LEN(hek)); SvLEN_set(sv, 0); @@ -9878,10 +9561,9 @@ Perl_newSVpvn_share(pTHX_ const char *src, I32 len, U32 hash) } if (!hash) PERL_HASH(hash, src, len); - new_SV(sv); + sv = newSV_type(SVt_PV); /* The logic for this is inlined in S_mro_get_linear_isa_dfs(), so if it changes here, update it there too. */ - sv_upgrade(sv, SVt_PV); SvPV_set(sv, sharepvn(src, is_utf8?-len:len, hash)); SvCUR_set(sv, len); SvLEN_set(sv, 0); @@ -10070,27 +9752,6 @@ Perl_newSVuv(pTHX_ const UV u) return sv; } -/* -=for apidoc newSV_type - -Creates a new SV, of the type specified. The reference count for the new SV -is set to 1. - -=cut -*/ - -SV * -Perl_newSV_type(pTHX_ const svtype type) -{ - SV *sv; - - new_SV(sv); - ASSUME(SvTYPE(sv) == SVt_FIRST); - if(type != SVt_FIRST) - sv_upgrade(sv, type); - return sv; -} - /* =for apidoc newRV_noinc @@ -16651,7 +16312,7 @@ Perl_varname(pTHX_ const GV *const gv, const char gvtype, PADOFFSET targ, } if (subscript_type == FUV_SUBSCRIPT_HASH) { - SV * const sv = newSV(0); + SV * const sv = newSV_type(SVt_NULL); STRLEN len; const char * const pv = SvPV_nomg_const((SV*)keyname, len); diff --git a/sv.h b/sv.h index b426354d85c7..a16e25407b7c 100644 --- a/sv.h +++ b/sv.h @@ -176,6 +176,7 @@ typedef enum { /* The array of arena roots for SV bodies is indexed by SvTYPE. SVt_NULL doesn't * use a body, so that arena root is re-used for HEs. SVt_IV also doesn't, so * that arena root is used for HVs with struct xpvhv_aux. */ + #if defined(PERL_IN_HV_C) || defined(PERL_IN_XS_APITEST) # define HE_ARENA_ROOT_IX SVt_NULL #endif @@ -2581,7 +2582,6 @@ Evaluates C more than once. Sets C to 0 if C is false. /* The following two macros compute the necessary offsets for the above * trick and store them in SvANY for SvIV() (and friends) to use. */ -#ifdef PERL_CORE # define SET_SVANY_FOR_BODYLESS_IV(sv) \ SvANY(sv) = (XPVIV*)((char*)&(sv->sv_u.svu_iv) \ - STRUCT_OFFSET(XPVIV, xiv_iv)) @@ -2589,7 +2589,6 @@ Evaluates C more than once. Sets C to 0 if C is false. # define SET_SVANY_FOR_BODYLESS_NV(sv) \ SvANY(sv) = (XPVNV*)((char*)&(sv->sv_u.svu_nv) \ - STRUCT_OFFSET(XPVNV, xnv_u.xnv_nv)) -#endif /* * ex: set ts=8 sts=4 sw=4 et: diff --git a/sv_inline.h b/sv_inline.h new file mode 100644 index 000000000000..7288797d4181 --- /dev/null +++ b/sv_inline.h @@ -0,0 +1,532 @@ +/* sv_inline.h + * + * Copyright (C) 2022 by Larry Wall and others + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. + * + */ + +/* This file contains the newSV_type and newSV_type_mortal functions, as well as + * the various struct and macro definitions they require. In the main, these + * definitions were moved from sv.c, where many of them continue to also be used. + * (In Perl_more_bodies, Perl_sv_upgrade and Perl_sv_clear, for example.) Code + * comments associated with definitions and functions were also copied across + * verbatim. + * + * The rationale for having these as inline functions, rather than in sv.c, is + * that the target type is very often known at compile time, and therefore + * optimum code can be emitted by the compiler, rather than having all calls + * traverse the many branches of Perl_sv_upgrade at runtime. + */ + +/* This definition came from perl.h*/ + +/* The old value was hard coded at 1008. (4096-16) seems to be a bit faster, + at least on FreeBSD. YMMV, so experiment. */ +#ifndef PERL_ARENA_SIZE +#define PERL_ARENA_SIZE 4080 +#endif + +/* All other pre-existing definitions and functions that were moved into this + * file originally came from sv.c. */ + +#ifdef PERL_POISON +# define SvARENA_CHAIN(sv) ((sv)->sv_u.svu_rv) +# define SvARENA_CHAIN_SET(sv,val) (sv)->sv_u.svu_rv = MUTABLE_SV((val)) +/* Whilst I'd love to do this, it seems that things like to check on + unreferenced scalars +# define POISON_SV_HEAD(sv) PoisonNew(sv, 1, struct STRUCT_SV) +*/ +# define POISON_SV_HEAD(sv) PoisonNew(&SvANY(sv), 1, void *), \ + PoisonNew(&SvREFCNT(sv), 1, U32) +#else +# define SvARENA_CHAIN(sv) SvANY(sv) +# define SvARENA_CHAIN_SET(sv,val) SvANY(sv) = (void *)(val) +# define POISON_SV_HEAD(sv) +#endif + +#ifdef PERL_MEM_LOG +# define MEM_LOG_NEW_SV(sv, file, line, func) \ + Perl_mem_log_new_sv(sv, file, line, func) +# define MEM_LOG_DEL_SV(sv, file, line, func) \ + Perl_mem_log_del_sv(sv, file, line, func) +#else +# define MEM_LOG_NEW_SV(sv, file, line, func) NOOP +# define MEM_LOG_DEL_SV(sv, file, line, func) NOOP +#endif + +#define uproot_SV(p) \ + STMT_START { \ + (p) = PL_sv_root; \ + PL_sv_root = MUTABLE_SV(SvARENA_CHAIN(p)); \ + ++PL_sv_count; \ + } STMT_END + +/* Perl_more_sv lives in sv.c, we don't want to inline it. + * but the function declaration seems to be needed. */ +SV* Perl_more_sv(pTHX); + +/* new_SV(): return a new, empty SV head */ + +#ifdef DEBUG_LEAKING_SCALARS +/* provide a real function for a debugger to play with */ +STATIC SV* +S_new_SV(pTHX_ const char *file, int line, const char *func) +{ + SV* sv; + + if (PL_sv_root) + uproot_SV(sv); + else + sv = Perl_more_sv(aTHX); + SvANY(sv) = 0; + SvREFCNT(sv) = 1; + SvFLAGS(sv) = 0; + sv->sv_debug_optype = PL_op ? PL_op->op_type : 0; + sv->sv_debug_line = (U16) (PL_parser && PL_parser->copline != NOLINE + ? PL_parser->copline + : PL_curcop + ? CopLINE(PL_curcop) + : 0 + ); + sv->sv_debug_inpad = 0; + sv->sv_debug_parent = NULL; + sv->sv_debug_file = PL_curcop ? savesharedpv(CopFILE(PL_curcop)): NULL; + + sv->sv_debug_serial = PL_sv_serial++; + + MEM_LOG_NEW_SV(sv, file, line, func); + DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%" UVxf ": (%05ld) new_SV (from %s:%d [%s])\n", + PTR2UV(sv), (long)sv->sv_debug_serial, file, line, func)); + + return sv; +} +# define new_SV(p) (p)=S_new_SV(aTHX_ __FILE__, __LINE__, FUNCTION__) + +#else +# define new_SV(p) \ + STMT_START { \ + if (PL_sv_root) \ + uproot_SV(p); \ + else \ + (p) = Perl_more_sv(aTHX); \ + SvANY(p) = 0; \ + SvREFCNT(p) = 1; \ + SvFLAGS(p) = 0; \ + MEM_LOG_NEW_SV(p, __FILE__, __LINE__, FUNCTION__); \ + } STMT_END +#endif + + +typedef struct xpvhv_with_aux XPVHV_WITH_AUX; + +struct body_details { + U8 body_size; /* Size to allocate */ + U8 copy; /* Size of structure to copy (may be shorter) */ + U8 offset; /* Size of unalloced ghost fields to first alloced field*/ + PERL_BITFIELD8 type : 4; /* We have space for a sanity check. */ + PERL_BITFIELD8 cant_upgrade : 1;/* Cannot upgrade this type */ + PERL_BITFIELD8 zero_nv : 1; /* zero the NV when upgrading from this */ + PERL_BITFIELD8 arena : 1; /* Allocated from an arena */ + U32 arena_size; /* Size of arena to allocate */ +}; + +#define ALIGNED_TYPE_NAME(name) name##_aligned +#define ALIGNED_TYPE(name) \ + typedef union { \ + name align_me; \ + NV nv; \ + IV iv; \ + } ALIGNED_TYPE_NAME(name) + +ALIGNED_TYPE(regexp); +ALIGNED_TYPE(XPVGV); +ALIGNED_TYPE(XPVLV); +ALIGNED_TYPE(XPVAV); +ALIGNED_TYPE(XPVHV); +ALIGNED_TYPE(XPVHV_WITH_AUX); +ALIGNED_TYPE(XPVCV); +ALIGNED_TYPE(XPVFM); +ALIGNED_TYPE(XPVIO); + +#define HADNV FALSE +#define NONV TRUE + + +#ifdef PURIFY +/* With -DPURFIY we allocate everything directly, and don't use arenas. + This seems a rather elegant way to simplify some of the code below. */ +#define HASARENA FALSE +#else +#define HASARENA TRUE +#endif +#define NOARENA FALSE + +/* Size the arenas to exactly fit a given number of bodies. A count + of 0 fits the max number bodies into a PERL_ARENA_SIZE.block, + simplifying the default. If count > 0, the arena is sized to fit + only that many bodies, allowing arenas to be used for large, rare + bodies (XPVFM, XPVIO) without undue waste. The arena size is + limited by PERL_ARENA_SIZE, so we can safely oversize the + declarations. + */ +#define FIT_ARENA0(body_size) \ + ((size_t)(PERL_ARENA_SIZE / body_size) * body_size) +#define FIT_ARENAn(count,body_size) \ + ( count * body_size <= PERL_ARENA_SIZE) \ + ? count * body_size \ + : FIT_ARENA0 (body_size) +#define FIT_ARENA(count,body_size) \ + (U32)(count \ + ? FIT_ARENAn (count, body_size) \ + : FIT_ARENA0 (body_size)) + +/* Calculate the length to copy. Specifically work out the length less any + final padding the compiler needed to add. See the comment in sv_upgrade + for why copying the padding proved to be a bug. */ + +#define copy_length(type, last_member) \ + STRUCT_OFFSET(type, last_member) \ + + sizeof (((type*)SvANY((const SV *)0))->last_member) + +static const struct body_details bodies_by_type[] = { + /* HEs use this offset for their arena. */ + { 0, 0, 0, SVt_NULL, FALSE, NONV, NOARENA, 0 }, + + /* 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 */, 0 + }, + +#if NVSIZE <= IVSIZE + { 0, sizeof(NV), + STRUCT_OFFSET(XPVNV, xnv_u), + SVt_NV, FALSE, HADNV, NOARENA, 0 }, +#else + { sizeof(NV), sizeof(NV), + STRUCT_OFFSET(XPVNV, xnv_u), + SVt_NV, FALSE, HADNV, HASARENA, FIT_ARENA(0, sizeof(NV)) }, +#endif + + { sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur), + copy_length(XPV, xpv_len) - STRUCT_OFFSET(XPV, xpv_cur), + + STRUCT_OFFSET(XPV, xpv_cur), + SVt_PV, FALSE, NONV, HASARENA, + FIT_ARENA(0, sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur)) }, + + { sizeof(XINVLIST) - STRUCT_OFFSET(XPV, xpv_cur), + copy_length(XINVLIST, is_offset) - STRUCT_OFFSET(XPV, xpv_cur), + + STRUCT_OFFSET(XPV, xpv_cur), + SVt_INVLIST, TRUE, NONV, HASARENA, + FIT_ARENA(0, sizeof(XINVLIST) - STRUCT_OFFSET(XPV, xpv_cur)) }, + + { sizeof(XPVIV) - STRUCT_OFFSET(XPV, xpv_cur), + copy_length(XPVIV, xiv_u) - STRUCT_OFFSET(XPV, xpv_cur), + + STRUCT_OFFSET(XPV, xpv_cur), + SVt_PVIV, FALSE, NONV, HASARENA, + FIT_ARENA(0, sizeof(XPVIV) - STRUCT_OFFSET(XPV, xpv_cur)) }, + + { sizeof(XPVNV) - STRUCT_OFFSET(XPV, xpv_cur), + copy_length(XPVNV, xnv_u) - STRUCT_OFFSET(XPV, xpv_cur), + + STRUCT_OFFSET(XPV, xpv_cur), + SVt_PVNV, FALSE, HADNV, HASARENA, + FIT_ARENA(0, sizeof(XPVNV) - STRUCT_OFFSET(XPV, xpv_cur)) }, + + { sizeof(XPVMG), copy_length(XPVMG, xnv_u), 0, SVt_PVMG, FALSE, HADNV, + HASARENA, FIT_ARENA(0, sizeof(XPVMG)) }, + + { sizeof(ALIGNED_TYPE_NAME(regexp)), + sizeof(regexp), + 0, + SVt_REGEXP, TRUE, NONV, HASARENA, + FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(regexp))) + }, + + { sizeof(ALIGNED_TYPE_NAME(XPVGV)), sizeof(XPVGV), 0, SVt_PVGV, TRUE, HADNV, + HASARENA, FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVGV))) }, + + { sizeof(ALIGNED_TYPE_NAME(XPVLV)), sizeof(XPVLV), 0, SVt_PVLV, TRUE, HADNV, + HASARENA, FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVLV))) }, + + { sizeof(ALIGNED_TYPE_NAME(XPVAV)), + copy_length(XPVAV, xav_alloc), + 0, + SVt_PVAV, TRUE, NONV, HASARENA, + FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVAV))) }, + + { sizeof(ALIGNED_TYPE_NAME(XPVHV)), + copy_length(XPVHV, xhv_max), + 0, + SVt_PVHV, TRUE, NONV, HASARENA, + FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVHV))) }, + + { sizeof(ALIGNED_TYPE_NAME(XPVCV)), + sizeof(XPVCV), + 0, + SVt_PVCV, TRUE, NONV, HASARENA, + FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVCV))) }, + + { sizeof(ALIGNED_TYPE_NAME(XPVFM)), + sizeof(XPVFM), + 0, + SVt_PVFM, TRUE, NONV, NOARENA, + FIT_ARENA(20, sizeof(ALIGNED_TYPE_NAME(XPVFM))) }, + + { sizeof(ALIGNED_TYPE_NAME(XPVIO)), + sizeof(XPVIO), + 0, + SVt_PVIO, TRUE, NONV, HASARENA, + FIT_ARENA(24, sizeof(ALIGNED_TYPE_NAME(XPVIO))) }, +}; + +#define new_body_allocated(sv_type) \ + (void *)((char *)S_new_body(aTHX_ sv_type) \ + - bodies_by_type[sv_type].offset) + +#ifdef PURIFY +#if !(NVSIZE <= IVSIZE) +# define new_XNV() safemalloc(sizeof(XPVNV)) +#endif +#define new_XPVNV() safemalloc(sizeof(XPVNV)) +#define new_XPVMG() safemalloc(sizeof(XPVMG)) + +#define del_body_by_type(p, type) safefree(p) + +#else /* !PURIFY */ + +#if !(NVSIZE <= IVSIZE) +# define new_XNV() new_body_allocated(SVt_NV) +#endif +#define new_XPVNV() new_body_allocated(SVt_PVNV) +#define new_XPVMG() new_body_allocated(SVt_PVMG) + +#define del_body_by_type(p, type) \ + del_body(p + bodies_by_type[(type)].offset, \ + &PL_body_roots[(type)]) + +#endif /* PURIFY */ + +/* no arena for you! */ + +#define new_NOARENA(details) \ + safemalloc((details)->body_size + (details)->offset) +#define new_NOARENAZ(details) \ + safecalloc((details)->body_size + (details)->offset, 1) + +#ifndef PURIFY + +/* grab a new thing from the arena's free list, allocating more if necessary. */ +#define new_body_from_arena(xpv, root_index, type_meta) \ + STMT_START { \ + void ** const r3wt = &PL_body_roots[root_index]; \ + xpv = (PTR_TBL_ENT_t*) (*((void **)(r3wt)) \ + ? *((void **)(r3wt)) : Perl_more_bodies(aTHX_ root_index, \ + type_meta.body_size,\ + type_meta.arena_size)); \ + *(r3wt) = *(void**)(xpv); \ + } STMT_END + +PERL_STATIC_INLINE void * +S_new_body(pTHX_ const svtype sv_type) +{ + void *xpv; + new_body_from_arena(xpv, sv_type, bodies_by_type[sv_type]); + return xpv; +} + +#endif + +static const struct body_details fake_rv = + { 0, 0, 0, SVt_IV, FALSE, NONV, NOARENA, 0 }; + +static const struct body_details fake_hv_with_aux = + /* The SVt_IV arena is used for (larger) PVHV bodies. */ + { sizeof(ALIGNED_TYPE_NAME(XPVHV_WITH_AUX)), + copy_length(XPVHV, xhv_max), + 0, + SVt_PVHV, TRUE, NONV, HASARENA, + FIT_ARENA(0, sizeof(ALIGNED_TYPE_NAME(XPVHV_WITH_AUX))) }; + +/* +=for apidoc newSV_type + +Creates a new SV, of the type specified. The reference count for the new SV +is set to 1. + +=cut +*/ + +PERL_STATIC_INLINE SV * +Perl_newSV_type(pTHX_ const svtype type) +{ + SV *sv; + void* new_body; + const struct body_details *type_details; + + new_SV(sv); + + type_details = bodies_by_type + type; + + SvFLAGS(sv) &= ~SVTYPEMASK; + SvFLAGS(sv) |= type; + + switch (type) { + case SVt_NULL: + break; + case SVt_IV: + SET_SVANY_FOR_BODYLESS_IV(sv); + SvIV_set(sv, 0); + break; + case SVt_NV: +#if NVSIZE <= IVSIZE + SET_SVANY_FOR_BODYLESS_NV(sv); +#else + SvANY(sv) = new_XNV(); +#endif + SvNV_set(sv, 0); + break; + case SVt_PVHV: + case SVt_PVAV: + assert(type_details->body_size); + +#ifndef PURIFY + assert(type_details->arena); + assert(type_details->arena_size); + /* This points to the start of the allocated area. */ + new_body = S_new_body(aTHX_ type); + /* xpvav and xpvhv have no offset, so no need to adjust new_body */ + assert(!(type_details->offset)); +#else + /* We always allocated the full length item with PURIFY. To do this + we fake things so that arena is false for all 16 types.. */ + new_body = new_NOARENAZ(type_details); +#endif + SvANY(sv) = new_body; + + SvSTASH_set(sv, NULL); + SvMAGIC_set(sv, NULL); + + if (type == SVt_PVAV) { + AvFILLp(sv) = -1; + AvMAX(sv) = -1; + AvALLOC(sv) = NULL; + + AvREAL_only(sv); + } else { + HvTOTALKEYS(sv) = 0; + /* start with PERL_HASH_DEFAULT_HvMAX+1 buckets: */ + HvMAX(sv) = PERL_HASH_DEFAULT_HvMAX; + + assert(!SvOK(sv)); + SvOK_off(sv); +#ifndef NODEFAULT_SHAREKEYS + HvSHAREKEYS_on(sv); /* key-sharing on by default */ +#endif + /* start with PERL_HASH_DEFAULT_HvMAX+1 buckets: */ + HvMAX(sv) = PERL_HASH_DEFAULT_HvMAX; + } + + sv->sv_u.svu_array = NULL; /* or svu_hash */ + break; + + case SVt_PVIV: + case SVt_PVIO: + case SVt_PVGV: + case SVt_PVCV: + case SVt_PVLV: + case SVt_INVLIST: + case SVt_REGEXP: + case SVt_PVMG: + case SVt_PVNV: + case SVt_PV: + /* For a type known at compile time, it should be possible for the + * compiler to deduce the value of (type_details->arena), resolve + * that branch below, and inline the relevant values from + * bodies_by_type. Except, at least for gcc, it seems not to do that. + * We help it out here with two deviations from sv_upgrade: + * (1) Minor rearrangement here, so that PVFM - the only type at this + * point not to be allocated from an array appears last, not PV. + * (2) The ASSUME() statement here for everything that isn't PVFM. + * Obviously this all only holds as long as it's a true reflection of + * the bodies_by_type lookup table. */ +#ifndef PURIFY + ASSUME(type_details->arena); +#endif + /* FALLTHROUGH */ + case SVt_PVFM: + + assert(type_details->body_size); + /* We always allocated the full length item with PURIFY. To do this + we fake things so that arena is false for all 16 types.. */ +#ifndef PURIFY + if(type_details->arena) { + /* This points to the start of the allocated area. */ + new_body = S_new_body(aTHX_ type); + Zero(new_body, type_details->body_size, char); + new_body = ((char *)new_body) - type_details->offset; + } else +#endif + { + new_body = new_NOARENAZ(type_details); + } + SvANY(sv) = new_body; + + if (UNLIKELY(type == SVt_PVIO)) { + IO * const io = MUTABLE_IO(sv); + 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 */ + DEBUG_o(Perl_deb(aTHX_ "sv_upgrade clearing PL_stashcache\n")); + hv_clear(PL_stashcache); + + SvSTASH_set(io, MUTABLE_HV(SvREFCNT_inc(GvHV(iogv)))); + IoPAGE_LEN(sv) = 60; + } + + sv->sv_u.svu_rv = NULL; + break; + default: + Perl_croak(aTHX_ "panic: sv_upgrade to unknown type %lu", + (unsigned long)type); + } + + return sv; +} + +/* +=for apidoc newSV_type_mortal + +Creates a new mortal SV, of the type specified. The reference count for the +new SV is set to 1. + +This is equivalent to + SV* sv = sv_2mortal(newSV_type()) +and + SV* sv = sv_newmortal(); + sv_upgrade(sv, ) +but should be more efficient than both of them. (Unless sv_2mortal is inlined +at some point in the future.) + +=cut +*/ + +PERL_STATIC_INLINE SV * +Perl_newSV_type_mortal(pTHX_ const svtype type) +{ + SV *sv = newSV_type(type); + SSize_t ix = ++PL_tmps_ix; + if (UNLIKELY(ix >= PL_tmps_max)) + ix = Perl_tmps_grow_p(aTHX_ ix); + PL_tmps_stack[ix] = (sv); + SvTEMP_on(sv); + return sv; +} + +/* + * ex: set ts=8 sts=4 sw=4 et: + */ diff --git a/toke.c b/toke.c index 18e23e2c8577..c68a1b0ce118 100644 --- a/toke.c +++ b/toke.c @@ -2382,7 +2382,7 @@ S_force_strict_version(pTHX_ char *s) s++; if (is_STRICT_VERSION(s,&errstr)) { - SV *ver = newSV(0); + SV *ver = newSV_type(SVt_NULL); s = (char *)scan_version(s, ver, 0); version = newSVOP(OP_CONST, 0, ver); } diff --git a/universal.c b/universal.c index 955850431732..9c7be3199e68 100644 --- a/universal.c +++ b/universal.c @@ -304,12 +304,11 @@ Perl_sv_does_sv(pTHX_ SV *sv, SV *namesv, U32 flags) /* create a PV with value "isa", but with a special address * so that perl knows we're really doing "DOES" instead */ - methodname = newSV_type(SVt_PV); + methodname = newSV_type_mortal(SVt_PV); SvLEN_set(methodname, 0); SvCUR_set(methodname, strlen(PL_isa_DOES)); SvPVX(methodname) = (char *)PL_isa_DOES; /* discard 'const' qualifier */ SvPOK_on(methodname); - sv_2mortal(methodname); call_sv(methodname, G_SCALAR | G_METHOD); SPAGAIN; @@ -1126,7 +1125,7 @@ XS(XS_NamedCapture_TIEHASH) flag = SvTRUE(mark[1]) ? RXapif_ALL : RXapif_ONE; mark += 2; } - ST(0) = sv_2mortal(newSV_type(SVt_IV)); + ST(0) = newSV_type_mortal(SVt_IV); sv_setuv(newSVrv(ST(0), package), flag); } XSRETURN(1);