shift; optimization
authorRuslan Zakirov <ruz@bestpractical.com>
Mon, 3 May 2010 21:08:46 +0000 (23:08 +0200)
committerVincent Pit <vince@profvince.com>
Mon, 3 May 2010 21:08:46 +0000 (23:08 +0200)
AUTHORS
dist/B-Deparse/t/deparse.t
ext/B/t/optree_samples.t
op.c
pod/perl5130delta.pod
pp.c

diff --git a/AUTHORS b/AUTHORS
index 24ac6c3..92778cf 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -879,6 +879,7 @@ Ronald Schmidt                      <RonaldWS@aol.com>
 Ruben Schattevoy               <schattev@imb-jena.de>
 Rudolph Todd Maceyko           <rm55+@pitt.edu>
 Rujith S. de Silva             <desilva@netbox.com>
+Ruslan Zakirov                 <ruz@bestpractical.com>
 Russ Allbery                   <rra@stanford.edu>
 Russell Fulton                 <russell@ccu1.auckland.ac.nz>
 Russell Mosemann               <mose@ccsn.edu>
index e3c62ba..3a7d2aa 100644 (file)
@@ -17,7 +17,7 @@ BEGIN {
     require feature;
     feature->import(':5.10');
 }
-use Test::More tests => 85;
+use Test::More tests => 89;
 use Config ();
 
 use B::Deparse;
@@ -633,3 +633,15 @@ $r = qr/foo/;
     package Foo;
     label: print 123;
 }
+####
+shift;
+>>>>
+shift();
+####
+shift @_;
+####
+pop;
+>>>>
+pop();
+####
+pop @_;
index 065fcad..37f84f9 100644 (file)
@@ -26,45 +26,41 @@ checkOptree ( name  => '-basic sub {if shift print then,else}',
                             },
              strip_open_hints => 1,
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 9  <1> leavesub[1 ref] K/REFC,1 ->(end)
-# -     <@> lineseq KP ->9
-# 1        <;> nextstate(main 426 optree.t:16) v:>,<,% ->2
+# 7  <1> leavesub[1 ref] K/REFC,1 ->(end)
+# -     <@> lineseq KP ->7
+# 1        <;> nextstate(main 665 optree_samples.t:24) v ->2
 # -        <1> null K/1 ->-
-# 5           <|> cond_expr(other->6) K/1 ->a
-# 4              <1> shift sK/1 ->5
-# 3                 <1> rv2av[t2] sKRM/1 ->4
-# 2                    <#> gv[*_] s ->3
+# 3           <|> cond_expr(other->4) K/1 ->8
+# 2              <0> shift s* ->3
 # -              <@> scope K ->-
-# -                 <0> ex-nextstate v ->6
-# 8                 <@> print sK ->9
-# 6                    <0> pushmark s ->7
-# 7                    <$> const[PV "then"] s ->8
-# f              <@> leave KP ->9
-# a                 <0> enter ->b
-# b                 <;> nextstate(main 424 optree.t:17) v:>,<,% ->c
-# e                 <@> print sK ->f
-# c                    <0> pushmark s ->d
-# d                    <$> const[PV "else"] s ->e
+# -                 <0> ex-nextstate v ->4
+# 6                 <@> print sK ->7
+# 4                    <0> pushmark s ->5
+# 5                    <$> const[PV "then"] s ->6
+# d              <@> leave KP ->7
+# 8                 <0> enter ->9
+# 9                 <;> nextstate(main 663 optree_samples.t:25) v ->a
+# c                 <@> print sK ->d
+# a                    <0> pushmark s ->b
+# b                    <$> const[PV "else"] s ->c
 EOT_EOT
-# 9  <1> leavesub[1 ref] K/REFC,1 ->(end)
-# -     <@> lineseq KP ->9
-# 1        <;> nextstate(main 427 optree_samples.t:18) v:>,<,% ->2
+# 7  <1> leavesub[1 ref] K/REFC,1 ->(end)
+# -     <@> lineseq KP ->7
+# 1        <;> nextstate(main 665 optree_samples.t:24) v ->2
 # -        <1> null K/1 ->-
-# 5           <|> cond_expr(other->6) K/1 ->a
-# 4              <1> shift sK/1 ->5
-# 3                 <1> rv2av[t1] sKRM/1 ->4
-# 2                    <$> gv(*_) s ->3
+# 3           <|> cond_expr(other->4) K/1 ->8
+# 2              <0> shift s* ->3
 # -              <@> scope K ->-
-# -                 <0> ex-nextstate v ->6
-# 8                 <@> print sK ->9
-# 6                    <0> pushmark s ->7
-# 7                    <$> const(PV "then") s ->8
-# f              <@> leave KP ->9
-# a                 <0> enter ->b
-# b                 <;> nextstate(main 425 optree_samples.t:19) v:>,<,% ->c
-# e                 <@> print sK ->f
-# c                    <0> pushmark s ->d
-# d                    <$> const(PV "else") s ->e
+# -                 <0> ex-nextstate v ->4
+# 6                 <@> print sK ->7
+# 4                    <0> pushmark s ->5
+# 5                    <$> const(PV "then") s ->6
+# d              <@> leave KP ->7
+# 8                 <0> enter ->9
+# 9                 <;> nextstate(main 663 optree_samples.t:25) v ->a
+# c                 <@> print sK ->d
+# a                    <0> pushmark s ->b
+# b                    <$> const(PV "else") s ->c
 EONT_EONT
 
 checkOptree ( name     => '-basic (see above, with my $a = shift)',
@@ -75,53 +71,49 @@ checkOptree ( name  => '-basic (see above, with my $a = shift)',
                             },
              strip_open_hints => 1,
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# d  <1> leavesub[1 ref] K/REFC,1 ->(end)
-# -     <@> lineseq KP ->d
-# 1        <;> nextstate(main 431 optree.t:68) v:>,<,% ->2
-# 6        <2> sassign vKS/2 ->7
-# 4           <1> shift sK/1 ->5
-# 3              <1> rv2av[t3] sKRM/1 ->4
-# 2                 <#> gv[*_] s ->3
-# 5           <0> padsv[$a:431,435] sRM*/LVINTRO ->6
-# 7        <;> nextstate(main 435 optree.t:69) v:>,<,% ->8
+# b  <1> leavesub[1 ref] K/REFC,1 ->(end)
+# -     <@> lineseq KP ->b
+# 1        <;> nextstate(main 666 optree_samples.t:70) v ->2
+# 4        <2> sassign vKS/2 ->5
+# 2           <0> shift s* ->3
+# 3           <0> padsv[$a:666,670] sRM*/LVINTRO ->4
+# 5        <;> nextstate(main 670 optree_samples.t:71) v ->6
 # -        <1> null K/1 ->-
-# 9           <|> cond_expr(other->a) K/1 ->e
-# 8              <0> padsv[$a:431,435] s ->9
+# 7           <|> cond_expr(other->8) K/1 ->c
+# 6              <0> padsv[$a:666,670] s ->7
 # -              <@> scope K ->-
-# -                 <0> ex-nextstate v ->a
-# c                 <@> print sK ->d
-# a                    <0> pushmark s ->b
-# b                    <$> const[PV "foo"] s ->c
-# j              <@> leave KP ->d
-# e                 <0> enter ->f
-# f                 <;> nextstate(main 433 optree.t:70) v:>,<,% ->g
-# i                 <@> print sK ->j
-# g                    <0> pushmark s ->h
-# h                    <$> const[PV "bar"] s ->i
+# -                 <0> ex-nextstate v ->8
+# a                 <@> print sK ->b
+# 8                    <0> pushmark s ->9
+# 9                    <$> const[PV "foo"] s ->a
+# h              <@> leave KP ->b
+# c                 <0> enter ->d
+# d                 <;> nextstate(main 668 optree_samples.t:72) v ->e
+# g                 <@> print sK ->h
+# e                    <0> pushmark s ->f
+# f                    <$> const[PV "bar"] s ->g
 EOT_EOT
-# d  <1> leavesub[1 ref] K/REFC,1 ->(end)
-# -     <@> lineseq KP ->d
-# 1        <;> nextstate(main 428 optree_samples.t:48) v:>,<,% ->2
-# 6        <2> sassign vKS/2 ->7
-# 4           <1> shift sK/1 ->5
-# 3              <1> rv2av[t2] sKRM/1 ->4
-# 2                 <$> gv(*_) s ->3
-# 5           <0> padsv[$a:428,432] sRM*/LVINTRO ->6
-# 7        <;> nextstate(main 432 optree_samples.t:49) v:>,<,% ->8
+# b  <1> leavesub[1 ref] K/REFC,1 ->(end)
+# -     <@> lineseq KP ->b
+# 1        <;> nextstate(main 666 optree_samples.t:72) v ->2
+# 4        <2> sassign vKS/2 ->5
+# 2           <0> shift s* ->3
+# 3           <0> padsv[$a:666,670] sRM*/LVINTRO ->4
+# 5        <;> nextstate(main 670 optree_samples.t:73) v ->6
 # -        <1> null K/1 ->-
-# 9           <|> cond_expr(other->a) K/1 ->e
-# 8              <0> padsv[$a:428,432] s ->9
+# 7           <|> cond_expr(other->8) K/1 ->c
+# 6              <0> padsv[$a:666,670] s ->7
 # -              <@> scope K ->-
-# -                 <0> ex-nextstate v ->a
-# c                 <@> print sK ->d
-# a                    <0> pushmark s ->b
-# b                    <$> const(PV "foo") s ->c
-# j              <@> leave KP ->d
-# e                 <0> enter ->f
-# f                 <;> nextstate(main 430 optree_samples.t:50) v:>,<,% ->g
-# i                 <@> print sK ->j
-# g                    <0> pushmark s ->h
-# h                    <$> const(PV "bar") s ->i
+# -                 <0> ex-nextstate v ->8
+# a                 <@> print sK ->b
+# 8                    <0> pushmark s ->9
+# 9                    <$> const(PV "foo") s ->a
+# h              <@> leave KP ->b
+# c                 <0> enter ->d
+# d                 <;> nextstate(main 668 optree_samples.t:74) v ->e
+# g                 <@> print sK ->h
+# e                    <0> pushmark s ->f
+# f                    <$> const(PV "bar") s ->g
 EONT_EONT
 
 checkOptree ( name     => '-exec sub {if shift print then,else}',
@@ -131,39 +123,35 @@ checkOptree ( name        => '-exec sub {if shift print then,else}',
                             },
              strip_open_hints => 1,
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 426 optree.t:16) v:>,<,%
-# 2  <#> gv[*_] s
-# 3  <1> rv2av[t2] sKRM/1
-# 4  <1> shift sK/1
-# 5  <|> cond_expr(other->6) K/1
-# 6      <0> pushmark s
-# 7      <$> const[PV "then"] s
-# 8      <@> print sK
-#            goto 9
-# a  <0> enter 
-# b  <;> nextstate(main 424 optree.t:17) v:>,<,%
-# c  <0> pushmark s
-# d  <$> const[PV "else"] s
-# e  <@> print sK
-# f  <@> leave KP
-# 9  <1> leavesub[1 ref] K/REFC,1
+# 1  <;> nextstate(main 674 optree_samples.t:125) v
+# 2  <0> shift s*
+# 3  <|> cond_expr(other->4) K/1
+# 4      <0> pushmark s
+# 5      <$> const[PV "then"] s
+# 6      <@> print sK
+#            goto 7
+# 8  <0> enter 
+# 9  <;> nextstate(main 672 optree_samples.t:126) v
+# a  <0> pushmark s
+# b  <$> const[PV "else"] s
+# c  <@> print sK
+# d  <@> leave KP
+# 7  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 436 optree_samples.t:123) v:>,<,%
-# 2  <$> gv(*_) s
-# 3  <1> rv2av[t1] sKRM/1
-# 4  <1> shift sK/1
-# 5  <|> cond_expr(other->6) K/1
-# 6      <0> pushmark s
-# 7      <$> const(PV "then") s
-# 8      <@> print sK
-#            goto 9
-# a  <0> enter 
-# b  <;> nextstate(main 434 optree_samples.t:124) v:>,<,%
-# c  <0> pushmark s
-# d  <$> const(PV "else") s
-# e  <@> print sK
-# f  <@> leave KP
-# 9  <1> leavesub[1 ref] K/REFC,1
+# 1  <;> nextstate(main 674 optree_samples.t:129) v
+# 2  <0> shift s*
+# 3  <|> cond_expr(other->4) K/1
+# 4      <0> pushmark s
+# 5      <$> const(PV "then") s
+# 6      <@> print sK
+#            goto 7
+# 8  <0> enter 
+# 9  <;> nextstate(main 672 optree_samples.t:130) v
+# a  <0> pushmark s
+# b  <$> const(PV "else") s
+# c  <@> print sK
+# d  <@> leave KP
+# 7  <1> leavesub[1 ref] K/REFC,1
 EONT_EONT
 
 checkOptree ( name     => '-exec (see above, with my $a = shift)',
@@ -174,47 +162,43 @@ checkOptree ( name        => '-exec (see above, with my $a = shift)',
                             },
              strip_open_hints => 1,
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 423 optree.t:16) v:>,<,%
-# 2  <#> gv[*_] s
-# 3  <1> rv2av[t3] sKRM/1
-# 4  <1> shift sK/1
-# 5  <0> padsv[$a:423,427] sRM*/LVINTRO
-# 6  <2> sassign vKS/2
-# 7  <;> nextstate(main 427 optree.t:17) v:>,<,%
-# 8  <0> padsv[$a:423,427] s
-# 9  <|> cond_expr(other->a) K/1
-# a      <0> pushmark s
-# b      <$> const[PV "foo"] s
-# c      <@> print sK
-#            goto d
-# e  <0> enter 
-# f  <;> nextstate(main 425 optree.t:18) v:>,<,%
-# g  <0> pushmark s
-# h  <$> const[PV "bar"] s
-# i  <@> print sK
-# j  <@> leave KP
-# d  <1> leavesub[1 ref] K/REFC,1
+# 1  <;> nextstate(main 675 optree_samples.t:165) v
+# 2  <0> shift s*
+# 3  <0> padsv[$a:675,679] sRM*/LVINTRO
+# 4  <2> sassign vKS/2
+# 5  <;> nextstate(main 679 optree_samples.t:166) v
+# 6  <0> padsv[$a:675,679] s
+# 7  <|> cond_expr(other->8) K/1
+# 8      <0> pushmark s
+# 9      <$> const[PV "foo"] s
+# a      <@> print sK
+#            goto b
+# c  <0> enter 
+# d  <;> nextstate(main 677 optree_samples.t:167) v
+# e  <0> pushmark s
+# f  <$> const[PV "bar"] s
+# g  <@> print sK
+# h  <@> leave KP
+# b  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 437 optree_samples.t:112) v:>,<,%
-# 2  <$> gv(*_) s
-# 3  <1> rv2av[t2] sKRM/1
-# 4  <1> shift sK/1
-# 5  <0> padsv[$a:437,441] sRM*/LVINTRO
-# 6  <2> sassign vKS/2
-# 7  <;> nextstate(main 441 optree_samples.t:113) v:>,<,%
-# 8  <0> padsv[$a:437,441] s
-# 9  <|> cond_expr(other->a) K/1
-# a      <0> pushmark s
-# b      <$> const(PV "foo") s
-# c      <@> print sK
-#            goto d
-# e  <0> enter 
-# f  <;> nextstate(main 439 optree_samples.t:114) v:>,<,%
-# g  <0> pushmark s
-# h  <$> const(PV "bar") s
-# i  <@> print sK
-# j  <@> leave KP
-# d  <1> leavesub[1 ref] K/REFC,1
+# 1  <;> nextstate(main 675 optree_samples.t:171) v
+# 2  <0> shift s*
+# 3  <0> padsv[$a:675,679] sRM*/LVINTRO
+# 4  <2> sassign vKS/2
+# 5  <;> nextstate(main 679 optree_samples.t:172) v
+# 6  <0> padsv[$a:675,679] s
+# 7  <|> cond_expr(other->8) K/1
+# 8      <0> pushmark s
+# 9      <$> const(PV "foo") s
+# a      <@> print sK
+#            goto b
+# c  <0> enter 
+# d  <;> nextstate(main 677 optree_samples.t:173) v
+# e  <0> pushmark s
+# f  <$> const(PV "bar") s
+# g  <@> print sK
+# h  <@> leave KP
+# b  <1> leavesub[1 ref] K/REFC,1
 EONT_EONT
 
 checkOptree ( name     => '-exec sub { print (shift) ? "foo" : "bar" }',
@@ -222,29 +206,25 @@ checkOptree ( name        => '-exec sub { print (shift) ? "foo" : "bar" }',
              bcopts    => '-exec',
              strip_open_hints => 1,
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 428 optree.t:31) v:>,<,%
+# 1  <;> nextstate(main 680 optree_samples.t:213) v
 # 2  <0> pushmark s
-# 3  <#> gv[*_] s
-# 4  <1> rv2av[t2] sKRM/1
-# 5  <1> shift sK/1
-# 6  <@> print sK
-# 7  <|> cond_expr(other->8) K/1
-# 8      <$> const[PV "foo"] s
-#            goto 9
-# a  <$> const[PV "bar"] s
-# 9  <1> leavesub[1 ref] K/REFC,1
+# 3  <0> shift s*
+# 4  <@> print sK
+# 5  <|> cond_expr(other->6) K/1
+# 6      <$> const[PV "foo"] s
+#            goto 7
+# 8  <$> const[PV "bar"] s
+# 7  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 442 optree_samples.t:144) v:>,<,%
+# 1  <;> nextstate(main 680 optree_samples.t:221) v
 # 2  <0> pushmark s
-# 3  <$> gv(*_) s
-# 4  <1> rv2av[t1] sKRM/1
-# 5  <1> shift sK/1
-# 6  <@> print sK
-# 7  <|> cond_expr(other->8) K/1
-# 8      <$> const(PV "foo") s
-#            goto 9
-# a  <$> const(PV "bar") s
-# 9  <1> leavesub[1 ref] K/REFC,1
+# 3  <0> shift s*
+# 4  <@> print sK
+# 5  <|> cond_expr(other->6) K/1
+# 6      <$> const(PV "foo") s
+#            goto 7
+# 8  <$> const(PV "bar") s
+# 7  <1> leavesub[1 ref] K/REFC,1
 EONT_EONT
 
 pass ("FOREACH");
diff --git a/op.c b/op.c
index 76eb16f..661d0aa 100644 (file)
--- a/op.c
+++ b/op.c
@@ -7746,8 +7746,14 @@ Perl_ck_shift(pTHX_ OP *o)
     PERL_ARGS_ASSERT_CK_SHIFT;
 
     if (!(o->op_flags & OPf_KIDS)) {
-       OP *argop = newUNOP(OP_RV2AV, 0,
-           scalar(newGVOP(OP_GV, 0, CvUNIQUE(PL_compcv) ? PL_argvgv : PL_defgv)));
+       OP *argop;
+
+       if (!CvUNIQUE(PL_compcv)) {
+           o->op_flags |= OPf_SPECIAL;
+           return o;
+       }
+
+       argop = newUNOP(OP_RV2AV, 0, scalar(newGVOP(OP_GV, 0, PL_argvgv)));
 #ifdef PERL_MAD
        OP * const oldo = o;
        o = newUNOP(type, 0, scalar(argop));
index da78d14..343c2c5 100644 (file)
@@ -34,6 +34,12 @@ name such as ps, top and killall will recognize the name you set when
 assigning to C<$0>. The string you supply will be cut off at 16 bytes,
 this is a limitation imposed by Linux.
 
+=head2 Optimization of shift; and pop; calls without arguments
+
+Additional two OPs are not added anymore into op tree for shift and pop
+calls without argument (when it works on C<@_>). Makes C<shift;> 5%
+faster over C<shift @_;> on not threaded perl and 25% faster on threaded.
+
 =head1 Modules and Pragmata
 
 =head2 Updated Modules
diff --git a/pp.c b/pp.c
index 3cc8869..e998e21 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -5326,7 +5326,8 @@ PP(pp_shift)
 {
     dVAR;
     dSP;
-    AV * const av = MUTABLE_AV(POPs);
+    AV * const av = PL_op->op_flags & OPf_SPECIAL
+       ? MUTABLE_AV(GvAV(PL_defgv)) : MUTABLE_AV(POPs);
     SV * const sv = PL_op->op_type == OP_SHIFT ? av_shift(av) : av_pop(av);
     EXTEND(SP, 1);
     assert (sv);