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: 3413a4616748
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2939c730fe80
Choose a head ref
  • 10 commits
  • 14 files changed
  • 1 contributor

Commits on Aug 8, 2015

  1. 1
    Copy the full SHA
    ff14123 View commit details
  2. [Truffle] Untangle GetConstantNode and LookupConstantNode.

    * Composition is much simpler and flexible without executeWith.
    * Fix reading of Rational/Complex in translator.
    eregon committed Aug 8, 2015
    Copy the full SHA
    a8ad16a View commit details
  3. Copy the full SHA
    da5f108 View commit details
  4. Copy the full SHA
    92c3b56 View commit details
  5. Copy the full SHA
    8bd5b48 View commit details
  6. [Truffle] Prepare ReadConstantNode to know lss about LexicalScope.

    * Since there is a single user of lookup with LexicalScope and it's fairly different.
    eregon committed Aug 8, 2015
    Copy the full SHA
    7715e21 View commit details

Commits on Aug 9, 2015

  1. [Truffle] Let ReadConstantWithLexicalScopeNode have its own lookup node.

    * It is so much simpler!
    eregon committed Aug 9, 2015
    Copy the full SHA
    55b81da View commit details
  2. Copy the full SHA
    61828d8 View commit details
  3. Copy the full SHA
    65dbb89 View commit details
  4. Copy the full SHA
    2939c73 View commit details
Original file line number Diff line number Diff line change
@@ -9,65 +9,38 @@
*/
package org.jruby.truffle.nodes.constants;

import com.oracle.truffle.api.CompilerDirectives;
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;
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.core.ModuleNodes;
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.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyModule;
import org.jruby.util.IdUtil;

@NodeChildren({
@NodeChild("module"), @NodeChild("name"),
@NodeChild(value = "lookupConstantNode", type = LookupConstantNode.class, executeWith = { "module", "name" })
})
import com.oracle.truffle.api.CompilerDirectives;
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("constant") })
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, RubyConstant constant);

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

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

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

final RubyBasicObject path = (RubyBasicObject) constant.getValue();

// The autoload constant must only be removed if everything succeeds.
// We remove it first to allow lookup to ignore it and add it back if there was a failure.
ModuleNodes.getModel(constant.getDeclaringModule()).removeConstant(this, name);
try {
requireNode.require(path);
return executeGetConstant(frame, module, name);
} catch (RaiseException e) {
ModuleNodes.getModel(constant.getDeclaringModule()).setAutoloadConstant(this, name, path);
throw e;
}
}

@Specialization(guards = {"isRubyModule(module)", "constant == null"})
@Specialization(guards = "constant == null")
protected Object missingConstant(VirtualFrame frame, RubyBasicObject module, String name, Object constant,
@Cached("isValidConstantName(name)") boolean isValidConstantName,
@Cached("createConstMissingNode()") CallDispatchHeadNode constMissingNode,
@@ -79,10 +52,6 @@ protected Object missingConstant(VirtualFrame frame, RubyBasicObject module, Str
return constMissingNode.call(frame, module, "const_missing", null, symbolName);
}

protected RequireNode createRequireNode() {
return KernelNodesFactory.RequireNodeFactory.create(getContext(), getSourceSection(), null);
}

protected boolean isValidConstantName(String name) {
return IdUtil.isValidConstantName19(name);
}
Original file line number Diff line number Diff line change
@@ -9,6 +9,15 @@
*/
package org.jruby.truffle.nodes.constants;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.ModuleNodes;
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.RubyBasicObject;

import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -20,17 +29,6 @@
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;

import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.ModuleNodes;
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.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyModule;

/**
* Caches {@link ModuleOperations#lookupConstant}
* and checks visibility.
@@ -39,15 +37,8 @@
@NodeChildren({ @NodeChild("module"), @NodeChild("name") })
public abstract class LookupConstantNode extends RubyNode {

private final LexicalScope lexicalScope;

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

public LexicalScope getLexicalScope() {
return lexicalScope;
}

public abstract RubyConstant executeLookupConstant(VirtualFrame frame, Object module, String name);
@@ -103,11 +94,11 @@ protected boolean guardName(String name, String cachedName, ConditionProfile sam
}

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

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

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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.ModuleNodes;
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.RubyBasicObject;

import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

public abstract class LookupConstantWithLexicalScopeNode extends RubyNode {

private final LexicalScope lexicalScope;
private final String name;

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

public RubyBasicObject getModule() {
return lexicalScope.getLiveModule();
}

public abstract RubyConstant executeLookupConstant(VirtualFrame frame);

@Specialization(assumptions = "getUnmodifiedAssumption(getModule())")
protected RubyConstant lookupConstant(VirtualFrame frame,
@Cached("doLookup()") RubyConstant constant,
@Cached("isVisible(constant)") boolean isVisible) {
if (!isVisible) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().nameErrorPrivateConstant(getModule(), name, this));
}
return constant;
}

public Assumption getUnmodifiedAssumption(RubyBasicObject module) {
return ModuleNodes.getModel(module).getUnmodifiedAssumption();
}

protected RubyConstant doLookup() {
return ModuleOperations.lookupConstantWithLexicalScope(getContext(), lexicalScope, name);
}

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

}
Original file line number Diff line number Diff line change
@@ -9,87 +9,75 @@
*/
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.literal.LiteralNode;
import org.jruby.truffle.runtime.ConstantReplacer;
import org.jruby.truffle.runtime.LexicalScope;
import org.jruby.truffle.nodes.core.KernelNodes.RequireNode;
import org.jruby.truffle.nodes.core.KernelNodesFactory;
import org.jruby.truffle.nodes.core.ModuleNodes;
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.RubyBasicObject;

public class ReadConstantNode extends RubyNode {
import com.oracle.truffle.api.CompilerDirectives;
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 ReadConstantNode extends RubyNode {

private final String name;
@Child protected LookupConstantNode lookupConstantNode;
@Child private GetConstantNode getConstantNode;

public ReadConstantNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, LexicalScope lexicalScope) {
super(context, sourceSection);
@Child private RequireNode requireNode;

this.name = ConstantReplacer.replacementName(sourceSection, name);
this.getConstantNode =
GetConstantNodeGen.create(context, sourceSection, receiver, new LiteralNode(context, sourceSection, this.name),
LookupConstantNodeGen.create(context, sourceSection, lexicalScope, null, null));
public ReadConstantNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.lookupConstantNode = LookupConstantNodeGen.create(context, sourceSection, null, null);
this.getConstantNode = GetConstantNodeGen.create(context, sourceSection, null, null, null);
}

@Override
public Object execute(VirtualFrame frame) {
return getConstantNode.execute(frame);
}
public abstract RubyNode getName();
public abstract RubyNode getModule();

@Override
public Object isDefined(VirtualFrame frame) {
CompilerDirectives.transferToInterpreter();
public abstract Object executeReadConstant(VirtualFrame frame, Object module, String name);

RubyNode receiver = getConstantNode.getModule();
final RubyContext context = getContext();
@Specialization
public Object readConstant(VirtualFrame frame, Object module, String name) {
final RubyConstant constant = lookupConstantNode.executeLookupConstant(frame, module, name);

if (name.equals("Encoding")) {
// Work-around so I don't have to load the iconv library - runners/formatters/junit.rb.
return createString("constant");
if (constant != null && constant.isAutoload()) {
CompilerDirectives.transferToInterpreter();
return autoload(frame, module, name, constant);
}

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).
*
* 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 (((RubyBasicObject) e.getRubyException()).getLogicalClass() == context.getCoreLibrary().getNameErrorClass()) {
return nil();
}
throw e;
}
return getConstantNode.executeGetConstant(frame, module, name, constant);
}

final RubyConstant constant;
protected Object autoload(VirtualFrame frame, Object module, String name, RubyConstant constant) {

final RubyBasicObject path = (RubyBasicObject) constant.getValue();

// The autoload constant must only be removed if everything succeeds.
// We remove it first to allow lookup to ignore it and add it back if there was a failure.
ModuleNodes.getModel(constant.getDeclaringModule()).removeConstant(this, name);
try {
constant = getConstantNode.getLookupConstantNode().executeLookupConstant(frame, receiverObject, name);
require(path);
return readConstant(frame, module, name); // retry
} catch (RaiseException e) {
if (((RubyBasicObject) e.getRubyException()).getLogicalClass() == context.getCoreLibrary().getTypeErrorClass()) {
// module is not a class/module
return nil();
} else if (((RubyBasicObject) e.getRubyException()).getLogicalClass() == context.getCoreLibrary().getNameErrorClass()) {
// private constant
return nil();
}
ModuleNodes.getModel(constant.getDeclaringModule()).setAutoloadConstant(this, name, path);
throw e;
}

if (constant == null) {
return nil();
} else {
return createString("constant");
}
}

public String getName() {
return name;
private boolean require(RubyBasicObject feature) {
if (requireNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
requireNode = insert(KernelNodesFactory.RequireNodeFactory.create(getContext(), getSourceSection(), null));
}
return requireNode.require(feature);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* 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.core.ModuleNodes;
import org.jruby.truffle.runtime.LexicalScope;
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.RubyBasicObject;

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

public class ReadConstantWithLexicalScopeNode extends RubyNode {

private final LexicalScope lexicalScope;
private final String name;
@Child protected LookupConstantWithLexicalScopeNode lookupConstantNode;
@Child private GetConstantNode getConstantNode;

@Child private RequireNode requireNode;

public ReadConstantWithLexicalScopeNode(RubyContext context, SourceSection sourceSection, LexicalScope lexicalScope, String name) {
super(context, sourceSection);
this.lexicalScope = lexicalScope;
this.name = name;
this.lookupConstantNode = LookupConstantWithLexicalScopeNodeGen.create(context, sourceSection, lexicalScope, name);
this.getConstantNode = GetConstantNodeGen.create(context, sourceSection, null, null, null);
}

@Override
public Object execute(VirtualFrame frame) {
final RubyConstant constant = lookupConstantNode.executeLookupConstant(frame);

if (constant != null && constant.isAutoload()) {
CompilerDirectives.transferToInterpreter();
return autoload(frame, constant);
}

return getConstantNode.executeGetConstant(frame, lexicalScope.getLiveModule(), name, constant);
}

protected Object autoload(VirtualFrame frame, RubyConstant constant) {
final RubyBasicObject path = (RubyBasicObject) constant.getValue();

// The autoload constant must only be removed if everything succeeds.
// We remove it first to allow lookup to ignore it and add it back if there was a failure.
ModuleNodes.getModel(constant.getDeclaringModule()).removeConstant(this, name);
try {
require(path);
return execute(frame); // retry
} catch (RaiseException e) {
ModuleNodes.getModel(constant.getDeclaringModule()).setAutoloadConstant(this, name, path);
throw e;
}
}

private boolean require(RubyBasicObject feature) {
if (requireNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
requireNode = insert(KernelNodesFactory.RequireNodeFactory.create(getContext(), getSourceSection(), null));
}
return requireNode.require(feature);
}

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

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

final RubyConstant constant;
try {
constant = lookupConstantNode.executeLookupConstant(frame);
} catch (RaiseException e) {
if (((RubyBasicObject) e.getRubyException()).getLogicalClass() == getContext().getCoreLibrary().getNameErrorClass()) {
// private constant
return nil();
}
throw e;
}

if (constant == null) {
return nil();
} else {
return createString("constant");
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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.literal.LiteralNode;
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.RubyBasicObject;

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

public class ReadLiteralConstantNode extends RubyNode {

@Child private ReadConstantNode readConstantNode;

public ReadLiteralConstantNode(RubyContext context, SourceSection sourceSection, RubyNode module, String name) {
super(context, sourceSection);
RubyNode nameNode = new LiteralNode(context, sourceSection, name);
this.readConstantNode = ReadConstantNodeGen.create(context, sourceSection, module, nameNode);
}

@Override
public Object execute(VirtualFrame frame) {
return readConstantNode.execute(frame);
}

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

final RubyContext context = getContext();
final String name = (String) readConstantNode.getName().execute(frame);

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

final Object moduleObject;
try {
moduleObject = readConstantNode.getModule().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).
*
* 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 (((RubyBasicObject) e.getRubyException()).getLogicalClass() == context.getCoreLibrary().getNameErrorClass()) {
return nil();
}
throw e;
}

final RubyConstant constant;
try {
constant = readConstantNode.lookupConstantNode.executeLookupConstant(frame, moduleObject, name);
} catch (RaiseException e) {
if (((RubyBasicObject) e.getRubyException()).getLogicalClass() == context.getCoreLibrary().getTypeErrorClass()) {
// module is not a class/module
return nil();
} else if (((RubyBasicObject) e.getRubyException()).getLogicalClass() == context.getCoreLibrary().getNameErrorClass()) {
// private constant
return nil();
}
throw e;
}

if (constant == null) {
return nil();
} else {
return createString("constant");
}
}

}
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ private void addCoreMethod(MethodDetails methodDetails) {
module = objectClass;

for (String moduleName : fullName.split("::")) {
final RubyConstant constant = ModuleOperations.lookupConstant(context, LexicalScope.NONE, module, moduleName);
final RubyConstant constant = ModuleOperations.lookupConstant(context, module, moduleName);

if (constant == null) {
throw new RuntimeException(String.format("Module %s not found when adding core library", moduleName));
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;

import org.jcodings.Encoding;
import org.jcodings.specific.USASCIIEncoding;
import org.jcodings.specific.UTF8Encoding;
@@ -1519,27 +1520,28 @@ public RubyNode coerceFeatureToPath(RubyNode feature) {
return ToPathNodeGen.create(getContext(), getSourceSection(), feature);
}

@Specialization(guards = "isRubyString(feature)")
public boolean require(RubyBasicObject feature) {
@Specialization(guards = "isRubyString(featureString)")
public boolean require(RubyBasicObject featureString) {
CompilerDirectives.transferToInterpreter();
final String feature = featureString.toString();

// TODO CS 1-Mar-15 ERB will use strscan if it's there, but strscan is not yet complete, so we need to hide it

if (feature.toString().equals("strscan") && RubyCallStack.getCallerFrame(getContext()).getCallNode()
if (feature.equals("strscan") && RubyCallStack.getCallerFrame(getContext()).getCallNode()
.getEncapsulatingSourceSection().getSource().getName().endsWith("erb.rb")) {
throw new RaiseException(getContext().getCoreLibrary().loadErrorCannotLoad(feature.toString(), this));
throw new RaiseException(getContext().getCoreLibrary().loadErrorCannotLoad(feature, this));
}

// TODO CS 19-May-15 securerandom will use openssl if it's there, but we've only shimmed it

if (feature.toString().equals("openssl") && RubyCallStack.getCallerFrame(getContext()).getCallNode()
if (feature.equals("openssl") && RubyCallStack.getCallerFrame(getContext()).getCallNode()
.getEncapsulatingSourceSection().getSource().getName().endsWith("securerandom.rb")) {
ModuleNodes.getModel(getContext().getCoreLibrary().getObjectClass()).getConstants().remove("OpenSSL");
throw new RaiseException(getContext().getCoreLibrary().loadErrorCannotLoad(feature.toString(), this));
throw new RaiseException(getContext().getCoreLibrary().loadErrorCannotLoad(feature, this));
}

try {
getContext().getFeatureManager().require(feature.toString(), this);
getContext().getFeatureManager().require(feature, this);
} catch (IOException e) {
throw new RuntimeException(e);
}
Original file line number Diff line number Diff line change
@@ -41,6 +41,8 @@
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.constants.ReadConstantNode;
import org.jruby.truffle.nodes.constants.ReadConstantNodeGen;
import org.jruby.truffle.nodes.control.SequenceNode;
import org.jruby.truffle.nodes.core.ModuleNodesFactory.GenerateAccessorNodeGen;
import org.jruby.truffle.nodes.core.ModuleNodesFactory.SetMethodVisibilityNodeGen;
@@ -588,7 +590,7 @@ public Object autoloadQueryString(RubyBasicObject module, RubyBasicObject name)
}

private Object autoloadQuery(RubyBasicObject module, String name) {
final RubyConstant constant = ModuleOperations.lookupConstant(getContext(), LexicalScope.NONE, module, name);
final RubyConstant constant = ModuleOperations.lookupConstant(getContext(), module, name);

if ((constant == null) || ! constant.isAutoload()) {
return nil();
@@ -892,12 +894,11 @@ public boolean isConstDefined(RubyBasicObject module, String fullName, boolean i
})
public abstract static class ConstGetNode extends CoreMethodNode {

@Child private GetConstantNode getConstantNode;
@Child private ReadConstantNode readConstantNode;

public ConstGetNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.getConstantNode = GetConstantNodeGen.create(context, sourceSection, null, null,
LookupConstantNodeGen.create(context, sourceSection, LexicalScope.NONE, null, null));
this.readConstantNode = ReadConstantNodeGen.create(context, sourceSection, null, null);
}

@CreateCast("name")
@@ -913,7 +914,7 @@ public RubyNode coerceToBoolean(RubyNode inherit) {
// Symbol
@Specialization(guards = {"inherit", "isRubySymbol(name)"})
public Object getConstant(VirtualFrame frame, RubyBasicObject module, RubyBasicObject name, boolean inherit) {
return getConstantNode.executeGetConstant(frame, module, SymbolNodes.getString(name));
return readConstantNode.executeReadConstant(frame, module, SymbolNodes.getString(name));
}

@Specialization(guards = {"!inherit", "isRubySymbol(name)"})
@@ -924,7 +925,7 @@ public Object getConstantNoInherit(RubyBasicObject module, RubyBasicObject name,
// String
@Specialization(guards = { "inherit", "isRubyString(name)", "!isScoped(name)" })
public Object getConstantString(VirtualFrame frame, RubyBasicObject module, RubyBasicObject name, boolean inherit) {
return getConstantNode.executeGetConstant(frame, module, name.toString());
return readConstantNode.executeReadConstant(frame, module, name.toString());
}

@Specialization(guards = { "!inherit", "isRubyString(name)", "!isScoped(name)" })
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
import com.oracle.truffle.api.object.*;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;

import org.jruby.ext.bigdecimal.RubyBigDecimal;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyGuards;
@@ -30,6 +31,8 @@
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.constants.ReadConstantNode;
import org.jruby.truffle.nodes.constants.ReadConstantNodeGen;
import org.jruby.truffle.nodes.core.*;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
@@ -403,7 +406,7 @@ private RubyBasicObject createWithMode(VirtualFrame frame, Type value, RubyBasic
setupGetIntegerConstant();
setupBooleanCast();

final int exceptionConstant = getIntegerConstant.executeGetIntegerConstant(frame, constantName);
final int exceptionConstant = getIntegerConstant.executeGetIntegerConstant(frame, getBigDecimalClass(), constantName);
final boolean raise = booleanCast.executeBoolean(frame,
modeCall.call(frame, getBigDecimalClass(), "boolean_mode", null, exceptionConstant));
if (raise) {
@@ -425,8 +428,7 @@ private void setupBooleanCast() {
private void setupGetIntegerConstant() {
if (getIntegerConstant == null) {
CompilerDirectives.transferToInterpreter();
getIntegerConstant = insert(GetIntegerConstantNodeGen.create(getContext(), getSourceSection(),
new LiteralNode(getContext(), getSourceSection(), getBigDecimalClass())));
getIntegerConstant = insert(GetIntegerConstantNodeGen.create(getContext(), getSourceSection(), null, null));
}
}

@@ -1694,45 +1696,26 @@ public boolean zeroSpecial(RubyBasicObject value) {
}
}

@NodeChildren({
@NodeChild(value = "name", type = RubyNode.class),
@NodeChild(value = "module", type = RubyNode.class),
@NodeChild(value = "getConst", type = GetConstantNode.class, executeWith = { "module", "name" }),
@NodeChild(value = "coerce", type = ToIntNode.class, executeWith = "getConst"),
@NodeChild(value = "cast", type = IntegerCastNode.class, executeWith = "coerce")
})
@NodeChildren({ @NodeChild("module"), @NodeChild("name") })
public abstract static class GetIntegerConstantNode extends RubyNode {

@Child ReadConstantNode readConstantNode;
@Child ToIntNode toIntNode;
@Child IntegerCastNode integerCastNode;

public GetIntegerConstantNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readConstantNode = ReadConstantNodeGen.create(context, sourceSection, null, null);
toIntNode = ToIntNodeGen.create(context, sourceSection, null);
integerCastNode = IntegerCastNodeGen.create(context, sourceSection, null);
}

public static GetIntegerConstantNode create(RubyContext context, SourceSection sourceSection) {
return create(context, sourceSection, null);
}

public static GetIntegerConstantNode create(RubyContext context, SourceSection sourceSection, RubyNode module) {
return GetIntegerConstantNodeGen.create(
context, sourceSection, null, module,
GetConstantNodeGen.create(context, sourceSection, null, null,
LookupConstantNodeGen.create(context, sourceSection, LexicalScope.NONE, null, null)),
ToIntNodeGen.create(context, sourceSection, null),
IntegerCastNodeGen.create(context, sourceSection, null));
}

public abstract IntegerCastNode getCast();

public abstract int executeGetIntegerConstant(VirtualFrame frame, String name, RubyBasicObject module);

public abstract int executeGetIntegerConstant(VirtualFrame frame, String name);
public abstract int executeGetIntegerConstant(VirtualFrame frame, RubyBasicObject module, String name);

@Specialization(guards = "isRubyModule(module)")
public int doInteger(String name,
RubyBasicObject module,
Object constValue,
Object coercedConstValue,
int castedValue) {
return castedValue;
public int doInteger(VirtualFrame frame, RubyBasicObject module, String name) {
final Object value = readConstantNode.executeReadConstant(frame, module, name);
return integerCastNode.executeInteger(frame, toIntNode.executeIntOrLong(frame, value));
}
}

@@ -1744,39 +1727,38 @@ public abstract static class SignNode extends BigDecimalCoreMethodArrayArguments

public SignNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
sign = GetIntegerConstantNodeGen.create(context, sourceSection,
new LiteralNode(context, sourceSection, getBigDecimalClass()));
sign = GetIntegerConstantNodeGen.create(context, sourceSection, null, null);
}

@Specialization(guards = {
"isNormal(value)",
"isNormalZero(value)" })
public int signNormalZero(VirtualFrame frame, RubyBasicObject value) {
return sign.executeGetIntegerConstant(frame, "SIGN_POSITIVE_ZERO");
return sign.executeGetIntegerConstant(frame, getBigDecimalClass(), "SIGN_POSITIVE_ZERO");
}

@Specialization(guards = {
"isNormal(value)",
"!isNormalZero(value)" })
public int signNormal(VirtualFrame frame, RubyBasicObject value) {
if (positive.profile(getBigDecimalValue(value).signum() > 0)) {
return sign.executeGetIntegerConstant(frame, "SIGN_POSITIVE_FINITE");
return sign.executeGetIntegerConstant(frame, getBigDecimalClass(), "SIGN_POSITIVE_FINITE");
} else {
return sign.executeGetIntegerConstant(frame, "SIGN_NEGATIVE_FINITE");
return sign.executeGetIntegerConstant(frame, getBigDecimalClass(), "SIGN_NEGATIVE_FINITE");
}
}

@Specialization(guards = "!isNormal(value)")
public int signSpecial(VirtualFrame frame, RubyBasicObject value) {
switch (getBigDecimalType(value)) {
case NEGATIVE_INFINITY:
return sign.executeGetIntegerConstant(frame, "SIGN_NEGATIVE_INFINITE");
return sign.executeGetIntegerConstant(frame, getBigDecimalClass(), "SIGN_NEGATIVE_INFINITE");
case POSITIVE_INFINITY:
return sign.executeGetIntegerConstant(frame, "SIGN_POSITIVE_INFINITE");
return sign.executeGetIntegerConstant(frame, getBigDecimalClass(), "SIGN_POSITIVE_INFINITE");
case NEGATIVE_ZERO:
return sign.executeGetIntegerConstant(frame, "SIGN_NEGATIVE_ZERO");
return sign.executeGetIntegerConstant(frame, getBigDecimalClass(), "SIGN_NEGATIVE_ZERO");
case NAN:
return sign.executeGetIntegerConstant(frame, "SIGN_NaN");
return sign.executeGetIntegerConstant(frame, getBigDecimalClass(), "SIGN_NaN");
default:
throw new UnreachableCodeBranch();
}
Original file line number Diff line number Diff line change
@@ -11,9 +11,12 @@

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

import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.constants.ReadConstantNode;
import org.jruby.truffle.nodes.constants.ReadConstantNodeGen;
import org.jruby.truffle.nodes.constants.ReadLiteralConstantNode;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.nodes.literal.LiteralNode;
@@ -24,16 +27,15 @@
public class ReadTimeZoneNode extends RubyNode {

@Child private CallDispatchHeadNode hashNode;
@Child private ReadConstantNode envNode;
@Child private ReadLiteralConstantNode envNode;

private final RubyBasicObject TZ;

public ReadTimeZoneNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
hashNode = DispatchHeadNodeFactory.createMethodCall(context);
envNode = new ReadConstantNode(context, sourceSection, "ENV",
new LiteralNode(context, sourceSection, getContext().getCoreLibrary().getObjectClass()),
LexicalScope.NONE);
envNode = new ReadLiteralConstantNode(context, sourceSection,
new LiteralNode(context, sourceSection, getContext().getCoreLibrary().getObjectClass()), "ENV");
TZ = createString("TZ");
}

Original file line number Diff line number Diff line change
@@ -80,50 +80,39 @@ public static Map<String, RubyConstant> getAllConstants(RubyBasicObject module)
return constants;
}

/**
* @param lexicalScope The surrounding LexicalScope (as in Constant),
* or null if it is ignored (as in Mod::Constant or ::Constant)
* @param module The receiver of the constant lookup.
* Must be identical to lexicalScope.getLiveModule() if lexicalScope != null.
*/
@TruffleBoundary
public static RubyConstant lookupConstant(RubyContext context, LexicalScope lexicalScope, RubyBasicObject module, String name) {
public static RubyConstant lookupConstantWithLexicalScope(RubyContext context, LexicalScope lexicalScope, String name) {
CompilerAsserts.neverPartOfCompilation();

assert lexicalScope == null || lexicalScope.getLiveModule() == module;
assert RubyGuards.isRubyModule(module);

RubyConstant constant;

// Look in the current module
constant = ModuleNodes.getModel(module).getConstants().get(name);

if (constant != null) {
return constant;
}
final RubyBasicObject module = lexicalScope.getLiveModule();

// Look in lexical scope
if (lexicalScope != null) {
if (lexicalScope != context.getRootLexicalScope()) {
// Already looked in the top lexical scope, which is module.
lexicalScope = lexicalScope.getParent();
while (lexicalScope != context.getRootLexicalScope()) {
RubyConstant constant = ModuleNodes.getModel(lexicalScope.getLiveModule()).getConstants().get(name);
if (constant != null) {
return constant;
}

while (lexicalScope != context.getRootLexicalScope()) {
constant = ModuleNodes.getModel(lexicalScope.getLiveModule()).getConstants().get(name);
lexicalScope = lexicalScope.getParent();
}

if (constant != null) {
return constant;
}
return lookupConstant(context, module, name);
}

lexicalScope = lexicalScope.getParent();
}
@TruffleBoundary
public static RubyConstant lookupConstant(RubyContext context, RubyBasicObject module, String name) {
CompilerAsserts.neverPartOfCompilation();
assert RubyGuards.isRubyModule(module);

// Look in the current module
RubyConstant constant = ModuleNodes.getModel(module).getConstants().get(name);
if (constant != null) {
return constant;
}

// Look in ancestors
for (RubyBasicObject ancestor : ModuleNodes.getModel(module).parentAncestors()) {
constant = ModuleNodes.getModel(ancestor).getConstants().get(name);

if (constant != null) {
return constant;
}
@@ -140,7 +129,6 @@ public static RubyConstant lookupConstant(RubyContext context, LexicalScope lexi

for (RubyBasicObject ancestor : ModuleNodes.getModel(objectClass).prependedAndIncludedModules()) {
constant = ModuleNodes.getModel(ancestor).getConstants().get(name);

if (constant != null) {
return constant;
}
@@ -187,7 +175,7 @@ public static RubyConstant lookupConstantWithInherit(RubyContext context, RubyBa
}

if (inherit) {
return ModuleOperations.lookupConstant(context, LexicalScope.NONE, module, name);
return ModuleOperations.lookupConstant(context, module, name);
} else {
return ModuleNodes.getModel(module).getConstants().get(name);
}
Original file line number Diff line number Diff line change
@@ -49,7 +49,7 @@ public FeatureManager(RubyContext context) {
// TODO CS 27-May-15 we should do lookup in one phase, returning a path, and then do the load

public boolean require(String feature, Node currentNode) throws IOException {
final RubyConstant dataConstantBefore = ModuleOperations.lookupConstant(context, LexicalScope.NONE, context.getCoreLibrary().getObjectClass(), "DATA");
final RubyConstant dataConstantBefore = ModuleOperations.lookupConstant(context, context.getCoreLibrary().getObjectClass(), "DATA");

if (feature.startsWith("./")) {
final String cwd = context.getRuntime().getCurrentDirectory();
Original file line number Diff line number Diff line change
@@ -27,6 +27,9 @@
import org.jruby.truffle.nodes.cast.*;
import org.jruby.truffle.nodes.cast.LambdaNode;
import org.jruby.truffle.nodes.constants.ReadConstantNode;
import org.jruby.truffle.nodes.constants.ReadConstantNodeGen;
import org.jruby.truffle.nodes.constants.ReadConstantWithLexicalScopeNode;
import org.jruby.truffle.nodes.constants.ReadLiteralConstantNode;
import org.jruby.truffle.nodes.constants.WriteConstantNode;
import org.jruby.truffle.nodes.control.AndNode;
import org.jruby.truffle.nodes.control.BreakNode;
@@ -66,6 +69,7 @@
import org.jruby.truffle.nodes.rubinius.RubiniusPrimitiveConstructor;
import org.jruby.truffle.nodes.rubinius.RubiniusSingleBlockArgNode;
import org.jruby.truffle.nodes.yield.YieldNode;
import org.jruby.truffle.runtime.ConstantReplacer;
import org.jruby.truffle.runtime.LexicalScope;
import org.jruby.truffle.runtime.ReturnID;
import org.jruby.truffle.runtime.RubyContext;
@@ -924,9 +928,12 @@ public RubyNode visitColon2Node(org.jruby.ast.Colon2Node node) {
throw new UnsupportedOperationException(node.toString());
}

final SourceSection sourceSection = translate(node.getPosition());
final String name = ConstantReplacer.replacementName(sourceSection, node.getName());

final RubyNode lhs = node.getLeftNode().accept(this);

final RubyNode ret = new ReadConstantNode(context, translate(node.getPosition()), node.getName(), lhs, LexicalScope.NONE);
final RubyNode ret = new ReadLiteralConstantNode(context, sourceSection, lhs, name);
return addNewlineIfNeeded(node, ret);
}

@@ -935,10 +942,11 @@ public RubyNode visitColon3Node(org.jruby.ast.Colon3Node node) {
// Root namespace constant access, as in ::Foo

final SourceSection sourceSection = translate(node.getPosition());
final String name = ConstantReplacer.replacementName(sourceSection, node.getName());

final LiteralNode root = new LiteralNode(context, sourceSection, context.getCoreLibrary().getObjectClass());

final RubyNode ret = new ReadConstantNode(context, sourceSection, node.getName(), root, LexicalScope.NONE);
final RubyNode ret = new ReadLiteralConstantNode(context, sourceSection, root, name);
return addNewlineIfNeeded(node, ret);
}

@@ -1005,14 +1013,15 @@ public RubyNode visitConstNode(org.jruby.ast.ConstNode node) {
* we will because we'll translate that to ::Rubinius. But it is a simpler translation.
*/

if (node.getName().equals("Rubinius") && sourceSection.getSource().getPath().startsWith("core:/core/rubinius")) {
final RubyNode ret = new org.jruby.ast.Colon3Node(node.getPosition(), node.getName()).accept(this);
final String name = ConstantReplacer.replacementName(sourceSection, node.getName());

if (name.equals("Rubinius") && sourceSection.getSource().getPath().startsWith("core:/core/rubinius")) {
final RubyNode ret = new org.jruby.ast.Colon3Node(node.getPosition(), name).accept(this);
return addNewlineIfNeeded(node, ret);
}

final LexicalScope lexicalScope = environment.getLexicalScope();
final RubyNode moduleNode = new LexicalScopeNode(context, sourceSection, lexicalScope);
final RubyNode ret = new ReadConstantNode(context, sourceSection, node.getName(), moduleNode, lexicalScope);
final RubyNode ret = new ReadConstantWithLexicalScopeNode(context, sourceSection, lexicalScope, name);
return addNewlineIfNeeded(node, ret);
}

@@ -2537,11 +2546,10 @@ public RubyNode visitRationalNode(RationalNode node) {
private RubyNode translateRationalComplex(SourceSection sourceSection, String name, RubyNode a, RubyNode b) {
// Translate as Rubinius.privately { Rational.convert(a, b) }

final LexicalScope lexicalScope = environment.getLexicalScope();
final RubyNode moduleNode = new LexicalScopeNode(context, sourceSection, lexicalScope);
final RubyNode moduleNode = new LiteralNode(context, sourceSection, context.getCoreLibrary().getObjectClass());
return new RubyCallNode(
context, sourceSection, "convert",
new ReadConstantNode(context, sourceSection, name, moduleNode, lexicalScope),
new ReadLiteralConstantNode(context, sourceSection, moduleNode, name),
null, false, true, new RubyNode[]{a, b});
}