Skip to content

Commit 9fdd7fc

Browse files
committed
Implement OP_PADSV_STORE - combined sassign/padsv OP
This commit introduces a new OP to replace simple cases of OP_SASSIGN and OP_PADSV. For example, 'my $x = 1' is currently implemented as: 1 <;> nextstate(main 1 -e:1) v:{ 2 <$> const(IV 1) s 3 <0> padsv[$x:1,2] sRM*/LVINTRO 4 <2> sassign vKS/2 But now will be turned into: 1 <;> nextstate(main 1 -e:1) v:{ 2 <$> const(IV 1) s 3 <1> padsv_store[$x:1,2] vKMS/LVINTRO This intended to be a transparent performance optimization. It should be applicable for RHS optrees of varying complexity.
1 parent 434ccf3 commit 9fdd7fc

15 files changed

+875
-755
lines changed

ext/B/t/b.t

+1-1
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ is(B::opnumber("pp_null"), 0, "Testing opnumber with opname (pp_null)");
306306

307307
is(B::class(bless {}, "Wibble::Bibble"), "Bibble", "Testing B::class()");
308308
is(B::cast_I32(3.14), 3, "Testing B::cast_I32()");
309-
is(B::opnumber("chop"), 38, "Testing opnumber with opname (chop)");
309+
is(B::opnumber("chop"), 39, "Testing opnumber with opname (chop)");
310310

311311
{
312312
no warnings 'once';

ext/B/t/optree_concise.t

+2-2
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,13 @@ checkOptree ( name => "terse basic",
178178
UNOP (0x82b0918) leavesub [1]
179179
LISTOP (0x82b08d8) lineseq
180180
COP (0x82b0880) nextstate
181-
UNOP (0x82b0860) null [14]
181+
UNOP (0x82b0860) null [15]
182182
PADOP (0x82b0840) gvsv GV (0x82a818c) *a
183183
EOT_EOT
184184
# UNOP (0x8282310) leavesub [1]
185185
# LISTOP (0x82822f0) lineseq
186186
# COP (0x82822b8) nextstate
187-
# UNOP (0x812fc20) null [14]
187+
# UNOP (0x812fc20) null [15]
188188
# SVOP (0x812fc00) gvsv GV (0x814692c) *a
189189
EONT_EONT
190190

ext/B/t/optree_samples.t

+65-67
Original file line numberDiff line numberDiff line change
@@ -67,49 +67,49 @@ checkOptree ( name => '-basic (see above, with my $a = shift)',
6767
},
6868
strip_open_hints => 1,
6969
expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
70-
# b <1> leavesub[1 ref] K/REFC,1 ->(end)
71-
# - <@> lineseq KP ->b
70+
# a <1> leavesub[1 ref] K/REFC,1 ->(end)
71+
# - <@> lineseq KP ->a
7272
# 1 <;> nextstate(main 666 optree_samples.t:70) v:>,<,% ->2
73-
# 4 <2> sassign vKS/2 ->5
73+
# 3 <1> padsv_store[$a:666,670] vKS/LVINTRO ->4
7474
# 2 <0> shift s* ->3
75-
# 3 <0> padsv[$a:666,670] sRM*/LVINTRO ->4
76-
# 5 <;> nextstate(main 670 optree_samples.t:71) v:>,<,% ->6
75+
# - <0> ex-padsv sRM*/LVINTRO ->3
76+
# 4 <;> nextstate(main 670 optree_samples.t:71) v:>,<,% ->5
7777
# - <1> null K/1 ->-
78-
# 7 <|> cond_expr(other->8) K/1 ->c
79-
# 6 <0> padsv[$a:666,670] s ->7
78+
# 6 <|> cond_expr(other->7) K/1 ->b
79+
# 5 <0> padsv[$a:666,670] s ->6
8080
# - <@> scope K ->-
81-
# - <;> ex-nextstate(main 1603 optree_samples.t:70) v:>,<,% ->8
82-
# a <@> print sK ->b
83-
# 8 <0> pushmark s ->9
84-
# 9 <$> const[PV "foo"] s ->a
85-
# h <@> leave KP ->b
86-
# c <0> enter ->d
87-
# d <;> nextstate(main 668 optree_samples.t:72) v:>,<,% ->e
88-
# g <@> print sK ->h
89-
# e <0> pushmark s ->f
90-
# f <$> const[PV "bar"] s ->g
81+
# - <;> ex-nextstate(main 1510 optree_samples.t:66) v:>,<,% ->7
82+
# 9 <@> print sK ->a
83+
# 7 <0> pushmark s ->8
84+
# 8 <$> const[PV "foo"] s ->9
85+
# g <@> leave KP ->a
86+
# b <0> enter ->c
87+
# c <;> nextstate(main 1510 optree_samples.t:66) v:>,<,% ->d
88+
# f <@> print sK ->g
89+
# d <0> pushmark s ->e
90+
# e <$> const[PV "bar"] s ->f
9191
EOT_EOT
92-
# b <1> leavesub[1 ref] K/REFC,1 ->(end)
93-
# - <@> lineseq KP ->b
94-
# 1 <;> nextstate(main 666 optree_samples.t:72) v:>,<,% ->2
95-
# 4 <2> sassign vKS/2 ->5
92+
# a <1> leavesub[1 ref] K/REFC,1 ->(end)
93+
# - <@> lineseq KP ->a
94+
# 1 <;> nextstate(main 666 optree_samples.t:70) v:>,<,% ->2
95+
# 3 <1> padsv_store[$a:666,670] vKS/LVINTRO ->4
9696
# 2 <0> shift s* ->3
97-
# 3 <0> padsv[$a:666,670] sRM*/LVINTRO ->4
98-
# 5 <;> nextstate(main 670 optree_samples.t:73) v:>,<,% ->6
97+
# - <0> ex-padsv sRM*/LVINTRO ->3
98+
# 4 <;> nextstate(main 670 optree_samples.t:71) v:>,<,% ->5
9999
# - <1> null K/1 ->-
100-
# 7 <|> cond_expr(other->8) K/1 ->c
101-
# 6 <0> padsv[$a:666,670] s ->7
100+
# 6 <|> cond_expr(other->7) K/1 ->b
101+
# 5 <0> padsv[$a:666,670] s ->6
102102
# - <@> scope K ->-
103-
# - <;> ex-nextstate(main 1603 optree_samples.t:70) v:>,<,% ->8
104-
# a <@> print sK ->b
105-
# 8 <0> pushmark s ->9
106-
# 9 <$> const(PV "foo") s ->a
107-
# h <@> leave KP ->b
108-
# c <0> enter ->d
109-
# d <;> nextstate(main 668 optree_samples.t:74) v:>,<,% ->e
110-
# g <@> print sK ->h
111-
# e <0> pushmark s ->f
112-
# f <$> const(PV "bar") s ->g
103+
# - <;> ex-nextstate(main 1510 optree_samples.t:70) v:>,<,% ->7
104+
# 9 <@> print sK ->a
105+
# 7 <0> pushmark s ->8
106+
# 8 <$> const(PV "foo") s ->9
107+
# g <@> leave KP ->a
108+
# b <0> enter ->c
109+
# c <;> nextstate(main 668 optree_samples.t:72) v:>,<,% ->d
110+
# f <@> print sK ->g
111+
# d <0> pushmark s ->e
112+
# e <$> const(PV "bar") s ->f
113113
EONT_EONT
114114

115115
checkOptree ( name => '-exec sub {if shift print then,else}',
@@ -160,41 +160,39 @@ checkOptree ( name => '-exec (see above, with my $a = shift)',
160160
expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
161161
# 1 <;> nextstate(main 675 optree_samples.t:165) v:>,<,%
162162
# 2 <0> shift s*
163-
# 3 <0> padsv[$a:675,679] sRM*/LVINTRO
164-
# 4 <2> sassign vKS/2
165-
# 5 <;> nextstate(main 679 optree_samples.t:166) v:>,<,%
166-
# 6 <0> padsv[$a:675,679] s
167-
# 7 <|> cond_expr(other->8) K/1
168-
# 8 <0> pushmark s
169-
# 9 <$> const[PV "foo"] s
170-
# a <@> print sK
171-
# goto b
172-
# c <0> enter
173-
# d <;> nextstate(main 677 optree_samples.t:167) v:>,<,%
174-
# e <0> pushmark s
175-
# f <$> const[PV "bar"] s
176-
# g <@> print sK
177-
# h <@> leave KP
178-
# b <1> leavesub[1 ref] K/REFC,1
163+
# 3 <1> padsv_store[$a:1522,1529] vKS/LVINTRO
164+
# 4 <;> nextstate(main 679 optree_samples.t:166) v:>,<,%
165+
# 5 <0> padsv[$a:675,679] s
166+
# 6 <|> cond_expr(other->7) K/1
167+
# 7 <0> pushmark s
168+
# 8 <$> const[PV "foo"] s
169+
# 9 <@> print sK
170+
# goto a
171+
# b <0> enter
172+
# c <;> nextstate(main 677 optree_samples.t:167) v:>,<,%
173+
# d <0> pushmark s
174+
# e <$> const[PV "bar"] s
175+
# f <@> print sK
176+
# g <@> leave KP
177+
# a <1> leavesub[1 ref] K/REFC,1
179178
EOT_EOT
180179
# 1 <;> nextstate(main 675 optree_samples.t:171) v:>,<,%
181180
# 2 <0> shift s*
182-
# 3 <0> padsv[$a:675,679] sRM*/LVINTRO
183-
# 4 <2> sassign vKS/2
184-
# 5 <;> nextstate(main 679 optree_samples.t:172) v:>,<,%
185-
# 6 <0> padsv[$a:675,679] s
186-
# 7 <|> cond_expr(other->8) K/1
187-
# 8 <0> pushmark s
188-
# 9 <$> const(PV "foo") s
189-
# a <@> print sK
190-
# goto b
191-
# c <0> enter
192-
# d <;> nextstate(main 677 optree_samples.t:173) v:>,<,%
193-
# e <0> pushmark s
194-
# f <$> const(PV "bar") s
195-
# g <@> print sK
196-
# h <@> leave KP
197-
# b <1> leavesub[1 ref] K/REFC,1
181+
# 3 <1> padsv_store[$a:1522,1529] vKS/LVINTRO
182+
# 4 <;> nextstate(main 679 optree_samples.t:172) v:>,<,%
183+
# 5 <0> padsv[$a:675,679] s
184+
# 6 <|> cond_expr(other->7) K/1
185+
# 7 <0> pushmark s
186+
# 8 <$> const(PV "foo") s
187+
# 9 <@> print sK
188+
# goto a
189+
# b <0> enter
190+
# c <;> nextstate(main 677 optree_samples.t:173) v:>,<,%
191+
# d <0> pushmark s
192+
# e <$> const(PV "bar") s
193+
# f <@> print sK
194+
# g <@> leave KP
195+
# a <1> leavesub[1 ref] K/REFC,1
198196
EONT_EONT
199197

200198
checkOptree ( name => '-exec sub { print (shift) ? "foo" : "bar" }',

ext/B/t/optree_varinit.t

+22-26
Original file line numberDiff line numberDiff line change
@@ -129,19 +129,19 @@ checkOptree ( name => 'sub {my $a=undef}',
129129
bcopts => '-basic',
130130
strip_open_hints => 1,
131131
expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
132-
5 <1> leavesub[1 ref] K/REFC,1 ->(end)
133-
- <@> lineseq KP ->5
132+
4 <1> leavesub[1 ref] K/REFC,1 ->(end)
133+
- <@> lineseq KP ->4
134134
1 <;> nextstate(main 641 optree_varinit.t:130) v:>,<,% ->2
135-
4 <2> sassign sKS/2 ->5
135+
3 <1> padsv_store[$a:1508,1509] sKS/LVINTRO ->4
136136
2 <0> undef s ->3
137-
3 <0> padsv[$a:641,642] sRM*/LVINTRO ->4
137+
- <0> ex-padsv sRM*/LVINTRO ->3
138138
EOT_EOT
139-
# 5 <1> leavesub[1 ref] K/REFC,1 ->(end)
140-
# - <@> lineseq KP ->5
139+
# 4 <1> leavesub[1 ref] K/REFC,1 ->(end)
140+
# - <@> lineseq KP ->4
141141
# 1 <;> nextstate(main 641 optree_varinit.t:130) v:>,<,% ->2
142-
# 4 <2> sassign sKS/2 ->5
142+
# 3 <1> padsv_store[$a:1508,1509] sKS/LVINTRO ->4
143143
# 2 <0> undef s ->3
144-
# 3 <0> padsv[$a:641,642] sRM*/LVINTRO ->4
144+
# - <0> ex-padsv sRM*/LVINTRO ->3
145145
EONT_EONT
146146

147147
checkOptree ( name => 'sub {our $a=undef}',
@@ -195,19 +195,19 @@ checkOptree ( name => 'my $a=undef',
195195
bcopts => '-basic',
196196
strip_open_hints => 1,
197197
expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
198-
6 <@> leave[1 ref] vKP/REFC ->(end)
198+
5 <@> leave[1 ref] vKP/REFC ->(end)
199199
1 <0> enter v ->2
200200
2 <;> nextstate(main 1 -e:1) v:>,<,%,{ ->3
201-
5 <2> sassign vKS/2 ->6
201+
4 <1> padsv_store[$a:1,2] vKS/LVINTRO ->5
202202
3 <0> undef s ->4
203-
4 <0> padsv[$a:1,2] sRM*/LVINTRO ->5
203+
- <0> ex-padsv sRM*/LVINTRO ->4
204204
EOT_EOT
205-
# 6 <@> leave[1 ref] vKP/REFC ->(end)
205+
# 5 <@> leave[1 ref] vKP/REFC ->(end)
206206
# 1 <0> enter v ->2
207207
# 2 <;> nextstate(main 1 -e:1) v:>,<,%,{ ->3
208-
# 5 <2> sassign vKS/2 ->6
208+
# 4 <1> padsv_store[$a:1,2] vKS/LVINTRO ->5
209209
# 3 <0> undef s ->4
210-
# 4 <0> padsv[$a:1,2] sRM*/LVINTRO ->5
210+
# - <0> ex-padsv sRM*/LVINTRO ->4
211211
EONT_EONT
212212

213213
checkOptree ( name => 'our $a=undef',
@@ -264,15 +264,13 @@ checkOptree ( name => 'sub {my $a=()}',
264264
expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
265265
1 <;> nextstate(main -439 optree.t:105) v:>,<,%
266266
2 <0> stub sP
267-
3 <0> padsv[$a:-439,-438] sRM*/LVINTRO
268-
4 <2> sassign sKS/2
269-
5 <1> leavesub[1 ref] K/REFC,1
267+
3 <1> padsv_store[$a:1516,1517] sKS/LVINTRO
268+
4 <1> leavesub[1 ref] K/REFC,1
270269
EOT_EOT
271270
# 1 <;> nextstate(main 438 optree_varinit.t:247) v:>,<,%
272271
# 2 <0> stub sP
273-
# 3 <0> padsv[$a:438,439] sRM*/LVINTRO
274-
# 4 <2> sassign sKS/2
275-
# 5 <1> leavesub[1 ref] K/REFC,1
272+
# 3 <1> padsv_store[$a:1516,1517] sKS/LVINTRO
273+
# 4 <1> leavesub[1 ref] K/REFC,1
276274
EONT_EONT
277275

278276
checkOptree ( name => 'sub {our $a=()}',
@@ -321,16 +319,14 @@ checkOptree ( name => 'my $a=()',
321319
1 <0> enter v
322320
2 <;> nextstate(main 1 -e:1) v:>,<,%,{
323321
3 <0> stub sP
324-
4 <0> padsv[$a:1,2] sRM*/LVINTRO
325-
5 <2> sassign vKS/2
326-
6 <@> leave[1 ref] vKP/REFC
322+
4 <1> padsv_store[$a:1516,1517] vKS/LVINTRO
323+
5 <@> leave[1 ref] vKP/REFC
327324
EOT_EOT
328325
# 1 <0> enter v
329326
# 2 <;> nextstate(main 1 -e:1) v:>,<,%,{
330327
# 3 <0> stub sP
331-
# 4 <0> padsv[$a:1,2] sRM*/LVINTRO
332-
# 5 <2> sassign vKS/2
333-
# 6 <@> leave[1 ref] vKP/REFC
328+
# 4 <1> padsv_store[$a:1516,1517] vKS/LVINTRO
329+
# 5 <@> leave[1 ref] vKP/REFC
334330
EONT_EONT
335331

336332
checkOptree ( name => 'our $a=()',

ext/Opcode/Opcode.pm

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package Opcode 1.59;
1+
package Opcode 1.60;
22

33
use strict;
44

@@ -302,7 +302,7 @@ invert_opset function.
302302
303303
null stub scalar pushmark wantarray const defined undef
304304
305-
rv2sv sassign
305+
rv2sv sassign padsv_store
306306
307307
rv2av aassign aelem aelemfast aelemfast_lex aslice kvaslice
308308
av2arylen

lib/B/Deparse.pm

+13-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# This is based on the module of the same name by Malcolm Beattie,
88
# but essentially none of his code remains.
99

10-
package B::Deparse 1.67;
10+
package B::Deparse 1.68;
1111
use strict;
1212
use Carp;
1313
use B qw(class main_root main_start main_cv svref_2object opnumber perlstring
@@ -3092,6 +3092,18 @@ sub pp_isa { binop(@_, "isa", 15) }
30923092
sub pp_sassign { binop(@_, "=", 7, SWAP_CHILDREN) }
30933093
sub pp_aassign { binop(@_, "=", 7, SWAP_CHILDREN | LIST_CONTEXT) }
30943094

3095+
sub pp_padsv_store {
3096+
my $self = shift;
3097+
my ($op, $cx, $forbid_parens, @args) = @_;
3098+
my $targ = $op->targ;
3099+
my $var = $self->maybe_my($op, $cx, $self->padname($targ),
3100+
$self->padname_sv($targ),
3101+
$forbid_parens);
3102+
3103+
my $val = $self->deparse($op->first, 7);
3104+
return $self->maybe_parens("$var = $val", $cx, 7);
3105+
}
3106+
30953107
sub pp_smartmatch {
30963108
my ($self, $op, $cx) = @_;
30973109
if (($op->flags & OPf_SPECIAL) && $self->{expand} < 2) {

lib/B/Op_private.pm

+5-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)