Skip to content

Commit

Permalink
Reduce cost of immediate block invocation.
Browse files Browse the repository at this point in the history
  • Loading branch information
jnthn committed Apr 27, 2013
1 parent 83fd61b commit 1cc2d3e
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
36 changes: 35 additions & 1 deletion src/vm/jvm/QAST/Compiler.nqp
Expand Up @@ -2076,6 +2076,10 @@ class QAST::CompilerJAST {
!! nqp::die("Unknown CUID '$cuid'")
}

method cuid_to_jastmethname($cuid) {
@!jastmeth_names[self.cuid_to_idx($cuid)]
}

method set_lexical_names($cuid, @ilex, @nlex, @slex, @olex) {
@!lexical_name_lists[self.cuid_to_idx($cuid)] := [@ilex, @nlex, @slex, @olex];
}
Expand Down Expand Up @@ -3039,7 +3043,37 @@ class QAST::CompilerJAST {
return self.as_jast(QAST::BVal.new( :value($node) ));
}
elsif $blocktype eq 'immediate' {
return self.as_jast(QAST::Op.new( :op('call'), QAST::BVal.new( :value($node) ) ));
# Can emit a direct JVM level call. First, get self, TC,
# code ref, callsite descriptor and args (both empty) onto
# the stack.
my $il := JAST::InstructionList.new();
$il.append(JAST::Instruction.new( :op('aload_0') ));
$il.append(JAST::Instruction.new( :op('aload_1') ));
$il.append(JAST::Instruction.new( :op('aload_0') ));
$il.append(JAST::PushSVal.new( :value($node.cuid) ));
$il.append(JAST::Instruction.new( :op('invokevirtual'),
$TYPE_CU, 'lookupCodeRef', $TYPE_CR, $TYPE_STR ));
$il.append(JAST::Instruction.new( :op('getstatic'),
$TYPE_OPS, 'emptyCallSite', $TYPE_CSD ));
$il.append(JAST::Instruction.new( :op('getstatic'),
$TYPE_OPS, 'emptyArgList', "[$TYPE_OBJ" ));

# Emit the virtual call.
$il.append(JAST::Instruction.new( :op('invokevirtual'),
'L' ~ $*JCLASS.name ~ ';',
$*CODEREFS.cuid_to_jastmethname($node.cuid),
'V', $TYPE_TC, $TYPE_CR, $TYPE_CSD, "[$TYPE_OBJ" ));

# Load result onto the stack, unless in void context.
if $*WANT != $RT_VOID {
$il.append(JAST::Instruction.new( :op('aload'), 'cf' ));
$il.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
'result_' ~ typechar($RT_OBJ), jtype($RT_OBJ), $TYPE_CF ));
return result($il, $RT_OBJ)
}
else {
return result($il, $RT_VOID)
}
}
elsif $blocktype eq 'raw' {
return self.as_jast(QAST::Op.new( :op('null') ));
Expand Down
1 change: 1 addition & 0 deletions src/vm/jvm/runtime/org/perl6/nqp/runtime/Ops.java
Expand Up @@ -1193,6 +1193,7 @@ public static SixModelObject captureposarg(SixModelObject obj, long idx, ThreadC

/* Invocation. */
public static final CallSiteDescriptor emptyCallSite = new CallSiteDescriptor(new byte[0], null);
public static final Object[] emptyArgList = new Object[0];
public static final CallSiteDescriptor invocantCallSite = new CallSiteDescriptor(new byte[] { CallSiteDescriptor.ARG_OBJ }, null);
public static void invoke(SixModelObject invokee, int callsiteIndex, Object[] args, ThreadContext tc) throws Exception {
// If it's lexotic, throw the exception right off.
Expand Down

0 comments on commit 1cc2d3e

Please sign in to comment.