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

Commits on Oct 10, 2015

  1. Copy the full SHA
    3189f27 View commit details
  2. [Truffle] Fix corner cases of constant lookup.

    * Follow the ISO spec for literal lookups.
    * Additional Object (and included/prepended modules)
      for dynamic const lookups (const_get, const_defined?).
    eregon committed Oct 10, 2015
    Copy the full SHA
    ba6218c View commit details
  3. Copy the full SHA
    0628437 View commit details
12 changes: 12 additions & 0 deletions spec/ruby/language/defined_spec.rb
Original file line number Diff line number Diff line change
@@ -755,10 +755,22 @@
defined?(DefinedSpecs::Child::B).should be_nil
end

it "returns nil when a constant is scoped to an undefined constant" do
defined?(Undefined::Object).should be_nil
end

it "returns nil when the undefined constant is scoped to an undefined constant" do
defined?(DefinedSpecs::Undefined::Undefined).should be_nil
end

it "returns nil when a constant is defined on top-level but not on the module" do
defined?(DefinedSpecs::String).should be_nil
end

it "returns 'constant' when a constant is defined on top-level but not on the class" do
defined?(DefinedSpecs::Basic::String).should == "constant"
end

it "returns 'constant' if the scoped-scoped constant is defined" do
defined?(DefinedSpecs::Child::A).should == "constant"
end
1 change: 0 additions & 1 deletion spec/truffle/tags/language/defined_tags.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -39,10 +39,12 @@
public abstract class LookupConstantNode extends RubyNode {

private final boolean ignoreVisibility;
private final boolean lookInObject;

public LookupConstantNode(RubyContext context, SourceSection sourceSection, boolean ignoreVisibility) {
public LookupConstantNode(RubyContext context, SourceSection sourceSection, boolean ignoreVisibility, boolean lookInObject) {
super(context, sourceSection);
this.ignoreVisibility = ignoreVisibility;
this.lookInObject = lookInObject;
}

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

protected RubyConstant doLookup(DynamicObject module, String name) {
return ModuleOperations.lookupConstant(getContext(), module, name);
if (lookInObject) {
return ModuleOperations.lookupConstantAndObject(getContext(), module, name);
} else {
return ModuleOperations.lookupConstant(getContext(), module, name);
}
}

protected boolean isVisible(DynamicObject module, RubyConstant constant) {
Original file line number Diff line number Diff line change
@@ -23,11 +23,11 @@ public class ReadConstantNode extends RubyNode implements RestartableReadConstan
@Child LookupConstantNode lookupConstantNode;
@Child GetConstantNode getConstantNode;

public ReadConstantNode(RubyContext context, SourceSection sourceSection, boolean ignoreVisibility, RubyNode moduleNode, RubyNode nameNode) {
public ReadConstantNode(RubyContext context, SourceSection sourceSection, boolean ignoreVisibility, boolean lookInObject, RubyNode moduleNode, RubyNode nameNode) {
super(context, sourceSection);
this.moduleNode = moduleNode;
this.nameNode = nameNode;
this.lookupConstantNode = LookupConstantNodeGen.create(context, sourceSection, ignoreVisibility, null, null);
this.lookupConstantNode = LookupConstantNodeGen.create(context, sourceSection, ignoreVisibility, lookInObject, null, null);
this.getConstantNode = GetConstantNodeGen.create(context, sourceSection, this, null, null, null);
}

Original file line number Diff line number Diff line change
@@ -20,7 +20,6 @@
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.StringSupport;

public class ReadConstantWithLexicalScopeNode extends RubyNode implements RestartableReadConstantNode {

Original file line number Diff line number Diff line change
@@ -10,17 +10,17 @@
package org.jruby.truffle.nodes.constants;

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

import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.nodes.RubyGuards;
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.StringOperations;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.StringSupport;

public class ReadLiteralConstantNode extends RubyNode {

@@ -29,7 +29,7 @@ public class ReadLiteralConstantNode extends RubyNode {
public ReadLiteralConstantNode(RubyContext context, SourceSection sourceSection, RubyNode moduleNode, String name) {
super(context, sourceSection);
RubyNode nameNode = new LiteralNode(context, sourceSection, name);
this.readConstantNode = new ReadConstantNode(context, sourceSection, false, moduleNode, nameNode);
this.readConstantNode = new ReadConstantNode(context, sourceSection, false, false, moduleNode, nameNode);
}

@Override
@@ -57,14 +57,15 @@ public Object isDefined(VirtualFrame frame) {
throw e;
}

if (!RubyGuards.isRubyModule(module)) {
return nil();
}

final RubyConstant constant;
try {
constant = readConstantNode.lookupConstantNode.executeLookupConstant(frame, module, name);
} catch (RaiseException e) {
if (Layouts.BASIC_OBJECT.getLogicalClass(e.getRubyException()) == context.getCoreLibrary().getTypeErrorClass()) {
// module is not a class/module
return nil();
} else if (Layouts.BASIC_OBJECT.getLogicalClass(e.getRubyException()) == context.getCoreLibrary().getNameErrorClass()) {
if (Layouts.BASIC_OBJECT.getLogicalClass(e.getRubyException()) == context.getCoreLibrary().getNameErrorClass()) {
// private constant
return nil();
}
Original file line number Diff line number Diff line change
@@ -886,11 +886,11 @@ public abstract static class ConstGetNode extends CoreMethodNode {

public ConstGetNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
this.readConstantNode = new ReadConstantNode(context, sourceSection, true, null, null);
this.readConstantNode = new ReadConstantNode(context, sourceSection, true, true, null, null);
}

@CreateCast("name")
public RubyNode coerceToString(RubyNode name) {
public RubyNode coerceToSymbolOrString(RubyNode name) {
return NameToSymbolOrStringNodeGen.create(getContext(), getSourceSection(), name);
}

@@ -900,12 +900,12 @@ public RubyNode coerceToBoolean(RubyNode inherit) {
}

// Symbol
@Specialization(guards = {"inherit", "isRubySymbol(name)"})
@Specialization(guards = { "inherit", "isRubySymbol(name)" })
public Object getConstant(VirtualFrame frame, DynamicObject module, DynamicObject name, boolean inherit) {
return readConstantNode.readConstant(frame, module, Layouts.SYMBOL.getString(name));
}

@Specialization(guards = {"!inherit", "isRubySymbol(name)"})
@Specialization(guards = { "!inherit", "isRubySymbol(name)" })
public Object getConstantNoInherit(DynamicObject module, DynamicObject name, boolean inherit) {
return getConstantNoInherit(module, Layouts.SYMBOL.getString(name), this);
}
Original file line number Diff line number Diff line change
@@ -1645,7 +1645,7 @@ public abstract static class GetIntegerConstantNode extends RubyNode {

public GetIntegerConstantNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readConstantNode = new ReadConstantNode(context, sourceSection, false, null, null);
readConstantNode = new ReadConstantNode(context, sourceSection, false, false, null, null);
toIntNode = ToIntNodeGen.create(context, sourceSection, null);
integerCastNode = IntegerCastNodeGen.create(context, sourceSection, null);
}
Original file line number Diff line number Diff line change
@@ -78,25 +78,6 @@ public static Map<String, RubyConstant> getAllConstants(DynamicObject module) {
return constants;
}

@TruffleBoundary
public static RubyConstant lookupConstantWithLexicalScope(RubyContext context, LexicalScope lexicalScope, String name) {
CompilerAsserts.neverPartOfCompilation();

final DynamicObject module = lexicalScope.getLiveModule();

// Look in lexical scope
while (lexicalScope != context.getRootLexicalScope()) {
RubyConstant constant = Layouts.MODULE.getFields(lexicalScope.getLiveModule()).getConstants().get(name);
if (constant != null) {
return constant;
}

lexicalScope = lexicalScope.getParent();
}

return lookupConstant(context, module, name);
}

@TruffleBoundary
public static RubyConstant lookupConstant(RubyContext context, DynamicObject module, String name) {
CompilerAsserts.neverPartOfCompilation();
@@ -116,11 +97,16 @@ public static RubyConstant lookupConstant(RubyContext context, DynamicObject mod
}
}

// Look in Object and its included modules
if (RubyGuards.isRubyModule(Layouts.MODULE.getFields(module).rubyModuleObject) && !RubyGuards.isRubyClass(Layouts.MODULE.getFields(module).rubyModuleObject)) {
// Nothing found
return null;
}

private static RubyConstant lookupConstantInObject(RubyContext context, DynamicObject module, String name) {
// Look in Object and its included modules for modules (not for classes)
if (!RubyGuards.isRubyClass(Layouts.MODULE.getFields(module).rubyModuleObject)) {
final DynamicObject objectClass = context.getCoreLibrary().getObjectClass();

constant = Layouts.MODULE.getFields(objectClass).getConstants().get(name);
RubyConstant constant = Layouts.MODULE.getFields(objectClass).getConstants().get(name);
if (constant != null) {
return constant;
}
@@ -133,10 +119,39 @@ public static RubyConstant lookupConstant(RubyContext context, DynamicObject mod
}
}

// Nothing found
return null;
}

public static RubyConstant lookupConstantAndObject(RubyContext context, DynamicObject module, String name) {
final RubyConstant constant = lookupConstant(context, module, name);
if (constant != null) {
return constant;
}

return lookupConstantInObject(context, module, name);
}

@TruffleBoundary
public static RubyConstant lookupConstantWithLexicalScope(RubyContext context, LexicalScope lexicalScope, String name) {
CompilerAsserts.neverPartOfCompilation();

final DynamicObject module = lexicalScope.getLiveModule();

RubyConstant constant = null;

// Look in lexical scope
while (lexicalScope != context.getRootLexicalScope()) {
constant = Layouts.MODULE.getFields(lexicalScope.getLiveModule()).getConstants().get(name);
if (constant != null) {
return constant;
}

lexicalScope = lexicalScope.getParent();
}

return lookupConstantAndObject(context, module, name);
}

public static RubyConstant lookupScopedConstant(RubyContext context, DynamicObject module, String fullName, boolean inherit, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();

@@ -178,7 +193,7 @@ public static RubyConstant lookupConstantWithInherit(RubyContext context, Dynami
}

if (inherit) {
return ModuleOperations.lookupConstant(context, module, name);
return ModuleOperations.lookupConstantAndObject(context, module, name);
} else {
return Layouts.MODULE.getFields(module).getConstants().get(name);
}
Original file line number Diff line number Diff line change
@@ -367,7 +367,6 @@ public void undefMethod(RubyContext context, Node currentNode, InternalMethod me
/**
* Also searches on Object for modules.
* Used for alias_method, visibility changes, etc.
* @param context TODO
*/
@CompilerDirectives.TruffleBoundary
public InternalMethod deepMethodSearch(RubyContext context, String name) {