Skip to content

Commit c6dfb67

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 fdc661e commit c6dfb67

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
@@ -110,7 +122,7 @@ S_mro_get_linear_isa_c3(pTHX_ HV* stash, U32 level)
110122
/* if no stash, make a temporary fake MRO
111123
containing just itself */
112124
AV* const isa_lin = newAV_alloc_xz(4);
113-
av_push_simple(isa_lin, newSVsv(isa_item));
125+
av_push_simple(isa_lin, mro_newSVsvhekok(isa_item));
114126
av_push_simple(seqs, MUTABLE_SV(isa_lin));
115127
}
116128
else {
@@ -139,16 +151,17 @@ S_mro_get_linear_isa_c3(pTHX_ HV* stash, U32 level)
139151
/* First entry is this class. We happen to make a shared
140152
hash key scalar because it's the cheapest and fastest
141153
way to do it. */
142-
*svp++ = newSVhek(stashhek);
154+
*svp++ = newSVhek(stashhek); /* Ex: Diamond_A */
143155

144156
while(subrv_items--) {
145157
/* These values are unlikely to be shared hash key
146158
scalars, so no point in adding code to optimising
147159
for a case that is unlikely to be true.
148160
(Or prove me wrong and do it.) */
149-
161+
/* Update: Example SVPV HEK*s seen on this line:
162+
MRO_A MRO_B Diamond_A */
150163
SV *const val = *subrv_p++;
151-
*svp++ = newSVsv(val);
164+
*svp++ = mro_newSVsvhekok(val);
152165
}
153166

154167
SvREFCNT_inc(retval);
@@ -223,7 +236,9 @@ S_mro_get_linear_isa_c3(pTHX_ HV* stash, U32 level)
223236
&& (val = HeVAL(tail_entry))
224237
&& (SvIVX(val) > 0))
225238
continue;
226-
winner = newSVsv(cand);
239+
/* Examples: SVPVHEK*s MRO_A HEK Diamond_B or a 0xd byte
240+
unprintable string. Rarely a NewXed buffer like "Test::O" */
241+
winner = mro_newSVsvhekok(cand);
227242
av_push_simple(retval, winner);
228243
/* note however that even when we find a winner,
229244
we continue looping over @seqs to do housekeeping */
@@ -371,7 +386,7 @@ mro_get_linear_isa(...)
371386
if(!class_stash) {
372387
/* No stash exists yet, give them just the classname */
373388
AV* isalin = newAV_alloc_xz(4);
374-
av_push_simple(isalin, newSVsv(classname));
389+
av_push_simple(isalin, mro_newSVsvhekok(classname));
375390
ST(0) = sv_2mortal(newRV_noinc(MUTABLE_SV(isalin)));
376391
XSRETURN(1);
377392
}

0 commit comments

Comments
 (0)