Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[dotnet] Stub in an NQP Optimizer. Only one optimization at the momen…
…t, which strips off return handlers from routines if they're never used (something we can statically detect in NQP).
  • Loading branch information
jnthn committed Nov 21, 2010
1 parent 2ff0334 commit 6fd5926
Showing 1 changed file with 93 additions and 0 deletions.
93 changes: 93 additions & 0 deletions dotnet/compiler/NQPOptimizer.pm
@@ -0,0 +1,93 @@
# This is a very basic optimizer for NQP. It works over the PAST tree. It makes
# various assumptions that are NQP-specific. In particular (please update this
# list if you add optimizations):
# * There is no eval that can see outer lexicals.
# * All returning is done through a PAST::Op node with :pasttype('return')

class NQPOptimizer {
method optimize($past) {
# Set up a block stack with a fake block.
my @*BLOCK_STACK;
@*BLOCK_STACK.push(PAST::Block.new());

# Run the optimizer.
optimizer($past);

$past
}
}

our multi optimizer(PAST::Block $block) {
# Mark that our parent block has an inner block and unshift ourself
# onto the block stack.
annotate(@*BLOCK_STACK[0], 'has_nested_blocks', 1);
@*BLOCK_STACK.unshift($block);

# Go through the block and call the optimizer on everything in it.
for @($block) {
optimizer($_);
}

# If we have a return handler but nothing marked it used, toss it.
if $block.control && !get_annotation($block, 'return_used') {
$block.control('');
}

# Remove this block from the block stack.
@*BLOCK_STACK.shift();
}

our multi optimizer(PAST::Stmts $stmts) {
# Need to do nothing other than loop through children.
for @($stmts) {
optimizer($_);
}
}

our multi optimizer(PAST::Op $op) {
# Need to visit the children.
for @($op) {
optimizer($_);
}

# If it's a return node, go find something with a return handler
# and annotate that the return is used.
if $op.pasttype eq 'return' {
for @*BLOCK_STACK {
if $_.control {
annotate($_, 'return_used', 1);
last;
}
}
}
}

our multi optimizer(PAST::Var $var) {
# May need to visit the viviself.
if $var.viviself ~~ PAST::Node {
optimizer($var.viviself);
}
}

our multi optimizer(PAST::Val $stmts) {
# Nothing to do at all :-)
}

our multi sub optimizer($any) {
if pir::isa($any, 'String') || pir::isa($any, 'Integer') || pir::isa($any, 'Float') {
# Literals - nothing to do.
}
else {
pir::die("optimizer() is missing a candidate for " ~ pir::typeof__SP($any) ~ "(" ~ $any ~ ")");
}
}

# Annotates a node with a given note.
sub annotate($node, $key, $value) {
$node{'nqp_opt_' ~ $key} := $value;
}

# Gets an annotation made on a node.
sub get_annotation($node, $key) {
$node{'nqp_opt_' ~ $key}
}

0 comments on commit 6fd5926

Please sign in to comment.