Skip to content

Commit efda4d6

Browse files
committed
mro.xs add more SVPV HEK* opportunities
- newSVsv()/newSVsv_flags() will not propagate a SVPV HEK* COW for us b/c we are not PERL_CORE, so manually detect SVPV HEK* COWs and send them to newSVhek(), probably faster too than the forest of logic trees inside sv_setsv_flags(). GMG test is paranoia.
1 parent feedd06 commit efda4d6

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

ext/mro/mro.xs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ init_MY_CXT(pTHX_ pMY_CXT)
3131
SvREADONLY_on(MY_CXT.sv_ISA);
3232
}
3333

34+
static SV*
35+
S_mro_newSVsvhekok(pTHX_ SV* sv)
36+
{
37+
char * pv = SvPVX(sv);
38+
if ( ((SvFLAGS(sv) & (SVf_POK|SVs_GMG)) == SVf_POK)
39+
&& SvIsCOW_shared_hash(sv))
40+
return newSVhek(SvSHARED_HEK_FROM_PV(pv));
41+
else
42+
return newSVsv(sv);
43+
}
44+
#define mro_newSVsvhekok(_sv) S_mro_newSVsvhekok(aTHX_ _sv)
45+
3446
/*
3547
=for apidoc mro_get_linear_isa_c3
3648
@@ -113,7 +125,7 @@ S_mro_get_linear_isa_c3(pTHX_ HV* stash, U32 level)
113125
/* if no stash, make a temporary fake MRO
114126
containing just itself */
115127
AV* const isa_lin = newAV_alloc_xz(4);
116-
av_push_simple(isa_lin, newSVsv(isa_item));
128+
av_push_simple(isa_lin, mro_newSVsvhekok(isa_item));
117129
av_push_simple(seqs, MUTABLE_SV(isa_lin));
118130
}
119131
else {
@@ -142,16 +154,17 @@ S_mro_get_linear_isa_c3(pTHX_ HV* stash, U32 level)
142154
/* First entry is this class. We happen to make a shared
143155
hash key scalar because it's the cheapest and fastest
144156
way to do it. */
145-
*svp++ = newSVhek(stashhek);
157+
*svp++ = newSVhek(stashhek); /* Ex: Diamond_A */
146158

147159
while(subrv_items--) {
148160
/* These values are unlikely to be shared hash key
149161
scalars, so no point in adding code to optimising
150162
for a case that is unlikely to be true.
151163
(Or prove me wrong and do it.) */
152-
164+
/* Update: Example SVPV HEK*s seen on this line:
165+
MRO_A MRO_B Diamond_A */
153166
SV *const val = *subrv_p++;
154-
*svp++ = newSVsv(val);
167+
*svp++ = mro_newSVsvhekok(val);
155168
}
156169

157170
SvREFCNT_inc(retval);
@@ -226,7 +239,9 @@ S_mro_get_linear_isa_c3(pTHX_ HV* stash, U32 level)
226239
&& (val = HeVAL(tail_entry))
227240
&& (SvIVX(val) > 0))
228241
continue;
229-
winner = newSVsv(cand);
242+
/* Examples: SVPVHEK*s MRO_A HEK Diamond_B or a 0xd byte
243+
unprintable string. Rarely a NewXed buffer like "Test::O" */
244+
winner = mro_newSVsvhekok(cand);
230245
av_push_simple(retval, winner);
231246
/* note however that even when we find a winner,
232247
we continue looping over @seqs to do housekeeping */
@@ -374,7 +389,7 @@ mro_get_linear_isa(...)
374389
if(!class_stash) {
375390
/* No stash exists yet, give them just the classname */
376391
AV* isalin = newAV_alloc_xz(4);
377-
av_push_simple(isalin, newSVsv(classname));
392+
av_push_simple(isalin, mro_newSVsvhekok(classname));
378393
ST(0) = sv_2mortal(newRV_noinc(MUTABLE_SV(isalin)));
379394
XSRETURN(1);
380395
}

0 commit comments

Comments
 (0)