diff options
author | David Mitchell <davem@iabyn.com> | 2016-09-19 12:35:13 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2016-10-04 11:18:40 +0100 |
commit | 692044df8403d4568b919fe9ad7e282e864ec85e (patch) | |
tree | cee2e122d90dc7fc942964679cfd808189e5c390 /pp.c | |
parent | 70027d69be2857dc45d5ff75021fc5f55d6295da (diff) | |
download | perl-692044df8403d4568b919fe9ad7e282e864ec85e.tar.gz |
Better optimise my/local @a = split()
There are currently two optimisations for when the results of a split
are assigned to an array.
For the first,
@array = split(...);
the aassign and padav/rv2av are optimised away, and pp_split() directly
assigns to the array attached to the split op (via op_pmtargetoff or
op_pmtargetgv).
For the second,
my @array = split(...);
local @array = split(...);
@{$expr} = split(...);
The aassign is optimised away, but the padav/rv2av is kept as an additional
arg to split. pp_split itself then uses the first arg popped off the stack
as the array (This was introduced by FC with v5.21.4-409-gef7999f).
This commit moves these two:
my @array = split(...);
local @array = split(...);
from the second case to the first case, by simply setting OPpLVAL_INTRO
on the OP_SPLIT, and making pp_split() do SAVECLEARSV() or save_ary()
as appropriate.
This makes my @a = split(...) a few percent faster.
Diffstat (limited to 'pp.c')
-rw-r--r-- | pp.c | 19 |
1 files changed, 14 insertions, 5 deletions
@@ -5708,8 +5708,8 @@ PP(pp_reverse) PP(pp_split) { dSP; dTARG; - AV *ary = ( (PL_op->op_private & OPpSPLIT_ASSIGN) - && (PL_op->op_flags & OPf_STACKED)) + AV *ary = ( (PL_op->op_private & OPpSPLIT_ASSIGN) /* @a = split */ + && (PL_op->op_flags & OPf_STACKED)) /* @{expr} = split */ ? (AV *)POPs : NULL; IV limit = POPi; /* note, negative is forever */ SV * const sv = POPs; @@ -5733,7 +5733,7 @@ PP(pp_split) I32 base; const U8 gimme = GIMME_V; bool gimme_scalar; - const I32 oldsave = PL_savestack_ix; + I32 oldsave = PL_savestack_ix; U32 make_mortal = SVs_TEMP; bool multiline = 0; MAGIC *mg = NULL; @@ -5743,10 +5743,14 @@ PP(pp_split) TAINT_IF(get_regex_charset(RX_EXTFLAGS(rx)) == REGEX_LOCALE_CHARSET && (RX_EXTFLAGS(rx) & (RXf_WHITE | RXf_SKIPWHITE))); + /* handle @ary = split(...) optimisation */ if (PL_op->op_private & OPpSPLIT_ASSIGN) { if (!(PL_op->op_flags & OPf_STACKED)) { - if (PL_op->op_private & OPpSPLIT_LEX) + if (PL_op->op_private & OPpSPLIT_LEX) { + if (PL_op->op_private & OPpLVAL_INTRO) + SAVECLEARSV(PAD_SVl(pm->op_pmreplrootu.op_pmtargetoff)); ary = (AV *)PAD_SVl(pm->op_pmreplrootu.op_pmtargetoff); + } else { GV *gv = #ifdef USE_ITHREADS @@ -5754,8 +5758,13 @@ PP(pp_split) #else pm->op_pmreplrootu.op_pmtargetgv; #endif - ary = GvAVn(gv); + if (PL_op->op_private & OPpLVAL_INTRO) + ary = save_ary(gv); + else + ary = GvAVn(gv); } + /* skip anything pushed by OPpLVAL_INTRO above */ + oldsave = PL_savestack_ix; } realarray = 1; |