Skip to content

Commit 131b418

Browse files
committed
Perl_newSVhek - refactor to prioritize the overwhelming common case.
Existing comments highlighted the common case, confirmed by a _gcov_ build and run of the test harness. For that workload: * `(!hek)` is vanishingly rare * `(flags & HVhek_NOTSHARED)` isn't hit by core at all. * `(HEK_LEN(hek) == HEf_SVKEY)` was about 1% of calls. The function was refactored in light of the existing comments and that _gcov_ data. This also cut the number of resulting CPU instructions by about half on a normal gcc build.
1 parent 38bd8e8 commit 131b418

File tree

1 file changed

+34
-43
lines changed

1 file changed

+34
-43
lines changed

sv.c

Lines changed: 34 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10290,54 +10290,45 @@ SV if C<hek> is NULL.
1029010290
SV *
1029110291
Perl_newSVhek(pTHX_ const HEK *const hek)
1029210292
{
10293-
if (!hek) {
10294-
SV *sv;
10295-
10296-
new_SV(sv);
10297-
return sv;
10298-
}
10299-
10300-
if (HEK_LEN(hek) == HEf_SVKEY) {
10301-
return newSVsv(*(SV**)HEK_KEY(hek));
10302-
} else {
10303-
const int flags = HEK_FLAGS(hek);
10304-
if (flags & HVhek_WASUTF8) {
10305-
/* Trouble :-)
10306-
Andreas would like keys he put in as utf8 to come back as utf8
10307-
*/
10308-
STRLEN utf8_len = HEK_LEN(hek);
10309-
SV * const sv = newSV_type(SVt_PV);
10310-
char *as_utf8 = (char *)bytes_to_utf8 ((U8*)HEK_KEY(hek), &utf8_len);
10311-
/* bytes_to_utf8() allocates a new string, which we can repurpose: */
10312-
sv_usepvn_flags(sv, as_utf8, utf8_len, SV_HAS_TRAILING_NUL);
10313-
SvUTF8_on (sv);
10314-
return sv;
10315-
} else if (flags & HVhek_NOTSHARED) {
10316-
/* A hash that isn't using shared hash keys has to have
10317-
the flag in every key so that we know not to try to call
10318-
share_hek_hek on it. */
10293+
SV *sv = newSV_type(SVt_PV);
1031910294

10320-
SV * const sv = newSVpvn (HEK_KEY(hek), HEK_LEN(hek));
10321-
if (HEK_UTF8(hek))
10295+
if (LIKELY(hek)) {
10296+
if (HEK_LEN(hek) != HEf_SVKEY) {
10297+
const int flags = HEK_FLAGS(hek);
10298+
if (LIKELY(!(flags & (HVhek_WASUTF8|HVhek_NOTSHARED)))) {
10299+
/* This will be overwhelmingly the most common case. */
10300+
/* Inline most of newSVpvn_share(), because share_hek_hek() is far
10301+
more efficient than sharepvn(). */
10302+
SvFLAGS(sv) = SVt_PV | SVf_POK | SVp_POK | SVf_IsCOW |
10303+
(HEK_UTF8(hek) ? SVf_UTF8 : 0);
10304+
SvCUR_set(sv, HEK_LEN(hek));
10305+
SvPV_set(sv, (char *)HEK_KEY(share_hek_hek(hek)));
10306+
assert(SvLEN(sv) == 0); /* SVt_PV should be initialized with this value */
10307+
return sv;
10308+
} else if (flags & HVhek_WASUTF8) {
10309+
/* Trouble :-)
10310+
Andreas would like keys he put in as utf8 to come back as utf8
10311+
*/
10312+
STRLEN utf8_len = HEK_LEN(hek);
10313+
char *as_utf8 = (char *)bytes_to_utf8 ((U8*)HEK_KEY(hek), &utf8_len);
10314+
/* bytes_to_utf8() allocates a new string, which we can repurpose: */
10315+
sv_usepvn_flags(sv, as_utf8, utf8_len, SV_HAS_TRAILING_NUL);
1032210316
SvUTF8_on (sv);
10323-
return sv;
10324-
}
10325-
/* This will be overwhelmingly the most common case. */
10326-
{
10327-
/* Inline most of newSVpvn_share(), because share_hek_hek() is far
10328-
more efficient than sharepvn(). */
10329-
SV *sv = newSV_type(SVt_PV);
10330-
10331-
SvPV_set(sv, (char *)HEK_KEY(share_hek_hek(hek)));
10332-
SvCUR_set(sv, HEK_LEN(hek));
10333-
SvLEN_set(sv, 0);
10334-
SvIsCOW_on(sv);
10335-
SvPOK_on(sv);
10336-
if (HEK_UTF8(hek))
10337-
SvUTF8_on(sv);
10317+
return sv;
10318+
} else {
10319+
assert(flags & HVhek_NOTSHARED);
10320+
sv_setpvn_fresh(sv,HEK_KEY(hek),HEK_LEN(hek));
10321+
if (HEK_UTF8(hek))
10322+
SvUTF8_on (sv);
10323+
return sv;
10324+
}
10325+
} else {
10326+
/* (HEK_LEN(hek) == HEf_SVKEY) is comparatively more rare nowadays */
10327+
sv_setsv_flags(sv, *(SV**)HEK_KEY(hek), SV_GMAGIC|SV_NOSTEAL);
1033810328
return sv;
1033910329
}
1034010330
}
10331+
return sv;
1034110332
}
1034210333

1034310334
/*

0 commit comments

Comments
 (0)