Skip to content

Commit ed174f6

Browse files
committed
Add variant of RubyArguments.getPositionalArgumentsCount() for the common methodHasKeywordParameters=false case
* This does not reduce the subTreeCost cost for host inlining as host inlining would optimize it the same, but it makes it cheaper to inline and the initial cost before optimizations is much smaller. In fact it becomes trivial inlined by Native Image and so host inlining does not even see it anymore.
1 parent a237dba commit ed174f6

File tree

9 files changed

+35
-29
lines changed

9 files changed

+35
-29
lines changed

src/main/java/org/truffleruby/core/basicobject/BasicObjectNodes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ public abstract static class InstanceEvalNode extends AlwaysInlinedMethodNode {
357357
protected Object evalWithBlock(Frame callerFrame, Object self, Object[] rubyArgs, RootCallTarget target,
358358
@Cached InstanceExecBlockNode instanceExecNode,
359359
@Cached @Exclusive BranchProfile wrongNumberOfArgumentsProfile) {
360-
final int count = RubyArguments.getPositionalArgumentsCount(rubyArgs, false);
360+
final int count = RubyArguments.getPositionalArgumentsCount(rubyArgs);
361361

362362
if (count > 0) {
363363
wrongNumberOfArgumentsProfile.enter();
@@ -380,7 +380,7 @@ protected Object evalWithString(Frame callerFrame, Object self, Object[] rubyArg
380380
final Object sourceCode;
381381
String fileName = coreStrings().EVAL_FILENAME_STRING.toString();
382382
int line = 1;
383-
int count = RubyArguments.getPositionalArgumentsCount(rubyArgs, false);
383+
int count = RubyArguments.getPositionalArgumentsCount(rubyArgs);
384384

385385
if (count == 0) {
386386
zeroNumberOfArguments.enter();

src/main/java/org/truffleruby/core/kernel/KernelNodes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,7 @@ protected Object eval(Frame callerFrame, Object callerSelf, Object[] rubyArgs, R
695695
@Cached ConditionProfile fileAndLineProfile,
696696
@Cached ConditionProfile fileNoLineProfile) {
697697

698-
final Object[] args = RubyArguments.getPositionalArguments(rubyArgs, false);
698+
final Object[] args = RubyArguments.getPositionalArguments(rubyArgs);
699699
final Object source = toStrNode.execute(args[0]);
700700

701701
final RubyBinding binding;
@@ -1446,7 +1446,7 @@ protected boolean doesRespondTo(Frame callerFrame, Object self, Object[] rubyArg
14461446
@Cached DispatchNode respondToMissingNode,
14471447
@Cached BooleanCastNode castMissingResultNode) {
14481448
final Object name = RubyArguments.getArgument(rubyArgs, 0);
1449-
final int nArgs = RubyArguments.getPositionalArgumentsCount(rubyArgs, false);
1449+
final int nArgs = RubyArguments.getPositionalArgumentsCount(rubyArgs);
14501450
final boolean includeProtectedAndPrivate = nArgs >= 2 &&
14511451
castArgumentNode.execute(RubyArguments.getArgument(rubyArgs, 1));
14521452

src/main/java/org/truffleruby/core/module/ModuleNodes.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ public abstract static class AttrNode extends GenerateAccessorNode {
565565
@Specialization
566566
protected Object attr(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target) {
567567
final boolean setter;
568-
Object[] names = RubyArguments.getPositionalArguments(rubyArgs, false);
568+
Object[] names = RubyArguments.getPositionalArguments(rubyArgs);
569569
if (names.length == 2 && names[1] instanceof Boolean) {
570570
warnObsoletedBooleanArgument();
571571
setter = (boolean) names[1];
@@ -592,7 +592,7 @@ private void warnObsoletedBooleanArgument() {
592592
public abstract static class AttrAccessorNode extends GenerateAccessorNode {
593593
@Specialization
594594
protected Object attrAccessor(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target) {
595-
Object[] names = RubyArguments.getPositionalArguments(rubyArgs, false);
595+
Object[] names = RubyArguments.getPositionalArguments(rubyArgs);
596596
return createArray(generateAccessors(callerFrame, module, names, BOTH, target));
597597
}
598598
}
@@ -602,7 +602,7 @@ protected Object attrAccessor(Frame callerFrame, RubyModule module, Object[] rub
602602
public abstract static class AttrReaderNode extends GenerateAccessorNode {
603603
@Specialization
604604
protected Object attrReader(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target) {
605-
Object[] names = RubyArguments.getPositionalArguments(rubyArgs, false);
605+
Object[] names = RubyArguments.getPositionalArguments(rubyArgs);
606606
return createArray(generateAccessors(callerFrame, module, names, READER, target));
607607
}
608608
}
@@ -612,7 +612,7 @@ protected Object attrReader(Frame callerFrame, RubyModule module, Object[] rubyA
612612
public abstract static class AttrWriterNode extends GenerateAccessorNode {
613613
@Specialization
614614
protected Object attrWriter(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target) {
615-
Object[] names = RubyArguments.getPositionalArguments(rubyArgs, false);
615+
Object[] names = RubyArguments.getPositionalArguments(rubyArgs);
616616
return createArray(generateAccessors(callerFrame, module, names, WRITER, target));
617617
}
618618
}
@@ -711,7 +711,7 @@ public abstract static class ClassEvalNode extends AlwaysInlinedMethodNode {
711711
protected Object evalWithBlock(Frame callerFrame, RubyModule self, Object[] rubyArgs, RootCallTarget target,
712712
@Cached @Exclusive BranchProfile wrongNumberOfArgumentsProfile,
713713
@Cached ClassExecBlockNode classExecNode) {
714-
final int count = RubyArguments.getPositionalArgumentsCount(rubyArgs, false);
714+
final int count = RubyArguments.getPositionalArgumentsCount(rubyArgs);
715715

716716
if (count > 0) {
717717
wrongNumberOfArgumentsProfile.enter();
@@ -734,7 +734,7 @@ protected Object evalWithString(Frame callerFrame, RubyModule self, Object[] rub
734734
String fileName = coreStrings().EVAL_FILENAME_STRING.toString();
735735
int line = 1;
736736

737-
int count = RubyArguments.getPositionalArgumentsCount(rubyArgs, false);
737+
int count = RubyArguments.getPositionalArgumentsCount(rubyArgs);
738738

739739
if (count == 0) {
740740
wrongNumberOfArgumentsProfile.enter();
@@ -1518,7 +1518,7 @@ private RubySymbol addInternalMethod(RubyModule module, String name, InternalMet
15181518
}
15191519

15201520
protected boolean isMethodParameterProvided(Object[] rubyArgs) {
1521-
final int count = RubyArguments.getPositionalArgumentsCount(rubyArgs, false);
1521+
final int count = RubyArguments.getPositionalArgumentsCount(rubyArgs);
15221522
return count >= 2;
15231523
}
15241524

@@ -1697,7 +1697,7 @@ protected boolean isMethodDefined(RubyModule module, String name, boolean inheri
16971697
public abstract static class ModuleFunctionNode extends AlwaysInlinedMethodNode {
16981698
@Specialization(guards = "names.length == 0")
16991699
protected Object frame(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target,
1700-
@Bind("getPositionalArguments(rubyArgs, false)") Object[] names,
1700+
@Bind("getPositionalArguments(rubyArgs)") Object[] names,
17011701
@Cached @Shared BranchProfile errorProfile) {
17021702
checkNotClass(module, errorProfile);
17031703
needCallerFrame(callerFrame, "Module#module_function with no arguments");
@@ -1707,7 +1707,7 @@ protected Object frame(Frame callerFrame, RubyModule module, Object[] rubyArgs,
17071707

17081708
@Specialization(guards = "names.length > 0")
17091709
protected Object methods(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target,
1710-
@Bind("getPositionalArguments(rubyArgs, false)") Object[] names,
1710+
@Bind("getPositionalArguments(rubyArgs)") Object[] names,
17111711
@Cached SetMethodVisibilityNode setMethodVisibilityNode,
17121712
@Cached @Shared BranchProfile errorProfile,
17131713
@Cached LoopConditionProfile loopProfile,
@@ -1785,15 +1785,15 @@ protected RubyArray nesting() {
17851785
public abstract static class PublicNode extends AlwaysInlinedMethodNode {
17861786
@Specialization(guards = "names.length == 0")
17871787
protected Object frame(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target,
1788-
@Bind("getPositionalArguments(rubyArgs, false)") Object[] names) {
1788+
@Bind("getPositionalArguments(rubyArgs)") Object[] names) {
17891789
needCallerFrame(callerFrame, "Module#public with no arguments");
17901790
DeclarationContext.setCurrentVisibility(callerFrame, Visibility.PUBLIC);
17911791
return nil;
17921792
}
17931793

17941794
@Specialization(guards = "names.length > 0")
17951795
protected Object methods(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target,
1796-
@Bind("getPositionalArguments(rubyArgs, false)") Object[] names,
1796+
@Bind("getPositionalArguments(rubyArgs)") Object[] names,
17971797
@Cached SetMethodVisibilityNode setMethodVisibilityNode,
17981798
@Cached SingleValueCastNode singleValueCastNode) {
17991799
for (Object name : names) {
@@ -1827,15 +1827,15 @@ protected RubyModule publicClassMethod(RubyModule module, Object[] names) {
18271827
public abstract static class PrivateNode extends AlwaysInlinedMethodNode {
18281828
@Specialization(guards = "names.length == 0")
18291829
protected Object frame(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target,
1830-
@Bind("getPositionalArguments(rubyArgs, false)") Object[] names) {
1830+
@Bind("getPositionalArguments(rubyArgs)") Object[] names) {
18311831
needCallerFrame(callerFrame, "Module#private with no arguments");
18321832
DeclarationContext.setCurrentVisibility(callerFrame, Visibility.PRIVATE);
18331833
return nil;
18341834
}
18351835

18361836
@Specialization(guards = "names.length > 0")
18371837
protected Object methods(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target,
1838-
@Bind("getPositionalArguments(rubyArgs, false)") Object[] names,
1838+
@Bind("getPositionalArguments(rubyArgs)") Object[] names,
18391839
@Cached SetMethodVisibilityNode setMethodVisibilityNode,
18401840
@Cached SingleValueCastNode singleValueCastNode) {
18411841
for (Object name : names) {
@@ -2132,15 +2132,15 @@ protected RubyModule publicConstant(RubyModule module, Object[] args) {
21322132
public abstract static class ProtectedNode extends AlwaysInlinedMethodNode {
21332133
@Specialization(guards = "names.length == 0")
21342134
protected Object frame(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target,
2135-
@Bind("getPositionalArguments(rubyArgs, false)") Object[] names) {
2135+
@Bind("getPositionalArguments(rubyArgs)") Object[] names) {
21362136
needCallerFrame(callerFrame, "Module#protected with no arguments");
21372137
DeclarationContext.setCurrentVisibility(callerFrame, Visibility.PROTECTED);
21382138
return nil;
21392139
}
21402140

21412141
@Specialization(guards = "names.length > 0")
21422142
protected Object methods(Frame callerFrame, RubyModule module, Object[] rubyArgs, RootCallTarget target,
2143-
@Bind("getPositionalArguments(rubyArgs, false)") Object[] names,
2143+
@Bind("getPositionalArguments(rubyArgs)") Object[] names,
21442144
@Cached SetMethodVisibilityNode setMethodVisibilityNode,
21452145
@Cached SingleValueCastNode singleValueCastNode) {
21462146
for (Object name : names) {

src/main/java/org/truffleruby/core/proc/ProcNodes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,15 +308,15 @@ protected Object singleBlockArg(VirtualFrame frame,
308308
* NB: In our case the arguments have already been destructured by the time this node is encountered. Thus,
309309
* we don't need to do the destructuring work that Rubinius would do and in the case that we receive
310310
* multiple arguments we need to reverse the destructuring by collecting the values into an array. */
311-
int userArgumentCount = RubyArguments.getPositionalArgumentsCount(frame, false);
311+
int userArgumentCount = RubyArguments.getPositionalArgumentsCount(frame.getArguments());
312312

313313
if (emptyArgsProfile.profile(userArgumentCount == 0)) {
314314
return nil;
315315
} else {
316316
if (singleArgProfile.profile(userArgumentCount == 1)) {
317317
return RubyArguments.getArgument(frame, 0);
318318
} else {
319-
Object[] extractedArguments = RubyArguments.getPositionalArguments(frame.getArguments(), false);
319+
Object[] extractedArguments = RubyArguments.getPositionalArguments(frame.getArguments());
320320
return createArray(extractedArguments, userArgumentCount);
321321
}
322322
}

src/main/java/org/truffleruby/language/arguments/KeywordArgumentsDescriptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
/** An arguments descriptor that says that keyword arguments were passed (either foo(a: 1) or foo(**kw)). Note that
1515
* currently, if kw is empty, then this descriptor is used even though it is semantically the same as if no keyword
1616
* arguments were passed. The callee must handle that for now. */
17-
public class KeywordArgumentsDescriptor extends ArgumentsDescriptor {
17+
public final class KeywordArgumentsDescriptor extends ArgumentsDescriptor {
1818

1919
@CompilationFinal(dimensions = 1) private final String[] keywords;
2020

src/main/java/org/truffleruby/language/arguments/ReadRemainingArgumentsNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public ReadRemainingArgumentsNode(int start) {
2727

2828
@Override
2929
public Object execute(VirtualFrame frame) {
30-
final int count = RubyArguments.getPositionalArgumentsCount(frame, false);
30+
final int count = RubyArguments.getPositionalArgumentsCount(frame.getArguments());
3131

3232
if (remainingArguments.profile(start < count)) {
3333
return RubyArguments.getRawArguments(frame, start, count - start);

src/main/java/org/truffleruby/language/arguments/RubyArguments.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,12 @@ public static int getPositionalArgumentsCount(Object[] rubyArgs, boolean methodH
294294
}
295295
}
296296

297+
/** Get the number of positional user arguments inside the frame arguments. Assumes
298+
* methodHasKeywordParameters=false. */
299+
public static int getPositionalArgumentsCount(Object[] rubyArgs) {
300+
return rubyArgs.length - RUNTIME_ARGUMENT_COUNT;
301+
}
302+
297303
/** Get the user argument at given index out of frame arguments */
298304
public static Object getArgument(Frame frame, int index) {
299305
assert index >= 0 && index < getRawArgumentsCount(frame);
@@ -331,9 +337,9 @@ public static void setArgument(Object[] rubyArgs, int index, Object value) {
331337
}
332338

333339
/** Get the positional user arguments out of frame arguments. Should only be used when strictly necessary,
334-
* {@link #repack} or {@link #getArgument} avoid the extra allocation. */
335-
public static Object[] getPositionalArguments(Object[] rubyArgs, boolean methodHasKeywordParameters) {
336-
int count = getPositionalArgumentsCount(rubyArgs, methodHasKeywordParameters);
340+
* {@link #repack} or {@link #getArgument} avoid the extra allocation. Assumes methodHasKeywordParameters=false. */
341+
public static Object[] getPositionalArguments(Object[] rubyArgs) {
342+
int count = getPositionalArgumentsCount(rubyArgs);
337343
return ArrayUtils.extractRange(rubyArgs, RUNTIME_ARGUMENT_COUNT, RUNTIME_ARGUMENT_COUNT + count);
338344
}
339345

src/main/java/org/truffleruby/language/dispatch/DispatchNode.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ private Object callMethodMissing(Frame frame, Object receiver, String methodName
339339
ExceptionFormatter.NO_METHOD_ERROR,
340340
receiver,
341341
methodName,
342-
RubyArguments.getPositionalArguments(rubyArgs, false),
342+
RubyArguments.getPositionalArguments(rubyArgs),
343343
this));
344344
}
345345

@@ -352,7 +352,7 @@ protected Object callForeign(Object receiver, String methodName, Object[] rubyAr
352352
final CallForeignMethodNode callForeignMethodNode = getCallForeignMethodNode();
353353

354354
final Object block = RubyArguments.getBlock(rubyArgs);
355-
final Object[] arguments = RubyArguments.getPositionalArguments(rubyArgs, false);
355+
final Object[] arguments = RubyArguments.getPositionalArguments(rubyArgs);
356356
return callForeignMethodNode.execute(receiver, methodName, block, arguments);
357357
}
358358

src/main/java/org/truffleruby/language/methods/CallInternalMethodNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ protected Object alwaysInlined(
109109
}
110110

111111
try {
112-
int given = RubyArguments.getPositionalArgumentsCount(rubyArgs, false);
112+
int given = RubyArguments.getPositionalArgumentsCount(rubyArgs);
113113
if (!cachedArity.checkPositionalArguments(given)) {
114114
checkArityProfile.enter();
115115
throw RubyCheckArityRootNode.checkArityError(cachedArity, given, alwaysInlinedNode);

0 commit comments

Comments
 (0)