3 # This file specifies an array-of-hashes that define snippets of code that
4 # can be run by various measurement and profiling tools.
6 # The basic idea is that any time you add an optimisation that is intended
7 # to make a particular construct faster, then you should add that construct
10 # Under the normal test suite, the test file benchmarks.t does a basic
11 # compile and run of each of these snippets; not to test performance,
12 # but just to ensure that the code doesn't have errors.
14 # Over time, it is intended that various measurement and profiling tools
15 # will be written that can run selected (or all) snippets in various
16 # environments. These will not be run as part of a normal test suite run.
18 # It is intended that the tests in this file will be lightweight; e.g.
19 # a hash access, an empty function call, or a single regex match etc.
21 # This file is designed to be read in by 'do' (and in such a way that
22 # multiple versions of this file from different releases can be read in
23 # by a single process).
25 # The top-level array has name/hash pairs (we use an array rather than a
26 # hash so that duplicate keys can be spotted) Each name is a token that
27 # describes a particular test. Code will be compiled in the package named
28 # after the token, so it should match /^(\w|::)+$/a. It is intended that
29 # this can be used on the command line of tools to select particular
31 # In addition, the package names are arranged into an informal hierarchy
32 # whose top members are (this is subject to change):
34 # call:: subroutine and method handling
35 # expr:: expressions: e.g. $x=1, $foo{bar}[0]
36 # func:: perl functions, e.g. func::sort::...
37 # loop:: structural code like for, while(), etc
38 # regex:: regular expressions
39 # string:: string handling
42 # Each hash has three fields:
44 # desc is a description of the test
45 # setup is a string containing setup code
46 # code is a string containing the code to run in a loop
48 # So typically a benchmark tool might do something like
50 # eval "package $token; $setup; for (1..1000000) { $code }"
52 # Currently the only tool that uses this file is Porting/bench.pl;
53 # try C<perl Porting/bench.pl --help> for more info
57 # Note: for the cachegrind variant, an entry like
62 # creates two temporary perl sources looking like:
67 # for my $__loop__ (1..$ARGV[0]) {
71 # and as above, but with the '1;' in the loop body replaced with:
75 # It then pipes each of the two sources into
77 # PERL_HASH_SEED=0 valgrind [options] someperl [options] - N
79 # where N is set to 10 and then 20.
81 # It then uses the result of those four cachegrind runs to subtract out
82 # the perl startup and loop overheads. So only what's in SETUP and CODE
83 # can affect the benchmark, and if the loop happens to leave some state
84 # changed (such as storing a value in a hash), then the final benchmark
85 # timing is the result of running CODE with the hash entry populated
90 'call::sub::empty' => {
91 desc => 'function call with no args or body',
95 'call::sub::amp_empty' => {
96 desc => '&foo function call with no args or body',
97 setup => 'sub f { }; @_ = ();',
100 'call::sub::args3' => {
101 desc => 'function call with 3 local lexical vars',
102 setup => 'sub f { my ($a, $b, $c) = @_; 1 }',
105 'call::sub::args2_ret1' => {
106 desc => 'function call with 2 local lex vars and 1 return value',
107 setup => 'my $x; sub f { my ($a, $b) = @_; $a+$b }',
108 code => '$x = f(1,2)',
110 'call::sub::args2_ret1temp' => {
111 desc => 'function call with 2 local lex vars and 1 return TEMP value',
112 setup => 'my $x; sub f { my ($a, $b) = @_; \$a }',
113 code => '$x = f(1,2)',
115 'call::sub::args3_ret3' => {
116 desc => 'function call with 3 local lex vars and 3 return values',
117 setup => 'my @a; sub f { my ($a, $b, $c) = @_; $a+$b, $c, 1 }',
118 code => '@a = f(1,2,3)',
120 'call::sub::args3_ret3str' => {
121 desc => 'function call with 3 local lex vars and 3 string return values',
122 setup => 'my @a; sub f { my ($a, $b, $c) = @_; my @s = ("aa","bb","cc"); @s }',
123 code => '@a = f(1,2,3)',
125 'call::sub::args3_ret3temp' => {
126 desc => 'function call with 3 local lex vars and 3 TEMP return values',
127 setup => 'my @a; sub f { my ($a, $b, $c) = @_; 1..3 }',
128 code => '@a = f(1,2,3)',
130 'call::sub::recursive' => {
131 desc => 'basic recursive function call',
132 setup => 'my $x; sub f { my ($i) = @_; $i > 0 ? $i + f($i-1) : 0 }',
136 'call::goto::empty' => {
137 desc => 'goto &funtion with no args or body',
138 setup => 'sub f { goto &g } sub g {}',
141 'call::goto::args3' => {
142 desc => 'goto &funtion with 3 local lexical vars',
143 setup => 'sub f { goto &g } sub g { my ($a, $b, $c) = @_ }',
148 'expr::array::lex_1const_0' => {
149 desc => 'lexical $array[0]',
150 setup => 'my @a = (1)',
153 'expr::array::lex_1const_m1' => {
154 desc => 'lexical $array[-1]',
155 setup => 'my @a = (1)',
158 'expr::array::lex_2const' => {
159 desc => 'lexical $array[const][const]',
160 setup => 'my @a = ([1,2])',
163 'expr::array::lex_2var' => {
164 desc => 'lexical $array[$i1][$i2]',
165 setup => 'my ($i1,$i2) = (0,1); my @a = ([1,2])',
166 code => '$a[$i1][$i2]',
168 'expr::array::ref_lex_2var' => {
169 desc => 'lexical $arrayref->[$i1][$i2]',
170 setup => 'my ($i1,$i2) = (0,1); my $r = [[1,2]]',
171 code => '$r->[$i1][$i2]',
173 'expr::array::ref_lex_3const' => {
174 desc => 'lexical $arrayref->[const][const][const]',
175 setup => 'my $r = [[[1,2]]]',
176 code => '$r->[0][0][0]',
178 'expr::array::ref_expr_lex_3const' => {
179 desc => '(lexical expr)->[const][const][const]',
180 setup => 'my $r = [[[1,2]]]',
181 code => '($r||0)->[0][0][0]',
185 'expr::array::pkg_1const_0' => {
186 desc => 'package $array[0]',
190 'expr::array::pkg_1const_m1' => {
191 desc => 'package $array[-1]',
195 'expr::array::pkg_2const' => {
196 desc => 'package $array[const][const]',
197 setup => '@a = ([1,2])',
200 'expr::array::pkg_2var' => {
201 desc => 'package $array[$i1][$i2]',
202 setup => '($i1,$i2) = (0,1); @a = ([1,2])',
203 code => '$a[$i1][$i2]',
205 'expr::array::ref_pkg_2var' => {
206 desc => 'package $arrayref->[$i1][$i2]',
207 setup => '($i1,$i2) = (0,1); $r = [[1,2]]',
208 code => '$r->[$i1][$i2]',
210 'expr::array::ref_pkg_3const' => {
211 desc => 'package $arrayref->[const][const][const]',
212 setup => '$r = [[[1,2]]]',
213 code => '$r->[0][0][0]',
215 'expr::array::ref_expr_pkg_3const' => {
216 desc => '(package expr)->[const][const][const]',
217 setup => '$r = [[[1,2]]]',
218 code => '($r||0)->[0][0][0]',
222 'expr::arrayhash::lex_3var' => {
223 desc => 'lexical $h{$k1}[$i]{$k2}',
224 setup => 'my ($i, $k1, $k2) = (0,"foo","bar");'
225 . 'my %h = (foo => [ { bar => 1 } ])',
226 code => '$h{$k1}[$i]{$k2}',
228 'expr::arrayhash::pkg_3var' => {
229 desc => 'package $h{$k1}[$i]{$k2}',
230 setup => '($i, $k1, $k2) = (0,"foo","bar");'
231 . '%h = (foo => [ { bar => 1 } ])',
232 code => '$h{$k1}[$i]{$k2}',
235 'expr::hash::lex_1const' => {
236 desc => 'lexical $hash{const}',
237 setup => 'my %h = ("foo" => 1)',
240 'expr::hash::lex_2const' => {
241 desc => 'lexical $hash{const}{const}',
242 setup => 'my %h = (foo => { bar => 1 })',
243 code => '$h{foo}{bar}',
245 'expr::hash::lex_2var' => {
246 desc => 'lexical $hash{$k1}{$k2}',
247 setup => 'my ($k1,$k2) = qw(foo bar); my %h = ($k1 => { $k2 => 1 })',
248 code => '$h{$k1}{$k2}',
250 'expr::hash::ref_lex_2var' => {
251 desc => 'lexical $hashref->{$k1}{$k2}',
252 setup => 'my ($k1,$k2) = qw(foo bar); my $r = {$k1 => { $k2 => 1 }}',
253 code => '$r->{$k1}{$k2}',
255 'expr::hash::ref_lex_3const' => {
256 desc => 'lexical $hashref->{const}{const}{const}',
257 setup => 'my $r = {foo => { bar => { baz => 1 }}}',
258 code => '$r->{foo}{bar}{baz}',
260 'expr::hash::ref_expr_lex_3const' => {
261 desc => '(lexical expr)->{const}{const}{const}',
262 setup => 'my $r = {foo => { bar => { baz => 1 }}}',
263 code => '($r||0)->{foo}{bar}{baz}',
266 'expr::hash::pkg_1const' => {
267 desc => 'package $hash{const}',
268 setup => '%h = ("foo" => 1)',
271 'expr::hash::pkg_2const' => {
272 desc => 'package $hash{const}{const}',
273 setup => '%h = (foo => { bar => 1 })',
274 code => '$h{foo}{bar}',
276 'expr::hash::pkg_2var' => {
277 desc => 'package $hash{$k1}{$k2}',
278 setup => '($k1,$k2) = qw(foo bar); %h = ($k1 => { $k2 => 1 })',
279 code => '$h{$k1}{$k2}',
281 'expr::hash::ref_pkg_2var' => {
282 desc => 'package $hashref->{$k1}{$k2}',
283 setup => '($k1,$k2) = qw(foo bar); $r = {$k1 => { $k2 => 1 }}',
284 code => '$r->{$k1}{$k2}',
286 'expr::hash::ref_pkg_3const' => {
287 desc => 'package $hashref->{const}{const}{const}',
288 setup => '$r = {foo => { bar => { baz => 1 }}}',
289 code => '$r->{foo}{bar}{baz}',
291 'expr::hash::ref_expr_pkg_3const' => {
292 desc => '(package expr)->{const}{const}{const}',
293 setup => '$r = {foo => { bar => { baz => 1 }}}',
294 code => '($r||0)->{foo}{bar}{baz}',
298 'expr::hash::exists_lex_2var' => {
299 desc => 'lexical exists $hash{$k1}{$k2}',
300 setup => 'my ($k1,$k2) = qw(foo bar); my %h = ($k1 => { $k2 => 1 });',
301 code => 'exists $h{$k1}{$k2}',
306 sprintf('expr::hash::notexists_lex_keylen%04d',$_) => {
307 desc => 'exists on non-key of length '. $_,
308 setup => 'my %h; my $key = "A" x ' . $_ . '; $h{$key."x"} = 1;',
309 code => 'exists $h{$key}',
313 # 1,2,3,7,8,9,14,15,16,20,24,
321 sprintf('expr::hash::exists_lex_keylen%04d',$_) => {
322 desc => 'exists on existing key of length '. $_,
323 setup => 'my %h; my $key = "A" x ' . $_ . '; $h{$key} = 1;',
324 code => 'exists $h{$key}',
328 # 1,2,3,7,8,9,14,15,16,20,24,
335 'expr::hash::delete_lex_2var' => {
336 desc => 'lexical delete $hash{$k1}{$k2}',
337 setup => 'my ($k1,$k2) = qw(foo bar); my %h = ($k1 => { $k2 => 1 });',
338 code => 'delete $h{$k1}{$k2}',
342 # list assign, OP_AASSIGN
347 'expr::aassign::ma_empty' => {
348 desc => 'my array assigned empty',
350 code => 'my @a = ()',
352 'expr::aassign::lax_empty' => {
353 desc => 'non-empty lexical array assigned empty',
354 setup => 'my @a = 1..3;',
357 'expr::aassign::llax_empty' => {
358 desc => 'non-empty lexical var and array assigned empty',
359 setup => 'my ($x, @a) = 1..4;',
360 code => '($x, @a) = ()',
362 'expr::aassign::mh_empty' => {
363 desc => 'my hash assigned empty',
365 code => 'my %h = ()',
367 'expr::aassign::lhx_empty' => {
368 desc => 'non-empty lexical hash assigned empty',
369 setup => 'my %h = 1..4;',
372 'expr::aassign::llhx_empty' => {
373 desc => 'non-empty lexical var and hash assigned empty',
374 setup => 'my ($x, %h) = 1..5;',
375 code => '($x, %h) = ()',
377 'expr::aassign::3m_empty' => {
378 desc => 'three my vars assigned empty',
380 code => 'my ($x,$y,$z) = ()',
382 'expr::aassign::3l_empty' => {
383 desc => 'three lexical vars assigned empty',
384 setup => 'my ($x,$y,$z)',
385 code => '($x,$y,$z) = ()',
387 'expr::aassign::3lref_empty' => {
388 desc => 'three lexical ref vars assigned empty',
389 setup => 'my ($x,$y,$z); my $r = []; ',
390 code => '($x,$y,$z) = ($r,$r,$r); ($x,$y,$z) = ()',
392 'expr::aassign::pa_empty' => {
393 desc => 'package array assigned empty',
397 'expr::aassign::pax_empty' => {
398 desc => 'non-empty package array assigned empty',
399 setup => '@a = (1,2,3)',
402 'expr::aassign::3p_empty' => {
403 desc => 'three package vars assigned empty',
404 setup => '($x,$y,$z) = 1..3;',
405 code => '($x,$y,$z) = ()',
410 'expr::aassign::ma_3c' => {
411 desc => 'my array assigned 3 consts',
413 code => 'my @a = (1,2,3)',
415 'expr::aassign::lax_3c' => {
416 desc => 'non-empty lexical array assigned 3 consts',
417 setup => 'my @a = 1..3;',
418 code => '@a = (1,2,3)',
420 'expr::aassign::llax_3c' => {
421 desc => 'non-empty lexical var and array assigned 3 consts',
422 setup => 'my ($x, @a) = 1..4;',
423 code => '($x, @a) = (1,2,3)',
425 'expr::aassign::mh_4c' => {
426 desc => 'my hash assigned 4 consts',
428 code => 'my %h = qw(a 1 b 2)',
430 'expr::aassign::lhx_4c' => {
431 desc => 'non-empty lexical hash assigned 4 consts',
432 setup => 'my %h = qw(a 1 b 2);',
433 code => '%h = qw(c 3 d 4)',
435 'expr::aassign::llhx_5c' => {
436 desc => 'non-empty lexical var and array assigned 5 consts',
437 setup => 'my ($x, %h) = (1, qw(a 1 b 2));',
438 code => '($x, %h) = (10, qw(c 3 d 4))',
440 'expr::aassign::3m_3c' => {
441 desc => 'three my vars assigned 3 consts',
443 code => 'my ($x,$y,$z) = (1,2,3)',
445 'expr::aassign::3l_3c' => {
446 desc => 'three lexical vars assigned 3 consts',
447 setup => 'my ($x,$y,$z)',
448 code => '($x,$y,$z) = (1,2,3)',
450 'expr::aassign::pa_3c' => {
451 desc => 'package array assigned 3 consts',
453 code => '@a = (1,2,3)',
455 'expr::aassign::pax_3c' => {
456 desc => 'non-empty package array assigned 3 consts',
457 setup => '@a = (1,2,3)',
458 code => '@a = (1,2,3)',
460 'expr::aassign::3p_3c' => {
461 desc => 'three package vars assigned 3 consts',
462 setup => '($x,$y,$z) = 1..3;',
463 code => '($x,$y,$z) = (1,2,3)',
468 'expr::aassign::ma_la' => {
469 desc => 'my array assigned lexical array',
470 setup => 'my @init = 1..3;',
471 code => 'my @a = @init',
473 'expr::aassign::lax_la' => {
474 desc => 'non-empty lexical array assigned lexical array',
475 setup => 'my @init = 1..3; my @a = 1..3;',
476 code => '@a = @init',
478 'expr::aassign::llax_la' => {
479 desc => 'non-empty lexical var and array assigned lexical array',
480 setup => 'my @init = 1..3; my ($x, @a) = 1..4;',
481 code => '($x, @a) = @init',
483 'expr::aassign::3m_la' => {
484 desc => 'three my vars assigned lexical array',
485 setup => 'my @init = 1..3;',
486 code => 'my ($x,$y,$z) = @init',
488 'expr::aassign::3l_la' => {
489 desc => 'three lexical vars assigned lexical array',
490 setup => 'my @init = 1..3; my ($x,$y,$z)',
491 code => '($x,$y,$z) = @init',
493 'expr::aassign::pa_la' => {
494 desc => 'package array assigned lexical array',
495 setup => 'my @init = 1..3;',
496 code => '@a = @init',
498 'expr::aassign::pax_la' => {
499 desc => 'non-empty package array assigned lexical array',
500 setup => 'my @init = 1..3; @a = @init',
501 code => '@a = @init',
503 'expr::aassign::3p_la' => {
504 desc => 'three package vars assigned lexical array',
505 setup => 'my @init = 1..3; ($x,$y,$z) = 1..3;',
506 code => '($x,$y,$z) = @init',
511 'expr::aassign::ma_pa' => {
512 desc => 'my array assigned package array',
513 setup => '@init = 1..3;',
514 code => 'my @a = @init',
516 'expr::aassign::lax_pa' => {
517 desc => 'non-empty lexical array assigned package array',
518 setup => '@init = 1..3; my @a = 1..3;',
519 code => '@a = @init',
521 'expr::aassign::llax_pa' => {
522 desc => 'non-empty lexical var and array assigned package array',
523 setup => '@init = 1..3; my ($x, @a) = 1..4;',
524 code => '($x, @a) = @init',
526 'expr::aassign::3m_pa' => {
527 desc => 'three my vars assigned package array',
528 setup => '@init = 1..3;',
529 code => 'my ($x,$y,$z) = @init',
531 'expr::aassign::3l_pa' => {
532 desc => 'three lexical vars assigned package array',
533 setup => '@init = 1..3; my ($x,$y,$z)',
534 code => '($x,$y,$z) = @init',
536 'expr::aassign::pa_pa' => {
537 desc => 'package array assigned package array',
538 setup => '@init = 1..3;',
539 code => '@a = @init',
541 'expr::aassign::pax_pa' => {
542 desc => 'non-empty package array assigned package array',
543 setup => '@init = 1..3; @a = @init',
544 code => '@a = @init',
546 'expr::aassign::3p_pa' => {
547 desc => 'three package vars assigned package array',
548 setup => '@init = 1..3; ($x,$y,$z) = 1..3;',
549 code => '($x,$y,$z) = @init',
554 'expr::aassign::ma_defary' => {
555 desc => 'my array assigned @_',
556 setup => '@_ = 1..3;',
557 code => 'my @a = @_',
559 'expr::aassign::lax_defary' => {
560 desc => 'non-empty lexical array assigned @_',
561 setup => '@_ = 1..3; my @a = 1..3;',
564 'expr::aassign::llax_defary' => {
565 desc => 'non-empty lexical var and array assigned @_',
566 setup => '@_ = 1..3; my ($x, @a) = 1..4;',
567 code => '($x, @a) = @_',
569 'expr::aassign::3m_defary' => {
570 desc => 'three my vars assigned @_',
571 setup => '@_ = 1..3;',
572 code => 'my ($x,$y,$z) = @_',
574 'expr::aassign::3l_defary' => {
575 desc => 'three lexical vars assigned @_',
576 setup => '@_ = 1..3; my ($x,$y,$z)',
577 code => '($x,$y,$z) = @_',
579 'expr::aassign::pa_defary' => {
580 desc => 'package array assigned @_',
581 setup => '@_ = 1..3;',
584 'expr::aassign::pax_defary' => {
585 desc => 'non-empty package array assigned @_',
586 setup => '@_ = 1..3; @a = @_',
589 'expr::aassign::3p_defary' => {
590 desc => 'three package vars assigned @_',
591 setup => '@_ = 1..3; ($x,$y,$z) = 1..3;',
592 code => '($x,$y,$z) = @_',
596 # (....) = ($lex1,$lex2,$lex3);
598 'expr::aassign::ma_3l' => {
599 desc => 'my array assigned lexicals',
600 setup => 'my ($v1,$v2,$v3) = 1..3;',
601 code => 'my @a = ($v1,$v2,$v3)',
603 'expr::aassign::lax_3l' => {
604 desc => 'non-empty lexical array assigned lexicals',
605 setup => 'my ($v1,$v2,$v3) = 1..3; my @a = 1..3;',
606 code => '@a = ($v1,$v2,$v3)',
608 'expr::aassign::llax_3l' => {
609 desc => 'non-empty lexical var and array assigned lexicals',
610 setup => 'my ($v1,$v2,$v3) = 1..3; my ($x, @a) = 1..4;',
611 code => '($x, @a) = ($v1,$v2,$v3)',
613 'expr::aassign::3m_3l' => {
614 desc => 'three my vars assigned lexicals',
615 setup => 'my ($v1,$v2,$v3) = 1..3;',
616 code => 'my ($x,$y,$z) = ($v1,$v2,$v3)',
618 'expr::aassign::3l_3l' => {
619 desc => 'three lexical vars assigned lexicals',
620 setup => 'my ($v1,$v2,$v3) = 1..3; my ($x,$y,$z)',
621 code => '($x,$y,$z) = ($v1,$v2,$v3)',
623 'expr::aassign::pa_3l' => {
624 desc => 'package array assigned lexicals',
625 setup => 'my ($v1,$v2,$v3) = 1..3;',
626 code => '@a = ($v1,$v2,$v3)',
628 'expr::aassign::pax_3l' => {
629 desc => 'non-empty package array assigned lexicals',
630 setup => 'my ($v1,$v2,$v3) = 1..3; @a = @_',
631 code => '@a = ($v1,$v2,$v3)',
633 'expr::aassign::3p_3l' => {
634 desc => 'three package vars assigned lexicals',
635 setup => 'my ($v1,$v2,$v3) = 1..3; ($x,$y,$z) = 1..3;',
636 code => '($x,$y,$z) = ($v1,$v2,$v3)',
640 # (....) = ($pkg1,$pkg2,$pkg3);
642 'expr::aassign::ma_3p' => {
643 desc => 'my array assigned 3 package vars',
644 setup => '($v1,$v2,$v3) = 1..3;',
645 code => 'my @a = ($v1,$v2,$v3)',
647 'expr::aassign::lax_3p' => {
648 desc => 'non-empty lexical array assigned 3 package vars',
649 setup => '($v1,$v2,$v3) = 1..3; my @a = 1..3;',
650 code => '@a = ($v1,$v2,$v3)',
652 'expr::aassign::llax_3p' => {
653 desc => 'non-empty lexical var and array assigned 3 package vars',
654 setup => '($v1,$v2,$v3) = 1..3; my ($x, @a) = 1..4;',
655 code => '($x, @a) = ($v1,$v2,$v3)',
657 'expr::aassign::3m_3p' => {
658 desc => 'three my vars assigned 3 package vars',
659 setup => '($v1,$v2,$v3) = 1..3;',
660 code => 'my ($x,$y,$z) = ($v1,$v2,$v3)',
662 'expr::aassign::3l_3p' => {
663 desc => 'three lexical vars assigned 3 package vars',
664 setup => '($v1,$v2,$v3) = 1..3; my ($x,$y,$z)',
665 code => '($x,$y,$z) = ($v1,$v2,$v3)',
667 'expr::aassign::pa_3p' => {
668 desc => 'package array assigned 3 package vars',
669 setup => '($v1,$v2,$v3) = 1..3;',
670 code => '@a = ($v1,$v2,$v3)',
672 'expr::aassign::pax_3p' => {
673 desc => 'non-empty package array assigned 3 package vars',
674 setup => '($v1,$v2,$v3) = 1..3; @a = @_',
675 code => '@a = ($v1,$v2,$v3)',
677 'expr::aassign::3p_3p' => {
678 desc => 'three package vars assigned 3 package vars',
679 setup => '($v1,$v2,$v3) = 1..3; ($x,$y,$z) = 1..3;',
680 code => '($x,$y,$z) = ($v1,$v2,$v3)',
684 # (....) = (1,2,$shared);
686 'expr::aassign::llax_2c1s' => {
687 desc => 'non-empty lexical var and array assigned 2 consts and 1 shared var',
688 setup => 'my ($x, @a) = 1..4;',
689 code => '($x, @a) = (1,2,$x)',
691 'expr::aassign::3l_2c1s' => {
692 desc => 'three lexical vars assigned 2 consts and 1 shared var',
693 setup => 'my ($x,$y,$z) = 1..3;',
694 code => '($x,$y,$z) = (1,2,$x)',
696 'expr::aassign::3p_2c1s' => {
697 desc => 'three package vars assigned 2 consts and 1 shared var',
698 setup => '($x,$y,$z) = 1..3;',
699 code => '($x,$y,$z) = (1,2,$x)',
705 'expr::aassign::2l_swap' => {
706 desc => 'swap two lexical vars',
707 setup => 'my ($a,$b) = (1,2)',
708 code => '($a,$b) = ($b,$a)',
710 'expr::aassign::2p_swap' => {
711 desc => 'swap two package vars',
712 setup => '($a,$b) = (1,2)',
713 code => '($a,$b) = ($b,$a)',
715 'expr::aassign::2laelem_swap' => {
716 desc => 'swap two lexical vars',
717 setup => 'my @a = (1,2)',
718 code => '($a[0],$a[1]) = ($a[1],$a[0])',
723 'expr::aassign::5l_4l1s' => {
724 desc => 'long list of lexical vars, 1 shared',
725 setup => 'my ($a,$b,$c,$d,$e) = 1..5',
726 code => '($a,$b,$c,$d,$e) = ($a,$a,$c,$d,$e)',
729 'expr::aassign::5p_4p1s' => {
730 desc => 'long list of package vars, 1 shared',
731 setup => '($a,$b,$c,$d,$e) = 1..5',
732 code => '($a,$b,$c,$d,$e) = ($a,$a,$c,$d,$e)',
734 'expr::aassign::5l_defary' => {
735 desc => 'long list of lexical vars to assign @_ to',
736 setup => '@_ = 1..5',
737 code => 'my ($a,$b,$c,$d,$e) = @_',
739 'expr::aassign::5l1la_defary' => {
740 desc => 'long list of lexical vars plus long slurp to assign @_ to',
741 setup => '@_ = 1..20',
742 code => 'my ($a,$b,$c,$d,$e,@rest) = @_',
744 'expr::aassign::1l_2l' => {
745 desc => 'single lexical LHS',
746 setup => 'my $x = 1;',
747 code => '(undef,$x) = ($x,$x)',
749 'expr::aassign::2l_1l' => {
750 desc => 'single lexical RHS',
751 setup => 'my $x = 1;',
752 code => '($x,$x) = ($x)',
754 'expr::aassign::2l_1ul' => {
755 desc => 'undef and single lexical RHS',
756 setup => 'my $x = 1;',
757 code => '($x,$x) = (undef, $x)',
760 'expr::aassign::2list_lex' => {
761 desc => 'lexical ($x, $y) = (1, 2)',
762 setup => 'my ($x, $y)',
763 code => '($x, $y) = (1, 2)',
766 'expr::aassign::lex_rv' => {
767 desc => 'lexical ($ref1, $ref2) = ($ref3, $ref4)',
768 setup => 'my ($r1, $r2, $r3, $r4);
769 ($r1, $r2) = (($r3, $r4) = ([], []));',
770 code => '($r1, $r2) = ($r3, $r4)',
773 'expr::aassign::lex_rv1' => {
774 desc => 'lexical ($ref1, $ref2) = ($ref3, $ref4) where ref1,2 are freed',
775 setup => 'my ($r1, $r2);',
776 code => '($r1, $r2) = ([], []);',
779 # array assign of strings
781 'expr::aassign::la_3s' => {
782 desc => 'assign 3 strings to empty lexical array',
784 code => '@a = (); @a = qw(abc defg hijkl);',
786 'expr::aassign::la_3ts' => {
787 desc => 'assign 3 temp strings to empty lexical array',
789 code => '@a = (); @a = map $_, qw(abc defg hijkl);',
791 'expr::aassign::lan_3s' => {
792 desc => 'assign 3 strings to non-empty lexical array',
793 setup => 'my @a = qw(abc defg hijkl)',
794 code => '@a = qw(abc defg hijkl);',
796 'expr::aassign::lan_3ts' => {
797 desc => 'assign 3 temp strings to non-empty lexical array',
798 setup => 'my @a = qw(abc defg hijkl)',
799 code => '@a = map $_, qw(abc defg hijkl);',
802 # hash assign of strings
804 'expr::aassign::lh_2s' => {
805 desc => 'assign 2 strings to empty lexical hash',
807 code => '%h = (); %h = qw(k1 abc k2 defg);',
809 'expr::aassign::lh_2ts' => {
810 desc => 'assign 2 temp strings to empty lexical hash',
812 code => '%h = (); %h = map $_, qw(k1 abc k2 defg);',
814 'expr::aassign::lhn_2s' => {
815 desc => 'assign 2 strings to non-empty lexical hash',
816 setup => 'my %h = qw(k1 abc k2 defg);',
817 code => '%h = qw(k1 abc k2 defg);',
819 'expr::aassign::lhn_2ts' => {
820 desc => 'assign 2 temp strings to non-empty lexical hash',
821 setup => 'my %h = qw(k1 abc k2 defg);',
822 code => '%h = map $_, qw(k1 abc k2 defg);',
826 'expr::arith::add_lex_ii' => {
827 desc => 'add two integers and assign to a lexical var',
828 setup => 'my ($x,$y,$z) = 1..3;',
829 code => '$z = $x + $y',
831 'expr::arith::add_pkg_ii' => {
832 desc => 'add two integers and assign to a package var',
833 setup => 'my ($x,$y) = 1..2; $z = 3;',
834 code => '$z = $x + $y',
836 'expr::arith::add_lex_nn' => {
837 desc => 'add two NVs and assign to a lexical var',
838 setup => 'my ($x,$y,$z) = (1.1, 2.2, 3.3);',
839 code => '$z = $x + $y',
841 'expr::arith::add_pkg_nn' => {
842 desc => 'add two NVs and assign to a package var',
843 setup => 'my ($x,$y); ($x,$y,$z) = (1.1, 2.2, 3.3);',
844 code => '$z = $x + $y',
846 'expr::arith::add_lex_ni' => {
847 desc => 'add an int and an NV and assign to a lexical var',
848 setup => 'my ($x,$y,$z) = (1, 2.2, 3.3);',
849 code => '$z = $x + $y',
851 'expr::arith::add_pkg_ni' => {
852 desc => 'add an int and an NV and assign to a package var',
853 setup => 'my ($x,$y); ($x,$y,$z) = (1, 2.2, 3.3);',
854 code => '$z = $x + $y',
856 'expr::arith::add_lex_ss' => {
857 desc => 'add two short strings and assign to a lexical var',
858 setup => 'my ($x,$y,$z) = ("1", "2", 1);',
859 code => '$z = $x + $y; $x = "1"; ',
862 'expr::arith::add_lex_ll' => {
863 desc => 'add two long strings and assign to a lexical var',
864 setup => 'my ($x,$y,$z) = ("12345", "23456", 1);',
865 code => '$z = $x + $y; $x = "12345"; ',
868 'expr::arith::sub_lex_ii' => {
869 desc => 'subtract two integers and assign to a lexical var',
870 setup => 'my ($x,$y,$z) = 1..3;',
871 code => '$z = $x - $y',
873 'expr::arith::sub_pkg_ii' => {
874 desc => 'subtract two integers and assign to a package var',
875 setup => 'my ($x,$y) = 1..2; $z = 3;',
876 code => '$z = $x - $y',
878 'expr::arith::sub_lex_nn' => {
879 desc => 'subtract two NVs and assign to a lexical var',
880 setup => 'my ($x,$y,$z) = (1.1, 2.2, 3.3);',
881 code => '$z = $x - $y',
883 'expr::arith::sub_pkg_nn' => {
884 desc => 'subtract two NVs and assign to a package var',
885 setup => 'my ($x,$y); ($x,$y,$z) = (1.1, 2.2, 3.3);',
886 code => '$z = $x - $y',
888 'expr::arith::sub_lex_ni' => {
889 desc => 'subtract an int and an NV and assign to a lexical var',
890 setup => 'my ($x,$y,$z) = (1, 2.2, 3.3);',
891 code => '$z = $x - $y',
893 'expr::arith::sub_pkg_ni' => {
894 desc => 'subtract an int and an NV and assign to a package var',
895 setup => 'my ($x,$y); ($x,$y,$z) = (1, 2.2, 3.3);',
896 code => '$z = $x - $y',
899 'expr::arith::mult_lex_ii' => {
900 desc => 'multiply two integers and assign to a lexical var',
901 setup => 'my ($x,$y,$z) = 1..3;',
902 code => '$z = $x * $y',
904 'expr::arith::mult_pkg_ii' => {
905 desc => 'multiply two integers and assign to a package var',
906 setup => 'my ($x,$y) = 1..2; $z = 3;',
907 code => '$z = $x * $y',
909 'expr::arith::mult_lex_nn' => {
910 desc => 'multiply two NVs and assign to a lexical var',
911 setup => 'my ($x,$y,$z) = (1.1, 2.2, 3.3);',
912 code => '$z = $x * $y',
914 'expr::arith::mult_pkg_nn' => {
915 desc => 'multiply two NVs and assign to a package var',
916 setup => 'my ($x,$y); ($x,$y,$z) = (1.1, 2.2, 3.3);',
917 code => '$z = $x * $y',
919 'expr::arith::mult_lex_ni' => {
920 desc => 'multiply an int and an NV and assign to a lexical var',
921 setup => 'my ($x,$y,$z) = (1, 2.2, 3.3);',
922 code => '$z = $x * $y',
924 'expr::arith::mult_pkg_ni' => {
925 desc => 'multiply an int and an NV and assign to a package var',
926 setup => 'my ($x,$y); ($x,$y,$z) = (1, 2.2, 3.3);',
927 code => '$z = $x * $y',
930 'expr::arith::preinc' => {
932 setup => 'my $x = 1;',
935 'expr::arith::predec' => {
937 setup => 'my $x = 1;',
940 'expr::arith::postinc' => {
942 setup => 'my $x = 1; my $y',
943 code => '$y = $x++', # scalar context so not optimised to ++$x
945 'expr::arith::postdec' => {
947 setup => 'my $x = 1; my $y',
948 code => '$y = $x--', # scalar context so not optimised to --$x
953 # scalar assign, OP_SASSIGN
956 'expr::sassign::scalar_lex_int' => {
957 desc => 'lexical $x = 1',
961 'expr::sassign::scalar_lex_str' => {
962 desc => 'lexical $x = "abc"',
964 code => '$x = "abc"',
966 'expr::sassign::scalar_lex_strint' => {
967 desc => 'lexical $x = 1 where $x was previously a string',
968 setup => 'my $x = "abc"',
971 'expr::sassign::scalar_lex_intstr' => {
972 desc => 'lexical $x = "abc" where $x was previously an int',
973 setup => 'my $x = 1;',
974 code => '$x = "abc"',
976 'expr::sassign::lex_rv' => {
977 desc => 'lexical $ref1 = $ref2;',
978 setup => 'my $r1 = []; my $r = $r1;',
981 'expr::sassign::lex_rv1' => {
982 desc => 'lexical $ref1 = $ref2; where $$ref1 gets freed',
983 setup => 'my $r1 = []; my $r',
984 code => '$r = []; $r = $r1;',
989 # using a const string as second arg to index triggers using FBM.
990 # the FBM matcher special-cases 1,2-byte strings.
992 'func::index::short_const1' => {
993 desc => 'index of a short string against a 1 char const substr',
994 setup => 'my $x = "aaaab"',
995 code => 'index $x, "b"',
997 'func::index::long_const1' => {
998 desc => 'index of a long string against a 1 char const substr',
999 setup => 'my $x = "a" x 1000 . "b"',
1000 code => 'index $x, "b"',
1002 'func::index::short_const2aabc_bc' => {
1003 desc => 'index of a short string against a 2 char const substr',
1004 setup => 'my $x = "aaaabc"',
1005 code => 'index $x, "bc"',
1007 'func::index::long_const2aabc_bc' => {
1008 desc => 'index of a long string against a 2 char const substr',
1009 setup => 'my $x = "a" x 1000 . "bc"',
1010 code => 'index $x, "bc"',
1012 'func::index::long_const2aa_ab' => {
1013 desc => 'index of a long string aaa.. against const substr "ab"',
1014 setup => 'my $x = "a" x 1000',
1015 code => 'index $x, "ab"',
1017 'func::index::long_const2bb_ab' => {
1018 desc => 'index of a long string bbb.. against const substr "ab"',
1019 setup => 'my $x = "b" x 1000',
1020 code => 'index $x, "ab"',
1022 'func::index::long_const2aa_bb' => {
1023 desc => 'index of a long string aaa.. against const substr "bb"',
1024 setup => 'my $x = "a" x 1000',
1025 code => 'index $x, "bb"',
1027 # this one is designed to be pathological
1028 'func::index::long_const2ab_aa' => {
1029 desc => 'index of a long string abab.. against const substr "aa"',
1030 setup => 'my $x = "ab" x 500',
1031 code => 'index $x, "aa"',
1033 # near misses with gaps, 1st letter
1034 'func::index::long_const2aaxx_xy' => {
1035 desc => 'index of a long string with "xx"s against const substr "xy"',
1036 setup => 'my $x = "aaaaaaaaxx" x 100',
1037 code => 'index $x, "xy"',
1039 # near misses with gaps, 2nd letter
1040 'func::index::long_const2aayy_xy' => {
1041 desc => 'index of a long string with "yy"s against const substr "xy"',
1042 setup => 'my $x = "aaaaaaaayy" x 100',
1043 code => 'index $x, "xy"',
1045 # near misses with gaps, duplicate letter
1046 'func::index::long_const2aaxy_xx' => {
1047 desc => 'index of a long string with "xy"s against const substr "xx"',
1048 setup => 'my $x = "aaaaaaaaxy" x 100',
1049 code => 'index $x, "xx"',
1051 # alternating near misses with gaps
1052 'func::index::long_const2aaxxaayy_xy' => {
1053 desc => 'index of a long string with "xx/yy"s against const substr "xy"',
1054 setup => 'my $x = "aaaaaaaaxxbbbbbbbbyy" x 50',
1055 code => 'index $x, "xy"',
1057 'func::index::short_const3aabcd_bcd' => {
1058 desc => 'index of a short string against a 3 char const substr',
1059 setup => 'my $x = "aaaabcd"',
1060 code => 'index $x, "bcd"',
1062 'func::index::long_const3aabcd_bcd' => {
1063 desc => 'index of a long string against a 3 char const substr',
1064 setup => 'my $x = "a" x 1000 . "bcd"',
1065 code => 'index $x, "bcd"',
1067 'func::index::long_const3ab_abc' => {
1068 desc => 'index of a long string of "ab"s against a 3 char const substr "abc"',
1069 setup => 'my $x = "ab" x 500',
1070 code => 'index $x, "abc"',
1072 'func::index::long_const3bc_abc' => {
1073 desc => 'index of a long string of "bc"s against a 3 char const substr "abc"',
1074 setup => 'my $x = "bc" x 500',
1075 code => 'index $x, "abc"',
1077 'func::index::utf8_position_1' => {
1078 desc => 'index of a utf8 string, matching at position 1',
1079 setup => 'my $x = "abc". chr(0x100); chop $x',
1080 code => 'index $x, "b"',
1085 'func::sort::num' => {
1086 desc => 'plain numeric sort',
1087 setup => 'my (@a, @b); @a = reverse 1..10;',
1088 code => '@b = sort { $a <=> $b } @a',
1090 'func::sort::num_block' => {
1091 desc => 'codeblock numeric sort',
1092 setup => 'my (@a, @b); @a = reverse 1..10;',
1093 code => '@b = sort { $a + 1 <=> $b + 1 } @a',
1095 'func::sort::num_fn' => {
1096 desc => 'function numeric sort',
1097 setup => 'sub f { $a + 1 <=> $b + 1 } my (@a, @b); @a = reverse 1..10;',
1098 code => '@b = sort f @a',
1100 'func::sort::str' => {
1101 desc => 'plain string sort',
1102 setup => 'my (@a, @b); @a = reverse "a".."j";',
1103 code => '@b = sort { $a cmp $b } @a',
1105 'func::sort::str_block' => {
1106 desc => 'codeblock string sort',
1107 setup => 'my (@a, @b); @a = reverse "a".."j";',
1108 code => '@b = sort { ($a . "") cmp ($b . "") } @a',
1110 'func::sort::str_fn' => {
1111 desc => 'function string sort',
1112 setup => 'sub f { ($a . "") cmp ($b . "") } my (@a, @b); @a = reverse "a".."j";',
1113 code => '@b = sort f @a',
1116 'func::sort::num_inplace' => {
1117 desc => 'plain numeric sort in-place',
1118 setup => 'my @a = reverse 1..10;',
1119 code => '@a = sort { $a <=> $b } @a',
1121 'func::sort::num_block_inplace' => {
1122 desc => 'codeblock numeric sort in-place',
1123 setup => 'my @a = reverse 1..10;',
1124 code => '@a = sort { $a + 1 <=> $b + 1 } @a',
1126 'func::sort::num_fn_inplace' => {
1127 desc => 'function numeric sort in-place',
1128 setup => 'sub f { $a + 1 <=> $b + 1 } my @a = reverse 1..10;',
1129 code => '@a = sort f @a',
1131 'func::sort::str_inplace' => {
1132 desc => 'plain string sort in-place',
1133 setup => 'my @a = reverse "a".."j";',
1134 code => '@a = sort { $a cmp $b } @a',
1136 'func::sort::str_block_inplace' => {
1137 desc => 'codeblock string sort in-place',
1138 setup => 'my @a = reverse "a".."j";',
1139 code => '@a = sort { ($a . "") cmp ($b . "") } @a',
1141 'func::sort::str_fn_inplace' => {
1142 desc => 'function string sort in-place',
1143 setup => 'sub f { ($a . "") cmp ($b . "") } my @a = reverse "a".."j";',
1144 code => '@a = sort f @a',
1148 'func::split::vars' => {
1149 desc => 'split into two lexical vars',
1150 setup => 'my $s = "abc:def";',
1151 code => 'my ($x, $y) = split /:/, $s, 2;',
1154 'func::split::array' => {
1155 desc => 'split into a lexical array',
1156 setup => 'my @a; my $s = "abc:def";',
1157 code => '@a = split /:/, $s, 2;',
1159 'func::split::myarray' => {
1160 desc => 'split into a lexical array declared in the assign',
1161 setup => 'my $s = "abc:def";',
1162 code => 'my @a = split /:/, $s, 2;',
1164 'func::split::arrayexpr' => {
1165 desc => 'split into an @{$expr} ',
1166 setup => 'my $s = "abc:def"; my $r = []',
1167 code => '@$r = split /:/, $s, 2;',
1169 'func::split::arraylist' => {
1170 desc => 'split into an array with extra arg',
1171 setup => 'my @a; my $s = "abc:def";',
1172 code => '@a = (split(/:/, $s, 2), 1);',
1177 desc => 'empty basic loop',
1183 desc => 'basic do block',
1184 setup => 'my $x; my $y = 2;',
1185 code => '$x = do {1; $y}', # the ';' stops the do being optimised
1188 'loop::for::my_range1' => {
1189 desc => 'empty for loop with my var and 1 integer range',
1191 code => 'for my $x (1..1) {}',
1193 'loop::for::lex_range1' => {
1194 desc => 'empty for loop with lexical var and 1 integer range',
1196 code => 'for $x (1..1) {}',
1198 'loop::for::pkg_range1' => {
1199 desc => 'empty for loop with package var and 1 integer range',
1201 code => 'for $x (1..1) {}',
1203 'loop::for::defsv_range1' => {
1204 desc => 'empty for loop with $_ and integer 1 range',
1206 code => 'for (1..1) {}',
1208 'loop::for::my_range4' => {
1209 desc => 'empty for loop with my var and 4 integer range',
1211 code => 'for my $x (1..4) {}',
1213 'loop::for::lex_range4' => {
1214 desc => 'empty for loop with lexical var and 4 integer range',
1216 code => 'for $x (1..4) {}',
1218 'loop::for::pkg_range4' => {
1219 desc => 'empty for loop with package var and 4 integer range',
1221 code => 'for $x (1..4) {}',
1223 'loop::for::defsv_range4' => {
1224 desc => 'empty for loop with $_ and integer 4 range',
1226 code => 'for (1..4) {}',
1229 'loop::for::my_list1' => {
1230 desc => 'empty for loop with my var and 1 integer list',
1232 code => 'for my $x (1) {}',
1234 'loop::for::lex_list1' => {
1235 desc => 'empty for loop with lexical var and 1 integer list',
1237 code => 'for $x (1) {}',
1239 'loop::for::pkg_list1' => {
1240 desc => 'empty for loop with package var and 1 integer list',
1242 code => 'for $x (1) {}',
1244 'loop::for::defsv_list1' => {
1245 desc => 'empty for loop with $_ and integer 1 list',
1247 code => 'for (1) {}',
1249 'loop::for::my_list4' => {
1250 desc => 'empty for loop with my var and 4 integer list',
1252 code => 'for my $x (1,2,3,4) {}',
1254 'loop::for::lex_list4' => {
1255 desc => 'empty for loop with lexical var and 4 integer list',
1257 code => 'for $x (1,2,3,4) {}',
1259 'loop::for::pkg_list4' => {
1260 desc => 'empty for loop with package var and 4 integer list',
1262 code => 'for $x (1,2,3,4) {}',
1264 'loop::for::defsv_list4' => {
1265 desc => 'empty for loop with $_ and integer 4 list',
1267 code => 'for (1,2,3,4) {}',
1270 'loop::for::my_array1' => {
1271 desc => 'empty for loop with my var and 1 integer array',
1272 setup => 'my @a = (1);',
1273 code => 'for my $x (@a) {}',
1275 'loop::for::lex_array1' => {
1276 desc => 'empty for loop with lexical var and 1 integer array',
1277 setup => 'my $x; my @a = (1);',
1278 code => 'for $x (@a) {}',
1280 'loop::for::pkg_array1' => {
1281 desc => 'empty for loop with package var and 1 integer array',
1282 setup => '$x = 1; my @a = (1);',
1283 code => 'for $x (@a) {}',
1285 'loop::for::defsv_array1' => {
1286 desc => 'empty for loop with $_ and integer 1 array',
1287 setup => 'my @a = (@a);',
1288 code => 'for (1) {}',
1290 'loop::for::my_array4' => {
1291 desc => 'empty for loop with my var and 4 integer array',
1292 setup => 'my @a = (1..4);',
1293 code => 'for my $x (@a) {}',
1295 'loop::for::lex_array4' => {
1296 desc => 'empty for loop with lexical var and 4 integer array',
1297 setup => 'my $x; my @a = (1..4);',
1298 code => 'for $x (@a) {}',
1300 'loop::for::pkg_array4' => {
1301 desc => 'empty for loop with package var and 4 integer array',
1302 setup => '$x = 1; my @a = (1..4);',
1303 code => 'for $x (@a) {}',
1305 'loop::for::defsv_array4' => {
1306 desc => 'empty for loop with $_ and integer 4 array',
1307 setup => 'my @a = (1..4);',
1308 code => 'for (@a) {}',
1311 'loop::for::next4' => {
1312 desc => 'for loop containing only next with my var and integer 4 array',
1313 setup => 'my @a = (1..4);',
1314 code => 'for my $x (@a) {next}',
1317 'loop::grep::expr_3int' => {
1318 desc => 'grep $_ > 0, 1,2,3',
1320 code => '@a = grep $_ > 0, 1,2,3',
1323 'loop::grep::block_3int' => {
1324 desc => 'grep { 1; $_ > 0} 1,2,3',
1326 code => '@a = grep { 1; $_ > 0} 1,2,3',
1329 'loop::map::expr_3int' => {
1330 desc => 'map $_+1, 1,2,3',
1332 code => '@a = map $_+1, 1,2,3',
1335 'loop::map::block_3int' => {
1336 desc => 'map { 1; $_+1} 1,2,3',
1338 code => '@a = map { 1; $_+1} 1,2,3',
1341 'loop::while::i1' => {
1342 desc => 'empty while loop 1 iteration',
1343 setup => 'my $i = 0;',
1344 code => 'while (++$i % 2) {}',
1346 'loop::while::i4' => {
1347 desc => 'empty while loop 4 iterations',
1348 setup => 'my $i = 0;',
1349 code => 'while (++$i % 4) {}',
1353 'regex::anyof_plus::anchored' => {
1354 desc => '/^[acgt]+/',
1355 setup => '$_ = "a" x 100;',
1356 code => '/^[acgt]+/',
1358 'regex::anyof_plus::floating' => {
1359 desc => '/[acgt]+where match starts at position 0 for 100 chars/',
1360 setup => '$_ = "a" x 100;',
1361 code => '/[acgt]+/',
1363 'regex::anyof_plus::floating_away' => {
1364 desc => '/[acgt]+/ where match starts at position 100 for 100 chars',
1365 setup => '$_ = ("0" x 100) . ("a" x 100);',
1366 code => '/[acgt]+/',