summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2015-04-17 20:12:54 +0100
committerDavid Mitchell <davem@iabyn.com>2015-04-19 18:42:00 +0100
commite7c18dde420590ee76509d2187610a43444ad069 (patch)
treed7c91acbb46b9227b8abf6b3b9e307f85507bce2 /op.c
parent3269ea419f8371979acd66adb243694f4bf710e1 (diff)
downloadperl-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.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/op.c b/op.c
index e03fc95abd..98ef1dfcf6 100644
--- a/op.c
+++ b/op.c
@@ -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;