diff options
author | David Mitchell <davem@iabyn.com> | 2016-09-19 15:39:34 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2016-10-04 11:18:40 +0100 |
commit | 47a8f19b6f8f837245506422e5a4d36804e7b56a (patch) | |
tree | 440117f4ea662c607be9195091a01ad97032efe8 /op.c | |
parent | 692044df8403d4568b919fe9ad7e282e864ec85e (diff) | |
download | perl-47a8f19b6f8f837245506422e5a4d36804e7b56a.tar.gz |
fix common assign issue on @a = (split(), 1)
RT #127999 Slowdown in split + list assign
The compile-time common-value detection mechanism for OP_ASSIGN
was getting OP_SPLIT wrong.
It was assuming that OP_SPLIT was always dangerous. In fact,
OP_SPLIT is usually completely safe, not passing though any of its
arguments, except where the assign in (@a = split()) has been optimised
away and the array attached directly to the OP_SPLIT op, or the ops that
produce the array have been appended as an extra child of the OP_SPLIT op
(OPf_STACKED).
Diffstat (limited to 'op.c')
-rw-r--r-- | op.c | 33 |
1 files changed, 25 insertions, 8 deletions
@@ -12520,6 +12520,7 @@ S_aassign_scan(pTHX_ OP* o, bool rhs, bool top, int *scalars_p) case OP_PADAV: case OP_PADHV: (*scalars_p) += 2; + /* if !top, could be e.g. @a[0,1] */ if (top && (o->op_flags & OPf_REF)) return (o->op_private & OPpLVAL_INTRO) ? AAS_MY_AGG : AAS_LEX_AGG; @@ -12540,6 +12541,7 @@ S_aassign_scan(pTHX_ OP* o, bool rhs, bool top, int *scalars_p) if (cUNOPx(o)->op_first->op_type != OP_GV) return AAS_DANGEROUS; /* @{expr}, %{expr} */ /* @pkg, %pkg */ + /* if !top, could be e.g. @a[0,1] */ if (top && (o->op_flags & OPf_REF)) return AAS_PKG_AGG; return AAS_DANGEROUS; @@ -12553,17 +12555,32 @@ S_aassign_scan(pTHX_ OP* o, bool rhs, bool top, int *scalars_p) return AAS_PKG_SCALAR; /* $pkg */ case OP_SPLIT: - if (1) { /* XXX this condition is wrong - fix later - if (cLISTOPo->op_first->op_type == OP_PUSHRE) { - */ - /* "@foo = split... " optimises away the aassign and stores its - * destination array in the OP_PUSHRE that precedes it. - * A flattened array is always dangerous. + if (o->op_private & OPpSPLIT_ASSIGN) { + /* the assign in @a = split() has been optimised away + * and the @a attached directly to the split op + * Treat the array as appearing on the RHS, i.e. + * ... = (@a = split) + * is treated like + * ... = @a; */ + + if (o->op_flags & OPf_STACKED) + /* @{expr} = split() - the array expression is tacked + * on as an extra child to split - process kid */ + return S_aassign_scan(aTHX_ cLISTOPo->op_last, rhs, + top, scalars_p); + + /* ... else array is directly attached to split op */ (*scalars_p) += 2; - return AAS_DANGEROUS; + if (PL_op->op_private & OPpSPLIT_LEX) + return (o->op_private & OPpLVAL_INTRO) + ? AAS_MY_AGG : AAS_LEX_AGG; + else + return AAS_PKG_AGG; } - break; + (*scalars_p)++; + /* other args of split can't be returned */ + return AAS_SAFE_SCALAR; case OP_UNDEF: /* undef counts as a scalar on the RHS: |