diff options
author | David Mitchell <davem@iabyn.com> | 2015-04-17 20:12:54 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2015-04-19 18:42:00 +0100 |
commit | e7c18dde420590ee76509d2187610a43444ad069 (patch) | |
tree | d7c91acbb46b9227b8abf6b3b9e307f85507bce2 /op.c | |
parent | 3269ea419f8371979acd66adb243694f4bf710e1 (diff) | |
download | perl-e7c18dde420590ee76509d2187610a43444ad069.tar.gz |
rpeep(): use op_sibling_splice()
There is an optimisation in rpeep() to convert the optree produced
by 'my $x; my $x' into the optree that would have been produced by
'my ($x, $y)', which allows a padrange optimisation to kick in a bit
later.
Currently the optree is morphed at this point by directly using
OpSIBLING_set() etc. This commit makes it use op_sibling_splice() instead.
We can do this following on from the previous commit, which allows
op_sibling_splice() to be used when we don't know the parent, as long as
we are only splicing in the middle of the children, not at either end.
As well as being cleaner, it also serves as a test for the new feature
of op_sibling_splice().
Diffstat (limited to 'op.c')
-rw-r--r-- | op.c | 23 |
1 files changed, 12 insertions, 11 deletions
@@ -13163,32 +13163,33 @@ Perl_rpeep(pTHX_ OP *o) assert(OpSIBLING(ns2) == pad2); assert(OpSIBLING(pad2) == ns3); + /* excise and delete ns2 */ + op_sibling_splice(NULL, pad1, 1, NULL); + op_free(ns2); + + /* excise pad1 and pad2 */ + op_sibling_splice(NULL, o, 2, NULL); + /* create new listop, with children consisting of: * a new pushmark, pad1, pad2. */ - OpSIBLING_set(pad2, NULL); newop = newLISTOP(OP_LIST, 0, pad1, pad2); newop->op_flags |= OPf_PARENS; newop->op_flags = (newop->op_flags & ~OPf_WANT) | OPf_WANT_VOID; - newpm = cUNOPx(newop)->op_first; /* pushmark */ - /* Kill nextstate2 between padop1/padop2 */ - op_free(ns2); + /* insert newop between o and ns3 */ + op_sibling_splice(NULL, o, 0, newop); + /*fixup op_next chain */ + newpm = cUNOPx(newop)->op_first; /* pushmark */ o ->op_next = newpm; newpm->op_next = pad1; pad1 ->op_next = pad2; pad2 ->op_next = newop; /* listop */ newop->op_next = ns3; - OpSIBLING_set(o, newop); - OpSIBLING_set(newop, ns3); - newop->op_moresib = 1; - - newop->op_flags = (newop->op_flags & ~OPf_WANT) | OPf_WANT_VOID; - /* Ensure pushmark has this flag if padops do */ if (pad1->op_flags & OPf_MOD && pad2->op_flags & OPf_MOD) { - o->op_next->op_flags |= OPf_MOD; + newpm->op_flags |= OPf_MOD; } break; |