Skip to content

Commit

Permalink
Showing 16 changed files with 169 additions and 93 deletions.
1 change: 1 addition & 0 deletions spec/truffle/tags/core/thread/raise_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Thread#raise on a sleeping thread raises the given exception and the backtrace is the one of the interrupted thread
2 changes: 1 addition & 1 deletion test/truffle/compiler/pe/core/eval_pe.rb
Original file line number Diff line number Diff line change
@@ -14,4 +14,4 @@

example "eval([1, 2, 3].inspect)[1]", 2

counter_example "eval(rand.to_s)"
tagged_counter_example "eval(rand.to_s)"
Original file line number Diff line number Diff line change
@@ -84,6 +84,7 @@
import org.jruby.truffle.language.backtrace.BacktraceFormatter;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.control.TruffleFatalException;
import org.jruby.truffle.language.loader.CodeLoader;
import org.jruby.truffle.language.methods.DeclarationContext;
import org.jruby.truffle.language.methods.InternalMethod;
import org.jruby.truffle.language.objects.FreezeNode;
@@ -766,7 +767,8 @@ public void initializeAfterBasicMethodsAdded() {
state = State.LOADING_RUBY_CORE;
try {
final RubyRootNode rootNode = context.getCodeLoader().parse(context.getSourceCache().getSource(getCoreLoadPath() + "/core.rb"), UTF8Encoding.INSTANCE, ParserContext.TOP_LEVEL, null, true, node);
context.getCodeLoader().execute(ParserContext.TOP_LEVEL, DeclarationContext.TOP_LEVEL, rootNode, null, context.getCoreLibrary().getMainObject());
final CodeLoader.DeferredCall deferredCall = context.getCodeLoader().prepareExecute(ParserContext.TOP_LEVEL, DeclarationContext.TOP_LEVEL, rootNode, null, context.getCoreLibrary().getMainObject());
deferredCall.getCallTarget().call(deferredCall.getArguments());
} catch (IOException e) {
throw new RuntimeException(e);
}
Original file line number Diff line number Diff line change
@@ -12,9 +12,11 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.CreateCast;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.Source;
@@ -39,6 +41,7 @@
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.language.dispatch.MissingBehavior;
import org.jruby.truffle.language.dispatch.RubyCallNode;
import org.jruby.truffle.language.loader.CodeLoader;
import org.jruby.truffle.language.methods.DeclarationContext;
import org.jruby.truffle.language.methods.InternalMethod;
import org.jruby.truffle.language.methods.UnsupportedOperationBehavior;
@@ -158,13 +161,13 @@ public InstanceEvalNode(RubyContext context, SourceSection sourceSection) {
yield = new YieldNode(context, DeclarationContext.INSTANCE_EVAL);
}

@CompilerDirectives.TruffleBoundary
@Specialization(guards = "isRubyString(string)")
public Object instanceEval(Object receiver, DynamicObject string, NotProvided block) {
public Object instanceEval(VirtualFrame frame, Object receiver, DynamicObject string, NotProvided block, @Cached("create()")IndirectCallNode callNode) {
ByteList code = StringOperations.getByteListReadOnly(string);
final Source source = Source.fromText(code, "(eval)");
final RubyRootNode rootNode = getContext().getCodeLoader().parse(source, code.getEncoding(), ParserContext.EVAL, null, true, this);
return getContext().getCodeLoader().execute(ParserContext.EVAL, DeclarationContext.INSTANCE_EVAL, rootNode, null, receiver);
final CodeLoader.DeferredCall deferredCall = getContext().getCodeLoader().prepareExecute(ParserContext.EVAL, DeclarationContext.INSTANCE_EVAL, rootNode, null, receiver);
return callNode.call(frame, deferredCall.getCallTarget(), deferredCall.getArguments());
}

@Specialization
13 changes: 11 additions & 2 deletions truffle/src/main/java/org/jruby/truffle/core/hash/HashNodes.java
Original file line number Diff line number Diff line change
@@ -45,6 +45,8 @@
import org.jruby.truffle.language.methods.InternalMethod;
import org.jruby.truffle.language.objects.AllocateObjectNode;
import org.jruby.truffle.language.objects.AllocateObjectNodeGen;
import org.jruby.truffle.language.yield.CallBlockNode;
import org.jruby.truffle.language.yield.CallBlockNodeGen;
import org.jruby.truffle.language.yield.YieldNode;

import java.util.Arrays;
@@ -1196,6 +1198,8 @@ public Object setDefault(DynamicObject hash, Object defaultValue) {
@ImportStatic(HashGuards.class)
public abstract static class ShiftNode extends CoreMethodArrayArgumentsNode {

@Child private YieldNode yieldNode;

public ShiftNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}
@@ -1211,8 +1215,13 @@ public Object shiftEmpyDefaultValue(DynamicObject hash) {
}

@Specialization(guards = {"isEmptyHash(hash)", "!hasDefaultValue(hash)", "hasDefaultBlock(hash)"})
public Object shiftEmptyDefaultProc(DynamicObject hash) {
return ProcNodes.rootCall(Layouts.HASH.getDefaultBlock(hash), hash, nil());
public Object shiftEmptyDefaultProc(VirtualFrame frame, DynamicObject hash) {
if (yieldNode == null) {
CompilerDirectives.transferToInterpreter();
yieldNode = insert(new YieldNode(getContext()));
}

return yieldNode.dispatch(frame, Layouts.HASH.getDefaultBlock(hash), hash, nil());
}

@Specialization(guards = {"!isEmptyHash(hash)", "isPackedHash(hash)"})
Original file line number Diff line number Diff line change
@@ -99,6 +99,7 @@
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.language.dispatch.DoesRespondDispatchHeadNode;
import org.jruby.truffle.language.dispatch.MissingBehavior;
import org.jruby.truffle.language.loader.CodeLoader;
import org.jruby.truffle.language.loader.FeatureLoader;
import org.jruby.truffle.language.loader.SourceLoader;
import org.jruby.truffle.language.methods.DeclarationContext;
@@ -600,11 +601,13 @@ public Object evalNoBindingCached(
"isRubyString(source)"
}, contains = "evalNoBindingCached")
public Object evalNoBindingUncached(VirtualFrame frame, DynamicObject source, NotProvided noBinding,
NotProvided filename, NotProvided lineNumber) {
NotProvided filename, NotProvided lineNumber, @Cached("create()") IndirectCallNode callNode) {
final DynamicObject binding = getCallerBinding(frame);
final MaterializedFrame topFrame = Layouts.BINDING.getFrame(binding);
RubyArguments.setSelf(topFrame.getArguments(), RubyArguments.getSelf(frame));
return doEval(source, binding, "(eval)", true);
final CodeLoader.DeferredCall deferredCall = doEvalX(source, binding, "(eval)", true);
return callNode.call(frame, deferredCall.getCallTarget(), deferredCall.getArguments());

}

@Specialization(guards = {
@@ -613,17 +616,18 @@ public Object evalNoBindingUncached(VirtualFrame frame, DynamicObject source, No
"isRubyString(filename)"
})
public Object evalNilBinding(VirtualFrame frame, DynamicObject source, DynamicObject noBinding,
DynamicObject filename, int lineNumber) {
return evalNoBindingUncached(frame, source, NotProvided.INSTANCE, NotProvided.INSTANCE, NotProvided.INSTANCE);
DynamicObject filename, int lineNumber, @Cached("create()") IndirectCallNode callNode) {
return evalNoBindingUncached(frame, source, NotProvided.INSTANCE, NotProvided.INSTANCE, NotProvided.INSTANCE, callNode);
}

@Specialization(guards = {
"isRubyString(source)",
"isRubyBinding(binding)"
})
public Object evalBinding(DynamicObject source, DynamicObject binding, NotProvided filename,
NotProvided lineNumber) {
return doEval(source, binding, "(eval)", false);
public Object evalBinding(VirtualFrame frame, DynamicObject source, DynamicObject binding, NotProvided filename,
NotProvided lineNumber, @Cached("create()") IndirectCallNode callNode) {
final CodeLoader.DeferredCall deferredCall = doEvalX(source, binding, "(eval)", false);
return callNode.call(frame, deferredCall.getCallTarget(), deferredCall.getArguments());
}

@Specialization(guards = {
@@ -632,18 +636,17 @@ public Object evalBinding(DynamicObject source, DynamicObject binding, NotProvid
"isNil(noFilename)",
"isNil(noLineNumber)"
})
public Object evalBinding(DynamicObject source, DynamicObject binding, DynamicObject noFilename, DynamicObject noLineNumber) {
return evalBinding(source, binding, NotProvided.INSTANCE, NotProvided.INSTANCE);
public Object evalBinding(VirtualFrame frame, DynamicObject source, DynamicObject binding, DynamicObject noFilename, DynamicObject noLineNumber, @Cached("create()") IndirectCallNode callNode) {
return evalBinding(frame, source, binding, NotProvided.INSTANCE, NotProvided.INSTANCE, callNode);
}

@TruffleBoundary
@Specialization(guards = {
"isRubyString(source)",
"isRubyBinding(binding)",
"isRubyString(filename)" })
public Object evalBindingFilename(DynamicObject source, DynamicObject binding, DynamicObject filename,
NotProvided lineNumber) {
return evalBindingFilenameLine(source, binding, filename, 0);
public Object evalBindingFilename(VirtualFrame frame, DynamicObject source, DynamicObject binding, DynamicObject filename,
NotProvided lineNumber, @Cached("create()") IndirectCallNode callNode) {
return evalBindingFilenameLine(frame, source, binding, filename, 0, callNode);
}

@Specialization(guards = {
@@ -652,18 +655,18 @@ public Object evalBindingFilename(DynamicObject source, DynamicObject binding, D
"isRubyString(filename)",
"isNil(noLineNumber)"
})
public Object evalBindingFilename(DynamicObject source, DynamicObject binding, DynamicObject filename, DynamicObject noLineNumber) {
return evalBindingFilename(source, binding, filename, NotProvided.INSTANCE);
public Object evalBindingFilename(VirtualFrame frame, DynamicObject source, DynamicObject binding, DynamicObject filename, DynamicObject noLineNumber, @Cached("create()") IndirectCallNode callNode) {
return evalBindingFilename(frame, source, binding, filename, NotProvided.INSTANCE, callNode);
}

@TruffleBoundary
@Specialization(guards = {
"isRubyString(source)",
"isRubyBinding(binding)",
"isRubyString(filename)" })
public Object evalBindingFilenameLine(DynamicObject source, DynamicObject binding, DynamicObject filename,
int lineNumber) {
return doEval(source, binding, filename.toString(), false);
public Object evalBindingFilenameLine(VirtualFrame frame, DynamicObject source, DynamicObject binding, DynamicObject filename,
int lineNumber, @Cached("create()") IndirectCallNode callNode) {
final CodeLoader.DeferredCall deferredCall = doEvalX(source, binding, filename.toString(), false);
return callNode.call(frame, deferredCall.getCallTarget(), deferredCall.getArguments());
}

@TruffleBoundary
@@ -676,15 +679,13 @@ public Object evalBadBinding(DynamicObject source, DynamicObject badBinding, Not
}

@TruffleBoundary
private Object doEval(DynamicObject source, DynamicObject binding, String filename, boolean ownScopeForAssignments) {
private CodeLoader.DeferredCall doEvalX(DynamicObject source, DynamicObject binding, String filename, boolean ownScopeForAssignments) {
ByteList code = StringOperations.getByteListReadOnly(source);
final Source source1 = Source.fromText(code, filename);
final MaterializedFrame frame = Layouts.BINDING.getFrame(binding);
final DeclarationContext declarationContext = RubyArguments.getDeclarationContext(frame);
final RubyRootNode rootNode = getContext().getCodeLoader().parse(source1, code.getEncoding(), ParserContext.EVAL, frame, ownScopeForAssignments, this);
final Object result = getContext().getCodeLoader().execute(ParserContext.EVAL, declarationContext, rootNode, frame, RubyArguments.getSelf(frame));
assert result != null;
return result;
return getContext().getCodeLoader().prepareExecute(ParserContext.EVAL, declarationContext, rootNode, frame, RubyArguments.getSelf(frame));
}

protected RootNodeWrapper compileSource(VirtualFrame frame, DynamicObject sourceText) {
@@ -1572,14 +1573,15 @@ public RubyNode coerceFeatureToPath(RubyNode feature) {
return ToPathNodeGen.create(getContext(), getSourceSection(), feature);
}

@TruffleBoundary
@Specialization(guards = "isRubyString(featureString)")
public boolean require(DynamicObject featureString) {
public boolean require(VirtualFrame frame, DynamicObject featureString, @Cached("create()") IndirectCallNode callNode) {
CompilerDirectives.transferToInterpreter();

final String feature = featureString.toString();

// Pysch loads either the jar or the so - we need to intercept
if (feature.equals("psych.so") && callerIs("psych.rb")) {
getContext().getFeatureLoader().require("truffle/psych.rb", this);
getContext().getFeatureLoader().require(frame, "truffle/psych.rb", callNode);
return true;
}

@@ -1588,7 +1590,7 @@ public boolean require(DynamicObject featureString) {
throw new RaiseException(coreLibrary().loadErrorCannotLoad(feature, this));
}

return getContext().getFeatureLoader().require(feature, this);
return getContext().getFeatureLoader().require(frame, feature, callNode);
}

private boolean callerIs(String caller) {
@@ -1604,9 +1606,10 @@ public RequireRelativeNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@TruffleBoundary
@Specialization(guards = "isRubyString(feature)")
public boolean requireRelative(DynamicObject feature) {
public boolean requireRelative(VirtualFrame frame, DynamicObject feature, @Cached("create()") IndirectCallNode callNode) {
CompilerDirectives.transferToInterpreter();

final FeatureLoader featureLoader = getContext().getFeatureLoader();

final String featureString = feature.toString();
@@ -1632,7 +1635,7 @@ public boolean requireRelative(DynamicObject feature) {
featurePath = dirname(sourcePath) + "/" + featureString;
}

featureLoader.require(featurePath, this);
featureLoader.require(frame, featurePath, callNode);

return true;
}
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@
import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.object.DynamicObject;
@@ -72,6 +73,7 @@
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.language.loader.CodeLoader;
import org.jruby.truffle.language.methods.AddMethodNode;
import org.jruby.truffle.language.methods.AddMethodNodeGen;
import org.jruby.truffle.language.methods.Arity;
@@ -633,36 +635,38 @@ protected DynamicObject toStr(VirtualFrame frame, Object object) {
}

@Specialization(guards = "isRubyString(code)")
public Object classEval(DynamicObject module, DynamicObject code, NotProvided file, NotProvided line, NotProvided block) {
return classEvalSource(module, code, "(eval)");
public Object classEval(VirtualFrame frame, DynamicObject module, DynamicObject code, NotProvided file, NotProvided line, NotProvided block, @Cached("create()") IndirectCallNode callNode) {
return classEvalSource(frame, module, code, "(eval)", callNode);
}

@Specialization(guards = {"isRubyString(code)", "isRubyString(file)"})
public Object classEval(DynamicObject module, DynamicObject code, DynamicObject file, NotProvided line, NotProvided block) {
return classEvalSource(module, code, file.toString());
public Object classEval(VirtualFrame frame, DynamicObject module, DynamicObject code, DynamicObject file, NotProvided line, NotProvided block, @Cached("create()") IndirectCallNode callNode) {
return classEvalSource(frame, module, code, file.toString(), callNode);
}

@Specialization(guards = {"isRubyString(code)", "isRubyString(file)"})
public Object classEval(DynamicObject module, DynamicObject code, DynamicObject file, int line, NotProvided block) {
return classEvalSource(module, code, file.toString(), line);
public Object classEval(VirtualFrame frame, DynamicObject module, DynamicObject code, DynamicObject file, int line, NotProvided block, @Cached("create()") IndirectCallNode callNode) {
final CodeLoader.DeferredCall deferredCall = classEvalSource(module, code, file.toString(), line);
return callNode.call(frame, deferredCall.getCallTarget(), deferredCall.getArguments());
}

@Specialization(guards = "wasProvided(code)")
public Object classEval(VirtualFrame frame, DynamicObject module, Object code, NotProvided file, NotProvided line, NotProvided block) {
return classEvalSource(module, toStr(frame, code), file.toString());
public Object classEval(VirtualFrame frame, DynamicObject module, Object code, NotProvided file, NotProvided line, NotProvided block, @Cached("create()") IndirectCallNode callNode) {
return classEvalSource(frame, module, toStr(frame, code), file.toString(), callNode);
}

@Specialization(guards = {"isRubyString(code)", "wasProvided(file)"})
public Object classEval(VirtualFrame frame, DynamicObject module, DynamicObject code, Object file, NotProvided line, NotProvided block) {
return classEvalSource(module, code, toStr(frame, file).toString());
public Object classEval(VirtualFrame frame, DynamicObject module, DynamicObject code, Object file, NotProvided line, NotProvided block, @Cached("create()") IndirectCallNode callNode) {
return classEvalSource(frame, module, code, toStr(frame, file).toString(), callNode);
}

private Object classEvalSource(DynamicObject module, DynamicObject code, String file) {
return classEvalSource(module, code, file, 1);
private Object classEvalSource(VirtualFrame frame, DynamicObject module, DynamicObject code, String file, @Cached("create()") IndirectCallNode callNode) {
final CodeLoader.DeferredCall deferredCall = classEvalSource(module, code, file, 1);
return callNode.call(frame, deferredCall.getCallTarget(), deferredCall.getArguments());
}

@TruffleBoundary
private Object classEvalSource(DynamicObject module, DynamicObject code, String file, int line) {
private CodeLoader.DeferredCall classEvalSource(DynamicObject module, DynamicObject code, String file, int line) {
assert RubyGuards.isRubyString(code);

final MaterializedFrame callerFrame = getContext().getCallStack().getCallerFrameIgnoringSend()
@@ -675,7 +679,7 @@ private Object classEvalSource(DynamicObject module, DynamicObject code, String
Source source = Source.fromText(space + code.toString(), file);

final RubyRootNode rootNode = getContext().getCodeLoader().parse(source, encoding, ParserContext.MODULE, callerFrame, true, this);
return getContext().getCodeLoader().execute(ParserContext.MODULE, DeclarationContext.CLASS_EVAL, rootNode, callerFrame, module);
return getContext().getCodeLoader().prepareExecute(ParserContext.MODULE, DeclarationContext.CLASS_EVAL, rootNode, callerFrame, module);
}

@Specialization
@@ -915,6 +919,7 @@ public abstract static class ConstGetNode extends CoreMethodNode {

@Child private ReadConstantNode readConstantNode;
@Child private KernelNodes.RequireNode requireNode;
@Child private IndirectCallNode indirectCallNode;

public ConstGetNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
@@ -938,8 +943,8 @@ public Object getConstant(VirtualFrame frame, DynamicObject module, DynamicObjec
}

@Specialization(guards = { "!inherit", "isRubySymbol(name)" })
public Object getConstantNoInherit(DynamicObject module, DynamicObject name, boolean inherit) {
return getConstantNoInherit(module, Layouts.SYMBOL.getString(name), this);
public Object getConstantNoInherit(VirtualFrame frame, DynamicObject module, DynamicObject name, boolean inherit) {
return getConstantNoInherit(frame, module, Layouts.SYMBOL.getString(name), this);
}

// String
@@ -949,8 +954,8 @@ public Object getConstantString(VirtualFrame frame, DynamicObject module, Dynami
}

@Specialization(guards = { "!inherit", "isRubyString(name)", "!isScoped(name)" })
public Object getConstantNoInheritString(DynamicObject module, DynamicObject name, boolean inherit) {
return getConstantNoInherit(module, name.toString(), this);
public Object getConstantNoInheritString(VirtualFrame frame, DynamicObject module, DynamicObject name, boolean inherit) {
return getConstantNoInherit(frame, module, name.toString(), this);
}

// Scoped String
@@ -959,16 +964,15 @@ public Object getConstantScoped(DynamicObject module, DynamicObject fullName, bo
return getConstantScoped(module, fullName.toString(), inherit);
}

@TruffleBoundary
private Object getConstantNoInherit(DynamicObject module, String name, Node currentNode) {
private Object getConstantNoInherit(VirtualFrame frame, DynamicObject module, String name, Node currentNode) {
RubyConstant constant = ModuleOperations.lookupConstantWithInherit(getContext(), module, name, false, currentNode);

if (constant == null) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(coreLibrary().nameErrorUninitializedConstant(module, name, this));
} else {
if (constant.isAutoload()) {
loadAutoloadedConstant(module, name, constant);
loadAutoloadedConstant(frame, constant);
constant = ModuleOperations.lookupConstantWithInherit(getContext(), module, name, false, currentNode);
}

@@ -994,13 +998,18 @@ boolean isScoped(DynamicObject name) {
return name.toString().contains("::");
}

private void loadAutoloadedConstant(DynamicObject module, String name, RubyConstant constant) {
private void loadAutoloadedConstant(VirtualFrame frame, RubyConstant constant) {
if (requireNode == null) {
CompilerDirectives.transferToInterpreter();
requireNode = insert(KernelNodesFactory.RequireNodeFactory.create(getContext(), getSourceSection(), null));
}

requireNode.require((DynamicObject) constant.getValue());
if (indirectCallNode == null) {
CompilerDirectives.transferToInterpreter();
indirectCallNode = insert(IndirectCallNode.create());
}

requireNode.require(frame, (DynamicObject) constant.getValue(), indirectCallNode);
}

}
Original file line number Diff line number Diff line change
@@ -14,12 +14,14 @@
import com.oracle.truffle.api.RootCallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.TruffleOptions;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.FrameInstanceVisitor;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrument.Instrument;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.Source;
@@ -53,6 +55,7 @@
import org.jruby.truffle.language.RubyRootNode;
import org.jruby.truffle.language.backtrace.BacktraceFormatter;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.loader.CodeLoader;
import org.jruby.truffle.language.loader.SourceLoader;
import org.jruby.truffle.language.methods.DeclarationContext;
import org.jruby.truffle.language.methods.InternalMethod;
@@ -833,16 +836,16 @@ public LoadNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@TruffleBoundary
@Specialization(guards = "isRubyString(file)")
public boolean load(DynamicObject file, boolean wrap) {
public boolean load(VirtualFrame frame, DynamicObject file, boolean wrap, @Cached("create()") IndirectCallNode callNode) {
if (wrap) {
throw new UnsupportedOperationException();
}

try {
final RubyRootNode rootNode = getContext().getCodeLoader().parse(getContext().getSourceCache().getSource(StringOperations.getString(getContext(), file)), UTF8Encoding.INSTANCE, ParserContext.TOP_LEVEL, null, true, this);
getContext().getCodeLoader().execute(ParserContext.TOP_LEVEL, DeclarationContext.TOP_LEVEL, rootNode, null, getContext().getCoreLibrary().getMainObject());
final CodeLoader.DeferredCall deferredCall = getContext().getCodeLoader().prepareExecute(ParserContext.TOP_LEVEL, DeclarationContext.TOP_LEVEL, rootNode, null, getContext().getCoreLibrary().getMainObject());
callNode.call(frame, deferredCall.getCallTarget(), deferredCall.getArguments());
} catch (IOException e) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(coreLibrary().loadErrorCannotLoad(file.toString(), this));
@@ -852,8 +855,8 @@ public boolean load(DynamicObject file, boolean wrap) {
}

@Specialization(guards = "isRubyString(file)")
public boolean load(DynamicObject file, NotProvided wrap) {
return load(file, false);
public boolean load(VirtualFrame frame, DynamicObject file, NotProvided wrap, @Cached("create()") IndirectCallNode callNode) {
return load(frame, file, false, callNode);
}
}

@@ -865,7 +868,7 @@ public RunJRubyRootNode(RubyContext context, SourceSection sourceSection) {
}

@Specialization
public Object runJRubyRootNode() {
public Object runJRubyRootNode(VirtualFrame frame, @Cached("create()")IndirectCallNode callNode) {
coreLibrary().getGlobalVariablesObject().define(
"$0",
StringOperations.createString(getContext(),
@@ -893,12 +896,14 @@ public Object runJRubyRootNode() {
true,
null);

return getContext().getCodeLoader().execute(
final CodeLoader.DeferredCall deferredCall = getContext().getCodeLoader().prepareExecute(
ParserContext.TOP_LEVEL,
DeclarationContext.TOP_LEVEL,
rootNode,
null,
coreLibrary().getMainObject());

return callNode.call(frame, deferredCall.getCallTarget(), deferredCall.getArguments());
}
}

Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.Source;
@@ -529,12 +530,12 @@ public Object evalCached(
return callNode.call(frame, new Object[]{});
}

@TruffleBoundary
@Specialization(guards = {"isRubyString(mimeType)", "isRubyString(source)"}, contains = "evalCached")
public Object evalUncached(DynamicObject mimeType, DynamicObject source) {
return parse(mimeType, source).call();
public Object evalUncached(VirtualFrame frame, DynamicObject mimeType, DynamicObject source, @Cached("create()")IndirectCallNode callNode) {
return callNode.call(frame, parse(mimeType, source), new Object[]{});
}

@TruffleBoundary
protected CallTarget parse(DynamicObject mimeType, DynamicObject source) {
final String mimeTypeString = mimeType.toString();
final Source sourceObject = Source.fromText(source.toString(), "(eval)").withMimeType(mimeTypeString);
Original file line number Diff line number Diff line change
@@ -164,6 +164,12 @@ public Object visitFrame(FrameInstance frameInstance) {

});

// TODO CS 3-Mar-16 The last activation is I think what calls jruby_root_node, and I can't seem to remove it any other way

if (!activations.isEmpty()) {
activations.remove(activations.size() - 1);
}

if (context.getOptions().EXCEPTIONS_STORE_JAVA || context.getOptions().BACKTRACES_INTERLEAVE_JAVA) {
if (javaThrowable == null) {
javaThrowable = new Exception();
@@ -190,8 +196,7 @@ private boolean ignoreFrame(FrameInstance frameInstance) {

final SourceSection sourceSection = callNode.getEncapsulatingSourceSection();

if (sourceSection != null && sourceSection.getSource() != null
&& sourceSection.getSource().getName().equals("run_jruby_root")) {
if (sourceSection != null && sourceSection.getShortDescription().endsWith("#run_jruby_root")) {
return true;
}

Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@
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.nodes.IndirectCallNode;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.source.SourceSection;
@@ -50,15 +51,16 @@ protected Object getConstant(DynamicObject module, String name, RubyConstant con
@Specialization(guards = { "constant != null", "constant.isAutoload()" })
protected Object autoloadConstant(VirtualFrame frame, DynamicObject module, String name, RubyConstant constant,
@Cached("createRequireNode()") RequireNode requireNode,
@Cached("deepCopyReadConstantNode()") RestartableReadConstantNode readConstantNode) {
@Cached("deepCopyReadConstantNode()") RestartableReadConstantNode readConstantNode,
@Cached("create()")IndirectCallNode callNode) {

final DynamicObject path = (DynamicObject) 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.
Layouts.MODULE.getFields(constant.getDeclaringModule()).removeConstant(getContext(), this, name);
try {
requireNode.require(path);
requireNode.require(frame, path, callNode);
return readConstantNode.readConstant(frame, module, name);
} catch (RaiseException e) {
Layouts.MODULE.getFields(constant.getDeclaringModule()).setAutoloadConstant(getContext(), this, name, path);
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ public RubyRootNode parse(Source source,
}

@TruffleBoundary
public Object execute(ParserContext parserContext,
public DeferredCall prepareExecute(ParserContext parserContext,
DeclarationContext declarationContext,
RubyRootNode rootNode,
MaterializedFrame parentFrame,
@@ -77,7 +77,7 @@ public Object execute(ParserContext parserContext,
Visibility.PUBLIC,
callTarget);

return callTarget.call(RubyArguments.pack(
return new DeferredCall(callTarget, RubyArguments.pack(
parentFrame,
null,
method,
@@ -129,12 +129,33 @@ public Object inline(Node currentNode, Frame frame, String expression, Object...
true,
currentNode);

return context.getCodeLoader().execute(
final DeferredCall deferredCall = context.getCodeLoader().prepareExecute(
ParserContext.INLINE,
DeclarationContext.INSTANCE_EVAL,
rootNode,
evalFrame,
RubyArguments.getSelf(evalFrame));

return deferredCall.getCallTarget().call(deferredCall.getArguments());
}

public static class DeferredCall {

private final CallTarget callTarget;
private final Object[] arguments;

public DeferredCall(CallTarget callTarget, Object[] arguments) {
this.callTarget = callTarget;
this.arguments = arguments;
}

public CallTarget getCallTarget() {
return callTarget;
}

public Object[] getArguments() {
return arguments;
}
}

}
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@
*/
package org.jruby.truffle.language.loader;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.Source;
@@ -35,14 +37,14 @@ public FeatureLoader(RubyContext context) {
this.context = context;
}

public boolean require(String feature, Node currentNode) {
public boolean require(VirtualFrame frame, String feature, IndirectCallNode callNode) {
final String featurePath = findFeature(feature);

if (featurePath == null) {
throw new RaiseException(context.getCoreLibrary().loadErrorCannotLoad(feature, currentNode));
throw new RaiseException(context.getCoreLibrary().loadErrorCannotLoad(feature, callNode));
}

return doRequire(featurePath, currentNode);
return doRequire(frame, featurePath, callNode);
}

private String findFeature(String feature) {
@@ -110,7 +112,7 @@ private String findFeatureWithExactPath(String path) {
}
}

private boolean doRequire(String expandedPath, Node currentNode) {
private boolean doRequire(VirtualFrame frame, String expandedPath, IndirectCallNode calNode) {
if (isFeatureLoaded(expandedPath)) {
return false;
}
@@ -135,13 +137,15 @@ private boolean doRequire(String expandedPath, Node currentNode) {
ParserContext.TOP_LEVEL,
null,
true,
currentNode);
calNode);

context.getCodeLoader().execute(
final CodeLoader.DeferredCall deferredCall = context.getCodeLoader().prepareExecute(
ParserContext.TOP_LEVEL,
DeclarationContext.TOP_LEVEL,
rootNode, null,
context.getCoreLibrary().getMainObject());

calNode.call(frame, deferredCall.getCallTarget(), deferredCall.getArguments());
} catch (RaiseException e) {
removeFromLoadedFeatures(pathString);
throw e;
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -32,6 +33,7 @@ public class DefineClassNode extends RubyNode {
@Child private RubyNode superClass;
@Child private CallDispatchHeadNode inheritedNode;
@Child private RubyNode lexicalParentModule;
@Child private IndirectCallNode indirectCallNode;

private final ConditionProfile needToDefineProfile = ConditionProfile.createBinaryProfile();
private final BranchProfile errorProfile = BranchProfile.create();
@@ -42,6 +44,7 @@ public DefineClassNode(RubyContext context, SourceSection sourceSection, String
this.name = name;
this.lexicalParentModule = lexicalParent;
this.superClass = superClass;
indirectCallNode = IndirectCallNode.create();
}

@Override
@@ -56,7 +59,7 @@ public Object execute(VirtualFrame frame) {
DynamicObject lexicalParentModule = (DynamicObject) lexicalParentObject;

final RubyConstant constant = DefineModuleNode.lookupForExistingModule(
getContext(), name, lexicalParentModule, this);
frame, getContext(), name, lexicalParentModule, indirectCallNode);

final DynamicObject definingClass;
final Object superClassObject = superClass.execute(frame);
Original file line number Diff line number Diff line change
@@ -9,8 +9,10 @@
*/
package org.jruby.truffle.language.objects;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.IndirectCallNode;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -29,6 +31,7 @@ public class DefineModuleNode extends RubyNode {
private final String name;

@Child private RubyNode lexicalParentModule;
@Child private IndirectCallNode indirectCallNode;

private final ConditionProfile needToDefineProfile = ConditionProfile.createBinaryProfile();
private final BranchProfile errorProfile = BranchProfile.create();
@@ -37,6 +40,7 @@ public DefineModuleNode(RubyContext context, SourceSection sourceSection, String
super(context, sourceSection);
this.name = name;
this.lexicalParentModule = lexicalParent;
indirectCallNode = IndirectCallNode.create();
}

@Override
@@ -49,7 +53,7 @@ public Object execute(VirtualFrame frame) {
}

final DynamicObject lexicalParentModule = (DynamicObject) lexicalParentObject;
final RubyConstant constant = lookupForExistingModule(getContext(), name, lexicalParentModule, this);
final RubyConstant constant = lookupForExistingModule(frame, getContext(), name, lexicalParentModule, indirectCallNode);

final DynamicObject definingModule;

@@ -70,9 +74,10 @@ public Object execute(VirtualFrame frame) {
return definingModule;
}

@TruffleBoundary
public static RubyConstant lookupForExistingModule(RubyContext context, String name,
DynamicObject lexicalParent, RubyNode node) {
public static RubyConstant lookupForExistingModule(VirtualFrame frame, RubyContext context, String name,
DynamicObject lexicalParent, IndirectCallNode callNode) {
CompilerDirectives.transferToInterpreter();

RubyConstant constant = Layouts.MODULE.getFields(lexicalParent).getConstant(name);

final DynamicObject objectClass = context.getCoreLibrary().getObjectClass();
@@ -88,7 +93,7 @@ public static RubyConstant lookupForExistingModule(RubyContext context, String n
}

if (constant != null && !constant.isVisibleTo(context, LexicalScope.NONE, lexicalParent)) {
throw new RaiseException(context.getCoreLibrary().nameErrorPrivateConstant(lexicalParent, name, node));
throw new RaiseException(context.getCoreLibrary().nameErrorPrivateConstant(lexicalParent, name, callNode));
}

// If a constant already exists with this class/module name and it's an autoload module, we have to trigger
@@ -100,9 +105,9 @@ public static RubyConstant lookupForExistingModule(RubyContext context, String n
// the constant here rather than just overwrite it in order to prevent autoload loops in either the require
// call or the recursive execute call.

Layouts.MODULE.getFields(lexicalParent).removeConstant(context, node, name);
context.getFeatureLoader().require(constant.getValue().toString(), node);
return lookupForExistingModule(context, name, lexicalParent, node);
Layouts.MODULE.getFields(lexicalParent).removeConstant(context, callNode, name);
context.getFeatureLoader().require(frame, constant.getValue().toString(), callNode);
return lookupForExistingModule(frame, context, name, lexicalParent, callNode);
}

return constant;
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@
import org.jruby.truffle.language.backtrace.Activation;
import org.jruby.truffle.language.backtrace.BacktraceFormatter;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.loader.CodeLoader;
import org.jruby.truffle.language.parser.ParserContext;

import java.io.IOException;
@@ -113,12 +114,14 @@ public void run(MaterializedFrame frame, Node currentNode) {
false,
currentNode);

final Object result = context.getCodeLoader().execute(
final CodeLoader.DeferredCall deferredCall = context.getCodeLoader().prepareExecute(
ParserContext.EVAL,
RubyArguments.getDeclarationContext(currentFrame.getArguments()),
rootNode, currentFrame,
RubyArguments.getSelf(currentFrame.getArguments()));

final Object result = deferredCall.getCallTarget().call(deferredCall.getArguments());

String inspected;

try {

0 comments on commit fbf5e53

Please sign in to comment.