Skip to content
Permalink
Browse files

Restore CALLER:: behavior on non-dynamic vars

We retain the lexical slot, but fill it with something that will always
come out as non-dynamic in the PseudoStash check, thus restoring the
behavior expected in the spectests. It'd be nice to be able to fully do
away with this at some point, but that needs either a better mechanism
or a spec change.
  • Loading branch information...
jnthn committed Jan 2, 2019
1 parent 852a593 commit 871b6f54623c5a698ce0ea7a14761d58df5d056d
Showing with 26 additions and 8 deletions.
  1. +21 −8 src/Perl6/Optimizer.nqp
  2. +5 −0 src/core/Rakudo/Internals.pm6
@@ -34,6 +34,7 @@ my class Symbols {
has $!Nil;
has $!Failure;
has $!Seq;
has $!LoweredAwayLexical;

# Top routine, for faking it when optimizing post-inline.
has $!fake_top_routine;
@@ -61,6 +62,7 @@ my class Symbols {
$!Nil := self.find_lexical('Nil');
$!Failure := self.find_lexical('Failure');
$!Seq := self.find_lexical('Seq');
$!LoweredAwayLexical := self.find_symbol(['Rakudo', 'Internals', 'LoweredAwayLexical']);
nqp::pop(@!block_stack);
}

@@ -103,6 +105,7 @@ my class Symbols {
method Nil() { $!Nil }
method Failure() { $!Failure }
method Seq() { $!Seq }
method LoweredAwayLexical() { $!LoweredAwayLexical }

# The following function is a nearly 1:1 copy of World.find_symbol.
# Finds a symbol that has a known value at compile time from the
@@ -618,7 +621,7 @@ my class BlockVarOptimizer {
}
}

method lexical_vars_to_locals($block) {
method lexical_vars_to_locals($block, $LoweredAwayLexical) {
return 0 if $!poisoned || $!uses_bindsig;
return 0 unless nqp::istype($block[0], QAST::Stmts);
for %!decls {
@@ -671,13 +674,23 @@ my class BlockVarOptimizer {
next if $ref'd;

# Seems good; lower it. Note we need to retain a lexical in
# case of binder failover to generate errors for parameters
# (we don't do this for contvar, which is a decent heuristic
# for "not a parameter").
# case of binder failover to generate errors for parameters,
# and also to preserve behavior of CALLER::foo dying when we
# try to access a lexical that was lowered. We install the
# symbol Rakudo::Internals::LoweredAwayLexical for the latter
# purpose.
my $new_name := $qast.unique('__lowered_lex');
unless $is_contvar {
$block[0].unshift(QAST::Var.new( :name($qast.name), :scope('lexical'),
:decl('var'), :returns($qast.returns) ));
if nqp::objprimspec($qast.returns) {
$block[0].unshift(QAST::Var.new(
:name($qast.name), :scope('lexical'), :decl('var'),
:returns($qast.returns)
));
}
else {
$block[0].unshift(QAST::Var.new(
:name($qast.name), :scope('lexical'), :decl('static'),
:value($LoweredAwayLexical)
));
}
$qast.name($new_name);
$qast.scope('local');
@@ -1053,7 +1066,7 @@ class Perl6::Optimizer {

# Do any possible lexical => local lowering.
if $!level >= 2 {
$vars_info.lexical_vars_to_locals($block);
$vars_info.lexical_vars_to_locals($block, $!symbols.LoweredAwayLexical);
}

# Incorporate this block's info into outer block's info.
@@ -36,6 +36,11 @@ my class Rakudo::Internals {
}
}

# Marker symbol for lexicals that we have lowered away.
class LoweredAwayLexical {
method dynamic() { False }
}

# rotate nqp list to another given list without using push/pop
method RotateListToList(\from,\n,\to) {
nqp::stmts(

0 comments on commit 871b6f5

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