Skip to content

Commit

Permalink
Showing 10 changed files with 86 additions and 108 deletions.
Original file line number Diff line number Diff line change
@@ -10,6 +10,9 @@
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.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.nodes.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.runtime.RubyConstant;
@@ -29,8 +32,11 @@
@NodeChildren({ @NodeChild("module"), @NodeChild("name"), @NodeChild("constant") })
public abstract class GetConstantNode extends RubyNode {

public GetConstantNode(RubyContext context, SourceSection sourceSection) {
private final RestartableReadConstantNode readConstantNode;

public GetConstantNode(RubyContext context, SourceSection sourceSection, RestartableReadConstantNode readConstantNode) {
super(context, sourceSection);
this.readConstantNode = readConstantNode;
}

public abstract Object executeGetConstant(VirtualFrame frame, Object module, String name, RubyConstant constant);
@@ -40,6 +46,25 @@ protected Object getConstant(RubyBasicObject module, String name, RubyConstant c
return constant.getValue();
}

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

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 readConstantNode.readConstant(frame, module, name);
} catch (RaiseException e) {
ModuleNodes.getModel(constant.getDeclaringModule()).setAutoloadConstant(this, name, path);
throw e;
}
}

@Specialization(guards = "constant == null")
protected Object missingConstant(VirtualFrame frame, RubyBasicObject module, String name, Object constant,
@Cached("isValidConstantName(name)") boolean isValidConstantName,
@@ -52,6 +77,14 @@ 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 RestartableReadConstantNode deepCopyReadConstantNode() {
return (RestartableReadConstantNode) readConstantNode.deepCopy();
}

protected boolean isValidConstantName(String name) {
return IdUtil.isValidConstantName19(name);
}
Original file line number Diff line number Diff line change
@@ -32,7 +32,6 @@
/**
* Caches {@link ModuleOperations#lookupConstant}
* and checks visibility.
* The {@link LexicalScope} is constant here.
*/
@NodeChildren({ @NodeChild("module"), @NodeChild("name") })
public abstract class LookupConstantNode extends RubyNode {
Original file line number Diff line number Diff line change
@@ -10,74 +10,40 @@
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.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.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 {
public class ReadConstantNode extends RubyNode implements RestartableReadConstantNode {

@Child protected LookupConstantNode lookupConstantNode;
@Child private GetConstantNode getConstantNode;
@Child RubyNode moduleNode;
@Child RubyNode nameNode;

@Child private RequireNode requireNode;
@Child LookupConstantNode lookupConstantNode;
@Child GetConstantNode getConstantNode;

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

public abstract RubyNode getName();
public abstract RubyNode getModule();

public abstract Object executeReadConstant(VirtualFrame frame, Object module, String name);
@Override
public Object execute(VirtualFrame frame) {
final String name = (String) nameNode.execute(frame);
final Object module = moduleNode.execute(frame);
return readConstant(frame, module, name);
}

@Specialization
@Override
public Object readConstant(VirtualFrame frame, Object module, String name) {
final RubyConstant constant = lookupConstantNode.executeLookupConstant(frame, module, name);

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

return getConstantNode.executeGetConstant(frame, module, name, 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 {
require(path);
return readConstant(frame, module, name); // 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);
}

}
Original file line number Diff line number Diff line change
@@ -10,9 +10,6 @@
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;
@@ -23,56 +20,32 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;

public class ReadConstantWithLexicalScopeNode extends RubyNode {
public class ReadConstantWithLexicalScopeNode extends RubyNode implements RestartableReadConstantNode {

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);
this.getConstantNode = GetConstantNodeGen.create(context, sourceSection, this, null, null, null);
}

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

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;
}
return getConstantNode.executeGetConstant(frame, module, name, constant);
}

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 readConstant(VirtualFrame frame, Object module, String name) {
return execute(frame);
}

@Override
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ public class ReadLiteralConstantNode extends RubyNode {
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);
this.readConstantNode = new ReadConstantNode(context, sourceSection, module, nameNode);
}

@Override
@@ -40,7 +40,7 @@ public Object isDefined(VirtualFrame frame) {
CompilerDirectives.transferToInterpreter();

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

if (name.equals("Encoding")) {
// Work-around so I don't have to load the iconv library - runners/formatters/junit.rb.
@@ -49,7 +49,7 @@ public Object isDefined(VirtualFrame frame) {

final Object moduleObject;
try {
moduleObject = readConstantNode.getModule().execute(frame);
moduleObject = readConstantNode.moduleNode.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).
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;

public interface RestartableReadConstantNode {

public Node deepCopy();

public Object readConstant(VirtualFrame frame, Object module, String name);

}
Original file line number Diff line number Diff line change
@@ -38,11 +38,7 @@
import org.jruby.truffle.nodes.cast.BooleanCastWithDefaultNodeGen;
import org.jruby.truffle.nodes.cast.TaintResultNode;
import org.jruby.truffle.nodes.coerce.*;
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;
@@ -898,7 +894,7 @@ public abstract static class ConstGetNode extends CoreMethodNode {

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

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

@Specialization(guards = {"!inherit", "isRubySymbol(name)"})
@@ -925,7 +921,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 readConstantNode.executeReadConstant(frame, module, name.toString());
return readConstantNode.readConstant(frame, module, name.toString());
}

@Specialization(guards = { "!inherit", "isRubyString(name)", "!isScoped(name)" })
Original file line number Diff line number Diff line change
@@ -28,11 +28,7 @@
import org.jruby.truffle.nodes.cast.IntegerCastNodeGen;
import org.jruby.truffle.nodes.coerce.ToIntNode;
import org.jruby.truffle.nodes.coerce.ToIntNodeGen;
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;
@@ -41,9 +37,7 @@
import org.jruby.truffle.nodes.ext.BigDecimalNodesFactory.CreateBigDecimalNodeFactory;
import org.jruby.truffle.nodes.ext.BigDecimalNodesFactory.GetIntegerConstantNodeGen;
import org.jruby.truffle.nodes.internal.UnreachableCodeBranch;
import org.jruby.truffle.nodes.literal.LiteralNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.LexicalScope;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
@@ -1705,7 +1699,7 @@ public abstract static class GetIntegerConstantNode extends RubyNode {

public GetIntegerConstantNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readConstantNode = ReadConstantNodeGen.create(context, sourceSection, null, null);
readConstantNode = new ReadConstantNode(context, sourceSection, null, null);
toIntNode = ToIntNodeGen.create(context, sourceSection, null);
integerCastNode = IntegerCastNodeGen.create(context, sourceSection, null);
}
@@ -1714,7 +1708,7 @@ public GetIntegerConstantNode(RubyContext context, SourceSection sourceSection)

@Specialization(guards = "isRubyModule(module)")
public int doInteger(VirtualFrame frame, RubyBasicObject module, String name) {
final Object value = readConstantNode.executeReadConstant(frame, module, name);
final Object value = readConstantNode.readConstant(frame, module, name);
return integerCastNode.executeInteger(frame, toIntNode.executeIntOrLong(frame, value));
}
}
Original file line number Diff line number Diff line change
@@ -14,13 +14,10 @@

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;
import org.jruby.truffle.runtime.LexicalScope;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;

Original file line number Diff line number Diff line change
@@ -27,7 +27,6 @@
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;

0 comments on commit 883e8db

Please sign in to comment.