Skip to content

Commit 3d0e862

Browse files
committed
[GR-16336] Always-inline Kernel#method and Kernel#public_method
PullRequest: truffleruby/2616
2 parents 3539679 + a2b43de commit 3d0e862

File tree

7 files changed

+59
-76
lines changed

7 files changed

+59
-76
lines changed

src/main/java/org/truffleruby/core/cast/ToStringOrSymbolNode.java

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,40 @@
99
*/
1010
package org.truffleruby.core.cast;
1111

12+
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
13+
import com.oracle.truffle.api.dsl.CachedContext;
14+
import com.oracle.truffle.api.dsl.GenerateUncached;
15+
import com.oracle.truffle.api.frame.VirtualFrame;
1216
import com.oracle.truffle.api.library.CachedLibrary;
17+
import org.truffleruby.RubyContext;
18+
import org.truffleruby.RubyLanguage;
1319
import org.truffleruby.core.string.RubyString;
1420
import org.truffleruby.core.symbol.RubySymbol;
1521
import org.truffleruby.core.string.ImmutableRubyString;
16-
import org.truffleruby.language.RubyContextSourceNode;
17-
import org.truffleruby.language.RubyNode;
22+
import org.truffleruby.language.RubyBaseNodeWithExecute;
1823
import org.truffleruby.language.control.RaiseException;
1924
import org.truffleruby.language.dispatch.DispatchNode;
2025

21-
import com.oracle.truffle.api.CompilerDirectives;
2226
import com.oracle.truffle.api.dsl.Cached;
2327
import com.oracle.truffle.api.dsl.NodeChild;
2428
import com.oracle.truffle.api.dsl.Specialization;
2529
import com.oracle.truffle.api.profiles.BranchProfile;
2630
import org.truffleruby.language.library.RubyStringLibrary;
2731

2832
/** Convert objects to a String by calling #to_str, but leave existing Strings or Symbols as they are. */
29-
@NodeChild(value = "child", type = RubyNode.class)
30-
public abstract class ToStringOrSymbolNode extends RubyContextSourceNode {
33+
@GenerateUncached
34+
@NodeChild(value = "child", type = RubyBaseNodeWithExecute.class)
35+
public abstract class ToStringOrSymbolNode extends RubyBaseNodeWithExecute {
3136

32-
@Child private DispatchNode toStr;
37+
public static ToStringOrSymbolNode create() {
38+
return ToStringOrSymbolNodeGen.create(null);
39+
}
40+
41+
/** Execute with child node */
42+
public abstract Object execute(VirtualFrame frame);
43+
44+
/** Execute with given value */
45+
public abstract Object execute(Object value);
3346

3447
@Specialization
3548
protected RubySymbol coerceRubySymbol(RubySymbol symbol) {
@@ -48,17 +61,20 @@ protected ImmutableRubyString coerceRubyString(ImmutableRubyString string) {
4861

4962
@Specialization(guards = { "!isRubySymbol(object)", "isNotRubyString(object)" })
5063
protected Object coerceObject(Object object,
64+
@Cached DispatchNode toStr,
5165
@Cached BranchProfile errorProfile,
52-
@CachedLibrary(limit = "2") RubyStringLibrary libString) {
66+
@CachedLibrary(limit = "2") RubyStringLibrary libString,
67+
@CachedContext(RubyLanguage.class) ContextReference<RubyContext> contextRef) {
5368
final Object coerced;
5469
try {
55-
coerced = callToStr(object);
70+
coerced = toStr.call(object, "to_str");
5671
} catch (RaiseException e) {
5772
errorProfile.enter();
58-
if (e.getException().getLogicalClass() == coreLibrary().noMethodErrorClass) {
73+
final RubyContext context = contextRef.get();
74+
if (e.getException().getLogicalClass() == context.getCoreLibrary().noMethodErrorClass) {
5975
throw new RaiseException(
60-
getContext(),
61-
coreExceptions().typeErrorNoImplicitConversion(object, "String", this));
76+
context,
77+
context.getCoreExceptions().typeErrorNoImplicitConversion(object, "String", this));
6278
} else {
6379
throw e;
6480
}
@@ -68,17 +84,11 @@ protected Object coerceObject(Object object,
6884
return coerced;
6985
} else {
7086
errorProfile.enter();
87+
final RubyContext context = contextRef.get();
7188
throw new RaiseException(
72-
getContext(),
73-
coreExceptions().typeErrorBadCoercion(object, "String", "to_str", coerced, this));
89+
context,
90+
context.getCoreExceptions().typeErrorBadCoercion(object, "String", "to_str", coerced, this));
7491
}
7592
}
7693

77-
private Object callToStr(Object object) {
78-
if (toStr == null) {
79-
CompilerDirectives.transferToInterpreterAndInvalidate();
80-
toStr = insert(DispatchNode.create());
81-
}
82-
return toStr.call(object, "to_str");
83-
}
8494
}

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

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@
99
*/
1010
package org.truffleruby.core.kernel;
1111

12-
import static org.truffleruby.language.dispatch.DispatchConfiguration.PRIVATE;
13-
import static org.truffleruby.language.dispatch.DispatchConfiguration.PUBLIC;
14-
1512
import java.io.File;
1613
import java.nio.file.Paths;
1714
import java.util.ArrayList;
@@ -45,7 +42,7 @@
4542
import org.truffleruby.core.cast.BooleanCastWithDefaultNodeGen;
4643
import org.truffleruby.core.cast.DurationToMillisecondsNodeGen;
4744
import org.truffleruby.core.cast.NameToJavaStringNode;
48-
import org.truffleruby.core.cast.ToStringOrSymbolNodeGen;
45+
import org.truffleruby.core.cast.ToStringOrSymbolNode;
4946
import org.truffleruby.core.cast.ToSymbolNode;
5047
import org.truffleruby.core.encoding.RubyEncoding;
5148
import org.truffleruby.core.exception.GetBacktraceException;
@@ -108,6 +105,7 @@
108105
import org.truffleruby.language.backtrace.Backtrace;
109106
import org.truffleruby.language.backtrace.BacktraceFormatter;
110107
import org.truffleruby.language.control.RaiseException;
108+
import org.truffleruby.language.dispatch.DispatchConfiguration;
111109
import org.truffleruby.language.dispatch.DispatchNode;
112110
import org.truffleruby.language.dispatch.DispatchingNode;
113111
import org.truffleruby.language.dispatch.InternalRespondToNode;
@@ -1283,22 +1281,16 @@ protected RubySymbol methodName() {
12831281

12841282
}
12851283

1286-
@CoreMethod(names = "method", required = 1)
1287-
@NodeChild(value = "receiver", type = RubyNode.class)
1288-
@NodeChild(value = "name", type = RubyNode.class)
1289-
public abstract static class MethodNode extends CoreMethodNode {
1290-
1291-
@Child private GetMethodObjectNode getMethodObjectNode = GetMethodObjectNode.create();
1292-
@Child private ReadCallerFrameNode readCallerFrame = ReadCallerFrameNode.create();
1293-
1294-
@CreateCast("name")
1295-
protected RubyNode coerceToString(RubyNode name) {
1296-
return ToStringOrSymbolNodeGen.create(name);
1297-
}
1284+
@GenerateUncached
1285+
@CoreMethod(names = "method", required = 1, alwaysInlined = true)
1286+
public abstract static class MethodNode extends AlwaysInlinedMethodNode {
12981287

12991288
@Specialization
1300-
protected RubyMethod method(VirtualFrame frame, Object self, Object name) {
1301-
return getMethodObjectNode.execute(frame, self, name, PRIVATE, readCallerFrame.execute(frame));
1289+
protected RubyMethod method(Frame callerFrame, Object self, Object[] args, Object block, RootCallTarget target,
1290+
@Cached ToStringOrSymbolNode toStringOrSymbolNode,
1291+
@Cached GetMethodObjectNode getMethodObjectNode) {
1292+
Object name = toStringOrSymbolNode.execute(args[0]);
1293+
return getMethodObjectNode.execute(callerFrame, self, name, DispatchConfiguration.PRIVATE);
13021294
}
13031295

13041296
}
@@ -1423,22 +1415,16 @@ protected RubyArray protectedMethods(Object self, boolean includeAncestors) {
14231415

14241416
}
14251417

1426-
@CoreMethod(names = "public_method", required = 1)
1427-
@NodeChild(value = "receiver", type = RubyNode.class)
1428-
@NodeChild(value = "name", type = RubyNode.class)
1429-
public abstract static class PublicMethodNode extends CoreMethodNode {
1430-
1431-
@Child private GetMethodObjectNode getMethodObjectNode = GetMethodObjectNode.create();
1432-
@Child private ReadCallerFrameNode readCallerFrame = ReadCallerFrameNode.create();
1433-
1434-
@CreateCast("name")
1435-
protected RubyNode coerceToString(RubyNode name) {
1436-
return ToStringOrSymbolNodeGen.create(name);
1437-
}
1418+
@GenerateUncached
1419+
@CoreMethod(names = "public_method", required = 1, alwaysInlined = true)
1420+
public abstract static class PublicMethodNode extends AlwaysInlinedMethodNode {
14381421

14391422
@Specialization
1440-
protected RubyMethod publicMethod(VirtualFrame frame, Object self, Object name) {
1441-
return getMethodObjectNode.execute(frame, self, name, PUBLIC, readCallerFrame.execute(frame));
1423+
protected RubyMethod method(Frame callerFrame, Object self, Object[] args, Object block, RootCallTarget target,
1424+
@Cached ToStringOrSymbolNode toStringOrSymbolNode,
1425+
@Cached GetMethodObjectNode getMethodObjectNode) {
1426+
Object name = toStringOrSymbolNode.execute(args[0]);
1427+
return getMethodObjectNode.execute(callerFrame, self, name, DispatchConfiguration.PUBLIC);
14421428
}
14431429

14441430
}
@@ -1500,7 +1486,7 @@ public abstract static class RespondToNode extends CoreMethodNode {
15001486
private final ConditionProfile respondToMissingProfile = ConditionProfile.create();
15011487

15021488
public RespondToNode() {
1503-
dispatch = InternalRespondToNode.create(PUBLIC);
1489+
dispatch = InternalRespondToNode.create(DispatchConfiguration.PUBLIC);
15041490
dispatchIgnoreVisibility = InternalRespondToNode.create();
15051491
dispatchRespondToMissing = InternalRespondToNode.create();
15061492
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import org.truffleruby.language.Nil;
7676
import org.truffleruby.language.NotProvided;
7777
import org.truffleruby.language.RubyBaseNode;
78+
import org.truffleruby.language.RubyBaseNodeWithExecute;
7879
import org.truffleruby.language.RubyConstant;
7980
import org.truffleruby.language.RubyContextNode;
8081
import org.truffleruby.language.RubyContextSourceNode;
@@ -982,7 +983,7 @@ protected boolean isConstDefined(RubyModule module, String fullName, boolean inh
982983

983984
@Primitive(name = "module_const_get")
984985
@NodeChild(value = "module", type = RubyNode.class)
985-
@NodeChild(value = "name", type = RubyNode.class)
986+
@NodeChild(value = "name", type = RubyBaseNodeWithExecute.class)
986987
@NodeChild(value = "inherit", type = RubyNode.class)
987988
@NodeChild(value = "check_name", type = RubyNode.class)
988989
@ImportStatic({ StringCachingGuards.class, StringOperations.class })
@@ -992,7 +993,7 @@ public abstract static class ConstGetNode extends PrimitiveNode {
992993
@Child private GetConstantNode getConstantNode = GetConstantNode.create();
993994

994995
@CreateCast("name")
995-
protected RubyNode coerceToSymbolOrString(RubyNode name) {
996+
protected RubyBaseNodeWithExecute coerceToSymbolOrString(RubyBaseNodeWithExecute name) {
996997
// We want to know if the name is a Symbol, as then scoped lookup is not tried
997998
return ToStringOrSymbolNodeGen.create(name);
998999
}
@@ -1109,14 +1110,14 @@ protected Object constMissing(RubyModule module, String name) {
11091110

11101111
@CoreMethod(names = "const_source_location", required = 1, optional = 1)
11111112
@NodeChild(value = "module", type = RubyNode.class)
1112-
@NodeChild(value = "name", type = RubyNode.class)
1113+
@NodeChild(value = "name", type = RubyBaseNodeWithExecute.class)
11131114
@NodeChild(value = "inherit", type = RubyNode.class)
11141115
public abstract static class ConstSourceLocationNode extends CoreMethodNode {
11151116

11161117
@Child private MakeStringNode makeStringNode = MakeStringNode.create();
11171118

11181119
@CreateCast("name")
1119-
protected RubyNode coerceToStringOrSymbol(RubyNode name) {
1120+
protected RubyBaseNodeWithExecute coerceToStringOrSymbol(RubyBaseNodeWithExecute name) {
11201121
return ToStringOrSymbolNodeGen.create(name);
11211122
}
11221123

src/main/java/org/truffleruby/language/ImmutableRubyObject.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.truffleruby.RubyLanguage;
1515
import org.truffleruby.cext.ValueWrapper;
1616
import org.truffleruby.interop.ForeignToRubyArgumentsNode;
17-
import org.truffleruby.interop.ForeignToRubyNode;
1817
import org.truffleruby.language.dispatch.DispatchConfiguration;
1918
import org.truffleruby.language.dispatch.DispatchNode;
2019
import org.truffleruby.language.dispatch.InternalRespondToNode;
@@ -112,13 +111,11 @@ public boolean isMemberReadable(String name,
112111
@ExportMessage
113112
public Object readMember(String name,
114113
@Cached @Shared("definedNode") InternalRespondToNode definedNode,
115-
@Cached ForeignToRubyNode nameToRubyNode,
116114
@Cached GetMethodObjectNode getMethodObjectNode,
117115
@Shared("errorProfile") @Cached BranchProfile errorProfile)
118116
throws UnknownIdentifierException {
119117
if (definedNode.execute(null, this, name)) {
120-
Object rubyName = nameToRubyNode.executeConvert(name);
121-
return getMethodObjectNode.execute(null, this, rubyName, DispatchConfiguration.PRIVATE, null);
118+
return getMethodObjectNode.execute(null, this, name, DispatchConfiguration.PRIVATE);
122119
} else {
123120
errorProfile.enter();
124121
throw UnknownIdentifierException.create(name);

src/main/java/org/truffleruby/language/RubyDynamicObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ public Object readMember(String name,
591591
if (ivarFoundProfile.profile(iVar != null)) {
592592
return iVar;
593593
} else if (definedNode.execute(null, this, name)) {
594-
return getMethodObjectNode.execute(null, this, rubyName, DispatchConfiguration.PRIVATE, null);
594+
return getMethodObjectNode.execute(null, this, name, DispatchConfiguration.PRIVATE);
595595
} else {
596596
errorProfile.enter();
597597
throw UnknownIdentifierException.create(name);

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

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import com.oracle.truffle.api.dsl.Specialization;
2020
import com.oracle.truffle.api.frame.Frame;
2121
import com.oracle.truffle.api.frame.FrameDescriptor;
22-
import com.oracle.truffle.api.frame.MaterializedFrame;
2322
import com.oracle.truffle.api.frame.VirtualFrame;
2423
import com.oracle.truffle.api.profiles.ConditionProfile;
2524
import org.truffleruby.RubyContext;
@@ -51,12 +50,10 @@ public static GetMethodObjectNode create() {
5150
return GetMethodObjectNodeGen.create();
5251
}
5352

54-
public abstract RubyMethod execute(Frame frame, Object self, Object name,
55-
DispatchConfiguration dispatchConfig, MaterializedFrame callerFrame);
53+
public abstract RubyMethod execute(Frame frame, Object self, Object name, DispatchConfiguration dispatchConfig);
5654

5755
@Specialization
58-
protected RubyMethod getMethodObject(
59-
Frame frame, Object self, Object name, DispatchConfiguration dispatchConfig, MaterializedFrame callerFrame,
56+
protected RubyMethod getMethodObject(Frame frame, Object self, Object name, DispatchConfiguration dispatchConfig,
6057
@CachedLanguage RubyLanguage language,
6158
@CachedContext(RubyLanguage.class) RubyContext context,
6259
@Cached NameToJavaStringNode nameToJavaStringNode,
@@ -67,13 +64,6 @@ protected RubyMethod getMethodObject(
6764
@Cached ConditionProfile notFoundProfile,
6865
@Cached ConditionProfile respondToMissingProfile,
6966
@Cached LogicalClassNode logicalClassNode) {
70-
if (frame != null) {
71-
final DeclarationContext declarationContext = RubyArguments.getDeclarationContext(callerFrame);
72-
if (declarationContext != null) {
73-
RubyArguments.setDeclarationContext(frame, declarationContext);
74-
}
75-
}
76-
7767
final String normalizedName = nameToJavaStringNode.execute(name);
7868
InternalMethod method = lookupMethodNode.execute(frame, self, normalizedName, dispatchConfig);
7969

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ public static LookupMethodNode create() {
4040
return LookupMethodNodeGen.create();
4141
}
4242

43-
public abstract InternalMethod execute(Frame frame, RubyClass metaClass, String name,
44-
DispatchConfiguration config);
43+
public abstract InternalMethod execute(Frame frame, RubyClass metaClass, String name, DispatchConfiguration config);
4544

4645
@Specialization(
4746
// no need to guard on the context, the metaClass is context-specific

0 commit comments

Comments
 (0)