summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2016-09-19 12:35:13 +0100
committerDavid Mitchell <davem@iabyn.com>2016-10-04 11:18:40 +0100
commit692044df8403d4568b919fe9ad7e282e864ec85e (patch)
treecee2e122d90dc7fc942964679cfd808189e5c390 /pp.c
parent70027d69be2857dc45d5ff75021fc5f55d6295da (diff)
downloadperl-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.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/pp.c b/pp.c
index eab970d3cc..00a577e278 100644
--- a/pp.c
+++ b/pp.c
@@ -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;