Skip to content

Commit a7f2425

Browse files
committed
Special-case one object arg case of invocation.
Many method invocations where no extra parameters look like this, such as almost all grammar rule invocations.
1 parent 04341ad commit a7f2425

File tree

4 files changed

+84
-6
lines changed

4 files changed

+84
-6
lines changed

src/vm/jvm/QAST/Compiler.nqp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3295,7 +3295,7 @@ class QAST::CompilerJAST {
32953295
if $node.custom_args {
32963296
$*JMETH.add_argument('__args', "[$TYPE_OBJ");
32973297
}
3298-
elsif !self.try_setup_args_expectation($*JMETH, $block) {
3298+
elsif !self.try_setup_args_expectation($*JMETH, $block, $il) {
32993299
# Analyze parameters to get count of required/optional and make sure
33003300
# all is in order.
33013301
my int $pos_required := 0;
@@ -3642,19 +3642,49 @@ class QAST::CompilerJAST {
36423642

36433643
my $ARG_EXP_USE_BINDER := 0;
36443644
my $ARG_EXP_NO_ARGS := 1;
3645-
method try_setup_args_expectation($jmeth, $block) {
3645+
my $ARG_EXP_OBJ := 2;
3646+
method try_setup_args_expectation($jmeth, $block, $il) {
36463647
# Needing an args array forces the binder.
36473648
if $*NEED_ARGS_ARRAY {
36483649
return $ARG_EXP_USE_BINDER;
36493650
}
36503651

36513652
# Otherwise, go by arity, then look at particular cases.
3652-
my $num_params := $block.params;
3653+
my int $num_params := +$block.params;
36533654
if $num_params == 0 {
36543655
# Easy; just don't add any extra args in.
36553656
$jmeth.args_expectation($ARG_EXP_NO_ARGS);
36563657
return $ARG_EXP_NO_ARGS;
36573658
}
3659+
elsif $num_params == 1 {
3660+
# Look for one required positional case. Methods with no params
3661+
# beyond the invocant are always this.
3662+
my $param := $block.params[0];
3663+
if !$param.named && !$param.slurpy && !$param.default {
3664+
if nqp::objprimspec($param.returns) == 0 {
3665+
$jmeth.add_argument('__arg_0', $TYPE_SMO);
3666+
$il.append(JAST::Instruction.new( :op('aload'), '__arg_0' ));
3667+
if $param.scope eq 'local' {
3668+
$il.append(JAST::Instruction.new( :op('astore'), $param.name ));
3669+
}
3670+
else {
3671+
$il.append(JAST::Instruction.new( :op('aload'), 'cf' ));
3672+
$il.append(JAST::PushIndex.new( :value($block.lexical_idx($param.name)) ));
3673+
$il.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS,
3674+
'bindlex_o', $TYPE_SMO, $TYPE_SMO, $TYPE_CF, 'Integer' ));
3675+
$il.append($POP);
3676+
}
3677+
$jmeth.args_expectation($ARG_EXP_OBJ);
3678+
return $ARG_EXP_OBJ;
3679+
}
3680+
else {
3681+
return $ARG_EXP_USE_BINDER;
3682+
}
3683+
}
3684+
else {
3685+
return $ARG_EXP_USE_BINDER;
3686+
}
3687+
}
36583688
else {
36593689
return $ARG_EXP_USE_BINDER;
36603690
}

src/vm/jvm/runtime/org/perl6/nqp/runtime/ArgsExpectation.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.perl6.nqp.runtime;
22

3+
import org.perl6.nqp.sixmodel.*;
4+
35
/* Argument expectations are used to indicate what, exactly, a block we are
46
* invoking expects. The default is that it wants the args in an Object[] and
57
* will use the binder to process them specially. We special-case various of
@@ -9,6 +11,7 @@
911
public class ArgsExpectation {
1012
public static final short USE_BINDER = 0;
1113
public static final short NO_ARGS = 1;
14+
public static final short OBJ = 2;
1215

1316
public static void invokeByExpectation(ThreadContext tc, CodeRef cr,
1417
CallSiteDescriptor csd, Object[] args) throws Throwable {
@@ -19,14 +22,56 @@ public static void invokeByExpectation(ThreadContext tc, CodeRef cr,
1922
case ArgsExpectation.NO_ARGS:
2023
if (csd.argFlags.length != 0) {
2124
// Probable error, but consider flattening.
22-
csd = csd.explodeFlattening(tc.curFrame, args);
25+
if (csd.hasFlattening)
26+
csd = csd.explodeFlattening(tc.curFrame, args);
2327
if (csd.argFlags.length != 0)
2428
ExceptionHandling.dieInternal(tc,
2529
"Wrong number of arguments passed; expected 0..0, but got " +
2630
csd.numPositionals);
2731
}
2832
cr.staticInfo.mh.invokeExact(tc, cr, csd);
2933
break;
34+
case ArgsExpectation.OBJ:
35+
if (csd.argFlags.length == 1 && csd.argFlags[0] == CallSiteDescriptor.ARG_OBJ) {
36+
/* Simple, common case. */
37+
cr.staticInfo.mh.invokeExact(tc, cr, csd, (SixModelObject)args[0]);
38+
}
39+
else {
40+
/* Flatten if needed. */
41+
if (csd.hasFlattening) {
42+
csd = csd.explodeFlattening(tc.curFrame, args);
43+
args = tc.flatArgs;
44+
}
45+
if (csd.argFlags.length == 1) {
46+
switch (csd.argFlags[0]) {
47+
case CallSiteDescriptor.ARG_OBJ:
48+
cr.staticInfo.mh.invokeExact(tc, cr, csd, (SixModelObject)args[0]);
49+
break;
50+
case CallSiteDescriptor.ARG_INT:
51+
cr.staticInfo.mh.invokeExact(tc, cr, csd, Ops.box_i(
52+
(long)args[0], cr.staticInfo.compUnit.hllConfig.intBoxType, tc));
53+
break;
54+
case CallSiteDescriptor.ARG_NUM:
55+
cr.staticInfo.mh.invokeExact(tc, cr, csd, Ops.box_n(
56+
(double)args[0], cr.staticInfo.compUnit.hllConfig.numBoxType, tc));
57+
break;
58+
case CallSiteDescriptor.ARG_STR:
59+
cr.staticInfo.mh.invokeExact(tc, cr, csd, Ops.box_s(
60+
(String)args[0], cr.staticInfo.compUnit.hllConfig.strBoxType, tc));
61+
break;
62+
default:
63+
ExceptionHandling.dieInternal(tc,
64+
"Wrong number of arguments passed; expected 1..1, but got " +
65+
csd.numPositionals);
66+
}
67+
}
68+
else {
69+
ExceptionHandling.dieInternal(tc,
70+
"Wrong number of arguments passed; expected 1..1, but got " +
71+
csd.numPositionals);
72+
}
73+
}
74+
break;
3075
default:
3176
ExceptionHandling.dieInternal(tc, "Unknown Argument Expectation in invoke");
3277
}

src/vm/jvm/runtime/org/perl6/nqp/runtime/IndyBootstrap.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ public static void methcallResolve_noa(Lookup caller, MutableCallSite cs, String
408408

409409
/* Make the call directly for this initial call. */
410410
try {
411-
cr.staticInfo.mh.invokeExact(tc, cr, csd, args);
411+
ArgsExpectation.invokeByExpectation(tc, cr, csd, args);
412412
}
413413
catch (ControlException e) {
414414
throw e;
@@ -482,7 +482,7 @@ public static void indmethcallInvoker_noa(MutableCallSite cs, int csIdx,
482482

483483
/* Make the call. */
484484
try {
485-
cr.staticInfo.mh.invokeExact(tc, cr, csd, args);
485+
ArgsExpectation.invokeByExpectation(tc, cr, csd, args);
486486
}
487487
catch (ControlException e) {
488488
throw e;

src/vm/jvm/runtime/org/perl6/nqp/runtime/StaticCodeInfo.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ else if (t.parameterCount() >= 4 && (t.parameterType(3) == ResumeStatus.Frame.cl
184184
case ArgsExpectation.NO_ARGS:
185185
/* Nothing to insert. */
186186
break;
187+
case ArgsExpectation.OBJ:
188+
mhResume = MethodHandles.insertArguments(mhResume, 1, (SixModelObject)null);
189+
break;
187190
default:
188191
throw new RuntimeException("Unhandled ArgsExpectation in StaticCodeInfo");
189192
}

0 commit comments

Comments
 (0)