Skip to content

Commit

Permalink
Don't inline immediate blocks using p6return
Browse files Browse the repository at this point in the history
Otherwise, we can end up with, for instance, a `loop` that does a
smart-match ending up causing a return from the block containing the
loop itself, thus terminating not only the loop, but also skipping any
code in the block after the loop. Related to #2644.
  • Loading branch information
jnthn committed Jan 30, 2019
1 parent 82fde76 commit c6053e6
Showing 1 changed file with 13 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/Perl6/Optimizer.nqp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -450,6 +450,9 @@ my class BlockVarOptimizer {
# If p6bindsig is used. # If p6bindsig is used.
has int $!uses_bindsig; has int $!uses_bindsig;


# If p6return is used
has int $!uses_p6return;

# If we're currently inside a handler argument of an nqp::handle. These # If we're currently inside a handler argument of an nqp::handle. These
# are code-gen'd with an implicit block around them, so we mustn't lower # are code-gen'd with an implicit block around them, so we mustn't lower
# lexicals referenced in them to locals. # lexicals referenced in them to locals.
Expand Down Expand Up @@ -503,6 +506,8 @@ my class BlockVarOptimizer {


method uses_bindsig() { $!uses_bindsig := 1; } method uses_bindsig() { $!uses_bindsig := 1; }


method uses_p6return() { $!uses_p6return := 1; }

method entering_handle_handler() { $!in_handle_handler++; } method entering_handle_handler() { $!in_handle_handler++; }


method leaving_handle_handler() { $!in_handle_handler--; } method leaving_handle_handler() { $!in_handle_handler--; }
Expand All @@ -519,6 +524,10 @@ my class BlockVarOptimizer {


method is_poisoned() { $!poisoned } method is_poisoned() { $!poisoned }


method is_inlineable() {
!($!poisoned || $!uses_p6return)
}

method get_escaping_handler_vars() { method get_escaping_handler_vars() {
my @esc; my @esc;
for %!used_in_handle_handler { for %!used_in_handle_handler {
Expand Down Expand Up @@ -1123,7 +1132,7 @@ class Perl6::Optimizer {
my int $flattened := 0; my int $flattened := 0;
my $result := $block; my $result := $block;
if $!level >= 2 && $block.blocktype eq 'immediate' && $block.arity == 0 if $!level >= 2 && $block.blocktype eq 'immediate' && $block.arity == 0
&& !$vars_info.is_poisoned && !$block.has_exit_handler { && $vars_info.is_inlineable && !$block.has_exit_handler {
# Scan symbols for any non-lowered ones. # Scan symbols for any non-lowered ones.
my $impossible := 0; my $impossible := 0;
for $block.symtable() { for $block.symtable() {
Expand Down Expand Up @@ -1499,6 +1508,9 @@ class Perl6::Optimizer {
elsif $optype eq 'p6bindsig' || $optype eq 'p6bindcaptosig' { elsif $optype eq 'p6bindsig' || $optype eq 'p6bindcaptosig' {
@!block_var_stack[nqp::elems(@!block_var_stack) - 1].uses_bindsig(); @!block_var_stack[nqp::elems(@!block_var_stack) - 1].uses_bindsig();
} }
elsif $optype eq 'p6return' {
@!block_var_stack[nqp::elems(@!block_var_stack) - 1].uses_p6return();
}
elsif $optype eq 'call' || $optype eq 'callmethod' || $optype eq 'chain' { elsif $optype eq 'call' || $optype eq 'callmethod' || $optype eq 'chain' {
@!block_var_stack[nqp::elems(@!block_var_stack) - 1].register_call(); @!block_var_stack[nqp::elems(@!block_var_stack) - 1].register_call();
if nqp::existskey(%poison_calls, $op.name) { if nqp::existskey(%poison_calls, $op.name) {
Expand Down

0 comments on commit c6053e6

Please sign in to comment.