Skip to content

Commit

Permalink
[Truffle] Add current node information to safepoint actions; use it t…
Browse files Browse the repository at this point in the history
…o properly implement backtrace command in debugger.
  • Loading branch information
chrisseaton committed Feb 28, 2015
1 parent 766e5e4 commit 9710b08
Show file tree
Hide file tree
Showing 42 changed files with 195 additions and 119 deletions.
Expand Up @@ -50,7 +50,7 @@ public boolean isCloningAllowed() {

@Override
public Object execute(VirtualFrame frame) {
context.getSafepointManager().poll();
context.getSafepointManager().poll(this);
return body.execute(frame);
}

Expand Down
Expand Up @@ -66,7 +66,7 @@ public Object execute(VirtualFrame frame) {
try {
return handleException(frame, exception);
} catch (RetryException e) {
getContext().getSafepointManager().poll();
getContext().getSafepointManager().poll(this);
continue;
}
} finally {
Expand Down
Expand Up @@ -87,7 +87,7 @@ public boolean executeRepeating(VirtualFrame frame) {
}

while (true) { // for redo
context.getSafepointManager().poll();
context.getSafepointManager().poll(this);
try {
body.execute(frame);
return true;
Expand All @@ -111,7 +111,7 @@ public DoWhileRepeatingNode(RubyContext context, RubyNode condition, RubyNode bo

@Override
public boolean executeRepeating(VirtualFrame frame) {
context.getSafepointManager().poll();
context.getSafepointManager().poll(this);
try {
body.execute(frame);
} catch (NextException e) {
Expand Down
Expand Up @@ -17,6 +17,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.Node;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;
Expand Down Expand Up @@ -392,7 +393,7 @@ public RubyNilClass attrReader(RubyModule module, Object[] args) {
return getContext().getCoreLibrary().getNilObject();
}

public static void attrReader(RubyNode currentNode, RubyContext context, SourceSection sourceSection, RubyModule module, String name) {
public static void attrReader(Node currentNode, RubyContext context, SourceSection sourceSection, RubyModule module, String name) {
CompilerDirectives.transferToInterpreter();

final CheckArityNode checkArity = new CheckArityNode(context, sourceSection, new Arity(0, 0, false, false));
Expand Down Expand Up @@ -444,7 +445,7 @@ public RubyNilClass attrWriter(RubyModule module, Object[] args) {
return getContext().getCoreLibrary().getNilObject();
}

public static void attrWriter(RubyNode currentNode, RubyContext context, SourceSection sourceSection, RubyModule module, String name) {
public static void attrWriter(Node currentNode, RubyContext context, SourceSection sourceSection, RubyModule module, String name) {
CompilerDirectives.transferToInterpreter();

final CheckArityNode checkArity = new CheckArityNode(context, sourceSection, new Arity(1, 0, false, false));
Expand Down Expand Up @@ -497,7 +498,7 @@ public RubyNilClass attrAccessor(RubyModule module, Object[] args) {
return getContext().getCoreLibrary().getNilObject();
}

public static void attrAccessor(RubyNode currentNode, RubyContext context, SourceSection sourceSection, RubyModule module, String name) {
public static void attrAccessor(Node currentNode, RubyContext context, SourceSection sourceSection, RubyModule module, String name) {
CompilerDirectives.transferToInterpreter();
AttrReaderNode.attrReader(currentNode, context, sourceSection, module, name);
AttrWriterNode.attrWriter(currentNode, context, sourceSection, module, name);
Expand Down
Expand Up @@ -12,6 +12,7 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.RubyThread.Status;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
Expand All @@ -22,6 +23,7 @@
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.control.ThreadExitException;
import org.jruby.truffle.runtime.core.*;
import org.jruby.truffle.runtime.subsystems.SafepointAction;
import org.jruby.truffle.runtime.util.Consumer;

@CoreClass(name = "Thread")
Expand Down Expand Up @@ -97,10 +99,10 @@ public KillNode(KillNode prev) {

@Specialization
public RubyThread kill(final RubyThread thread) {
getContext().getSafepointManager().pauseAllThreadsAndExecute(new Consumer<RubyThread>() {
getContext().getSafepointManager().pauseAllThreadsAndExecute(this, new SafepointAction() {

@Override
public void accept(RubyThread currentThread) {
public void run(RubyThread currentThread, Node currentNode) {
if (currentThread == thread) {
currentThread.exit();
}
Expand Down Expand Up @@ -215,10 +217,10 @@ public RubyNilClass raise(VirtualFrame frame, final RubyThread thread, RubyClass

final RaiseException exceptionWrapper = new RaiseException((RubyException) exception);

getContext().getSafepointManager().pauseAllThreadsAndExecute(new Consumer<RubyThread>() {
getContext().getSafepointManager().pauseAllThreadsAndExecute(this, new SafepointAction() {

@Override
public void accept(RubyThread currentThread) {
public void run(RubyThread currentThread, Node currentNode) {
if (currentThread == thread) {
throw exceptionWrapper;
}
Expand Down
Expand Up @@ -35,7 +35,7 @@ public Object execute(VirtualFrame frame) {
return body.execute(frame);
} catch (RedoException e) {
redoProfile.enter();
getContext().getSafepointManager().poll();
getContext().getSafepointManager().poll(this);
continue;
}
}
Expand Down
Expand Up @@ -9,6 +9,7 @@
*/
package org.jruby.truffle.nodes.objects;

import com.oracle.truffle.api.nodes.Node;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;
Expand All @@ -17,6 +18,6 @@
public interface Allocator {

// TODO(CS): do we need all these parameters?
RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode);
RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode);

}
Expand Up @@ -12,6 +12,7 @@
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;

import com.oracle.truffle.api.nodes.Node;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.core.RubyClass;
import org.jruby.truffle.runtime.core.RubyModule;
Expand Down Expand Up @@ -248,7 +249,7 @@ public static Object lookupClassVariable(RubyModule module, String name) {
}

@TruffleBoundary
public static void setClassVariable(RubyModule module, String name, Object value, RubyNode currentNode) {
public static void setClassVariable(RubyModule module, String name, Object value, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();

// Look in the current module
Expand Down
23 changes: 12 additions & 11 deletions truffle/src/main/java/org/jruby/truffle/runtime/RubyContext.java
Expand Up @@ -12,6 +12,7 @@
import com.oracle.truffle.api.*;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.source.BytesDecoder;
import com.oracle.truffle.api.source.Source;
Expand Down Expand Up @@ -122,7 +123,7 @@ public Shape getEmptyShape() {
return emptyShape;
}

public static String checkInstanceVariableName(RubyContext context, String name, RubyNode currentNode) {
public static String checkInstanceVariableName(RubyContext context, String name, Node currentNode) {
RubyNode.notDesignedForCompilation();

if (!name.startsWith("@")) {
Expand All @@ -133,7 +134,7 @@ public static String checkInstanceVariableName(RubyContext context, String name,
return name;
}

public static String checkClassVariableName(RubyContext context, String name, RubyNode currentNode) {
public static String checkClassVariableName(RubyContext context, String name, Node currentNode) {
RubyNode.notDesignedForCompilation();

if (!name.startsWith("@@")) {
Expand All @@ -148,15 +149,15 @@ public boolean isRunningOnWindows() {
return runningOnWindows;
}

public void loadFile(String fileName, RubyNode currentNode) {
public void loadFile(String fileName, Node currentNode) {
if (new File(fileName).isAbsolute()) {
loadFileAbsolute(fileName, currentNode);
} else {
loadFileAbsolute(this.getRuntime().getCurrentDirectory() + File.separator + fileName, currentNode);
}
}

private void loadFileAbsolute(String fileName, RubyNode currentNode) {
private void loadFileAbsolute(String fileName, Node currentNode) {
final byte[] bytes = FileUtils.readAllBytesInterruptedly(this, fileName);

// Assume UTF-8 for the moment
Expand All @@ -165,7 +166,7 @@ private void loadFileAbsolute(String fileName, RubyNode currentNode) {
load(source, currentNode, NodeWrapper.IDENTITY);
}

public void load(Source source, RubyNode currentNode, final NodeWrapper nodeWrapper) {
public void load(Source source, Node currentNode, final NodeWrapper nodeWrapper) {
final NodeWrapper loadWrapper = new NodeWrapper() {
@Override
public RubyNode wrap(RubyNode node) {
Expand Down Expand Up @@ -204,7 +205,7 @@ public RubySymbol newSymbol(ByteList name) {
}

@TruffleBoundary
public Object instanceEval(ByteList code, Object self, String filename, RubyNode currentNode) {
public Object instanceEval(ByteList code, Object self, String filename, Node currentNode) {
final Source source = Source.fromText(code, filename);
return execute(source, code.getEncoding(), TranslatorDriver.ParserContext.EVAL, self, null, currentNode, new NodeWrapper() {
@Override
Expand All @@ -214,26 +215,26 @@ public RubyNode wrap(RubyNode node) {
});
}

public Object instanceEval(ByteList code, Object self, RubyNode currentNode) {
public Object instanceEval(ByteList code, Object self, Node currentNode) {
return instanceEval(code, self, "(eval)", currentNode);
}

@TruffleBoundary
public Object eval(ByteList code, RubyBinding binding, boolean ownScopeForAssignments, String filename, RubyNode currentNode) {
public Object eval(ByteList code, RubyBinding binding, boolean ownScopeForAssignments, String filename, Node currentNode) {
final Source source = Source.fromText(code, filename);
return execute(source, code.getEncoding(), TranslatorDriver.ParserContext.EVAL, binding.getSelf(), binding.getFrame(), ownScopeForAssignments, currentNode, NodeWrapper.IDENTITY);
}

public Object eval(ByteList code, RubyBinding binding, boolean ownScopeForAssignments, RubyNode currentNode) {
public Object eval(ByteList code, RubyBinding binding, boolean ownScopeForAssignments, Node currentNode) {
return eval(code, binding, ownScopeForAssignments, "(eval)", currentNode);
}

public Object execute(Source source, Encoding defaultEncoding, TranslatorDriver.ParserContext parserContext, Object self, MaterializedFrame parentFrame, RubyNode currentNode, NodeWrapper wrapper) {
public Object execute(Source source, Encoding defaultEncoding, TranslatorDriver.ParserContext parserContext, Object self, MaterializedFrame parentFrame, Node currentNode, NodeWrapper wrapper) {
return execute(source, defaultEncoding, parserContext, self, parentFrame, true, currentNode, wrapper);
}

@TruffleBoundary
public Object execute(Source source, Encoding defaultEncoding, TranslatorDriver.ParserContext parserContext, Object self, MaterializedFrame parentFrame, boolean ownScopeForAssignments, RubyNode currentNode, NodeWrapper wrapper) {
public Object execute(Source source, Encoding defaultEncoding, TranslatorDriver.ParserContext parserContext, Object self, MaterializedFrame parentFrame, boolean ownScopeForAssignments, Node currentNode, NodeWrapper wrapper) {
final RubyRootNode rootNode = translator.parse(this, source, defaultEncoding, parserContext, parentFrame, ownScopeForAssignments, currentNode, wrapper);
final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);

Expand Down
Expand Up @@ -11,6 +11,7 @@

import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.nodes.Node;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.ArrayAllocationSite;
import org.jruby.truffle.nodes.objects.Allocator;
Expand Down Expand Up @@ -338,7 +339,7 @@ public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visit
public static class ArrayAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyArray(rubyClass);
}

Expand Down
Expand Up @@ -150,7 +150,7 @@ public Object[] getFieldNames() {
return getOperations().getFieldNames(this);
}

public void extend(RubyModule module, RubyNode currentNode) {
public void extend(RubyModule module, Node currentNode) {
RubyNode.notDesignedForCompilation();
getSingletonClass(currentNode).include(currentNode, module);
}
Expand Down Expand Up @@ -217,7 +217,7 @@ public static class BasicObjectAllocator implements Allocator {
// TODO(CS): why on earth is this a boundary? Seems like a really bad thing.
@CompilerDirectives.TruffleBoundary
@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyBasicObject(rubyClass);
}

Expand Down
Expand Up @@ -9,6 +9,7 @@
*/
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.nodes.Node;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
Expand Down Expand Up @@ -40,7 +41,7 @@ public BigInteger bigIntegerValue() {
public static class BignumAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyBignum(rubyClass, BigInteger.ZERO);
}

Expand Down
Expand Up @@ -11,6 +11,7 @@

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.nodes.Node;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
Expand Down Expand Up @@ -58,7 +59,7 @@ public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visit

public static class BindingAllocator implements Allocator {
@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyBinding(rubyClass);
}
}
Expand Down
Expand Up @@ -129,7 +129,7 @@ private RubyClass createOneSingletonClass() {
return metaClass;
}

public RubyBasicObject allocate(RubyNode currentNode) {
public RubyBasicObject allocate(Node currentNode) {
return allocator.allocate(getContext(), this, currentNode);
}

Expand All @@ -156,7 +156,7 @@ public Allocator getAllocator() {
public static class ClassAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyClass(context, context.getCoreLibrary().getClassClass(), null, null, null, false);
}

Expand Down
Expand Up @@ -9,6 +9,7 @@
*/
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.nodes.Node;
import org.jcodings.Encoding;
import org.jcodings.EncodingDB;
import org.jruby.truffle.nodes.RubyNode;
Expand Down Expand Up @@ -95,7 +96,7 @@ public static RubyEncoding[] cloneEncodingList() {
public static class EncodingAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
throw new UnsupportedOperationException();
}

Expand Down
Expand Up @@ -9,6 +9,7 @@
*/
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.nodes.Node;
import org.jcodings.transcode.EConv;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
Expand All @@ -34,7 +35,7 @@ public void setEConv(EConv econv) {
public static class EncodingConverterAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyEncodingConverter(rubyClass, null);
}

Expand Down
Expand Up @@ -9,6 +9,7 @@
*/
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.nodes.Node;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
Expand Down Expand Up @@ -63,7 +64,7 @@ public RubyArray asRubyStringArray() {
public static class ExceptionAllocator implements Allocator {

@Override
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, RubyNode currentNode) {
public RubyBasicObject allocate(RubyContext context, RubyClass rubyClass, Node currentNode) {
return new RubyException(rubyClass);
}

Expand Down

3 comments on commit 9710b08

@chrisseaton
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eregon also take a look at this

@eregon
Copy link
Member

@eregon eregon commented on 9710b08 Feb 28, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, quite unfortunate we can not obtain the current node without explicitly passing it.

@chrisseaton
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah - and I think we might ending up having to pass it around a lot, but without we cannot tell the user what line they are currently on, only what method they are in.

Please sign in to comment.