summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorSteffen Mueller <smueller@cpan.org>2014-02-22 10:08:25 +0100
committerSteffen Mueller <smueller@cpan.org>2014-02-26 21:27:57 +0100
commit7d3c8a6837b55fff0e6294ebf8c94a1601367c76 (patch)
treea73bc7c98cf940228a9be15c13c3521a13b865c9 /ext
parent11ee9dd668c24ff655cfec47610c8939e74a8506 (diff)
downloadperl-7d3c8a6837b55fff0e6294ebf8c94a1601367c76.tar.gz
Optimization: Remove needless list/pushmark pairs from the OP execution
This is an optimization for OP trees that involve list OPs in list context. In list context, the list OP's first child, a pushmark, will do what its name claims and push a mark to the mark stack, indicating the start of a list of parameters to another OP. Then the list's other child OPs will do their stack pushing. Finally, the list OP will be executed and do nothing but undo what the pushmark has done. This is because the main effect of the list OP only really kicks in if it's not in array context (actually, it should probably only kick in if it's in scalar context, but I don't know of any valid examples of list OPs in void contexts). This optimization is quite a measurable speed-up for array or hash slicing and some other situations. Another (contrived) example is that (1,2,(3,4)) now actually is the same, performance-wise as (1,2,3,4), albeit that's rarely relevant. The price to pay for this is a slightly convoluted (by standards other than the perl core) bit of optimization logic that has to do minor look-ahead on certain OPs in the peephole optimizer. A number of tests failed after the first attack on this problem. The failures were in two categories: a) Tests that are sensitive to details of the OP tree structure and did verbatim text comparisons of B::Concise output (ouch). These are just patched according to the new red in this commit. b) Test that validly failed because certain conditions in op.c were expecting OP_LISTs where there are now OP_NULLs (with op_targ=OP_LIST). For these, the respective conditions in op.c were adjusted. The change includes modifying B::Deparse to handle the new OP tree structure in the face of nulled OP_LISTs.
Diffstat (limited to 'ext')
-rw-r--r--ext/B/t/f_map.t48
-rw-r--r--ext/B/t/optree_samples.t48
2 files changed, 44 insertions, 52 deletions
diff --git a/ext/B/t/f_map.t b/ext/B/t/f_map.t
index 2c2561b2f1..a7a9c26880 100644
--- a/ext/B/t/f_map.t
+++ b/ext/B/t/f_map.t
@@ -101,20 +101,18 @@ checkOptree(note => q{},
# 8 <0> enter l
# 9 <;> nextstate(main 475 (eval 10):1) v:{
# a <0> pushmark s
-# b <0> pushmark s
-# c <#> gvsv[*_] s
-# d <#> gv[*getkey] s/EARLYCV
-# e <1> entersub[t5] lKS/TARG
-# f <#> gvsv[*_] s
-# g <@> list lK
-# h <@> leave lKP
+# b <#> gvsv[*_] s
+# c <#> gv[*getkey] s/EARLYCV
+# d <1> entersub[t5] lKS/TARG
+# e <#> gvsv[*_] s
+# f <@> leave lKP
# goto 7
-# i <0> pushmark s
-# j <#> gv[*hash] s
-# k <1> rv2hv[t2] lKRM*/1 < 5.019006
-# k <1> rv2hv lKRM*/1 >=5.019006
-# l <2> aassign[t10] KS/COMMON
-# m <1> leavesub[1 ref] K/REFC,1
+# g <0> pushmark s
+# h <#> gv[*hash] s
+# i <1> rv2hv[t2] lKRM*/1 < 5.019006
+# i <1> rv2hv lKRM*/1 >=5.019006
+# j <2> aassign[t10] KS/COMMON
+# k <1> leavesub[1 ref] K/REFC,1
EOT_EOT
# 1 <;> nextstate(main 560 (eval 15):1) v:{
# 2 <0> pushmark s
@@ -127,20 +125,18 @@ EOT_EOT
# 8 <0> enter l
# 9 <;> nextstate(main 559 (eval 15):1) v:{
# a <0> pushmark s
-# b <0> pushmark s
-# c <$> gvsv(*_) s
-# d <$> gv(*getkey) s/EARLYCV
-# e <1> entersub[t2] lKS/TARG
-# f <$> gvsv(*_) s
-# g <@> list lK
-# h <@> leave lKP
+# b <$> gvsv(*_) s
+# c <$> gv(*getkey) s/EARLYCV
+# d <1> entersub[t2] lKS/TARG
+# e <$> gvsv(*_) s
+# f <@> leave lKP
# goto 7
-# i <0> pushmark s
-# j <$> gv(*hash) s
-# k <1> rv2hv[t1] lKRM*/1 < 5.019006
-# k <1> rv2hv lKRM*/1 >=5.019006
-# l <2> aassign[t5] KS/COMMON
-# m <1> leavesub[1 ref] K/REFC,1
+# g <0> pushmark s
+# h <$> gv(*hash) s
+# i <1> rv2hv[t1] lKRM*/1 < 5.019006
+# i <1> rv2hv lKRM*/1 >=5.019006
+# j <2> aassign[t5] KS/COMMON
+# k <1> leavesub[1 ref] K/REFC,1
EONT_EONT
diff --git a/ext/B/t/optree_samples.t b/ext/B/t/optree_samples.t
index 0e93405732..2a9c010542 100644
--- a/ext/B/t/optree_samples.t
+++ b/ext/B/t/optree_samples.t
@@ -475,20 +475,18 @@ checkOptree ( name => '%h = map { getkey($_) => $_ } @a',
# 8 <0> enter l
# 9 <;> nextstate(main 500 (eval 22):1) v:{
# a <0> pushmark s
-# b <0> pushmark s
-# c <#> gvsv[*_] s
-# d <#> gv[*getkey] s/EARLYCV
-# e <1> entersub[t5] lKS/TARG
-# f <#> gvsv[*_] s
-# g <@> list lK
-# h <@> leave lKP
+# b <#> gvsv[*_] s
+# c <#> gv[*getkey] s/EARLYCV
+# d <1> entersub[t5] lKS/TARG
+# e <#> gvsv[*_] s
+# f <@> leave lKP
# goto 7
-# i <0> pushmark s
-# j <#> gv[*h] s
-# k <1> rv2hv[t2] lKRM*/1 < 5.019006
-# k <1> rv2hv lKRM*/1 >=5.019006
-# l <2> aassign[t10] KS/COMMON
-# m <1> leavesub[1 ref] K/REFC,1
+# g <0> pushmark s
+# h <#> gv[*h] s
+# i <1> rv2hv[t2] lKRM*/1 < 5.019006
+# i <1> rv2hv lKRM*/1 >=5.019006
+# j <2> aassign[t10] KS/COMMON
+# k <1> leavesub[1 ref] K/REFC,1
EOT_EOT
# 1 <;> nextstate(main 501 (eval 22):1) v:{
# 2 <0> pushmark s
@@ -501,20 +499,18 @@ EOT_EOT
# 8 <0> enter l
# 9 <;> nextstate(main 500 (eval 22):1) v:{
# a <0> pushmark s
-# b <0> pushmark s
-# c <$> gvsv(*_) s
-# d <$> gv(*getkey) s/EARLYCV
-# e <1> entersub[t2] lKS/TARG
-# f <$> gvsv(*_) s
-# g <@> list lK
-# h <@> leave lKP
+# b <$> gvsv(*_) s
+# c <$> gv(*getkey) s/EARLYCV
+# d <1> entersub[t2] lKS/TARG
+# e <$> gvsv(*_) s
+# f <@> leave lKP
# goto 7
-# i <0> pushmark s
-# j <$> gv(*h) s
-# k <1> rv2hv[t1] lKRM*/1 < 5.019006
-# k <1> rv2hv lKRM*/1 >=5.019006
-# l <2> aassign[t5] KS/COMMON
-# m <1> leavesub[1 ref] K/REFC,1
+# g <0> pushmark s
+# h <$> gv(*h) s
+# i <1> rv2hv[t1] lKRM*/1 < 5.019006
+# i <1> rv2hv lKRM*/1 >=5.019006
+# j <2> aassign[t5] KS/COMMON
+# k <1> leavesub[1 ref] K/REFC,1
EONT_EONT
checkOptree ( name => '%h=(); for $_(@a){$h{getkey($_)} = $_}',