Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Truffle] Adopt new instrumentation API.
Browse files Browse the repository at this point in the history
chrisseaton committed Feb 15, 2016
1 parent 9498ddf commit 28ac89d
Showing 9 changed files with 80 additions and 141 deletions.
3 changes: 2 additions & 1 deletion truffle/pom.rb
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
repository( :url => 'http://lafo.ssw.uni-linz.ac.at/nexus/content/repositories/snapshots/',
:id => 'truffle' )

truffle_version = '385095c3a988e6b16fbcdeb8dc8d55150cfbbefd-SNAPSHOT'
truffle_version = '4592e4936b3c19a9e578477baab474387b0947d2'
jar 'com.oracle.truffle:truffle-api:' + truffle_version
jar 'com.oracle.truffle:truffle-debug:' + truffle_version
jar 'com.oracle.truffle:truffle-dsl-processor:' + truffle_version, :scope => 'provided'
@@ -47,6 +47,7 @@
:id => 'default-compile',
:phase => 'compile',
'annotationProcessors' => [ 'org.jruby.truffle.om.dsl.processor.OMProcessor',
'com.oracle.truffle.dsl.processor.InstrumentableProcessor',
'com.oracle.truffle.dsl.processor.TruffleProcessor',
'com.oracle.truffle.dsl.processor.verify.VerifyTruffleProcessor',
'com.oracle.truffle.dsl.processor.LanguageRegistrationProcessor' ],
9 changes: 5 additions & 4 deletions truffle/pom.xml
Original file line number Diff line number Diff line change
@@ -41,23 +41,23 @@ DO NOT MODIFIY - GENERATED CODE
<dependency>
<groupId>com.oracle.truffle</groupId>
<artifactId>truffle-api</artifactId>
<version>385095c3a988e6b16fbcdeb8dc8d55150cfbbefd-SNAPSHOT</version>
<version>4592e4936b3c19a9e578477baab474387b0947d2</version>
</dependency>
<dependency>
<groupId>com.oracle.truffle</groupId>
<artifactId>truffle-debug</artifactId>
<version>385095c3a988e6b16fbcdeb8dc8d55150cfbbefd-SNAPSHOT</version>
<version>4592e4936b3c19a9e578477baab474387b0947d2</version>
</dependency>
<dependency>
<groupId>com.oracle.truffle</groupId>
<artifactId>truffle-dsl-processor</artifactId>
<version>385095c3a988e6b16fbcdeb8dc8d55150cfbbefd-SNAPSHOT</version>
<version>4592e4936b3c19a9e578477baab474387b0947d2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.oracle.truffle</groupId>
<artifactId>truffle-tck</artifactId>
<version>385095c3a988e6b16fbcdeb8dc8d55150cfbbefd-SNAPSHOT</version>
<version>4592e4936b3c19a9e578477baab474387b0947d2</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -124,6 +124,7 @@ DO NOT MODIFIY - GENERATED CODE
<configuration>
<annotationProcessors>
<annotationProcessor>org.jruby.truffle.om.dsl.processor.OMProcessor</annotationProcessor>
<annotationProcessor>com.oracle.truffle.dsl.processor.InstrumentableProcessor</annotationProcessor>
<annotationProcessor>com.oracle.truffle.dsl.processor.TruffleProcessor</annotationProcessor>
<annotationProcessor>com.oracle.truffle.dsl.processor.verify.VerifyTruffleProcessor</annotationProcessor>
<annotationProcessor>com.oracle.truffle.dsl.processor.LanguageRegistrationProcessor</annotationProcessor>
13 changes: 7 additions & 6 deletions truffle/src/main/java/org/jruby/truffle/RubyContext.java
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
import com.oracle.truffle.api.ExecutionContext;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.instrumentation.Instrumenter;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.tools.CoverageTracker;
import org.jruby.Ruby;
@@ -81,11 +82,11 @@ public class RubyContext extends ExecutionContext {
private final LexicalScope rootLexicalScope;
private final CoverageTracker coverageTracker;
private final InstrumentationServerManager instrumentationServerManager;
private final AttachmentsManager attachmentsManager;
private final CallGraph callGraph;
private final PrintStream debugStandardOut;

private org.jruby.ast.RootNode initialJRubyRootNode;
private final AttachmentsManager attachmentsManager;

public RubyContext(Ruby jrubyRuntime, TruffleLanguage.Env env) {
latestInstance = this;
@@ -159,7 +160,7 @@ public RubyContext(Ruby jrubyRuntime, TruffleLanguage.Env env) {
instrumentationServerManager = null;
}

attachmentsManager = new AttachmentsManager(this);
attachmentsManager = new AttachmentsManager(this, env.lookup(Instrumenter.class));
}

public Object send(Object object, String methodName, DynamicObject block, Object... arguments) {
@@ -299,15 +300,15 @@ public SymbolTable getSymbolTable() {
return symbolTable;
}

public CallGraph getCallGraph() {
return callGraph;
}

public CodeLoader getCodeLoader() {
return codeLoader;
}

public InteropManager getInteropManager() {
return interopManager;
}

public CallGraph getCallGraph() {
return callGraph;
}
}
1 change: 0 additions & 1 deletion truffle/src/main/java/org/jruby/truffle/RubyLanguage.java
Original file line number Diff line number Diff line change
@@ -123,5 +123,4 @@ public Node unprotectedCreateFindContextNode() {
public RubyContext unprotectedFindContext(Node node) {
return super.findContext(node);
}

}
118 changes: 34 additions & 84 deletions truffle/src/main/java/org/jruby/truffle/extra/AttachmentsManager.java
Original file line number Diff line number Diff line change
@@ -10,126 +10,76 @@

package org.jruby.truffle.extra;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrument.EvalInstrumentListener;
import com.oracle.truffle.api.instrument.Instrument;
import com.oracle.truffle.api.instrument.Probe;
import com.oracle.truffle.api.instrument.StandardSyntaxTag;
import com.oracle.truffle.api.instrumentation.EventBinding;
import com.oracle.truffle.api.instrumentation.EventContext;
import com.oracle.truffle.api.instrumentation.EventNode;
import com.oracle.truffle.api.instrumentation.EventNodeFactory;
import com.oracle.truffle.api.instrumentation.Instrumenter;
import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.LineLocation;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.tools.LineToProbesMap;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.RubyLanguage;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.core.binding.BindingNodes;
import org.jruby.truffle.core.proc.ProcNodes;
import org.jruby.truffle.language.RubyGuards;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AttachmentsManager {

public static final Source ATTACHMENT_SOURCE = Source.fromText("(attachment)", "(attachment)").withMimeType(RubyLanguage.MIME_TYPE);

private final RubyContext context;
private final LineToProbesMap lineToProbesMap;
private final Map<LineLocation, List<Instrument>> attachments = new HashMap<>();
private final Instrumenter instrumenter;

public AttachmentsManager(RubyContext context) {
public AttachmentsManager(RubyContext context, Instrumenter instrumenter) {
this.context = context;

lineToProbesMap = new LineToProbesMap();
context.getEnv().instrumenter().install(lineToProbesMap);
this.instrumenter = instrumenter;
}

public synchronized Instrument attach(String file, int line, final DynamicObject block) {
public synchronized EventBinding<?> attach(String file, int line, final DynamicObject block) {
assert RubyGuards.isRubyProc(block);

final String info = String.format("Truffle::Primitive.attach@%s:%d", file, line);

final EvalInstrumentListener listener = new EvalInstrumentListener() {

@Override
public void onExecution(Node node, VirtualFrame virtualFrame, Object o) {
}

@Override
public void onFailure(Node node, VirtualFrame virtualFrame, Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw new RuntimeException(e);
}
}

};

final Source source = context.getSourceCache().getBestSourceFuzzily(file);

final LineLocation lineLocation = source.createLineLocation(line);

for (Probe probe : lineToProbesMap.findProbes(lineLocation)) {
if (probe.isTaggedAs(StandardSyntaxTag.STATEMENT)) {
final Map<String, Object> parameters = new HashMap<>();
parameters.put("section", probe.getProbedSourceSection());
parameters.put("block", block);
return context.getEnv().instrumenter().attach(probe, ATTACHMENT_SOURCE, listener, info, parameters);
SourceSectionFilter filter = SourceSectionFilter.newBuilder().sourceIs(source).lineIs(line).tagIs("statement").build();
return instrumenter.attachFactory(filter, new EventNodeFactory() {
public EventNode create(EventContext eventContext) {
return new AttachmentEventNode(context, block);
}
}
});

// with the new API you are not notified if a statement is not actually installed
// because wrappers and installing is lazy. Is that a problem?

throw new RuntimeException("couldn't find a statement!");
// throw new RuntimeException("couldn't find a statement!");
}

public static class AttachmentRootNode extends RootNode {
private static class AttachmentEventNode extends EventNode {

private final RubyContext context;
private final DynamicObject block;
@Node.Child
private DirectCallNode callNode;

@Child private DirectCallNode callNode;

public AttachmentRootNode(Class<? extends TruffleLanguage<?>> language, RubyContext context, SourceSection sourceSection, FrameDescriptor frameDescriptor, DynamicObject block) {
super(language, sourceSection, frameDescriptor);
public AttachmentEventNode(RubyContext context, DynamicObject block) {
this.context = context;
this.block = block;
}

@Override
public Object execute(VirtualFrame frame) {
final MaterializedFrame callerFrame = (MaterializedFrame)frame.getArguments()[0];

final DynamicObject binding = BindingNodes.createBinding(context, callerFrame);

if (callNode == null) {
CompilerDirectives.transferToInterpreter();

callNode = insert(Truffle.getRuntime().createDirectCallNode(Layouts.PROC.getCallTargetForType(block)));
this.callNode = Truffle.getRuntime().createDirectCallNode(Layouts.PROC.getCallTargetForType(block));

if (callNode.isCallTargetCloningAllowed()) {
callNode.cloneCallTarget();
}

if (callNode.isInlinable()) {
callNode.forceInlining();
}
// (chumer): do we still want to clone and inline always? don't think so
if (callNode.isCallTargetCloningAllowed()) {
callNode.cloneCallTarget();
}
if (callNode.isInlinable()) {
callNode.forceInlining();
}

callNode.call(frame, ProcNodes.packArguments(block, binding));

return null;
}

@Override
public void onEnter(VirtualFrame frame) {
callNode.call(frame, ProcNodes.packArguments(block, new Object[] { BindingNodes.createBinding(context, frame.materialize())}));
}
}

}
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@
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.instrumentation.EventBinding;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.Source;
@@ -392,8 +392,8 @@ public DetachNode(RubyContext context, SourceSection sourceSection) {
@TruffleBoundary
@Specialization(guards = "isHandle(handle)")
public DynamicObject detach(DynamicObject handle) {
final Instrument instrument = (Instrument) Layouts.HANDLE.getObject(handle);
instrument.dispose();
final EventBinding<?> binding = (EventBinding<?>) Layouts.HANDLE.getObject(handle);
binding.dispose();
return getContext().getCoreLibrary().getNilObject();
}

Original file line number Diff line number Diff line change
@@ -14,8 +14,6 @@
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.Node;
@@ -27,7 +25,6 @@
import org.jruby.runtime.Visibility;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.RubyLanguage;
import org.jruby.truffle.extra.AttachmentsManager;
import org.jruby.truffle.language.arguments.RubyArguments;
import org.jruby.truffle.language.methods.DeclarationContext;
import org.jruby.truffle.language.methods.InternalMethod;
@@ -70,52 +67,23 @@ public Object execute(VirtualFrame frame) {
if (callNode == null || context != cachedContext) {
CompilerDirectives.transferToInterpreter();

if (AttachmentsManager.ATTACHMENT_SOURCE == source) {
final SourceSection sourceSection = (SourceSection) frame.getArguments()[getIndex("section")];
final DynamicObject block = (DynamicObject) frame.getArguments()[getIndex("block")];
final TranslatorDriver translator = new TranslatorDriver(context);

final RootNode rootNode = new AttachmentsManager.AttachmentRootNode(RubyLanguage.class, cachedContext,
sourceSection, null, block);
final RubyRootNode rootNode = translator.parse(context, source, UTF8Encoding.INSTANCE,
ParserContext.TOP_LEVEL, argumentNames, null, true, null);

final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);

callNode = insert(Truffle.getRuntime().createDirectCallNode(callTarget));
callNode.forceInlining();
} else {
final TranslatorDriver translator = new TranslatorDriver(context);
callNode = insert(Truffle.getRuntime().createDirectCallNode(callTarget));
callNode.forceInlining();

final RubyRootNode rootNode = translator.parse(context, source, UTF8Encoding.INSTANCE,
ParserContext.TOP_LEVEL, argumentNames, null, true, null);

final CallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);

callNode = insert(Truffle.getRuntime().createDirectCallNode(callTarget));
callNode.forceInlining();

mainObject = context.getCoreLibrary().getMainObject();
method = new InternalMethod(rootNode.getSharedMethodInfo(), rootNode.getSharedMethodInfo().getName(),
context.getCoreLibrary().getObjectClass(), Visibility.PUBLIC, callTarget);
}
}

if (method == null) {
final MaterializedFrame callerFrame = Truffle.getRuntime().getCallerFrame()
.getFrame(FrameInstance.FrameAccess.MATERIALIZE, false).materialize();

return callNode.call(frame, new Object[] { callerFrame });
mainObject = context.getCoreLibrary().getMainObject();
method = new InternalMethod(rootNode.getSharedMethodInfo(), rootNode.getSharedMethodInfo().getName(),
context.getCoreLibrary().getObjectClass(), Visibility.PUBLIC, callTarget);
}

return callNode.call(frame, RubyArguments.pack(null, null, method, DeclarationContext.TOP_LEVEL, null,
mainObject, null, frame.getArguments()));
}

private int getIndex(String name) {
for (int i = 0; i < argumentNames.length; i++) {
if (name.equals(argumentNames[i])) {
return i;
}
}
return -1;
}

}
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.TypeSystemReference;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrumentation.Instrumentable;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.object.DynamicObject;
@@ -31,6 +32,7 @@

@TypeSystemReference(RubyTypes.class)
@ImportStatic(RubyGuards.class)
@Instrumentable(factory = RubyNodeWrapper.class)
public abstract class RubyNode extends Node {

private final RubyContext context;
@@ -42,6 +44,10 @@ public RubyNode(RubyContext context, SourceSection sourceSection) {
this.context = context;
}

public RubyNode(RubyNode node) {
this(node.getContext(), node.getSourceSection());
}

// Fundamental execute methods

public abstract Object execute(VirtualFrame frame);
Original file line number Diff line number Diff line change
@@ -441,7 +441,17 @@ public RubyNode visitBlockNode(org.jruby.ast.BlockNode node) {
if (translatedChildren.size() == 1) {
ret = translatedChildren.get(0);
} else {
ret = SequenceNode.sequence(context, sourceSection, translatedChildren.toArray(new RubyNode[translatedChildren.size()]));
final int startIndex = sourceSection.getSource().getLineStartOffset(node.getPosition().getLine() + 1);

int length = 0;

for (int n = firstLine; n <= lastLine; n++) {
length += sourceSection.getSource().getLineLength(n);
}

length = Math.min(length + startIndex, sourceSection.getSource().getLength()) - startIndex;

ret = SequenceNode.sequence(context, sourceSection.getSource().createSection(sourceSection.getIdentifier(), startIndex, length), translatedChildren.toArray(new RubyNode[translatedChildren.size()]));
}

return addNewlineIfNeeded(node, ret);
@@ -3143,6 +3153,9 @@ private void copyNewline(org.jruby.ast.Node from, org.jruby.ast.Node to) {
private RubyNode addNewlineIfNeeded(org.jruby.ast.Node jrubyNode, RubyNode node) {
if (jrubyNode.isNewline()) {
node.setAtNewline();
final SourceSection current = node.getEncapsulatingSourceSection();
node.clearSourceSection();
node.assignSourceSection(current.withTags("statement"));
}

return node;

0 comments on commit 28ac89d

Please sign in to comment.