Skip to content

Commit 6f86b0e

Browse files
committed
Perl_newSV_type_mortal - new inline function introduced and used
There's no efficient way to create a mortal SV of any type other than SVt_NULL (via sv_newmortal). The options are either to do: * SV* sv = sv_newmortal; sv_upgrade(sv, SVt_SOMETYPE); but sv_upgrade is needlessly inefficient on new SVs. * SV* sv = sv_2mortal(newSV_type(SVt_SOMETYPE) but this will perform runtime checks to see if (sv) and if (SvIMMORTAL(sv), and for a new SV we know that those answers will always be yes and no. This commit adds a new inline function which is basically a mortalizing wrapper around the now-inlined newSV_type.
1 parent 562f242 commit 6f86b0e

File tree

16 files changed

+93
-48
lines changed

16 files changed

+93
-48
lines changed

av.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,7 @@ Perl_av_fetch(pTHX_ AV *av, SSize_t key, I32 lval)
267267
return NULL;
268268
}
269269

270-
sv = sv_newmortal();
271-
sv_upgrade(sv, SVt_PVLV);
270+
sv = newSV_type_mortal(SVt_PVLV);
272271
mg_copy(MUTABLE_SV(av), sv, 0, key);
273272
if (!tied_magic) /* for regdata, force leavesub to make copies */
274273
SvTEMP_off(sv);

doop.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,7 @@ Perl_do_kv(pTHX)
11761176

11771177
if (gimme == G_SCALAR) {
11781178
if (PL_op->op_flags & OPf_MOD || LVRET) { /* lvalue */
1179-
SV * const ret = sv_2mortal(newSV_type(SVt_PVLV)); /* Not TARG RT#67838 */
1179+
SV * const ret = newSV_type_mortal(SVt_PVLV); /* Not TARG RT#67838 */
11801180
sv_magic(ret, NULL, PERL_MAGIC_nkeys, NULL, 0);
11811181
LvTYPE(ret) = 'k';
11821182
LvTARG(ret) = SvREFCNT_inc_simple(keys);

embed.fnc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,7 @@ ApMbdR |SV* |newSVsv |NULLOK SV *const old
15201520
AmdR |SV* |newSVsv_nomg |NULLOK SV *const old
15211521
AdpR |SV* |newSVsv_flags |NULLOK SV *const old|I32 flags
15221522
ApdiR |SV* |newSV_type |const svtype type
1523+
ApdiR |SV* |newSV_type_mortal|const svtype type
15231524
ApdR |OP* |newUNOP |I32 type|I32 flags|NULLOK OP* first
15241525
ApdR |OP* |newUNOP_AUX |I32 type|I32 flags|NULLOK OP* first \
15251526
|NULLOK UNOP_AUX_item *aux

embed.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@
386386
#define newSVOP(a,b,c) Perl_newSVOP(aTHX_ a,b,c)
387387
#define newSVREF(a) Perl_newSVREF(aTHX_ a)
388388
#define newSV_type(a) Perl_newSV_type(aTHX_ a)
389+
#define newSV_type_mortal(a) Perl_newSV_type_mortal(aTHX_ a)
389390
#define newSVhek(a) Perl_newSVhek(aTHX_ a)
390391
#define newSViv(a) Perl_newSViv(aTHX_ a)
391392
#define newSVnv(a) Perl_newSVnv(aTHX_ a)

gv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3801,7 +3801,7 @@ Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags)
38013801
break;
38023802
case G_LIST:
38033803
if (flags & AMGf_want_list) {
3804-
res = sv_2mortal((SV *)newAV());
3804+
res = newSV_type_mortal(SVt_PVAV);
38053805
av_extend((AV *)res, nret);
38063806
while (nret--)
38073807
av_store((AV *)res, nret, POPs);

hv.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,12 +200,12 @@ static void
200200
S_hv_notallowed(pTHX_ int flags, const char *key, I32 klen,
201201
const char *msg)
202202
{
203-
SV * const sv = sv_newmortal();
203+
/* Straight to SVt_PVN here, as needed by sv_setpvn_fresh and
204+
* sv_usepvn would otherwise call it */
205+
SV * const sv = newSV_type_mortal(SVt_PV);
204206

205207
PERL_ARGS_ASSERT_HV_NOTALLOWED;
206208

207-
sv_upgrade(sv, SVt_PV); /* Needed by sv_setpvn_fresh and
208-
* sv_usepvn would otherwise call it */
209209
if (!(flags & HVhek_FREEKEY)) {
210210
sv_setpvn_fresh(sv, key, klen);
211211
}
@@ -968,6 +968,7 @@ SV *
968968
Perl_hv_scalar(pTHX_ HV *hv)
969969
{
970970
SV *sv;
971+
UV u;
971972

972973
PERL_ARGS_ASSERT_HV_SCALAR;
973974

@@ -977,8 +978,21 @@ Perl_hv_scalar(pTHX_ HV *hv)
977978
return magic_scalarpack(hv, mg);
978979
}
979980

980-
sv = sv_newmortal();
981-
sv_setuv(sv, HvUSEDKEYS(hv));
981+
sv = newSV_type_mortal(SVt_IV);
982+
983+
/* Inlined sv_setuv(sv, HvUSEDKEYS(hv)) follows:*/
984+
u = HvUSEDKEYS(hv);
985+
986+
if (u <= (UV)IV_MAX) {
987+
SvIV_set(sv, (IV)u);
988+
(void)SvIOK_only(sv);
989+
SvTAINT(sv);
990+
} else {
991+
SvIV_set(sv, 0);
992+
SvUV_set(sv, u);
993+
(void)SvIOK_only_UV(sv);
994+
SvTAINT(sv);
995+
}
982996

983997
return sv;
984998
}

mg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ Perl_sv_string_from_errnum(pTHX_ int errnum, SV *tgtsv)
877877
{
878878
char const *errstr;
879879
if(!tgtsv)
880-
tgtsv = sv_newmortal();
880+
tgtsv = newSV_type_mortal(SVt_PV);
881881
errstr = my_strerror(errnum);
882882
if(errstr) {
883883
sv_setpv(tgtsv, errstr);

mro_core.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ S_mro_get_linear_isa_dfs(pTHX_ HV *stash, U32 level)
255255

256256
/* not in cache, make a new one */
257257

258-
retval = MUTABLE_AV(sv_2mortal(MUTABLE_SV(newAV())));
258+
retval = MUTABLE_AV(newSV_type_mortal(SVt_PVAV));
259259
/* We use this later in this function, but don't need a reference to it
260260
beyond the end of this function, so reference count is fine. */
261261
our_name = newSVhek(stashhek);
@@ -347,7 +347,7 @@ S_mro_get_linear_isa_dfs(pTHX_ HV *stash, U32 level)
347347
} else {
348348
/* They have no stash. So create ourselves an ->isa cache
349349
as if we'd copied it from what theirs should be. */
350-
stored = MUTABLE_HV(sv_2mortal(MUTABLE_SV(newHV())));
350+
stored = MUTABLE_HV(newSV_type_mortal(SVt_PVHV));
351351
(void) hv_stores(stored, "UNIVERSAL", &PL_sv_undef);
352352
av_push(retval,
353353
newSVhek(HeKEY_hek(hv_store_ent(stored, sv,
@@ -357,7 +357,7 @@ S_mro_get_linear_isa_dfs(pTHX_ HV *stash, U32 level)
357357
}
358358
} else {
359359
/* We have no parents. */
360-
stored = MUTABLE_HV(sv_2mortal(MUTABLE_SV(newHV())));
360+
stored = MUTABLE_HV(newSV_type_mortal(SVt_PVHV));
361361
(void) hv_stores(stored, "UNIVERSAL", &PL_sv_undef);
362362
}
363363

@@ -428,7 +428,7 @@ Perl_mro_get_linear_isa(pTHX_ HV *stash)
428428
SV **svp;
429429
SV **ovp = AvARRAY(old);
430430
SV * const * const oend = ovp + AvFILLp(old) + 1;
431-
isa = (AV *)sv_2mortal((SV *)newAV());
431+
isa = (AV *)newSV_type_mortal(SVt_PVAV);
432432
av_extend(isa, AvFILLp(isa) = AvFILLp(old)+1);
433433
*AvARRAY(isa) = namesv;
434434
svp = AvARRAY(isa)+1;
@@ -570,7 +570,7 @@ Perl_mro_isa_changed_in(pTHX_ HV* stash)
570570
if(hv_iterinit(isarev)) {
571571
/* Only create the hash if we need it; i.e., if isarev has
572572
any elements. */
573-
isa_hashes = (HV *)sv_2mortal((SV *)newHV());
573+
isa_hashes = (HV *)newSV_type_mortal(SVt_PVHV);
574574
}
575575
while((iter = hv_iternext(isarev))) {
576576
HV* revstash = gv_stashsv(hv_iterkeysv(iter), 0);
@@ -817,7 +817,7 @@ Perl_mro_package_moved(pTHX_ HV * const stash, HV * const oldstash,
817817
}
818818
else {
819819
SV *aname;
820-
namesv = sv_2mortal((SV *)newAV());
820+
namesv = newSV_type_mortal(SVt_PVAV);
821821
while (name_count--) {
822822
if(memEQs(HEK_KEY(*namep), HEK_LEN(*namep), "main")){
823823
aname = GvNAMELEN(gv) == 1
@@ -854,9 +854,9 @@ Perl_mro_package_moved(pTHX_ HV * const stash, HV * const oldstash,
854854
wrong name. The names must be set on *all* affected stashes before
855855
we do anything else. (And linearisations must be cleared, too.)
856856
*/
857-
stashes = (HV *) sv_2mortal((SV *)newHV());
857+
stashes = (HV *) newSV_type_mortal(SVt_PVHV);
858858
mro_gather_and_rename(
859-
stashes, (HV *) sv_2mortal((SV *)newHV()),
859+
stashes, (HV *) newSV_type_mortal(SVt_PVHV),
860860
stash, oldstash, namesv
861861
);
862862

@@ -1119,7 +1119,7 @@ S_mro_gather_and_rename(pTHX_ HV * const stashes, HV * const seen_stashes,
11191119
/* Skip the entire loop if the hash is empty. */
11201120
if(oldstash && HvTOTALKEYS(oldstash)) {
11211121
xhv = (XPVHV*)SvANY(oldstash);
1122-
seen = (HV *) sv_2mortal((SV *)newHV());
1122+
seen = (HV *) newSV_type_mortal(SVt_PVHV);
11231123

11241124
/* Iterate through entries in the oldstash, adding them to the
11251125
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,
11641164
SV *aname;
11651165
items = AvFILLp((AV *)namesv) + 1;
11661166
svp = AvARRAY((AV *)namesv);
1167-
subname = sv_2mortal((SV *)newAV());
1167+
subname = newSV_type_mortal(SVt_PVAV);
11681168
while (items--) {
11691169
aname = newSVsv(*svp++);
11701170
if (len == 1)
@@ -1247,7 +1247,7 @@ S_mro_gather_and_rename(pTHX_ HV * const stashes, HV * const seen_stashes,
12471247
SV *aname;
12481248
items = AvFILLp((AV *)namesv) + 1;
12491249
svp = AvARRAY((AV *)namesv);
1250-
subname = sv_2mortal((SV *)newAV());
1250+
subname = newSV_type_mortal(SVt_PVAV);
12511251
while (items--) {
12521252
aname = newSVsv(*svp++);
12531253
if (len == 1)

pad.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,13 +1252,13 @@ S_pad_findlex(pTHX_ const char *namepv, STRLEN namelen, U32 flags, const CV* cv,
12521252
}
12531253
if (!*out_capture) {
12541254
if (namelen != 0 && *namepv == '@')
1255-
*out_capture = sv_2mortal(MUTABLE_SV(newAV()));
1255+
*out_capture = newSV_type_mortal(SVt_PVAV);
12561256
else if (namelen != 0 && *namepv == '%')
1257-
*out_capture = sv_2mortal(MUTABLE_SV(newHV()));
1257+
*out_capture = newSV_type_mortal(SVt_PVHV);
12581258
else if (namelen != 0 && *namepv == '&')
1259-
*out_capture = sv_2mortal(newSV_type(SVt_PVCV));
1259+
*out_capture = newSV_type_mortal(SVt_PVCV);
12601260
else
1261-
*out_capture = sv_newmortal();
1261+
*out_capture = newSV_type_mortal(SVt_NULL);
12621262
}
12631263
}
12641264

@@ -2063,7 +2063,7 @@ S_cv_clone_pad(pTHX_ CV *proto, CV *cv, CV *outside, HV *cloned,
20632063
*/
20642064
bool cloned_in_this_pass;
20652065
if (!cloned)
2066-
cloned = (HV *)sv_2mortal((SV *)newHV());
2066+
cloned = (HV *)newSV_type_mortal(SVt_PVHV);
20672067
do {
20682068
cloned_in_this_pass = FALSE;
20692069
for (ix = fpad; ix > 0; ix--) {

pp.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ PP(pp_pos)
313313
dSP; dTOPss;
314314

315315
if (PL_op->op_flags & OPf_MOD || LVRET) {
316-
SV * const ret = sv_2mortal(newSV_type(SVt_PVLV));/* Not TARG RT#67838 */
316+
SV * const ret = newSV_type_mortal(SVt_PVLV);/* Not TARG RT#67838 */
317317
sv_magic(ret, NULL, PERL_MAGIC_pos, NULL, 0);
318318
LvTYPE(ret) = '.';
319319
LvTARG(ret) = SvREFCNT_inc_simple(sv);
@@ -467,7 +467,7 @@ S_refto(pTHX_ SV *sv)
467467
SvTEMP_off(sv);
468468
SvREFCNT_inc_void_NN(sv);
469469
}
470-
rv = sv_newmortal();
470+
rv = newSV_type_mortal(SVt_IV);
471471
sv_setrv_noinc(rv, sv);
472472
return rv;
473473
}
@@ -3300,7 +3300,7 @@ PP(pp_substr)
33003300
}
33013301
if (lvalue && !repl_sv) {
33023302
SV * ret;
3303-
ret = sv_2mortal(newSV_type(SVt_PVLV)); /* Not TARG RT#67838 */
3303+
ret = newSV_type_mortal(SVt_PVLV); /* Not TARG RT#67838 */
33043304
sv_magic(ret, NULL, PERL_MAGIC_substr, NULL, 0);
33053305
LvTYPE(ret) = 'x';
33063306
LvTARG(ret) = SvREFCNT_inc_simple(sv);
@@ -3432,7 +3432,7 @@ PP(pp_vec)
34323432
retuv = errflags ? 0 : do_vecget(src, offset, size);
34333433

34343434
if (lvalue) { /* it's an lvalue! */
3435-
ret = sv_2mortal(newSV_type(SVt_PVLV)); /* Not TARG RT#67838 */
3435+
ret = newSV_type_mortal(SVt_PVLV); /* Not TARG RT#67838 */
34363436
sv_magic(ret, NULL, PERL_MAGIC_vec, NULL, 0);
34373437
LvTYPE(ret) = 'v';
34383438
LvTARG(ret) = SvREFCNT_inc_simple(src);
@@ -6830,7 +6830,7 @@ PP(pp_refassign)
68306830
PP(pp_lvref)
68316831
{
68326832
dSP;
6833-
SV * const ret = sv_2mortal(newSV_type(SVt_PVMG));
6833+
SV * const ret = newSV_type_mortal(SVt_PVMG);
68346834
SV * const elem = PL_op->op_private & OPpLVREF_ELEM ? POPs : NULL;
68356835
SV * const arg = PL_op->op_flags & OPf_STACKED ? POPs : NULL;
68366836
MAGIC * const mg = sv_magicext(ret, arg, PERL_MAGIC_lvref,
@@ -6898,7 +6898,7 @@ PP(pp_lvrefslice)
68986898
else
68996899
S_localise_helem_lval(aTHX_ (HV *)av, elemsv, can_preserve);
69006900
}
6901-
*MARK = sv_2mortal(newSV_type(SVt_PVMG));
6901+
*MARK = newSV_type_mortal(SVt_PVMG);
69026902
sv_magic(*MARK,(SV *)av,PERL_MAGIC_lvref,(char *)elemsv,HEf_SVKEY);
69036903
}
69046904
RETURN;

pp_ctl.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5169,12 +5169,10 @@ S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other, const bool copied)
51695169
const Size_t other_len = av_count(other_av);
51705170

51715171
if (NULL == seen_this) {
5172-
seen_this = newHV();
5173-
(void) sv_2mortal(MUTABLE_SV(seen_this));
5172+
seen_this = (HV*)newSV_type_mortal(SVt_PVHV);
51745173
}
51755174
if (NULL == seen_other) {
5176-
seen_other = newHV();
5177-
(void) sv_2mortal(MUTABLE_SV(seen_other));
5175+
seen_other = (HV*)newSV_type_mortal(SVt_PVHV);
51785176
}
51795177
for(i = 0; i < other_len; ++i) {
51805178
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)
58825880
don't want to pass it in a second time.
58835881
I'm going to use a mortal in case the upstream filter croaks. */
58845882
upstream = ((SvOK(buf_sv) && sv_len(buf_sv)) || SvGMAGICAL(buf_sv))
5885-
? sv_newmortal() : buf_sv;
5883+
? newSV_type_mortal(SVt_PV) : buf_sv;
58865884
SvUPGRADE(upstream, SVt_PV);
58875885

58885886
if (filter_has_file) {

pp_hot.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -991,7 +991,7 @@ PP(pp_multiconcat)
991991
)
992992
)
993993
{
994-
SV *tmp = sv_newmortal();
994+
SV *tmp = newSV_type_mortal(SVt_PV);
995995
sv_copypv(tmp, left);
996996
SvSETMAGIC(tmp);
997997
left = tmp;
@@ -2868,7 +2868,7 @@ PP(pp_qr)
28682868
REGEXP * rx = PM_GETRE(pm);
28692869
regexp *prog = ReANY(rx);
28702870
SV * const pkg = RXp_ENGINE(prog)->qr_package(aTHX_ (rx));
2871-
SV * const rv = sv_newmortal();
2871+
SV * const rv = newSV_type_mortal(SVt_IV);
28722872
CV **cvp;
28732873
CV *cv;
28742874

@@ -3406,8 +3406,7 @@ PP(pp_helem)
34063406
if (!defer) {
34073407
DIE(aTHX_ PL_no_helem_sv, SVfARG(keysv));
34083408
}
3409-
lv = sv_newmortal();
3410-
sv_upgrade(lv, SVt_PVLV);
3409+
lv = newSV_type_mortal(SVt_PVLV);
34113410
LvTYPE(lv) = 'y';
34123411
sv_magic(lv, key2 = newSVsv(keysv), PERL_MAGIC_defelem, NULL, 0);
34133412
SvREFCNT_dec_NN(key2); /* sv_magic() increments refcount */
@@ -3846,8 +3845,7 @@ PP(pp_multideref)
38463845
SV* key2;
38473846
if (!defer)
38483847
DIE(aTHX_ PL_no_helem_sv, SVfARG(keysv));
3849-
lv = sv_newmortal();
3850-
sv_upgrade(lv, SVt_PVLV);
3848+
lv = newSV_type_mortal(SVt_PVLV);
38513849
LvTYPE(lv) = 'y';
38523850
sv_magic(lv, key2 = newSVsv(keysv),
38533851
PERL_MAGIC_defelem, NULL, 0);

proto.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,6 +2488,12 @@ PERL_STATIC_INLINE SV* Perl_newSV_type(pTHX_ const svtype type)
24882488
#define PERL_ARGS_ASSERT_NEWSV_TYPE
24892489
#endif
24902490

2491+
#ifndef PERL_NO_INLINE_FUNCTIONS
2492+
PERL_STATIC_INLINE SV* Perl_newSV_type_mortal(pTHX_ const svtype type)
2493+
__attribute__warn_unused_result__;
2494+
#define PERL_ARGS_ASSERT_NEWSV_TYPE_MORTAL
2495+
#endif
2496+
24912497
PERL_CALLCONV SV* Perl_newSVavdefelem(pTHX_ AV *av, SSize_t ix, bool extendible)
24922498
__attribute__warn_unused_result__;
24932499
#define PERL_ARGS_ASSERT_NEWSVAVDEFELEM \

regcomp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16673,8 +16673,8 @@ S_handle_regex_sets(pTHX_ RExC_state_t *pRExC_state, SV** return_invlist,
1667316673
* so that everything gets evaluated down to a single operand, which is the
1667416674
* result */
1667516675

16676-
sv_2mortal((SV *)(stack = newAV()));
16677-
sv_2mortal((SV *)(fence_stack = newAV()));
16676+
stack = (AV*)newSV_type_mortal(SVt_PVAV);
16677+
fence_stack = (AV*)newSV_type_mortal(SVt_PVAV);
1667816678

1667916679
while (RExC_parse < RExC_end) {
1668016680
I32 top_index; /* Index of top-most element in 'stack' */

sv_inline.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,35 @@ Perl_newSV_type(pTHX_ const svtype type)
491491
return sv;
492492
}
493493

494+
/*
495+
=for apidoc newSV_type_mortal
496+
497+
Creates a new mortal SV, of the type specified. The reference count for the
498+
new SV is set to 1.
499+
500+
This is equivalent to
501+
SV* sv = sv_2mortal(newSV_type(<some type>))
502+
and
503+
SV* sv = sv_newmortal();
504+
sv_upgrade(sv, <some_type>)
505+
but should be more efficient than both of them. (Unless sv_2mortal is inlined
506+
at some point in the future.)
507+
508+
=cut
509+
*/
510+
511+
PERL_STATIC_INLINE SV *
512+
Perl_newSV_type_mortal(pTHX_ const svtype type)
513+
{
514+
SV *sv = newSV_type(type);
515+
SSize_t ix = ++PL_tmps_ix;
516+
if (UNLIKELY(ix >= PL_tmps_max))
517+
ix = Perl_tmps_grow_p(aTHX_ ix);
518+
PL_tmps_stack[ix] = (sv);
519+
SvTEMP_on(sv);
520+
return sv;
521+
}
522+
494523
/*
495524
* ex: set ts=8 sts=4 sw=4 et:
496525
*/

0 commit comments

Comments
 (0)