diff options
author | Daniel Dragan <bulk88@hotmail.com> | 2014-09-23 18:19:32 -0400 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2014-09-23 18:15:20 -0700 |
commit | 7776003ecba252f04a5359ee75d84770ad318f9a (patch) | |
tree | 9f2a41d3b2de4e7af3c02dc05192f01a6a671d92 | |
parent | 0c7df90239f4c313f42964755700c2a3c78ec63c (diff) | |
download | perl-7776003ecba252f04a5359ee75d84770ad318f9a.tar.gz |
optimize pp_length for simple PVs
Previously in pp_length, for non-magic, non-utf8 PVs, a number of
conditional branches based on bitfield testing had to execute, and finally
the length of a non-utf8 SVPV was fetched with sv_len_utf8_nomg.
sv_len_utf8_nomg checks SvUTF8, and if false, use the len from
SvPV_nomg_const call in sv_len_utf8_nomg. Note in pp_length,
SvPV_nomg_const already exists for the "use bytes" branch.
After this patch, a !SvGMAGICAL && (!SvUTF8 || use_bytes) SV will take
only 1 conditional branch and no func calls before reaching sv_setiv.
svflags is reused for the mg_get test since partially masked svflags will
already be in a register vs fetching the whole flags from SV head again.
SETS(TARG) was factored out from all the SETI/SETTARG macros. If targ is
not set/written to (the PL_sv_undef branch), do not check/call for
set magic on it, just return from the opcode. Also a putback was removed
since the operand SV is replaced inplace on Perl stack with a SV with IV
length in it.
For profiling info, profiling stats, and rejected implementations see
[perl #122835]
-rw-r--r-- | pod/perldelta.pod | 3 | ||||
-rw-r--r-- | pp.c | 39 |
2 files changed, 32 insertions, 10 deletions
diff --git a/pod/perldelta.pod b/pod/perldelta.pod index 608c1df506..65c495aa0e 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -104,7 +104,8 @@ There may well be none in a stable release. =item * -XXX +C<length> is upto 20% faster for non-magical/non-tied containing a string and +either non-utf8 or C<use bytes;> scalars. =back @@ -2956,24 +2956,45 @@ PP(pp_length) dSP; dTARGET; SV * const sv = TOPs; - SvGETMAGIC(sv); + U32 in_bytes = IN_BYTES; + /* simplest case shortcut */ + /* turn off SVf_UTF8 in tmp flags if HINT_BYTES on*/ + U32 svflags = (SvFLAGS(sv) ^ (in_bytes << 26)) & (SVf_POK|SVs_GMG|SVf_UTF8); + assert(HINT_BYTES == 0x00000008 && SVf_UTF8 == 0x20000000 && (SVf_UTF8 == HINT_BYTES << 26)); + SETs(TARG); + + if(LIKELY(svflags == SVf_POK)) + goto simple_pv; + if(svflags & SVs_GMG) + mg_get(sv); if (SvOK(sv)) { - if (!IN_BYTES) - SETi(sv_len_utf8_nomg(sv)); + if (!IN_BYTES) /* reread to avoid using an C auto/register */ + sv_setiv(TARG, (IV)sv_len_utf8_nomg(sv)); else { STRLEN len; - (void)SvPV_nomg_const(sv,len); - SETi(len); + /* unrolled SvPV_nomg_const(sv,len) */ + if(SvPOK_nog(sv)){ + simple_pv: + len = SvCUR(sv); + } else { + (void)sv_2pv_flags(sv, &len, 0|SV_CONST_RETURN); + } + sv_setiv(TARG, (IV)(len)); } } else { if (!SvPADTMP(TARG)) { sv_setsv_nomg(TARG, &PL_sv_undef); - SETTARG; - } - SETs(&PL_sv_undef); + } else { /* TARG is on stack at this point and is overwriten by SETs. + This branch is the odd one out, so put TARG by default on + stack earlier to let local SP go out of liveness sooner */ + SETs(&PL_sv_undef); + goto no_set_magic; + } } - RETURN; + SvSETMAGIC(TARG); + no_set_magic: + return NORMAL; /* no putback, SP didn't move in this opcode */ } /* Returns false if substring is completely outside original string. |