Skip to content
Permalink
Browse files

Don't inline immediate blocks using p6return

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 c6053e6a5dc64dd66dd14f44c03a28db99783b35
Showing with 13 additions and 1 deletion.
  1. +13 −1 src/Perl6/Optimizer.nqp
@@ -450,6 +450,9 @@ my class BlockVarOptimizer {
# If p6bindsig is used.
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
# are code-gen'd with an implicit block around them, so we mustn't lower
# lexicals referenced in them to locals.
@@ -503,6 +506,8 @@ my class BlockVarOptimizer {

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

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

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

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

method is_poisoned() { $!poisoned }

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

method get_escaping_handler_vars() {
my @esc;
for %!used_in_handle_handler {
@@ -1123,7 +1132,7 @@ class Perl6::Optimizer {
my int $flattened := 0;
my $result := $block;
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.
my $impossible := 0;
for $block.symtable() {
@@ -1499,6 +1508,9 @@ class Perl6::Optimizer {
elsif $optype eq 'p6bindsig' || $optype eq 'p6bindcaptosig' {
@!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' {
@!block_var_stack[nqp::elems(@!block_var_stack) - 1].register_call();
if nqp::existskey(%poison_calls, $op.name) {

0 comments on commit c6053e6

Please sign in to comment.
You can’t perform that action at this time.