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: 79eee3f69dab
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 31de8b2b3116
Choose a head ref
  • 4 commits
  • 18 files changed
  • 1 contributor

Commits on May 19, 2015

  1. Copy the full SHA
    8d90339 View commit details
  2. Copy the full SHA
    f759e83 View commit details
  3. Copy the full SHA
    0931291 View commit details
  4. Copy the full SHA
    31de8b2 View commit details
Showing with 307 additions and 377 deletions.
  1. +75 −0 truffle/src/main/java/org/jruby/truffle/nodes/constants/GetConstantNode.java
  2. +93 −0 truffle/src/main/java/org/jruby/truffle/nodes/constants/LookupConstantNode.java
  3. +32 −44 truffle/src/main/java/org/jruby/truffle/nodes/constants/ReadConstantNode.java
  4. +14 −10 truffle/src/main/java/org/jruby/truffle/nodes/core/ModuleNodes.java
  5. +0 −10 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedBooleanDispatchNode.java
  6. +1 −33 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedBoxedDispatchNode.java
  7. +0 −23 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedBoxedMethodMissingDispatchNode.java
  8. +0 −7 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedBoxedSymbolDispatchNode.java
  9. +0 −7 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedUnboxedDispatchNode.java
  10. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CallDispatchHeadNode.java
  11. +0 −1 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/DispatchAction.java
  12. +1 −8 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/DispatchHeadNode.java
  13. +0 −24 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/DispatchNode.java
  14. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/DoesRespondDispatchHeadNode.java
  15. +0 −1 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/MissingBehavior.java
  16. +45 −79 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/UncachedDispatchNode.java
  17. +36 −120 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/UnresolvedDispatchNode.java
  18. +8 −8 truffle/src/main/java/org/jruby/truffle/nodes/interop/InteropNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.constants;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.KernelNodes.RequireNode;
import org.jruby.truffle.nodes.core.KernelNodesFactory;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyConstant;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyModule;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.truffle.runtime.core.RubySymbol;

import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

@NodeChildren({
@NodeChild("module"), @NodeChild("name"),
@NodeChild(value = "lookupConstantNode", type = LookupConstantNode.class, executeWith = { "module", "name" })
})
public abstract class GetConstantNode extends RubyNode {

public GetConstantNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public abstract RubyNode getModule();
public abstract LookupConstantNode getLookupConstantNode();

public abstract Object executeGetConstant(VirtualFrame frame, Object module, String name);

@Specialization(guards = { "constant != null", "!constant.isAutoload()" })
protected Object getConstant(RubyModule module, String name, RubyConstant constant) {
return constant.getValue();
}

@Specialization(guards = { "constant != null", "constant.isAutoload()" })
protected Object autoloadConstant(VirtualFrame frame, RubyModule module, String name, RubyConstant constant,
@Cached("createRequireNode()") RequireNode requireNode) {

requireNode.require((RubyString) constant.getValue());

// retry
return this.executeGetConstant(frame, module, name);
}

@Specialization(guards = "constant == null")
protected Object missingConstant(VirtualFrame frame, RubyModule module, String name, Object constant,
@Cached("createConstMissingNode()") CallDispatchHeadNode constMissingNode,
@Cached("getContext().getSymbol(name)") RubySymbol symbolName) {
return constMissingNode.call(frame, module, "const_missing", null, symbolName);
}

protected RequireNode createRequireNode() {
return KernelNodesFactory.RequireNodeFactory.create(getContext(), getSourceSection(), new RubyNode[] {});
}

protected CallDispatchHeadNode createConstMissingNode() {
return DispatchHeadNodeFactory.createMethodCall(getContext());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.constants;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.dispatch.DispatchNode;
import org.jruby.truffle.runtime.LexicalScope;
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.RubyConstant;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyModule;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

@NodeChildren({ @NodeChild("module"), @NodeChild("name") })
public abstract class LookupConstantNode extends RubyNode {

public static int getCacheLimit() {
return DispatchNode.DISPATCH_POLYMORPHIC_MAX;
}

private final LexicalScope lexicalScope;

public LookupConstantNode(RubyContext context, SourceSection sourceSection, LexicalScope lexicalScope) {
super(context, sourceSection);
this.lexicalScope = lexicalScope;
}

public LexicalScope getLexicalScope() {
return lexicalScope;
}

public abstract RubyConstant executeLookupConstant(VirtualFrame frame, Object module, String name);

@Specialization(guards = {
"module == cachedModule",
"name.equals(cachedName)"
}, assumptions = "cachedModule.getUnmodifiedAssumption()", limit = "getCacheLimit()")
protected RubyConstant lookupConstant(VirtualFrame frame, RubyModule module, String name,
@Cached("module") RubyModule cachedModule,
@Cached("name") String cachedName,
@Cached("doLookup(cachedModule, cachedName)") RubyConstant constant,
@Cached("isVisible(cachedModule, constant)") boolean isVisible) {
if (!isVisible) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorPrivateConstant(module, name, this));
}
return constant;
}

@TruffleBoundary
@Specialization
protected RubyConstant lookupConstantUncached(RubyModule module, String name) {
RubyConstant constant = doLookup(module, name);
boolean isVisible = isVisible(module, constant);

if (!isVisible) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorPrivateConstant(module, name, this));
}
return constant;
}

@Specialization(guards = "!isRubyModule(module)")
protected RubyConstant lookupNotModule(Object module, String name) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorIsNotA(module.toString(), "class/module", this));
}

protected RubyConstant doLookup(RubyModule module, String name) {
return ModuleOperations.lookupConstant(getContext(), lexicalScope, module, name);
}

protected boolean isVisible(RubyModule module, RubyConstant constant) {
return constant == null || constant.isVisibleTo(getContext(), lexicalScope, module);
}

}
Original file line number Diff line number Diff line change
@@ -9,89 +9,77 @@
*/
package org.jruby.truffle.nodes.constants;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.dispatch.DispatchAction;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.MissingBehavior;
import org.jruby.truffle.nodes.literal.ObjectLiteralNode;
import org.jruby.truffle.runtime.LexicalScope;
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.RubyConstant;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyModule;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

public class ReadConstantNode extends RubyNode {

private final String name;
@Child private RubyNode receiver;
@Child private DispatchHeadNode dispatch;
@Child private GetConstantNode getConstantNode;

public ReadConstantNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, LexicalScope lexicalScope) {
super(context, sourceSection);
this.name = name;
this.receiver = receiver;
dispatch = new DispatchHeadNode(context, false, false, MissingBehavior.CALL_CONST_MISSING, lexicalScope, DispatchAction.READ_CONSTANT);

this.getConstantNode =
GetConstantNodeGen.create(context, sourceSection, receiver, new ObjectLiteralNode(context, sourceSection, name),
LookupConstantNodeGen.create(context, sourceSection, lexicalScope, null, null));
}

@Override
public Object execute(VirtualFrame frame) {
final Object receiverObject = receiver.execute(frame);

if (!(receiverObject instanceof RubyModule)) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorIsNotA(receiverObject.toString(), "class/module", this));
}

return dispatch.dispatch(
frame,
receiverObject,
name,
null,
new Object[]{});
}

@Override
public void executeVoid(VirtualFrame frame) {
return getConstantNode.execute(frame);
}

@Override
public Object isDefined(VirtualFrame frame) {
CompilerDirectives.transferToInterpreter();

RubyNode receiver = getConstantNode.getModule();
final RubyContext context = getContext();

if (name.equals("Encoding")) {
/*
* Work-around so I don't have to load the iconv library - runners/formatters/junit.rb.
*/
// Work-around so I don't have to load the iconv library - runners/formatters/junit.rb.
return context.makeString("constant");
}

Object receiverObject;

final Object receiverObject;
try {
receiverObject = receiver.execute(frame);
} catch (RaiseException e) {
/*
* If we are looking up a constant in a constant that is itself undefined, we return Nil
* rather than raising the error. Eg.. defined?(Defined::Undefined1::Undefined2)
*/

/* If we are looking up a constant in a constant that is itself undefined, we return Nil
* rather than raising the error. Eg.. defined?(Defined::Undefined1::Undefined2).
*
* We should maybe try to see if receiver.isDefined() but we also need its value if it is,
* and we do not want to execute receiver twice. */
if (e.getRubyException().getLogicalClass() == context.getCoreLibrary().getNameErrorClass()) {
return nil();
}

throw e;
}

RubyModule module = (RubyModule) receiverObject; // TODO(cs): cast
RubyConstant constant = ModuleOperations.lookupConstant(context, dispatch.getLexicalScope(), module, name);
final RubyConstant constant;
try {
constant = getConstantNode.getLookupConstantNode().executeLookupConstant(frame, receiverObject, name);
} catch (RaiseException e) {
if (e.getRubyException().getLogicalClass() == context.getCoreLibrary().getTypeErrorClass()) {
// module is not a class/module
return nil();
} else if (e.getRubyException().getLogicalClass() == context.getCoreLibrary().getNameErrorClass()) {
// private constant
return nil();
}
throw e;
}

if (constant == null || !constant.isVisibleTo(context, dispatch.getLexicalScope(), module)) {
if (constant == null) {
return nil();
} else {
return context.makeString("constant");
24 changes: 14 additions & 10 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ModuleNodes.java
Original file line number Diff line number Diff line change
@@ -39,6 +39,9 @@
import org.jruby.truffle.nodes.coerce.SymbolOrToStrNodeGen;
import org.jruby.truffle.nodes.coerce.ToStrNode;
import org.jruby.truffle.nodes.coerce.ToStrNodeGen;
import org.jruby.truffle.nodes.constants.GetConstantNode;
import org.jruby.truffle.nodes.constants.GetConstantNodeGen;
import org.jruby.truffle.nodes.constants.LookupConstantNodeGen;
import org.jruby.truffle.nodes.control.SequenceNode;
import org.jruby.truffle.nodes.core.KernelNodes.BindingNode;
import org.jruby.truffle.nodes.core.ModuleNodesFactory.SetMethodVisibilityNodeGen;
@@ -846,11 +849,12 @@ public boolean isConstDefined(RubyModule module, String fullName, boolean inheri
})
public abstract static class ConstGetNode extends CoreMethodNode {

@Child private DispatchHeadNode dispatch;
@Child private GetConstantNode getConstantNode;

public ConstGetNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
dispatch = new DispatchHeadNode(context, false, false, MissingBehavior.CALL_CONST_MISSING, null, DispatchAction.READ_CONSTANT);
this.getConstantNode = GetConstantNodeGen.create(context, sourceSection, null, null,
LookupConstantNodeGen.create(context, sourceSection, LexicalScope.NONE, null, null));
}

@CreateCast("name")
@@ -863,17 +867,12 @@ public Object getConstant(VirtualFrame frame, RubyModule module, String name, Un
return getConstant(frame, module, name, true);
}

@Specialization(guards = "isScoped(name)")
public Object getConstantScoped(VirtualFrame frame, RubyModule module, String name, UndefinedPlaceholder inherit) {
return getConstantScoped(frame, module, name, true);
}

@Specialization(guards = { "isTrue(inherit)", "!isScoped(name)" })
@Specialization(guards = { "!isScoped(name)", "inherit" })
public Object getConstant(VirtualFrame frame, RubyModule module, String name, boolean inherit) {
return dispatch.dispatch(frame, module, name, null, new Object[] {});
return getConstantNode.executeGetConstant(frame, module, name);
}

@Specialization(guards = { "!isTrue(inherit)", "!isScoped(name)" })
@Specialization(guards = { "!isScoped(name)", "!inherit" })
public Object getConstantNoInherit(VirtualFrame frame, RubyModule module, String name, boolean inherit) {
CompilerDirectives.transferToInterpreter();

@@ -886,6 +885,11 @@ public Object getConstantNoInherit(VirtualFrame frame, RubyModule module, String
}
}

@Specialization(guards = "isScoped(fullName)")
public Object getConstantScoped(VirtualFrame frame, RubyModule module, String fullName, UndefinedPlaceholder inherit) {
return getConstantScoped(frame, module, fullName, true);
}

@Specialization(guards = "isScoped(fullName)")
public Object getConstantScoped(VirtualFrame frame, RubyModule module, String fullName, boolean inherit) {
CompilerDirectives.transferToInterpreter();
Loading