Skip to content

Commit b369834

Browse files
author
Zefram
committed
fix range op under aborted constant folding
When constant-folding a range/flipflop construct, the op_next threading of peephole optimisation caused multiple ops in the construct to have a null op_next, because the final (and top-level) op in the construct is a null op. This meant that simple restoration of the top-level op's op_next after execution wouldn't get it back into a fit state to be composed with other ops. In the event that the range construct couldn't be constant-folded this made it compile to a broken optree. If it couldn't be constant-folded but could actually be executed, for example because it generated a warning, this meant the brokenness would be encountered at runtime. Execution would stop after the range op, because of the null op_next. To avoid this, temporarily mark the null op as a custom op during the peephole optimisation that supports the execution for constant-folding. This prevents it being op_next-threaded out, so simple op_next restoring then works. If the constant-folding is aborted, it compiles to an operational optree. However, the suppression of duplicate peephole optimisation means that the null op is never ultimately threaded out as it should be. For the time being, this stands as a cost of failed constant-folding of range constructs. Fixes [perl #130639].
1 parent 475b224 commit b369834

File tree

2 files changed

+10
-1
lines changed

2 files changed

+10
-1
lines changed

op.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4632,6 +4632,7 @@ S_gen_constant_list(pTHX_ OP *o)
46324632
COP not_compiling;
46334633
int ret = 0;
46344634
dJMPENV;
4635+
bool op_was_null;
46354636

46364637
list(o);
46374638
if (PL_parser && PL_parser->error_count)
@@ -4640,7 +4641,12 @@ S_gen_constant_list(pTHX_ OP *o)
46404641
curop = LINKLIST(o);
46414642
old_next = o->op_next;
46424643
o->op_next = 0;
4644+
op_was_null = o->op_type == OP_NULL;
4645+
if (op_was_null)
4646+
o->op_type = OP_CUSTOM;
46434647
CALL_PEEP(curop);
4648+
if (op_was_null)
4649+
o->op_type = OP_NULL;
46444650
S_prune_chain_head(&curop);
46454651
PL_op = curop;
46464652

t/comp/fold.t

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# we've not yet verified that use works.
55
# use strict;
66

7-
print "1..34\n";
7+
print "1..35\n";
88
my $test = 0;
99

1010
# Historically constant folding was performed by evaluating the ops, and if
@@ -189,3 +189,6 @@ $b = 0;
189189
$a = eval 'my @z; @z = 0..~0 if $b; 3';
190190
is ($a, 3, "list constant folding doesn't signal compile-time error");
191191
is ($@, '', 'no error');
192+
193+
$a = eval 'local $SIG{__WARN__} = sub {}; join("", ":".."~", "z")';
194+
is ($a, ":z", "aborted list constant folding still executable");

0 commit comments

Comments
 (0)