Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: e4ce2686065b
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ceaf1780c7d8
Choose a head ref
  • 8 commits
  • 11 files changed
  • 1 contributor

Commits on May 12, 2015

  1. Copy the full SHA
    66f055a View commit details
  2. Copy the full SHA
    b1d476a View commit details
  3. Copy the full SHA
    85c5875 View commit details
  4. Copy the full SHA
    e3df94b View commit details
  5. [Truffle] Finally remove RubyBasicObject.getSingletonClass().

    * As well as hasNoSingleton() and hasClassAsSingleton().
    eregon committed May 12, 2015
    Copy the full SHA
    2e0b6f8 View commit details
  6. [Truffle] Have a node in CoreLibrary instead of always passing null.

    * Fixes usage of RubyBasicObject.freeze().
    eregon committed May 12, 2015
    Copy the full SHA
    7454800 View commit details
  7. Copy the full SHA
    433648c View commit details
  8. Copy the full SHA
    ceaf178 View commit details
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/module/public_class_method_tags.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
import com.oracle.truffle.api.dsl.GeneratedBy;
import com.oracle.truffle.api.dsl.NodeFactory;
import com.oracle.truffle.api.nodes.NodeUtil;

import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.RubyRootNode;
@@ -22,6 +23,7 @@
import org.jruby.truffle.nodes.core.fixnum.FixnumLowerNode;
import org.jruby.truffle.nodes.methods.ExceptionTranslatingNode;
import org.jruby.truffle.nodes.objects.SelfNode;
import org.jruby.truffle.nodes.objects.SingletonClassNode;
import org.jruby.truffle.runtime.*;
import org.jruby.truffle.runtime.control.TruffleFatalException;
import org.jruby.truffle.runtime.core.CoreSourceSection;
@@ -36,35 +38,43 @@
import java.util.Arrays;
import java.util.List;

public abstract class CoreMethodNodeManager {
public class CoreMethodNodeManager {

private final RubyClass objectClass;
private final SingletonClassNode singletonClassNode;

public static void addCoreMethodNodes(RubyClass rubyObjectClass, List<? extends NodeFactory<? extends RubyNode>> nodeFactories) {
public CoreMethodNodeManager(RubyClass objectClass, SingletonClassNode singletonClassNode) {
this.objectClass = objectClass;
this.singletonClassNode = singletonClassNode;
}

public void addCoreMethodNodes(List<? extends NodeFactory<? extends RubyNode>> nodeFactories) {
for (NodeFactory<? extends RubyNode> nodeFactory : nodeFactories) {
final GeneratedBy generatedBy = nodeFactory.getClass().getAnnotation(GeneratedBy.class);
final Class<?> nodeClass = generatedBy.value();
final CoreClass classAnnotation = nodeClass.getEnclosingClass().getAnnotation(CoreClass.class);
final CoreMethod methodAnnotation = nodeClass.getAnnotation(CoreMethod.class);

if (methodAnnotation != null) {
final MethodDetails details = new MethodDetails(classAnnotation, methodAnnotation, nodeFactory);
addMethod(rubyObjectClass, details);
addCoreMethod(new MethodDetails(classAnnotation, methodAnnotation, nodeFactory));
}
}
}

private static void addMethod(RubyClass rubyObjectClass, MethodDetails methodDetails) {
assert rubyObjectClass != null;
assert methodDetails != null;
private RubyClass getSingletonClass(Object object) {
return singletonClassNode.executeSingletonClass(null, object);
}

final RubyContext context = rubyObjectClass.getContext();
private void addCoreMethod(MethodDetails methodDetails) {
final RubyContext context = objectClass.getContext();

RubyModule module;
String fullName = methodDetails.getClassAnnotation().name();

if (fullName.equals("main")) {
module = context.getCoreLibrary().getMainObject().getSingletonClass(null);
module = getSingletonClass(context.getCoreLibrary().getMainObject());
} else {
module = rubyObjectClass;
module = objectClass;

for (String moduleName : fullName.split("::")) {
final RubyConstant constant = ModuleOperations.lookupConstant(context, LexicalScope.NONE, module, moduleName);
@@ -106,9 +116,9 @@ private static void addMethod(RubyClass rubyObjectClass, MethodDetails methodDet

if (anno.isModuleFunction()) {
addMethod(module, rootNode, names, Visibility.PRIVATE);
addMethod(module.getSingletonClass(null), rootNode, names, Visibility.PUBLIC);
addMethod(getSingletonClass(module), rootNode, names, Visibility.PUBLIC);
} else if (anno.onSingleton()) {
addMethod(module.getSingletonClass(null), rootNode, names, visibility);
addMethod(getSingletonClass(module), rootNode, names, visibility);
} else {
addMethod(module, rootNode, names, visibility);
}
139 changes: 67 additions & 72 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ModuleNodes.java
Original file line number Diff line number Diff line change
@@ -39,7 +39,8 @@
import org.jruby.truffle.nodes.coerce.ToStrNodeGen;
import org.jruby.truffle.nodes.control.SequenceNode;
import org.jruby.truffle.nodes.core.KernelNodes.BindingNode;
import org.jruby.truffle.nodes.core.ModuleNodesFactory.SetVisibilityNodeFactory;
import org.jruby.truffle.nodes.core.ModuleNodesFactory.SetMethodVisibilityNodeGen;
import org.jruby.truffle.nodes.core.ModuleNodesFactory.SetVisibilityNodeGen;
import org.jruby.truffle.nodes.dispatch.DispatchAction;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.MissingBehavior;
@@ -1181,7 +1182,7 @@ public abstract static class ModuleFunctionNode extends CoreMethodArrayArguments

public ModuleFunctionNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
setVisibilityNode = SetVisibilityNodeFactory.create(context, sourceSection, Visibility.MODULE_FUNCTION, null, null);
setVisibilityNode = SetVisibilityNodeGen.create(context, sourceSection, Visibility.MODULE_FUNCTION, null, null);
}

@Specialization
@@ -1251,7 +1252,7 @@ public abstract static class PublicNode extends CoreMethodArrayArgumentsNode {

public PublicNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
setVisibilityNode = SetVisibilityNodeFactory.create(context, sourceSection, Visibility.PUBLIC, null, null);
setVisibilityNode = SetVisibilityNodeGen.create(context, sourceSection, Visibility.PUBLIC, null, null);
}

public abstract RubyModule executePublic(VirtualFrame frame, RubyModule module, Object[] args);
@@ -1266,32 +1267,21 @@ public RubyModule doPublic(VirtualFrame frame, RubyModule module, Object[] names
@CoreMethod(names = "public_class_method", argumentsAsArray = true)
public abstract static class PublicClassMethodNode extends CoreMethodArrayArgumentsNode {

@Child SingletonClassNode singletonClassNode;
@Child SetMethodVisibilityNode setMethodVisibilityNode;

public PublicClassMethodNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.singletonClassNode = SingletonClassNodeGen.create(context, sourceSection, null);
this.setMethodVisibilityNode = SetMethodVisibilityNodeGen.create(context, sourceSection, Visibility.PUBLIC, null, null);
}

@Specialization
public RubyModule publicClassMethod(RubyModule module, Object... args) {
CompilerDirectives.transferToInterpreter();

final RubyClass moduleSingleton = module.getSingletonClass(this);

for (Object arg : args) {
final String methodName;

if (arg instanceof RubySymbol) {
methodName = arg.toString();
} else {
throw new UnsupportedOperationException();
}
RubyModule publicClassMethod(VirtualFrame frame, RubyModule module, Object[] names) {
final RubyClass singletonClass = singletonClassNode.executeSingletonClass(frame, module);

final InternalMethod method = ModuleOperations.lookupMethod(moduleSingleton, methodName);

if (method == null) {
throw new RuntimeException("Couldn't find method " + arg.toString());
}

moduleSingleton.addMethod(this, method.withVisibility(Visibility.PUBLIC));
for (Object name : names) {
setMethodVisibilityNode.executeSetMethodVisibility(frame, singletonClass, name);
}

return module;
@@ -1305,7 +1295,7 @@ public abstract static class PrivateNode extends CoreMethodArrayArgumentsNode {

public PrivateNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
setVisibilityNode = SetVisibilityNodeFactory.create(context, sourceSection, Visibility.PRIVATE, null, null);
setVisibilityNode = SetVisibilityNodeGen.create(context, sourceSection, Visibility.PRIVATE, null, null);
}

public abstract RubyModule executePrivate(VirtualFrame frame, RubyModule module, Object[] args);
@@ -1320,37 +1310,21 @@ public RubyModule doPrivate(VirtualFrame frame, RubyModule module, Object[] name
@CoreMethod(names = "private_class_method", argumentsAsArray = true)
public abstract static class PrivateClassMethodNode extends CoreMethodArrayArgumentsNode {

@Child SingletonClassNode singletonClassNode;
@Child SetMethodVisibilityNode setMethodVisibilityNode;

public PrivateClassMethodNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.singletonClassNode = SingletonClassNodeGen.create(context, sourceSection, null);
this.setMethodVisibilityNode = SetMethodVisibilityNodeGen.create(context, sourceSection, Visibility.PRIVATE, null, null);
}

@Specialization
public RubyModule privateClassMethod(RubyModule module, Object... args) {
CompilerDirectives.transferToInterpreter();

final RubyClass moduleSingleton = module.getSingletonClass(this);
public RubyModule privateClassMethod(VirtualFrame frame, RubyModule module, Object[] names) {
final RubyClass singletonClass = singletonClassNode.executeSingletonClass(frame, module);

for (Object arg : args) {
final String methodName;

if (arg instanceof RubySymbol) {
methodName = arg.toString();
} else if (arg instanceof RubyString) {
methodName = ((RubyString) arg).toString();
} else {
// TODO BF 26-APR-2015 the message could be improved to match MRI
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeError(" is not a symbol", this));
}

final InternalMethod method = ModuleOperations.lookupMethod(moduleSingleton, methodName);

if (method == null) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorUndefinedMethod(methodName, module, this));
}

moduleSingleton.addMethod(this, method.withVisibility(Visibility.PRIVATE));
for (Object name : names) {
setMethodVisibilityNode.executeSetMethodVisibility(frame, singletonClass, name);
}

return module;
@@ -1640,7 +1614,7 @@ public abstract static class ProtectedNode extends CoreMethodArrayArgumentsNode

public ProtectedNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
setVisibilityNode = SetVisibilityNodeFactory.create(context, sourceSection, Visibility.PROTECTED, null, null);
setVisibilityNode = SetVisibilityNodeGen.create(context, sourceSection, Visibility.PROTECTED, null, null);
}

@Specialization
@@ -1803,18 +1777,16 @@ public RubyString userHome(RubyString uname) {
}

@NodeChildren({ @NodeChild(value = "module"), @NodeChild(value = "names") })
public abstract static class SetVisibilityNode extends CoreMethodNode {

@Child SymbolOrToStrNode symbolOrToStrNode;
@Child private SingletonClassNode singletonClassNode;
public abstract static class SetVisibilityNode extends RubyNode {

private final Visibility visibility;

@Child SetMethodVisibilityNode setMethodVisibilityNode;

public SetVisibilityNode(RubyContext context, SourceSection sourceSection, Visibility visibility) {
super(context, sourceSection);
this.visibility = visibility;
this.symbolOrToStrNode = SymbolOrToStrNodeGen.create(context, sourceSection, null);
this.singletonClassNode = SingletonClassNodeGen.create(context, sourceSection, null);
this.setMethodVisibilityNode = SetMethodVisibilityNodeGen.create(context, sourceSection, visibility, null, null);
}

public abstract RubyModule executeSetVisibility(VirtualFrame frame, RubyModule module, Object[] arguments);
@@ -1827,15 +1799,50 @@ RubyModule setVisibility(VirtualFrame frame, RubyModule module, Object[] names)
setCurrentVisibility(visibility);
} else {
for (Object name : names) {
final String methodName = symbolOrToStrNode.executeToJavaString(frame, name);
setMethodVisibility(frame, module, methodName);
setMethodVisibilityNode.executeSetMethodVisibility(frame, module, name);
}
}

return module;
}

private void setMethodVisibility(VirtualFrame frame, RubyModule module, final String methodName) {
private void setCurrentVisibility(Visibility visibility) {
CompilerDirectives.transferToInterpreter();

final Frame callerFrame = Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_WRITE, false);

assert callerFrame != null;
assert callerFrame.getFrameDescriptor() != null;

final FrameSlot visibilitySlot = callerFrame.getFrameDescriptor().findOrAddFrameSlot(
RubyModule.VISIBILITY_FRAME_SLOT_ID, "visibility for frame", FrameSlotKind.Object);

callerFrame.setObject(visibilitySlot, visibility);
}

}

@NodeChildren({ @NodeChild(value = "module"), @NodeChild(value = "name") })
public abstract static class SetMethodVisibilityNode extends RubyNode {

private final Visibility visibility;

@Child SingletonClassNode singletonClassNode;
@Child SymbolOrToStrNode symbolOrToStrNode;

public SetMethodVisibilityNode(RubyContext context, SourceSection sourceSection, Visibility visibility) {
super(context, sourceSection);
this.visibility = visibility;
this.symbolOrToStrNode = SymbolOrToStrNodeGen.create(context, sourceSection, null);
this.singletonClassNode = SingletonClassNodeGen.create(context, sourceSection, null);
}

public abstract RubyModule executeSetMethodVisibility(VirtualFrame frame, RubyModule module, Object name);

@Specialization
RubyModule setMethodVisibility(VirtualFrame frame, RubyModule module, Object name) {
final String methodName = symbolOrToStrNode.executeToJavaString(frame, name);

final InternalMethod method = module.deepMethodSearch(methodName);

if (method == null) {
@@ -1855,20 +1862,8 @@ private void setMethodVisibility(VirtualFrame frame, RubyModule module, final St
} else {
module.addMethod(this, method.withVisibility(visibility));
}
}

private void setCurrentVisibility(Visibility visibility) {
CompilerDirectives.transferToInterpreter();

final Frame callerFrame = Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_WRITE, false);

assert callerFrame != null;
assert callerFrame.getFrameDescriptor() != null;

final FrameSlot visibilitySlot = callerFrame.getFrameDescriptor().findOrAddFrameSlot(
RubyModule.VISIBILITY_FRAME_SLOT_ID, "visibility for frame", FrameSlotKind.Object);

callerFrame.setObject(visibilitySlot, visibility);
return module;
}

}
Original file line number Diff line number Diff line change
@@ -18,10 +18,13 @@
import com.oracle.truffle.interop.messages.Read;
import com.oracle.truffle.interop.messages.Receiver;
import com.oracle.truffle.interop.node.ForeignObjectAccessNode;

import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.KernelNodes;
import org.jruby.truffle.nodes.core.KernelNodesFactory;
import org.jruby.truffle.nodes.objects.SingletonClassNode;
import org.jruby.truffle.nodes.objects.SingletonClassNodeGen;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyConstant;
import org.jruby.truffle.runtime.RubyContext;
@@ -39,6 +42,7 @@ public final class UnresolvedDispatchNode extends DispatchNode {
private final boolean indirect;
private final MissingBehavior missingBehavior;

@Child private SingletonClassNode singletonClassNode;
@Child private KernelNodes.RequireNode requireNode;

public UnresolvedDispatchNode(
@@ -216,13 +220,19 @@ private DispatchNode doRubyBasicObject(
requireNode.require((RubyString) constant.getValue());

return doRubyBasicObject(frame, first, receiverObject, methodName, argumentsObjects);
}
} else {
// The module, the "receiver" is an instance of its singleton class.
if (singletonClassNode == null) {
CompilerDirectives.transferToInterpreter();
singletonClassNode = insert(SingletonClassNodeGen.create(getContext(), getSourceSection(), null));
}
RubyClass moduleSingletonClass = singletonClassNode.executeSingletonClass(frame, module);

// The module, the "receiver" is an instance of its singleton class.
// But we want to check the module assumption, not its singleton class assumption.
return new CachedBoxedDispatchNode(getContext(), methodName, first,
module.getSingletonClass(null), module.getUnmodifiedAssumption(), constant.getValue(),
null, indirect, getDispatchAction());
// But we want to check the module assumption, not its singleton class assumption.
return new CachedBoxedDispatchNode(getContext(), methodName, first,
moduleSingletonClass, module.getUnmodifiedAssumption(), constant.getValue(),
null, indirect, getDispatchAction());
}
} else {
throw new UnsupportedOperationException();
}
Loading