Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Better handling of sink.
On MoarVM, this leads to a smaller QAST trees and much better code
generation. On JVM and Parrot, we get the first advantage, and we
could improve their code-gen in the future too. Note the Parrot bit
of this is untested due to being unable to build NQP Parrot on Win32
at present; the JVM patch worked right off, though, and there's very
little reason fro the Parrot one not to. Testing welcome.
  • Loading branch information
jnthn committed Jul 30, 2014
1 parent 7cac3a1 commit a398910
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 27 deletions.
29 changes: 2 additions & 27 deletions src/Perl6/Actions.nqp
Expand Up @@ -93,35 +93,10 @@ class Perl6::Actions is HLL::Actions does STDActions {
}

sub sink($past) {
my $name := $past.unique('sink');
QAST::Want.new(
$past,
'v',
QAST::Op.new(
:op('locallifetime'),
QAST::Stmts.new(
QAST::Op.new(:op<bind>,
QAST::Var.new(:$name, :scope<local>, :decl<var>),
$past,
),
QAST::Op.new(:op<if>,
QAST::Op.new(:op<if>,
QAST::Op.new(:op<isconcrete>,
QAST::Var.new(:$name, :scope<local>),
),
QAST::Op.new(:op<can>,
QAST::Var.new(:$name, :scope<local>),
QAST::SVal.new(:value('sink')),
)
),
QAST::Op.new(:op<callmethod>, :name<sink>,
QAST::Var.new(:$name, :scope<local>),
),
),
),
$name,
),
);
'v', QAST::Op.new( :op('p6sink'), $past )
)
}
my %sinkable := nqp::hash(
'call', 1,
Expand Down
27 changes: 27 additions & 0 deletions src/vm/jvm/Perl6/Ops.nqp
Expand Up @@ -162,6 +162,33 @@ $ops.add_hll_op('perl6', 'p6invokeflat', -> $qastcomp, $op {
$op[1].flat(1);
$qastcomp.as_jast(QAST::Op.new( :op('call'), $op[0], $op[1]));
});
$ops.add_hll_op('perl6', 'p6sink', -> $qastcomp, $past {
my $name := $past.unique('sink');
$qastcomp.as_jast(QAST::Op.new(
:op('locallifetime'),
QAST::Stmts.new(
QAST::Op.new(:op<bind>,
QAST::Var.new(:$name, :scope<local>, :decl<var>),
$past[0],
),
QAST::Op.new(:op<if>,
QAST::Op.new(:op<if>,
QAST::Op.new(:op<isconcrete>,
QAST::Var.new(:$name, :scope<local>),
),
QAST::Op.new(:op<can>,
QAST::Var.new(:$name, :scope<local>),
QAST::SVal.new(:value('sink')),
)
),
QAST::Op.new(:op<callmethod>, :name<sink>,
QAST::Var.new(:$name, :scope<local>),
),
),
),
$name
))
});

# Make some of them also available from NQP land, since we use them in the
# metamodel and bootstrap.
Expand Down
38 changes: 38 additions & 0 deletions src/vm/moar/Perl6/Ops.nqp
Expand Up @@ -433,6 +433,44 @@ $ops.add_hll_op('perl6', 'p6invokeflat', -> $qastcomp, $op {
$op[1].flat(1);
$qastcomp.as_mast(QAST::Op.new( :op('call'), $op[0], $op[1]));
});
$ops.add_hll_op('perl6', 'p6sink', -> $qastcomp, $op {
# Only need to do anything special if it's an object.
my $sinkee_res := $qastcomp.as_mast($op[0]);
if $sinkee_res.result_kind == $MVM_reg_obj {
# Put computation of sinkee first.
my @ops;
push_ilist(@ops, $sinkee_res);

# Check it's concrete and can sink.
my $sinkee_reg := $sinkee_res.result_reg;
my $itmp := $*REGALLOC.fresh_i();
my $done_lbl := MAST::Label.new( :name($op.unique('p6sink')) );
nqp::push(@ops, MAST::Op.new( :op('isconcrete'), $itmp, $sinkee_reg ));
nqp::push(@ops, MAST::Op.new( :op('unless_i'), $itmp, $done_lbl ));
nqp::push(@ops, MAST::Op.new( :op('can'), $itmp, $sinkee_reg,
MAST::SVal.new( :value('sink') )));
nqp::push(@ops, MAST::Op.new( :op('unless_i'), $itmp, $done_lbl ));
$*REGALLOC.release_register($itmp, $MVM_reg_int64);

# Emit sink method call.
my $meth := $*REGALLOC.fresh_o();
$*REGALLOC.release_register($meth, $MVM_reg_obj);
nqp::push(@ops, MAST::Op.new( :op('findmeth'), $meth, $sinkee_reg,
MAST::SVal.new( :value('sink') )));
nqp::push(@ops, MAST::Call.new(
:target($meth), :flags([$Arg::obj]), $sinkee_reg
));
$*REGALLOC.release_register($meth, $MVM_reg_obj);

# Add end label, and we're done.
nqp::push(@ops, $done_lbl);
$*REGALLOC.release_register($sinkee_res.result_reg, $MVM_reg_obj);
MAST::InstructionList.new(@ops, MAST::VOID, $MVM_reg_void);
}
else {
$sinkee_res
}
});

# Make some of them also available from NQP land, since we use them in the
# metamodel and bootstrap.
Expand Down
27 changes: 27 additions & 0 deletions src/vm/parrot/Perl6/Ops.nqp
Expand Up @@ -70,6 +70,33 @@ $ops.add_hll_op('perl6', 'p6staticouter', -> $qastcomp, $op {
});
$ops.add_hll_pirop_mapping('perl6', 'p6scalarfromdesc', 'p6scalarfromdesc', 'PP', :inlinable(1));
$ops.add_hll_pirop_mapping('perl6', 'p6invokehandler', 'perl6_invoke_catchhandler', 'vPP');
$ops.add_hll_op('perl6', 'p6sink', -> $qastcomp, $past {
my $name := $past.unique('sink');
$qastcomp.as_post(QAST::Op.new(
:op('locallifetime'),
QAST::Stmts.new(
QAST::Op.new(:op<bind>,
QAST::Var.new(:$name, :scope<local>, :decl<var>),
$past[0],
),
QAST::Op.new(:op<if>,
QAST::Op.new(:op<if>,
QAST::Op.new(:op<isconcrete>,
QAST::Var.new(:$name, :scope<local>),
),
QAST::Op.new(:op<can>,
QAST::Var.new(:$name, :scope<local>),
QAST::SVal.new(:value('sink')),
)
),
QAST::Op.new(:op<callmethod>, :name<sink>,
QAST::Var.new(:$name, :scope<local>),
),
),
),
$name
))
});

# Make some of them also available from NQP land, since we use them in the
# metamodel and bootstrap.
Expand Down

0 comments on commit a398910

Please sign in to comment.