This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
test for #127855 - Slowdown in m//g on COW strings of certain lengths
[perl5.git] / t / re / recompile.t
CommitLineData
23af30a1
DM
1#!./perl
2
3# Check that we don't recompile runtime patterns when the pattern hasn't
4# changed
5#
6# Works by checking the debugging output of 'use re debug' and, if
7# available, -Dr. We use both to check that the different code paths
e5bb0a1f 8# with Perl_foo() versus the my_foo() under ext/re/ don't cause any
23af30a1
DM
9# changes.
10
23af30a1
DM
11$| = 1;
12
23af30a1
DM
13BEGIN {
14 chdir 't' if -d 't';
15 @INC = ('../lib','.');
16 require './test.pl';
17 skip_all_if_miniperl("no dynamic loading on miniperl, no re");
18}
19
0b1b7115
JH
20use strict;
21use warnings;
23af30a1 22
10beeb31 23plan tests => 48;
23af30a1
DM
24
25my $results = runperl(
26 switches => [ '-Dr' ],
27 prog => '1',
28 stderr => 1,
29 );
30my $has_Dr = $results !~ /Recompile perl with -DDEBUGGING/;
31
32my $tmpfile = tempfile();
33
34
35# Check that a pattern triggers a regex compilation exactly N times,
36# using either -Dr or 'use re debug'
37# This is partially based on _fresh_perl() in test.pl
38
39sub _comp_n {
40 my ($use_Dr, $n, $prog, $desc) = @_;
41 open my $tf, ">$tmpfile" or die "Cannot open $tmpfile: $!";
42
43 my $switches = [];
44 if ($use_Dr) {
45 push @$switches, '-Dr';
46 }
47 else {
48 $prog = qq{use re qw(debug);\n$prog};
49 }
50
51 print $tf $prog;
52 close $tf or die "Cannot close $tmpfile: $!";
53 my $results = runperl(
54 switches => $switches,
55 progfile => $tmpfile,
56 stderr => 1,
57 );
58
59 my $status = $?;
60
61 my $count = () = $results =~ /Final program:/g;
49bb71ae 62 if ($count == $n && !$status) {
23af30a1
DM
63 pass($desc);
64 }
65 else {
66 fail($desc);
67 _diag "# COUNT: $count EXPECTED $n\n";
68 _diag "# STATUS: $status\n";
69 _diag "# SWITCHES: @$switches\n";
70 _diag "# PROG: \n$prog\n";
71 # this is verbose; uncomment for debugging
72 #_diag "# OUTPUT:\n------------------\n $results-------------------\n";
73 }
74}
75
76# Check that a pattern triggers a regex compilation exactly N times,
77
78sub comp_n {
79 my ($n, $prog, $desc) = @_;
80 if ($has_Dr) {
81 _comp_n(1, $n, $prog, "$desc -Dr");
82 }
83 else {
84 SKIP: {
85 skip("-Dr not compiled in");
86 }
87 }
88 _comp_n(0, @_);
89}
90
91# Check that a pattern triggers a regex compilation exactly once.
92
93sub comp_1 {
94 comp_n(1, @_);
95}
96
97
98comp_1(<<'CODE', 'simple');
99"a" =~ /$_/ for qw(a a a);
100CODE
101
102comp_1(<<'CODE', 'simple qr');
103"a" =~ qr/$_/ for qw(a a a);
104CODE
105
106comp_1(<<'CODE', 'literal utf8');
107"a" =~ /$_/ for "\x{100}", "\x{100}", "\x{100}";
108CODE
109
110comp_1(<<'CODE', 'literal utf8 qr');
111"a" =~ qr/$_/ for "\x{100}", "\x{100}", "\x{100}";
112CODE
113
114comp_1(<<'CODE', 'longjmp literal utf8');
115my $x = chr(0x80);
116"a" =~ /$x$_/ for "\x{100}", "\x{100}", "\x{100}";
117CODE
118
119comp_1(<<'CODE', 'longjmp literal utf8 qr');
120my $x = chr(0x80);
121"a" =~ qr/$x$_/ for "\x{100}", "\x{100}", "\x{100}";
122CODE
123
124comp_1(<<'CODE', 'utf8');
125"a" =~ /$_/ for '\x{100}', '\x{100}', '\x{100}';
126CODE
127
128comp_1(<<'CODE', 'utf8 qr');
129"a" =~ qr/$_/ for '\x{100}', '\x{100}', '\x{100}';
130CODE
131
132comp_1(<<'CODE', 'longjmp utf8');
133my $x = chr(0x80);
134"a" =~ /$x$_/ for '\x{100}', '\x{100}', '\x{100}';
135CODE
136
137comp_1(<<'CODE', 'longjmp utf8');
138my $x = chr(0x80);
139"a" =~ qr/$x$_/ for '\x{100}', '\x{100}', '\x{100}';
140CODE
141
142comp_n(3, <<'CODE', 'mixed utf8');
143"a" =~ /$_/ for "\x{c4}\x{80}", "\x{100}", "\x{c4}\x{80}";
144CODE
145
146comp_n(3, <<'CODE', 'mixed utf8 qr');
147"a" =~ qr/$_/ for "\x{c4}\x{80}", "\x{100}", "\x{c4}\x{80}";
148CODE
149
d24ca0c5
DM
150# note that that for runtime code, each pattern is compiled twice; the
151# second time to allow the parser to see the code.
152
153comp_n(6, <<'CODE', 'runtime code');
23af30a1
DM
154my $x = '(?{1})';
155BEGIN { $^H |= 0x00200000 } # lightweight "use re 'eval'"
156"a" =~ /a$_/ for $x, $x, $x;
157CODE
158
d24ca0c5 159comp_n(6, <<'CODE', 'runtime code qr');
23af30a1
DM
160my $x = '(?{1})';
161BEGIN { $^H |= 0x00200000 } # lightweight "use re 'eval'"
162"a" =~ qr/a$_/ for $x, $x, $x;
163CODE
164
165comp_n(4, <<'CODE', 'embedded code');
166my $x = qr/(?{1})/;
167"a" =~ /a$_/ for $x, $x, $x;
168CODE
169
170comp_n(4, <<'CODE', 'embedded code qr');
171my $x = qr/(?{1})/;
172"a" =~ qr/a$_/ for $x, $x, $x;
173CODE
174
d24ca0c5 175comp_n(7, <<'CODE', 'mixed code');
23af30a1
DM
176my $x = qr/(?{1})/;
177my $y = '(?{1})';
178BEGIN { $^H |= 0x00200000 } # lightweight "use re 'eval'"
179"a" =~ /a$x$_/ for $y, $y, $y;
180CODE
181
d24ca0c5 182comp_n(7, <<'CODE', 'mixed code qr');
23af30a1
DM
183my $x = qr/(?{1})/;
184my $y = '(?{1})';
185BEGIN { $^H |= 0x00200000 } # lightweight "use re 'eval'"
186"a" =~ qr/a$x$_/ for $y, $y, $y;
187CODE
dbc200c5
YO
188
189comp_n(6, <<'CODE', 'embedded code qr');
190my $x = qr/a/i;
191my $y = qr/a/;
192"a" =~ qr/a$_/ for $x, $y, $x, $y;
193CODE
237da807
FC
194
195comp_n(2, <<'CODE', '(??{"constant"})');
196"bb" =~ /(??{"abc"})/;
197CODE
198
199comp_n(2, <<'CODE', '(??{"folded"."constant"})');
200"bb" =~ /(??{"ab"."c"})/;
201CODE
202
203comp_n(2, <<'CODE', '(??{$preused_scalar})');
204$s = "abc";
205"bb" =~ /(??{$s})/;
206CODE
207
208comp_n(2, <<'CODE', '(??{number})');
209"bb" =~ /(??{123})/;
210CODE
10beeb31
FC
211
212comp_n(2, <<'CODE', '(??{$pvlv_regexp})');
213sub {
214 $_[0] = ${qr/abc/};
215 "bb" =~ /(??{$_[0]})/;
216}->($_[0]);
217CODE