Skip to content
Permalink
Browse files

Better tracking of what needs return handlers

So that we can produce code with a lot less of them. This can give a
speedup since it results in code that's easier to analyze and slightly
more compact.
  • Loading branch information...
jnthn committed Apr 9, 2019
1 parent 847783e commit 165f918403b390897b44fee5cbf24a6fe4450b3c
Showing with 39 additions and 61 deletions.
  1. +8 −56 src/Perl6/Actions.nqp
  2. +31 −5 src/Perl6/Grammar.nqp
@@ -3913,16 +3913,16 @@ class Perl6::Actions is HLL::Actions does STDActions {
$block.push(WANTED($<statementlist>.ast,'&def'));
$block.node($/);
}
if is_clearly_returnless($block) {
if $*MAY_USE_RETURN {
$block[1] := wrap_return_handler($block[1]);
}
else {
$block[1] := QAST::Op.new(
:op(decontrv_op()),
QAST::WVal.new( :value($*DECLARAND) ),
$block[1]);
$block[1] := wrap_return_type_check($block[1], $*DECLARAND);
}
else {
$block[1] := wrap_return_handler($block[1]);
}
}
$block.blocktype('declaration_static');

@@ -4348,16 +4348,16 @@ class Perl6::Actions is HLL::Actions does STDActions {
}
else {
$past := WANTED($<blockoid>.ast,'method_def');
if is_clearly_returnless($past) {
if $*MAY_USE_RETURN {
$past[1] := wrap_return_handler($past[1]);
}
else {
$past[1] := QAST::Op.new(
:op(decontrv_op()),
QAST::WVal.new( :value($*DECLARAND) ),
$past[1]);
$past[1] := wrap_return_type_check($past[1], $*DECLARAND);
}
else {
$past[1] := wrap_return_handler($past[1]);
}
}
$past.blocktype('declaration_static');

@@ -4661,54 +4661,6 @@ class Perl6::Actions is HLL::Actions does STDActions {
}
}

sub is_clearly_returnless($block) {
sub returnless_past($past) {
return 0 unless
# It's a simple operation.
nqp::istype($past, QAST::Op)
&& $past.op ne 'callmethod' # May be .return or similar
&& nqp::getcomp('QAST').operations.is_inlinable('perl6', $past.op) ||
# A QAST::Stmt node
nqp::istype($past, QAST::Stmt) ||
# Just a variable lookup.
nqp::istype($past, QAST::Var) ||
# Just a QAST::Want
nqp::istype($past, QAST::Want) ||
# Just a primitive or world value.
nqp::istype($past, QAST::WVal) ||
nqp::istype($past, QAST::IVal) ||
nqp::istype($past, QAST::NVal) ||
nqp::istype($past, QAST::SVal);
for @($past) {
if nqp::istype($_, QAST::Node) {
if !returnless_past($_) {
return 0;
}
}
}
1;
}

# Ensure second node is QAST::Stmts.
return 0 unless nqp::istype($block[1], QAST::Stmts);

# Ensure there's no nested blocks.
for @($block[0]) {
if nqp::istype($_, QAST::Block) { return 0; }
if nqp::istype($_, QAST::Stmts) {
for @($_) {
if nqp::istype($_, QAST::Block) { return 0; }
}
}
}

# Check the block content.
for @($block[1]) {
return 0 unless returnless_past($_);
}
return 1;
}

sub is_yada($/) {
if $<blockoid><statementlist> && +$<blockoid><statementlist><statement> == 1 {
my $btxt := ~$<blockoid><statementlist><statement>[0];
@@ -788,6 +788,7 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
:my $*SET_DEFAULT_LANG_VER := 1;
:my %*SIG_INFO; # information about recent signature
:my $*CAN_LOWER_TOPIC := 1; # true if we optimize the $_ lexical away
:my $*MAY_USE_RETURN := 0; # true if the current routine may use return
# Various interesting scopes we'd like to keep to hand.
:my $*GLOBALish;
@@ -2371,6 +2372,7 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
:my $outer := $*W.cur_lexpad();
:my $*BORG := {};
:my $*FATAL := self.pragma('fatal'); # can also be set from inside statementlist
:my $*MAY_USE_RETURN := 0;
{
if $*PRECEDING_DECL_LINE < $*LINE_NO {
$*PRECEDING_DECL_LINE := $*LINE_NO;
@@ -2445,6 +2447,7 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
:my %*SIG_INFO;
:my $*BORG := {};
:my $*FATAL := self.pragma('fatal'); # can also be set from inside statementlist
:my $*MAY_USE_RETURN := 0;
{
if $*PRECEDING_DECL_LINE < $*LINE_NO {
$*PRECEDING_DECL_LINE := $*LINE_NO;
@@ -3022,14 +3025,27 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
[ <?after ','\h*<.[ . … ]>+> { self.worry("Comma found before apparent sequence operator; please remove comma (or put parens around the ... call, or use 'fail' instead of ...)") } ]?
[ <?{ $*GOAL eq 'endargs' && !$*COMPILING_CORE_SETTING }> <?after <.:L + [\]]>\h*<[ . … ]>+> { self.worry("Apparent sequence operator parsed as stubbed function argument; please supply any missing argument to the function or the sequence (or parenthesize the ... call, or use 'fail' instead of ...)") } ]?
<args>
{ $*MAY_USE_RETURN := 1 }
}
token term:sym<???> { <sym> <args> }
token term:sym<!!!> { <sym> <args> }
my %returnish := nqp::hash(
'return', 1,
'return-rw', 1,
'fail', 1,
'nextsame', 1,
'nextwith', 1,
'EVAL', 1,
'EVALFILE', 1);
token term:sym<identifier> {
:my $pos;
<identifier> <!{ $*W.is_type([~$<identifier>]) }> [ <?before <.unsp>? '('> | \\ <?before '('> ]
{ $pos := $/.pos }
{
$pos := $/.pos;
if %returnish{$<identifier>.Str} { $*MAY_USE_RETURN := 1 }
}
<args(1)>
{
if !$<args><invocant> {
@@ -3065,12 +3081,18 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
:my %colonpairs;
:my $*longname;
:my $pos;
:my $*IN_RETURN;
:my $*IN_RETURN := 0;
:my $is_type := 0;
{
$*longname := $*W.dissect_longname($<longname>);
$pos := $/.pos;
$*IN_RETURN := $<longname>.Str eq 'return';
if $<longname>.Str eq 'return' {
$*IN_RETURN := 1;
$*MAY_USE_RETURN := 1;
}
elsif %returnish{$<longname>.Str} || $*longname.contains_indirect_lookup() {
$*MAY_USE_RETURN := 1;
}
$is_type := !$*longname.get_who && $*W.is_type($*longname.components());
}
[
@@ -3849,12 +3871,16 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
token methodop {
[
| <longname> { if $<longname> eq '::' { self.malformed("class-qualified postfix call") } }
| <?[$@&]> <variable> { self.check_variable($<variable>) }
| <longname> {
if $<longname> eq '::' { self.malformed("class-qualified postfix call") }
elsif %returnish{$<longname>.Str} { $*MAY_USE_RETURN := 1 }
}
| <?[$@&]> <variable> { self.check_variable($<variable>); $*MAY_USE_RETURN := 1 }
| <?['"]>
[ <!{$*QSIGIL}> || <!before '"' <.-["]>*? [\s|$] > ] # dwim on "$foo."
<quote>
[ <?before '(' | '.(' | '\\'> || <.panic: "Quoted method name requires parenthesized arguments. If you meant to concatenate two strings, use '~'."> ]
{ $*MAY_USE_RETURN := 1 }
] <.unsp>?
:dba('method arguments')
[

0 comments on commit 165f918

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