Skip to content

Commit 6ea8121

Browse files
committed
Always inline Module#{public,protected,private} to not need to lookup the caller frame
* Remove AddMethodNode as it is unnecessary
1 parent 416901b commit 6ea8121

File tree

7 files changed

+123
-148
lines changed

7 files changed

+123
-148
lines changed

src/main/java/org/truffleruby/core/MainNodes.java

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

12+
import com.oracle.truffle.api.RootCallTarget;
13+
import com.oracle.truffle.api.dsl.CachedContext;
14+
import com.oracle.truffle.api.dsl.GenerateUncached;
15+
import org.truffleruby.RubyContext;
16+
import org.truffleruby.RubyLanguage;
1217
import org.truffleruby.builtins.CoreMethod;
1318
import org.truffleruby.builtins.CoreMethodArrayArgumentsNode;
1419
import org.truffleruby.builtins.CoreModule;
20+
import org.truffleruby.core.inlined.AlwaysInlinedMethodNode;
1521
import org.truffleruby.core.module.ModuleNodes;
16-
import org.truffleruby.core.module.ModuleNodesFactory;
1722
import org.truffleruby.core.module.RubyModule;
1823
import org.truffleruby.language.Visibility;
1924
import org.truffleruby.language.arguments.RubyArguments;
@@ -26,31 +31,30 @@
2631
import com.oracle.truffle.api.dsl.Specialization;
2732
import com.oracle.truffle.api.frame.Frame;
2833
import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
29-
import com.oracle.truffle.api.frame.VirtualFrame;
3034
import com.oracle.truffle.api.profiles.BranchProfile;
3135

3236
@CoreModule(value = "main", isClass = true)
3337
public abstract class MainNodes {
3438

35-
@CoreMethod(names = "public", rest = true, needsSelf = false, visibility = Visibility.PRIVATE)
36-
public abstract static class PublicNode extends CoreMethodArrayArgumentsNode {
37-
38-
@Child private ModuleNodes.PublicNode publicNode = ModuleNodesFactory.PublicNodeFactory.create(null);
39-
39+
@GenerateUncached
40+
@CoreMethod(names = "public", rest = true, visibility = Visibility.PRIVATE, alwaysInlined = true)
41+
public abstract static class PublicNode extends AlwaysInlinedMethodNode {
4042
@Specialization
41-
protected RubyModule doPublic(VirtualFrame frame, Object[] args) {
42-
return publicNode.executePublic(frame, coreLibrary().objectClass, args);
43+
protected Object forward(Frame callerFrame, Object self, Object[] args, Object block, RootCallTarget target,
44+
@Cached ModuleNodes.PublicNode publicNode,
45+
@CachedContext(RubyLanguage.class) RubyContext context) {
46+
return publicNode.execute(callerFrame, context.getCoreLibrary().objectClass, args, block, target);
4347
}
4448
}
4549

46-
@CoreMethod(names = "private", rest = true, needsSelf = false, visibility = Visibility.PRIVATE)
47-
public abstract static class PrivateNode extends CoreMethodArrayArgumentsNode {
48-
49-
@Child private ModuleNodes.PrivateNode privateNode = ModuleNodesFactory.PrivateNodeFactory.create(null);
50-
50+
@GenerateUncached
51+
@CoreMethod(names = "private", rest = true, visibility = Visibility.PRIVATE, alwaysInlined = true)
52+
public abstract static class PrivateNode extends AlwaysInlinedMethodNode {
5153
@Specialization
52-
protected RubyModule doPrivate(VirtualFrame frame, Object[] args) {
53-
return privateNode.executePrivate(frame, coreLibrary().objectClass, args);
54+
protected Object forward(Frame callerFrame, Object self, Object[] args, Object block, RootCallTarget target,
55+
@Cached ModuleNodes.PrivateNode privateNode,
56+
@CachedContext(RubyLanguage.class) RubyContext context) {
57+
return privateNode.execute(callerFrame, context.getCoreLibrary().objectClass, args, block, target);
5458
}
5559
}
5660

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

Lines changed: 65 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@
9696
import org.truffleruby.language.library.RubyLibrary;
9797
import org.truffleruby.language.library.RubyStringLibrary;
9898
import org.truffleruby.language.loader.CodeLoader;
99-
import org.truffleruby.language.methods.AddMethodNode;
10099
import org.truffleruby.language.methods.Arity;
101100
import org.truffleruby.language.methods.CanBindMethodToModuleNode;
102101
import org.truffleruby.language.methods.DeclarationContext;
@@ -339,8 +338,6 @@ protected RubyNode coerceOldNameToString(RubyNode oldName) {
339338
return NameToJavaStringNode.create(oldName);
340339
}
341340

342-
@Child AddMethodNode addMethodNode = AddMethodNode.create(false);
343-
344341
@Specialization
345342
protected RubyModule aliasMethod(RubyModule module, String newName, String oldName,
346343
@Cached BranchProfile errorProfile) {
@@ -355,9 +352,8 @@ protected RubyModule aliasMethod(RubyModule module, String newName, String oldNa
355352
this));
356353
}
357354

358-
InternalMethod aliasMethod = method.withName(newName);
359-
360-
addMethodNode.executeAddMethod(module, aliasMethod, aliasMethod.getVisibility());
355+
final InternalMethod aliasMethod = method.withName(newName);
356+
module.addMethodConsiderNameVisibility(getContext(), aliasMethod, aliasMethod.getVisibility(), this);
361357
return module;
362358
}
363359

@@ -1243,7 +1239,6 @@ private void warnAlreadyInitializedConstant(RubyModule module, String name,
12431239
@NodeChild(value = "block", type = RubyNode.class)
12441240
public abstract static class DefineMethodNode extends CoreMethodNode {
12451241

1246-
@Child private AddMethodNode addMethodNode = AddMethodNode.create(false);
12471242
@Child private ReadCallerFrameNode readCallerFrame = ReadCallerFrameNode.create();
12481243

12491244
@CreateCast("name")
@@ -1375,7 +1370,7 @@ private RubySymbol addMethod(RubyModule module, String name, InternalMethod meth
13751370
method = method.withName(name);
13761371

13771372
final Visibility visibility = GetCurrentVisibilityNode.getVisibilityFromNameAndFrame(name, callerFrame);
1378-
addMethodNode.executeAddMethod(module, method, visibility);
1373+
module.addMethodConsiderNameVisibility(getContext(), method, visibility, this);
13791374
return getSymbol(method.getName());
13801375
}
13811376

@@ -1605,18 +1600,25 @@ protected RubyArray nesting() {
16051600
}
16061601
}
16071602

1608-
@CoreMethod(names = "public", rest = true, visibility = Visibility.PRIVATE)
1609-
public abstract static class PublicNode extends CoreMethodArrayArgumentsNode {
1610-
1611-
@Child private SetVisibilityNode setVisibilityNode = SetVisibilityNode.create();
1612-
1613-
public abstract RubyModule executePublic(VirtualFrame frame, RubyModule module, Object[] args);
1614-
1615-
@Specialization
1616-
protected RubyModule doPublic(VirtualFrame frame, RubyModule module, Object[] names) {
1617-
return setVisibilityNode.execute(frame, module, names, Visibility.PUBLIC);
1603+
@GenerateUncached
1604+
@CoreMethod(names = "public", rest = true, visibility = Visibility.PRIVATE, alwaysInlined = true)
1605+
public abstract static class PublicNode extends AlwaysInlinedMethodNode {
1606+
@Specialization(guards = "names.length == 0")
1607+
protected RubyModule frame(
1608+
Frame callerFrame, RubyModule module, Object[] names, Object block, RootCallTarget target) {
1609+
DeclarationContext.setCurrentVisibility(callerFrame, Visibility.PUBLIC);
1610+
return module;
16181611
}
16191612

1613+
@Specialization(guards = "names.length > 0")
1614+
protected RubyModule methods(
1615+
Frame callerFrame, RubyModule module, Object[] names, Object block, RootCallTarget target,
1616+
@Cached SetMethodVisibilityNode setMethodVisibilityNode) {
1617+
for (Object name : names) {
1618+
setMethodVisibilityNode.execute(module, name, Visibility.PUBLIC);
1619+
}
1620+
return module;
1621+
}
16201622
}
16211623

16221624
@CoreMethod(names = "public_class_method", rest = true)
@@ -1637,18 +1639,25 @@ protected RubyModule publicClassMethod(RubyModule module, Object[] names) {
16371639
}
16381640
}
16391641

1640-
@CoreMethod(names = "private", rest = true, visibility = Visibility.PRIVATE)
1641-
public abstract static class PrivateNode extends CoreMethodArrayArgumentsNode {
1642-
1643-
@Child private SetVisibilityNode setVisibilityNode = SetVisibilityNode.create();
1644-
1645-
public abstract RubyModule executePrivate(VirtualFrame frame, RubyModule module, Object[] args);
1646-
1647-
@Specialization
1648-
protected RubyModule doPrivate(VirtualFrame frame, RubyModule module, Object[] names) {
1649-
return setVisibilityNode.execute(frame, module, names, Visibility.PRIVATE);
1642+
@GenerateUncached
1643+
@CoreMethod(names = "private", rest = true, visibility = Visibility.PRIVATE, alwaysInlined = true)
1644+
public abstract static class PrivateNode extends AlwaysInlinedMethodNode {
1645+
@Specialization(guards = "names.length == 0")
1646+
protected RubyModule frame(
1647+
Frame callerFrame, RubyModule module, Object[] names, Object block, RootCallTarget target) {
1648+
DeclarationContext.setCurrentVisibility(callerFrame, Visibility.PRIVATE);
1649+
return module;
16501650
}
16511651

1652+
@Specialization(guards = "names.length > 0")
1653+
protected RubyModule methods(
1654+
Frame callerFrame, RubyModule module, Object[] names, Object block, RootCallTarget target,
1655+
@Cached SetMethodVisibilityNode setMethodVisibilityNode) {
1656+
for (Object name : names) {
1657+
setMethodVisibilityNode.execute(module, name, Visibility.PRIVATE);
1658+
}
1659+
return module;
1660+
}
16521661
}
16531662

16541663
@CoreMethod(names = "prepend_features", required = 1, visibility = Visibility.PRIVATE, split = Split.NEVER)
@@ -1936,16 +1945,25 @@ protected RubyModule publicConstant(RubyModule module, Object[] args) {
19361945
}
19371946
}
19381947

1939-
@CoreMethod(names = "protected", rest = true, visibility = Visibility.PRIVATE)
1940-
public abstract static class ProtectedNode extends CoreMethodArrayArgumentsNode {
1941-
1942-
@Child private SetVisibilityNode setVisibilityNode = SetVisibilityNode.create();
1943-
1944-
@Specialization
1945-
protected RubyModule doProtected(VirtualFrame frame, RubyModule module, Object[] names) {
1946-
return setVisibilityNode.execute(frame, module, names, Visibility.PROTECTED);
1948+
@GenerateUncached
1949+
@CoreMethod(names = "protected", rest = true, visibility = Visibility.PRIVATE, alwaysInlined = true)
1950+
public abstract static class ProtectedNode extends AlwaysInlinedMethodNode {
1951+
@Specialization(guards = "names.length == 0")
1952+
protected RubyModule frame(
1953+
Frame callerFrame, RubyModule module, Object[] names, Object block, RootCallTarget target) {
1954+
DeclarationContext.setCurrentVisibility(callerFrame, Visibility.PROTECTED);
1955+
return module;
19471956
}
19481957

1958+
@Specialization(guards = "names.length > 0")
1959+
protected RubyModule methods(
1960+
Frame callerFrame, RubyModule module, Object[] names, Object block, RootCallTarget target,
1961+
@Cached SetMethodVisibilityNode setMethodVisibilityNode) {
1962+
for (Object name : names) {
1963+
setMethodVisibilityNode.execute(module, name, Visibility.PROTECTED);
1964+
}
1965+
return module;
1966+
}
19491967
}
19501968

19511969
@CoreMethod(names = "remove_class_variable", required = 1)
@@ -2124,7 +2142,8 @@ public abstract RubyModule execute(VirtualFrame frame, RubyModule module, Object
21242142
protected RubyModule setVisibility(
21252143
VirtualFrame frame, RubyModule module, Object[] names, Visibility visibility) {
21262144
if (names.length == 0) {
2127-
DeclarationContext.setCurrentVisibility(getContext(), visibility);
2145+
final Frame callerFrame = getContext().getCallStack().getCallerFrame(FrameAccess.READ_WRITE);
2146+
DeclarationContext.setCurrentVisibility(callerFrame, visibility);
21282147
} else {
21292148
for (Object name : names) {
21302149
setMethodVisibilityNode.execute(module, name, visibility);
@@ -2136,29 +2155,29 @@ protected RubyModule setVisibility(
21362155

21372156
}
21382157

2139-
public abstract static class SetMethodVisibilityNode extends RubyContextNode {
2158+
@GenerateUncached
2159+
public abstract static class SetMethodVisibilityNode extends RubyBaseNode {
21402160

21412161
public static SetMethodVisibilityNode create() {
21422162
return SetMethodVisibilityNodeGen.create();
21432163
}
21442164

2145-
@Child private NameToJavaStringNode nameToJavaStringNode = NameToJavaStringNode.create();
2146-
@Child private AddMethodNode addMethodNode = AddMethodNode.create(true);
2147-
21482165
public abstract void execute(RubyModule module, Object name, Visibility visibility);
21492166

21502167
@Specialization
21512168
protected void setMethodVisibility(RubyModule module, Object name, Visibility visibility,
2152-
@Cached BranchProfile errorProfile) {
2169+
@CachedContext(RubyLanguage.class) RubyContext context,
2170+
@Cached BranchProfile errorProfile,
2171+
@Cached NameToJavaStringNode nameToJavaStringNode) {
21532172
final String methodName = nameToJavaStringNode.execute(name);
21542173

2155-
final InternalMethod method = module.fields.deepMethodSearch(getContext(), methodName);
2174+
final InternalMethod method = module.fields.deepMethodSearch(context, methodName);
21562175

21572176
if (method == null) {
21582177
errorProfile.enter();
21592178
throw new RaiseException(
2160-
getContext(),
2161-
coreExceptions().nameErrorUndefinedMethod(methodName, module, this));
2179+
context,
2180+
context.getCoreExceptions().nameErrorUndefinedMethod(methodName, module, this));
21622181
}
21632182

21642183
// Do nothing if the method already exists with the same visibility, like MRI
@@ -2168,7 +2187,7 @@ protected void setMethodVisibility(RubyModule module, Object name, Visibility vi
21682187

21692188
/* If the method was already defined in this class, that's fine {@link addMethod} will overwrite it,
21702189
* otherwise we do actually want to add a copy of the method with a different visibility to this module. */
2171-
addMethodNode.executeAddMethod(module, method, visibility);
2190+
module.addMethodIgnoreNameVisibility(context, method, visibility, this);
21722191
}
21732192

21742193
}

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@
1111

1212
import java.util.Set;
1313

14+
import com.oracle.truffle.api.nodes.Node;
15+
import org.truffleruby.RubyContext;
1416
import org.truffleruby.RubyLanguage;
1517
import org.truffleruby.core.klass.RubyClass;
1618
import org.truffleruby.language.RubyDynamicObject;
19+
import org.truffleruby.language.Visibility;
20+
import org.truffleruby.language.methods.InternalMethod;
1721
import org.truffleruby.language.objects.ObjectGraph;
1822
import org.truffleruby.language.objects.ObjectGraphNode;
1923

@@ -23,6 +27,7 @@
2327
import com.oracle.truffle.api.library.ExportMessage;
2428
import com.oracle.truffle.api.object.Shape;
2529
import com.oracle.truffle.api.source.SourceSection;
30+
import org.truffleruby.language.objects.SingletonClassNode;
2631

2732
@ExportLibrary(InteropLibrary.class)
2833
public class RubyModule extends RubyDynamicObject implements ObjectGraphNode {
@@ -69,6 +74,31 @@ public String toString() {
6974
return fields.getName();
7075
}
7176

77+
@TruffleBoundary
78+
public void addMethodConsiderNameVisibility(RubyContext context, InternalMethod method, Visibility visibility,
79+
Node currentNode) {
80+
if (ModuleOperations.isMethodPrivateFromName(method.getName())) {
81+
visibility = Visibility.PRIVATE;
82+
}
83+
84+
addMethodIgnoreNameVisibility(context, method, visibility, currentNode);
85+
}
86+
87+
@TruffleBoundary
88+
public void addMethodIgnoreNameVisibility(RubyContext context, InternalMethod method, Visibility visibility,
89+
Node currentNode) {
90+
if (visibility == Visibility.MODULE_FUNCTION) {
91+
fields.addMethod(context, currentNode, method.withVisibility(Visibility.PRIVATE));
92+
final RubyClass singletonClass = SingletonClassNode.getUncached().executeSingletonClass(this);
93+
singletonClass.fields.addMethod(
94+
context,
95+
currentNode,
96+
method.withDeclaringModule(singletonClass).withVisibility(Visibility.PUBLIC));
97+
} else {
98+
fields.addMethod(context, currentNode, method.withVisibility(visibility));
99+
}
100+
}
101+
72102
@Override
73103
public void getAdjacentObjects(Set<Object> reachable) {
74104
ObjectGraph.addProperty(reachable, fields);

0 commit comments

Comments
 (0)