diff options
author | Nicholas Clark <nick@ccl4.org> | 2010-08-27 21:48:55 +0100 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2010-08-27 21:48:55 +0100 |
commit | ac56e7de46621c6f2e373d11984c0a0fe4839b0b (patch) | |
tree | bb3bb0453fad0152bd4b0aaf97989c0c21cb192f | |
parent | ccfef76d964c8b719db5c7fd06ce897a3eb64c01 (diff) | |
download | perl-ac56e7de46621c6f2e373d11984c0a0fe4839b0b.tar.gz |
Peephole optimise adjacent pairs of nextstate ops.
Previously, in code such as
use constant DEBUG=>0;
sub GAK {
warn if DEBUG;
print "stuff\n";
}
the ops for C<warn if DEBUG;> would be folded to a null op (ex-const), but
the nextstate op would remain, resulting in a runtime op dispatch of nextstate,
nextstate, ...
The execution of a sequence of nexstate ops is indistinguishable from just the
last nextstate op, so teach the peephole optimiser to eliminate the first of a
pair of nextstate ops. (Except where the first carries a label, as labels
mustn't be eliminated by the optimiser, and label usage isn't conclusively
known at compile time.)
-rw-r--r-- | ext/B/t/optree_samples.t | 158 | ||||
-rw-r--r-- | ext/B/t/optree_specials.t | 452 | ||||
-rw-r--r-- | op.c | 54 | ||||
-rw-r--r-- | t/op/goto.t | 8 |
4 files changed, 358 insertions, 314 deletions
diff --git a/ext/B/t/optree_samples.t b/ext/B/t/optree_samples.t index 6003ab2a3c..2a789727ba 100644 --- a/ext/B/t/optree_samples.t +++ b/ext/B/t/optree_samples.t @@ -278,57 +278,57 @@ checkOptree ( name => '-basic sub { print "foo $_" foreach (1..10) }', bcopts => '-basic', strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); -# h <1> leavesub[1 ref] K/REFC,1 ->(end) -# - <@> lineseq KP ->h +# g <1> leavesub[1 ref] K/REFC,1 ->(end) +# - <@> lineseq KP ->g # 1 <;> nextstate(main 445 optree.t:167) v:>,<,% ->2 -# 2 <;> nextstate(main 445 optree.t:167) v:>,<,% ->3 -# g <2> leaveloop K/2 ->h -# 7 <{> enteriter(next->d last->g redo->8) lKS/8 ->e -# - <0> ex-pushmark s ->3 -# - <1> ex-list lK ->6 -# 3 <0> pushmark s ->4 -# 4 <$> const[IV 1] s ->5 -# 5 <$> const[IV 10] s ->6 -# 6 <#> gv[*_] s ->7 -# - <1> null K/1 ->g -# f <|> and(other->8) K/1 ->g -# e <0> iter s ->f +# - <0> null v ->- +# f <2> leaveloop K/2 ->g +# 6 <{> enteriter(next->c last->f redo->7) lKS/8 ->d +# - <0> ex-pushmark s ->2 +# - <1> ex-list lK ->5 +# 2 <0> pushmark s ->3 +# 3 <$> const[IV 1] s ->4 +# 4 <$> const[IV 10] s ->5 +# 5 <#> gv[*_] s ->6 +# - <1> null K/1 ->f +# e <|> and(other->7) K/1 ->f +# d <0> iter s ->e # - <@> lineseq sK ->- -# c <@> print vK ->d -# 8 <0> pushmark s ->9 -# - <1> ex-stringify sK/1 ->c -# - <0> ex-pushmark s ->9 -# b <2> concat[t2] sK/2 ->c -# 9 <$> const[PV "foo "] s ->a -# - <1> ex-rv2sv sK/1 ->b -# a <#> gvsv[*_] s ->b -# d <0> unstack s ->e +# b <@> print vK ->c +# 7 <0> pushmark s ->8 +# - <1> ex-stringify sK/1 ->b +# - <0> ex-pushmark s ->8 +# a <2> concat[t2] sK/2 ->b +# 8 <$> const[PV "foo "] s ->9 +# - <1> ex-rv2sv sK/1 ->a +# 9 <#> gvsv[*_] s ->a +# c <0> unstack s ->d EOT_EOT -# h <1> leavesub[1 ref] K/REFC,1 ->(end) -# - <@> lineseq KP ->h +# g <1> leavesub[1 ref] K/REFC,1 ->(end) +# - <@> lineseq KP ->g # 1 <;> nextstate(main 446 optree_samples.t:192) v:>,<,% ->2 -# 2 <;> nextstate(main 446 optree_samples.t:192) v:>,<,% ->3 -# g <2> leaveloop K/2 ->h -# 7 <{> enteriter(next->d last->g redo->8) lKS/8 ->e -# - <0> ex-pushmark s ->3 -# - <1> ex-list lK ->6 -# 3 <0> pushmark s ->4 -# 4 <$> const(IV 1) s ->5 -# 5 <$> const(IV 10) s ->6 -# 6 <$> gv(*_) s ->7 -# - <1> null K/1 ->g -# f <|> and(other->8) K/1 ->g -# e <0> iter s ->f +# - <0> null v ->- +# f <2> leaveloop K/2 ->g +# 6 <{> enteriter(next->c last->f redo->7) lKS/8 ->d +# - <0> ex-pushmark s ->2 +# - <1> ex-list lK ->5 +# 2 <0> pushmark s ->3 +# 3 <$> const(IV 1) s ->4 +# 4 <$> const(IV 10) s ->5 +# 5 <$> gv(*_) s ->6 +# - <1> null K/1 ->f +# e <|> and(other->7) K/1 ->f +# d <0> iter s ->e # - <@> lineseq sK ->- -# c <@> print vK ->d -# 8 <0> pushmark s ->9 -# - <1> ex-stringify sK/1 ->c -# - <0> ex-pushmark s ->9 -# b <2> concat[t1] sK/2 ->c -# 9 <$> const(PV "foo ") s ->a -# - <1> ex-rv2sv sK/1 ->b -# a <$> gvsv(*_) s ->b -# d <0> unstack s ->e +# b <@> print vK ->c +# 7 <0> pushmark s ->8 +# - <1> ex-stringify sK/1 ->b +# - <0> ex-pushmark s ->8 +# a <2> concat[t1] sK/2 ->b +# 8 <$> const(PV "foo ") s ->9 +# - <1> ex-rv2sv sK/1 ->a +# 9 <$> gvsv(*_) s ->a +# c <0> unstack s ->d EONT_EONT checkOptree ( name => '-exec -e foreach (1..10) {print qq{foo $_}}', @@ -383,42 +383,40 @@ checkOptree ( name => '-exec sub { print "foo $_" foreach (1..10) }', strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); # 1 <;> nextstate(main 445 optree.t:167) v:>,<,% -# 2 <;> nextstate(main 445 optree.t:167) v:>,<,% -# 3 <0> pushmark s -# 4 <$> const[IV 1] s -# 5 <$> const[IV 10] s -# 6 <#> gv[*_] s -# 7 <{> enteriter(next->d last->g redo->8) lKS/8 -# e <0> iter s -# f <|> and(other->8) K/1 -# 8 <0> pushmark s -# 9 <$> const[PV "foo "] s -# a <#> gvsv[*_] s -# b <2> concat[t2] sK/2 -# c <@> print vK -# d <0> unstack s -# goto e -# g <2> leaveloop K/2 -# h <1> leavesub[1 ref] K/REFC,1 +# 2 <0> pushmark s +# 3 <$> const[IV 1] s +# 4 <$> const[IV 10] s +# 5 <#> gv[*_] s +# 6 <{> enteriter(next->c last->f redo->7) lKS/8 +# d <0> iter s +# e <|> and(other->7) K/1 +# 7 <0> pushmark s +# 8 <$> const[PV "foo "] s +# 9 <#> gvsv[*_] s +# a <2> concat[t2] sK/2 +# b <@> print vK +# c <0> unstack s +# goto d +# f <2> leaveloop K/2 +# g <1> leavesub[1 ref] K/REFC,1 EOT_EOT # 1 <;> nextstate(main 447 optree_samples.t:252) v:>,<,% -# 2 <;> nextstate(main 447 optree_samples.t:252) v:>,<,% -# 3 <0> pushmark s -# 4 <$> const(IV 1) s -# 5 <$> const(IV 10) s -# 6 <$> gv(*_) s -# 7 <{> enteriter(next->d last->g redo->8) lKS/8 -# e <0> iter s -# f <|> and(other->8) K/1 -# 8 <0> pushmark s -# 9 <$> const(PV "foo ") s -# a <$> gvsv(*_) s -# b <2> concat[t1] sK/2 -# c <@> print vK -# d <0> unstack s -# goto e -# g <2> leaveloop K/2 -# h <1> leavesub[1 ref] K/REFC,1 +# 2 <0> pushmark s +# 3 <$> const(IV 1) s +# 4 <$> const(IV 10) s +# 5 <$> gv(*_) s +# 6 <{> enteriter(next->c last->f redo->7) lKS/8 +# d <0> iter s +# e <|> and(other->7) K/1 +# 7 <0> pushmark s +# 8 <$> const(PV "foo ") s +# 9 <$> gvsv(*_) s +# a <2> concat[t1] sK/2 +# b <@> print vK +# c <0> unstack s +# goto d +# f <2> leaveloop K/2 +# g <1> leavesub[1 ref] K/REFC,1 EONT_EONT pass("GREP: SAMPLES FROM PERLDOC -F GREP"); diff --git a/ext/B/t/optree_specials.t b/ext/B/t/optree_specials.t index 1f813230af..25f7335867 100644 --- a/ext/B/t/optree_specials.t +++ b/ext/B/t/optree_specials.t @@ -48,104 +48,104 @@ checkOptree ( name => 'BEGIN', strip_open_hints => 1, expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT'); # BEGIN 1: -# b <1> leavesub[1 ref] K/REFC,1 ->(end) -# - <@> lineseq KP ->b +# a <1> leavesub[1 ref] K/REFC,1 ->(end) +# - <@> lineseq KP ->a # 1 <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->2 # 3 <1> require sK/1 ->4 # 2 <$> const[PV "strict.pm"] s/BARE ->3 # 4 <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->5 # - <@> lineseq K ->- -# 5 <;> nextstate(B::Concise -275 Concise.pm:356) :*,&,{,$ ->6 -# a <1> entersub[t1] KS*/TARG,2 ->b -# 6 <0> pushmark s ->7 -# 7 <$> const[PV "strict"] sM ->8 -# 8 <$> const[PV "refs"] sM ->9 -# 9 <$> method_named[PV "unimport"] ->a +# - <0> null ->5 +# 9 <1> entersub[t1] KS*/TARG,2 ->a +# 5 <0> pushmark s ->6 +# 6 <$> const[PV "strict"] sM ->7 +# 7 <$> const[PV "refs"] sM ->8 +# 8 <$> method_named[PV "unimport"] ->9 # BEGIN 2: -# m <1> leavesub[1 ref] K/REFC,1 ->(end) -# - <@> lineseq K ->m -# c <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->d -# e <1> require sK/1 ->f -# d <$> const[PV "strict.pm"] s/BARE ->e -# f <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->g +# k <1> leavesub[1 ref] K/REFC,1 ->(end) +# - <@> lineseq K ->k +# b <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->c +# d <1> require sK/1 ->e +# c <$> const[PV "strict.pm"] s/BARE ->d +# e <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->f # - <@> lineseq K ->- -# g <;> nextstate(B::Concise -265 Concise.pm:367) :*,&,$ ->h -# l <1> entersub[t1] KS*/TARG,2 ->m -# h <0> pushmark s ->i -# i <$> const[PV "strict"] sM ->j -# j <$> const[PV "refs"] sM ->k -# k <$> method_named[PV "unimport"] ->l +# - <0> null ->f +# j <1> entersub[t1] KS*/TARG,2 ->k +# f <0> pushmark s ->g +# g <$> const[PV "strict"] sM ->h +# h <$> const[PV "refs"] sM ->i +# i <$> method_named[PV "unimport"] ->j # BEGIN 3: -# x <1> leavesub[1 ref] K/REFC,1 ->(end) -# - <@> lineseq KP ->x -# n <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->o -# p <1> require sK/1 ->q -# o <$> const[PV "warnings.pm"] s/BARE ->p -# q <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->r +# u <1> leavesub[1 ref] K/REFC,1 ->(end) +# - <@> lineseq KP ->u +# l <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->m +# n <1> require sK/1 ->o +# m <$> const[PV "warnings.pm"] s/BARE ->n +# o <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->p # - <@> lineseq K ->- -# r <;> nextstate(B::Concise -254 Concise.pm:386) :*,&,{,$ ->s -# w <1> entersub[t1] KS*/TARG,2 ->x -# s <0> pushmark s ->t -# t <$> const[PV "warnings"] sM ->u -# u <$> const[PV "qw"] sM ->v -# v <$> method_named[PV "unimport"] ->w +# - <0> null ->p +# t <1> entersub[t1] KS*/TARG,2 ->u +# p <0> pushmark s ->q +# q <$> const[PV "warnings"] sM ->r +# r <$> const[PV "qw"] sM ->s +# s <$> method_named[PV "unimport"] ->t # BEGIN 4: -# 11 <1> leavesub[1 ref] K/REFC,1 ->(end) -# - <@> lineseq KP ->11 -# y <;> nextstate(main 2 -e:1) v:>,<,%,{ ->z -# 10 <1> postinc[t3] sK/1 ->11 -# - <1> ex-rv2sv sKRM/1 ->10 -# z <#> gvsv[*beg] s ->10 +# y <1> leavesub[1 ref] K/REFC,1 ->(end) +# - <@> lineseq KP ->y +# v <;> nextstate(main 2 -e:1) v:>,<,%,{ ->w +# x <1> postinc[t3] sK/1 ->y +# - <1> ex-rv2sv sKRM/1 ->x +# w <#> gvsv[*beg] s ->x EOT_EOT # BEGIN 1: -# b <1> leavesub[1 ref] K/REFC,1 ->(end) -# - <@> lineseq KP ->b +# a <1> leavesub[1 ref] K/REFC,1 ->(end) +# - <@> lineseq KP ->a # 1 <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->2 # 3 <1> require sK/1 ->4 # 2 <$> const(PV "strict.pm") s/BARE ->3 # 4 <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->5 # - <@> lineseq K ->- -# 5 <;> nextstate(B::Concise -275 Concise.pm:356) :*,&,{,$ ->6 -# a <1> entersub[t1] KS*/TARG,2 ->b -# 6 <0> pushmark s ->7 -# 7 <$> const(PV "strict") sM ->8 -# 8 <$> const(PV "refs") sM ->9 -# 9 <$> method_named(PV "unimport") ->a +# - <0> null ->5 +# 9 <1> entersub[t1] KS*/TARG,2 ->a +# 5 <0> pushmark s ->6 +# 6 <$> const(PV "strict") sM ->7 +# 7 <$> const(PV "refs") sM ->8 +# 8 <$> method_named(PV "unimport") ->9 # BEGIN 2: -# m <1> leavesub[1 ref] K/REFC,1 ->(end) -# - <@> lineseq K ->m -# c <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->d -# e <1> require sK/1 ->f -# d <$> const(PV "strict.pm") s/BARE ->e -# f <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->g +# k <1> leavesub[1 ref] K/REFC,1 ->(end) +# - <@> lineseq K ->k +# b <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->c +# d <1> require sK/1 ->e +# c <$> const(PV "strict.pm") s/BARE ->d +# e <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->f # - <@> lineseq K ->- -# g <;> nextstate(B::Concise -265 Concise.pm:367) :*,&,$ ->h -# l <1> entersub[t1] KS*/TARG,2 ->m -# h <0> pushmark s ->i -# i <$> const(PV "strict") sM ->j -# j <$> const(PV "refs") sM ->k -# k <$> method_named(PV "unimport") ->l +# - <0> null ->f +# j <1> entersub[t1] KS*/TARG,2 ->k +# f <0> pushmark s ->g +# g <$> const(PV "strict") sM ->h +# h <$> const(PV "refs") sM ->i +# i <$> method_named(PV "unimport") ->j # BEGIN 3: -# x <1> leavesub[1 ref] K/REFC,1 ->(end) -# - <@> lineseq KP ->x -# n <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->o -# p <1> require sK/1 ->q -# o <$> const(PV "warnings.pm") s/BARE ->p -# q <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->r +# u <1> leavesub[1 ref] K/REFC,1 ->(end) +# - <@> lineseq KP ->u +# l <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->m +# n <1> require sK/1 ->o +# m <$> const(PV "warnings.pm") s/BARE ->n +# o <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->p # - <@> lineseq K ->- -# r <;> nextstate(B::Concise -254 Concise.pm:386) :*,&,{,$ ->s -# w <1> entersub[t1] KS*/TARG,2 ->x -# s <0> pushmark s ->t -# t <$> const(PV "warnings") sM ->u -# u <$> const(PV "qw") sM ->v -# v <$> method_named(PV "unimport") ->w +# - <0> null ->p +# t <1> entersub[t1] KS*/TARG,2 ->u +# p <0> pushmark s ->q +# q <$> const(PV "warnings") sM ->r +# r <$> const(PV "qw") sM ->s +# s <$> method_named(PV "unimport") ->t # BEGIN 4: -# 11 <1> leavesub[1 ref] K/REFC,1 ->(end) -# - <@> lineseq KP ->11 -# y <;> nextstate(main 2 -e:1) v:>,<,%,{ ->z -# 10 <1> postinc[t2] sK/1 ->11 -# - <1> ex-rv2sv sKRM/1 ->10 -# z <$> gvsv(*beg) s ->10 +# y <1> leavesub[1 ref] K/REFC,1 ->(end) +# - <@> lineseq KP ->y +# v <;> nextstate(main 2 -e:1) v:>,<,%,{ ->w +# x <1> postinc[t2] sK/1 ->y +# - <1> ex-rv2sv sKRM/1 ->x +# w <$> gvsv(*beg) s ->x EONT_EONT @@ -253,124 +253,118 @@ checkOptree ( name => 'all of BEGIN END INIT CHECK UNITCHECK -exec', # 2 <$> const[PV "strict.pm"] s/BARE # 3 <1> require sK/1 # 4 <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ -# 5 <;> nextstate(B::Concise -275 Concise.pm:356) :*,&,{,$ -# 6 <0> pushmark s -# 7 <$> const[PV "strict"] sM -# 8 <$> const[PV "refs"] sM -# 9 <$> method_named[PV "unimport"] -# a <1> entersub[t1] KS*/TARG,2 -# b <1> leavesub[1 ref] K/REFC,1 +# 5 <0> pushmark s +# 6 <$> const[PV "strict"] sM +# 7 <$> const[PV "refs"] sM +# 8 <$> method_named[PV "unimport"] +# 9 <1> entersub[t1] KS*/TARG,2 +# a <1> leavesub[1 ref] K/REFC,1 # BEGIN 2: -# c <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ -# d <$> const[PV "strict.pm"] s/BARE -# e <1> require sK/1 -# f <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ -# g <;> nextstate(B::Concise -265 Concise.pm:367) :*,&,$ -# h <0> pushmark s -# i <$> const[PV "strict"] sM -# j <$> const[PV "refs"] sM -# k <$> method_named[PV "unimport"] -# l <1> entersub[t1] KS*/TARG,2 -# m <1> leavesub[1 ref] K/REFC,1 +# b <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ +# c <$> const[PV "strict.pm"] s/BARE +# d <1> require sK/1 +# e <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ +# f <0> pushmark s +# g <$> const[PV "strict"] sM +# h <$> const[PV "refs"] sM +# i <$> method_named[PV "unimport"] +# j <1> entersub[t1] KS*/TARG,2 +# k <1> leavesub[1 ref] K/REFC,1 # BEGIN 3: -# n <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ -# o <$> const[PV "warnings.pm"] s/BARE -# p <1> require sK/1 -# q <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ -# r <;> nextstate(B::Concise -254 Concise.pm:386) :*,&,{,$ -# s <0> pushmark s -# t <$> const[PV "warnings"] sM -# u <$> const[PV "qw"] sM -# v <$> method_named[PV "unimport"] -# w <1> entersub[t1] KS*/TARG,2 -# x <1> leavesub[1 ref] K/REFC,1 +# l <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ +# m <$> const[PV "warnings.pm"] s/BARE +# n <1> require sK/1 +# o <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ +# p <0> pushmark s +# q <$> const[PV "warnings"] sM +# r <$> const[PV "qw"] sM +# s <$> method_named[PV "unimport"] +# t <1> entersub[t1] KS*/TARG,2 +# u <1> leavesub[1 ref] K/REFC,1 # BEGIN 4: -# y <;> nextstate(main 2 -e:1) v:>,<,%,{ -# z <#> gvsv[*beg] s -# 10 <1> postinc[t3] sK/1 -# 11 <1> leavesub[1 ref] K/REFC,1 +# v <;> nextstate(main 2 -e:1) v:>,<,%,{ +# w <#> gvsv[*beg] s +# x <1> postinc[t3] sK/1 +# y <1> leavesub[1 ref] K/REFC,1 # END 1: -# 12 <;> nextstate(main 5 -e:1) v:>,<,%,{ -# 13 <#> gvsv[*end] s -# 14 <1> postinc[t3] sK/1 -# 15 <1> leavesub[1 ref] K/REFC,1 +# z <;> nextstate(main 5 -e:1) v:>,<,%,{ +# 10 <#> gvsv[*end] s +# 11 <1> postinc[t3] sK/1 +# 12 <1> leavesub[1 ref] K/REFC,1 # INIT 1: -# 16 <;> nextstate(main 4 -e:1) v:>,<,%,{ -# 17 <#> gvsv[*init] s -# 18 <1> postinc[t3] sK/1 -# 19 <1> leavesub[1 ref] K/REFC,1 +# 13 <;> nextstate(main 4 -e:1) v:>,<,%,{ +# 14 <#> gvsv[*init] s +# 15 <1> postinc[t3] sK/1 +# 16 <1> leavesub[1 ref] K/REFC,1 # CHECK 1: -# 1a <;> nextstate(main 3 -e:1) v:>,<,%,{ -# 1b <#> gvsv[*chk] s -# 1c <1> postinc[t3] sK/1 -# 1d <1> leavesub[1 ref] K/REFC,1 +# 17 <;> nextstate(main 3 -e:1) v:>,<,%,{ +# 18 <#> gvsv[*chk] s +# 19 <1> postinc[t3] sK/1 +# 1a <1> leavesub[1 ref] K/REFC,1 # UNITCHECK 1: -# 1e <;> nextstate(main 6 -e:1) v:>,<,%,{ -# 1f <#> gvsv[*uc] s -# 1g <1> postinc[t3] sK/1 -# 1h <1> leavesub[1 ref] K/REFC,1 +# 1b <;> nextstate(main 6 -e:1) v:>,<,%,{ +# 1c <#> gvsv[*uc] s +# 1d <1> postinc[t3] sK/1 +# 1e <1> leavesub[1 ref] K/REFC,1 EOT_EOT # BEGIN 1: # 1 <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ # 2 <$> const(PV "strict.pm") s/BARE # 3 <1> require sK/1 # 4 <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ -# 5 <;> nextstate(B::Concise -275 Concise.pm:356) :*,&,{,$ -# 6 <0> pushmark s -# 7 <$> const(PV "strict") sM -# 8 <$> const(PV "refs") sM -# 9 <$> method_named(PV "unimport") -# a <1> entersub[t1] KS*/TARG,2 -# b <1> leavesub[1 ref] K/REFC,1 +# 5 <0> pushmark s +# 6 <$> const(PV "strict") sM +# 7 <$> const(PV "refs") sM +# 8 <$> method_named(PV "unimport") +# 9 <1> entersub[t1] KS*/TARG,2 +# a <1> leavesub[1 ref] K/REFC,1 # BEGIN 2: -# c <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ -# d <$> const(PV "strict.pm") s/BARE -# e <1> require sK/1 -# f <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ -# g <;> nextstate(B::Concise -265 Concise.pm:367) :*,&,$ -# h <0> pushmark s -# i <$> const(PV "strict") sM -# j <$> const(PV "refs") sM -# k <$> method_named(PV "unimport") -# l <1> entersub[t1] KS*/TARG,2 -# m <1> leavesub[1 ref] K/REFC,1 +# b <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ +# c <$> const(PV "strict.pm") s/BARE +# d <1> require sK/1 +# e <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ +# f <0> pushmark s +# g <$> const(PV "strict") sM +# h <$> const(PV "refs") sM +# i <$> method_named(PV "unimport") +# j <1> entersub[t1] KS*/TARG,2 +# k <1> leavesub[1 ref] K/REFC,1 # BEGIN 3: -# n <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ -# o <$> const(PV "warnings.pm") s/BARE -# p <1> require sK/1 -# q <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ -# r <;> nextstate(B::Concise -254 Concise.pm:386) :*,&,{,$ -# s <0> pushmark s -# t <$> const(PV "warnings") sM -# u <$> const(PV "qw") sM -# v <$> method_named(PV "unimport") -# w <1> entersub[t1] KS*/TARG,2 -# x <1> leavesub[1 ref] K/REFC,1 +# l <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ +# m <$> const(PV "warnings.pm") s/BARE +# n <1> require sK/1 +# o <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ +# p <0> pushmark s +# q <$> const(PV "warnings") sM +# r <$> const(PV "qw") sM +# s <$> method_named(PV "unimport") +# t <1> entersub[t1] KS*/TARG,2 +# u <1> leavesub[1 ref] K/REFC,1 # BEGIN 4: -# y <;> nextstate(main 2 -e:1) v:>,<,%,{ -# z <$> gvsv(*beg) s -# 10 <1> postinc[t2] sK/1 -# 11 <1> leavesub[1 ref] K/REFC,1 +# v <;> nextstate(main 2 -e:1) v:>,<,%,{ +# w <$> gvsv(*beg) s +# x <1> postinc[t2] sK/1 +# y <1> leavesub[1 ref] K/REFC,1 # END 1: -# 12 <;> nextstate(main 5 -e:1) v:>,<,%,{ -# 13 <$> gvsv(*end) s -# 14 <1> postinc[t2] sK/1 -# 15 <1> leavesub[1 ref] K/REFC,1 +# z <;> nextstate(main 5 -e:1) v:>,<,%,{ +# 10 <$> gvsv(*end) s +# 11 <1> postinc[t2] sK/1 +# 12 <1> leavesub[1 ref] K/REFC,1 # INIT 1: -# 16 <;> nextstate(main 4 -e:1) v:>,<,%,{ -# 17 <$> gvsv(*init) s -# 18 <1> postinc[t2] sK/1 -# 19 <1> leavesub[1 ref] K/REFC,1 +# 13 <;> nextstate(main 4 -e:1) v:>,<,%,{ +# 14 <$> gvsv(*init) s +# 15 <1> postinc[t2] sK/1 +# 16 <1> leavesub[1 ref] K/REFC,1 # CHECK 1: -# 1a <;> nextstate(main 3 -e:1) v:>,<,%,{ -# 1b <$> gvsv(*chk) s -# 1c <1> postinc[t2] sK/1 -# 1d <1> leavesub[1 ref] K/REFC,1 +# 17 <;> nextstate(main 3 -e:1) v:>,<,%,{ +# 18 <$> gvsv(*chk) s +# 19 <1> postinc[t2] sK/1 +# 1a <1> leavesub[1 ref] K/REFC,1 # UNITCHECK 1: -# 1e <;> nextstate(main 6 -e:1) v:>,<,%,{ -# 1f <$> gvsv(*uc) s -# 1g <1> postinc[t2] sK/1 -# 1h <1> leavesub[1 ref] K/REFC,1 +# 1b <;> nextstate(main 6 -e:1) v:>,<,%,{ +# 1c <$> gvsv(*uc) s +# 1d <1> postinc[t2] sK/1 +# 1e <1> leavesub[1 ref] K/REFC,1 EONT_EONT @@ -388,72 +382,66 @@ checkOptree ( name => 'regression test for patch 25352', # 2 <$> const[PV "strict.pm"] s/BARE # 3 <1> require sK/1 # 4 <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ -# 5 <;> nextstate(B::Concise -275 Concise.pm:356) :*,&,{,$ -# 6 <0> pushmark s -# 7 <$> const[PV "strict"] sM -# 8 <$> const[PV "refs"] sM -# 9 <$> method_named[PV "unimport"] -# a <1> entersub[t1] KS*/TARG,2 -# b <1> leavesub[1 ref] K/REFC,1 +# 5 <0> pushmark s +# 6 <$> const[PV "strict"] sM +# 7 <$> const[PV "refs"] sM +# 8 <$> method_named[PV "unimport"] +# 9 <1> entersub[t1] KS*/TARG,2 +# a <1> leavesub[1 ref] K/REFC,1 # BEGIN 2: -# c <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ -# d <$> const[PV "strict.pm"] s/BARE -# e <1> require sK/1 -# f <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ -# g <;> nextstate(B::Concise -265 Concise.pm:367) :*,&,$ -# h <0> pushmark s -# i <$> const[PV "strict"] sM -# j <$> const[PV "refs"] sM -# k <$> method_named[PV "unimport"] -# l <1> entersub[t1] KS*/TARG,2 -# m <1> leavesub[1 ref] K/REFC,1 +# b <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ +# c <$> const[PV "strict.pm"] s/BARE +# d <1> require sK/1 +# e <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ +# f <0> pushmark s +# g <$> const[PV "strict"] sM +# h <$> const[PV "refs"] sM +# i <$> method_named[PV "unimport"] +# j <1> entersub[t1] KS*/TARG,2 +# k <1> leavesub[1 ref] K/REFC,1 # BEGIN 3: -# n <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ -# o <$> const[PV "warnings.pm"] s/BARE -# p <1> require sK/1 -# q <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ -# r <;> nextstate(B::Concise -254 Concise.pm:386) :*,&,{,$ -# s <0> pushmark s -# t <$> const[PV "warnings"] sM -# u <$> const[PV "qw"] sM -# v <$> method_named[PV "unimport"] -# w <1> entersub[t1] KS*/TARG,2 -# x <1> leavesub[1 ref] K/REFC,1 +# l <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ +# m <$> const[PV "warnings.pm"] s/BARE +# n <1> require sK/1 +# o <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ +# p <0> pushmark s +# q <$> const[PV "warnings"] sM +# r <$> const[PV "qw"] sM +# s <$> method_named[PV "unimport"] +# t <1> entersub[t1] KS*/TARG,2 +# u <1> leavesub[1 ref] K/REFC,1 EOT_EOT # BEGIN 1: # 1 <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ # 2 <$> const(PV "strict.pm") s/BARE # 3 <1> require sK/1 # 4 <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ -# 5 <;> nextstate(B::Concise -275 Concise.pm:356) :*,&,{,$ -# 6 <0> pushmark s -# 7 <$> const(PV "strict") sM -# 8 <$> const(PV "refs") sM -# 9 <$> method_named(PV "unimport") -# a <1> entersub[t1] KS*/TARG,2 -# b <1> leavesub[1 ref] K/REFC,1 +# 5 <0> pushmark s +# 6 <$> const(PV "strict") sM +# 7 <$> const(PV "refs") sM +# 8 <$> method_named(PV "unimport") +# 9 <1> entersub[t1] KS*/TARG,2 +# a <1> leavesub[1 ref] K/REFC,1 # BEGIN 2: -# c <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ -# d <$> const(PV "strict.pm") s/BARE -# e <1> require sK/1 -# f <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ -# g <;> nextstate(B::Concise -265 Concise.pm:367) :*,&,$ -# h <0> pushmark s -# i <$> const(PV "strict") sM -# j <$> const(PV "refs") sM -# k <$> method_named(PV "unimport") -# l <1> entersub[t1] KS*/TARG,2 -# m <1> leavesub[1 ref] K/REFC,1 +# b <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ +# c <$> const(PV "strict.pm") s/BARE +# d <1> require sK/1 +# e <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ +# f <0> pushmark s +# g <$> const(PV "strict") sM +# h <$> const(PV "refs") sM +# i <$> method_named(PV "unimport") +# j <1> entersub[t1] KS*/TARG,2 +# k <1> leavesub[1 ref] K/REFC,1 # BEGIN 3: -# n <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ -# o <$> const(PV "warnings.pm") s/BARE -# p <1> require sK/1 -# q <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ -# r <;> nextstate(B::Concise -254 Concise.pm:386) :*,&,{,$ -# s <0> pushmark s -# t <$> const(PV "warnings") sM -# u <$> const(PV "qw") sM -# v <$> method_named(PV "unimport") -# w <1> entersub[t1] KS*/TARG,2 -# x <1> leavesub[1 ref] K/REFC,1 +# l <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ +# m <$> const(PV "warnings.pm") s/BARE +# n <1> require sK/1 +# o <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ +# p <0> pushmark s +# q <$> const(PV "warnings") sM +# r <$> const(PV "qw") sM +# s <$> method_named(PV "unimport") +# t <1> entersub[t1] KS*/TARG,2 +# u <1> leavesub[1 ref] K/REFC,1 EONT_EONT @@ -8862,10 +8862,62 @@ Perl_rpeep(pTHX_ register OP *o) o->op_opt = 1; PL_op = o; switch (o->op_type) { - case OP_NEXTSTATE: case OP_DBSTATE: PL_curcop = ((COP*)o); /* for warnings */ break; + case OP_NEXTSTATE: + PL_curcop = ((COP*)o); /* for warnings */ + + /* Two NEXTSTATEs in a row serve no purpose. Except if they happen + to carry two labels. For now, take the easier option, and skip + this optimisation if the first NEXTSTATE has a label. */ + if (!CopLABEL((COP*)o)) { + OP *nextop = o->op_next; + while (nextop && nextop->op_type == OP_NULL) + nextop = nextop->op_next; + + if (nextop && (nextop->op_type == OP_NEXTSTATE)) { + COP *firstcop = (COP *)o; + COP *secondcop = (COP *)nextop; + /* We want the COP pointed to by o (and anything else) to + become the next COP down the line. */ + cop_free(firstcop); + + firstcop->op_next = secondcop->op_next; + + /* Now steal all its pointers, and duplicate the other + data. */ + firstcop->cop_line = secondcop->cop_line; +#ifdef USE_ITHREADS + firstcop->cop_stashpv = secondcop->cop_stashpv; + firstcop->cop_file = secondcop->cop_file; +#else + firstcop->cop_stash = secondcop->cop_stash; + firstcop->cop_filegv = secondcop->cop_filegv; +#endif + firstcop->cop_hints = secondcop->cop_hints; + firstcop->cop_seq = secondcop->cop_seq; + firstcop->cop_warnings = secondcop->cop_warnings; + firstcop->cop_hints_hash = secondcop->cop_hints_hash; + +#ifdef USE_ITHREADS + secondcop->cop_stashpv = NULL; + secondcop->cop_file = NULL; +#else + secondcop->cop_stash = NULL; + secondcop->cop_filegv = NULL; +#endif + secondcop->cop_warnings = NULL; + secondcop->cop_hints_hash = NULL; + + /* If we use op_null(), and hence leave an ex-COP, some + warnings are misreported. For example, the compile-time + error in 'use strict; no strict refs;' */ + secondcop->op_type = OP_NULL; + secondcop->op_ppaddr = PL_ppaddr[OP_NULL]; + } + } + break; case OP_CONST: if (cSVOPo->op_private & OPpCONST_STRICT) diff --git a/t/op/goto.t b/t/op/goto.t index 0a8aeeecbb..a98e35496d 100644 --- a/t/op/goto.t +++ b/t/op/goto.t @@ -10,7 +10,7 @@ BEGIN { use warnings; use strict; -plan tests => 67; +plan tests => 68; our $TODO; my $deprecated = 0; @@ -483,3 +483,9 @@ is($deprecated, 0); is($x, 10, 'labels outside evals can be distinguished from the start of the eval'); } + +goto wham_eth; +die "You can't get here"; + +wham_eth: 1 if 0; +ouch_eth: pass('labels persist even if their statement is optimised away'); |