Skip to content

Commit

Permalink
Showing 6 changed files with 154 additions and 223 deletions.
2 changes: 1 addition & 1 deletion truffle/pom.rb
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
repository( :url => 'http://lafo.ssw.uni-linz.ac.at/nexus/content/repositories/snapshots/',
:id => 'truffle' )

truffle_version = '5309cc9668e30130c30f551b83c752dbcc1fd1cb-SNAPSHOT'
truffle_version = '145f995cd2fe236f65b53f36c41eeb420333647b-SNAPSHOT'
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'
8 changes: 4 additions & 4 deletions truffle/pom.xml
Original file line number Diff line number Diff line change
@@ -36,23 +36,23 @@ DO NOT MODIFIY - GENERATED CODE
<dependency>
<groupId>com.oracle.truffle</groupId>
<artifactId>truffle-api</artifactId>
<version>5309cc9668e30130c30f551b83c752dbcc1fd1cb-SNAPSHOT</version>
<version>145f995cd2fe236f65b53f36c41eeb420333647b-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.oracle.truffle</groupId>
<artifactId>truffle-debug</artifactId>
<version>5309cc9668e30130c30f551b83c752dbcc1fd1cb-SNAPSHOT</version>
<version>145f995cd2fe236f65b53f36c41eeb420333647b-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.oracle.truffle</groupId>
<artifactId>truffle-dsl-processor</artifactId>
<version>5309cc9668e30130c30f551b83c752dbcc1fd1cb-SNAPSHOT</version>
<version>145f995cd2fe236f65b53f36c41eeb420333647b-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.oracle.truffle</groupId>
<artifactId>truffle-tck</artifactId>
<version>5309cc9668e30130c30f551b83c752dbcc1fd1cb-SNAPSHOT</version>
<version>145f995cd2fe236f65b53f36c41eeb420333647b-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
Original file line number Diff line number Diff line change
@@ -13,13 +13,10 @@
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener;
import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory;
import com.oracle.truffle.api.instrument.Visualizer;
import com.oracle.truffle.api.instrument.WrapperNode;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.interop.java.JavaInterop;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.source.Source;
import org.jruby.Ruby;
@@ -118,11 +115,6 @@ protected Object evalInContext(Source source, Node node, MaterializedFrame mFram
return null;
}

@Override
protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException {
return null;
}

public Node unprotectedCreateFindContextNode() {
return super.createFindContextNode();
}
Original file line number Diff line number Diff line change
@@ -10,19 +10,14 @@

package org.jruby.truffle.runtime.subsystems;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrument.*;
import com.oracle.truffle.api.nodes.DirectCallNode;
import com.oracle.truffle.api.nodes.Node;
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.tools.LineToProbesMap;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.methods.DeclarationContext;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;

@@ -51,69 +46,7 @@ public synchronized void attach(String file, int line, final DynamicObject block

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

final AdvancedInstrumentResultListener listener = new AdvancedInstrumentResultListener() {

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

@Override
public void onFailure(Node node, VirtualFrame virtualFrame, RuntimeException exception) {
}

};

final AdvancedInstrumentRootFactory rootFactory = new AdvancedInstrumentRootFactory() {

@Override
public AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node) {
return new AdvancedInstrumentRoot() {

@Node.Child
private DirectCallNode callNode;

@Override
public Object executeRoot(Node node, VirtualFrame frame) {
final DynamicObject binding = Layouts.BINDING.createBinding(context.getCoreLibrary().getBindingFactory(), frame.materialize());

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

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

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

if (callNode.isInlinable()) {
callNode.forceInlining();
}
}

callNode.call(frame, RubyArguments.pack(
Layouts.PROC.getMethod(block),
Layouts.PROC.getDeclarationFrame(block),
null,
Layouts.PROC.getSelf(block),
Layouts.PROC.getBlock(block),
DeclarationContext.METHOD,
new Object[]{binding}));

return null;
}

@Override
public String instrumentationInfo() {
return info;
}

};
}

};

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

final LineLocation lineLocation = source.createLineLocation(line);

List<Instrument> instruments = attachments.get(lineLocation);
@@ -125,7 +58,7 @@ public String instrumentationInfo() {

for (Probe probe : lineToProbesMap.findProbes(lineLocation)) {
if (probe.isTaggedAs(StandardSyntaxTag.STATEMENT)) {
instruments.add(context.getEnv().instrumenter().attach(probe, listener, rootFactory, null, info));
instruments.add(context.getEnv().instrumenter().attach(probe, new AttachmentManagerInstrumentListener(context, block), info));
return;
}
}
@@ -147,4 +80,33 @@ public synchronized void detach(String file, int line) {
}
}

private final class AttachmentManagerInstrumentListener implements StandardInstrumentListener {

private final RubyContext context;
private final DynamicObject block;

public AttachmentManagerInstrumentListener(RubyContext context, DynamicObject block) {
this.context = context;
this.block = block;
}

@Override
public void onEnter(Probe probe, Node node, VirtualFrame frame) {
final DynamicObject binding = Layouts.BINDING.createBinding(context.getCoreLibrary().getBindingFactory(), frame.materialize());

context.inlineRubyHelper(node, frame, "x.call(binding)", "x", block, "binding", binding);
}

@Override
public void onReturnVoid(Probe probe, Node node, VirtualFrame frame) {
}

@Override
public void onReturnValue(Probe probe, Node node, VirtualFrame frame, Object result) {
}

@Override
public void onReturnExceptional(Probe probe, Node node, VirtualFrame frame, Exception exception) {
}
}
}
Original file line number Diff line number Diff line change
@@ -9,11 +9,9 @@
*/
package org.jruby.truffle.runtime.subsystems;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrument.*;
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;
@@ -22,7 +20,6 @@
import org.jcodings.specific.UTF8Encoding;
import org.jruby.RubyString;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.methods.DeclarationContext;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.RubySyntaxTag;
@@ -33,6 +30,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class TraceManager {
@@ -41,7 +39,7 @@ public class TraceManager {

private Collection<ProbeInstrument> instruments;
private boolean isInTraceFunc = false;
private final Map<SyntaxTag, AdvancedInstrumentRootFactory> eventFactories = new HashMap<>();
private final Map<SyntaxTag, TraceFuncEventFactory> eventFactories = new LinkedHashMap<>();

public TraceManager(RubyContext context) {
this.context = context;
@@ -61,123 +59,31 @@ public void setTraceFunc(final DynamicObject traceFunc) {
return;
}

final AdvancedInstrumentResultListener listener = new AdvancedInstrumentResultListener() {

final TraceFuncEventFactory lineEventFactory = new TraceFuncEventFactory() {
@Override
public void onExecution(Node node, VirtualFrame vFrame, Object result) {
}
public StandardInstrumentListener createInstrumentListener(RubyContext context, DynamicObject traceFunc) {
final DynamicObject event = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist("line", UTF8Encoding.INSTANCE), StringSupport.CR_7BIT, null);

@Override
public void onFailure(Node node, VirtualFrame vFrame, RuntimeException ex) {
return new BaseEventInstrumentListener(context, traceFunc, event);
}

};

final AdvancedInstrumentRootFactory lineEventFactory = new AdvancedInstrumentRootFactory() {

final TraceFuncEventFactory callEventFactory = new TraceFuncEventFactory() {
@Override
public AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node) {
final DynamicObject event = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist("line", UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null);

final SourceSection sourceSection = node.getEncapsulatingSourceSection();

final DynamicObject file = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist(sourceSection.getSource().getName(), UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null);
final int line = sourceSection.getStartLine();

return new BaseAdvancedIntrumentRoot(traceFunc, event, file, line);
}

};

final AdvancedInstrumentRootFactory callEventFactory = new AdvancedInstrumentRootFactory() {

@Override
public AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node) {
final DynamicObject event = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist("call", UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null);

return new AdvancedInstrumentRoot() {

@Child private DirectCallNode callNode;

private final ConditionProfile inTraceFuncProfile = ConditionProfile.createBinaryProfile();

@Override
public Object executeRoot(Node node, VirtualFrame frame) {
if (!inTraceFuncProfile.profile(isInTraceFunc)) {
// set_trace_func reports the file and line of the call site.
final SourceSection sourceSection = Truffle.getRuntime().getCallerFrame().getCallNode().getEncapsulatingSourceSection();
final String filename = sourceSection.getSource().getName();
final DynamicObject file = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist(filename, UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null);

if (!context.getOptions().INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC && filename.startsWith(SourceLoader.TRUFFLE_SCHEME)) {
return context.getCoreLibrary().getNilObject();
}

final int line = sourceSection.getStartLine();
public StandardInstrumentListener createInstrumentListener(RubyContext context, DynamicObject traceFunc) {
final DynamicObject event = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist("call", UTF8Encoding.INSTANCE), StringSupport.CR_7BIT, null);

final Object self = RubyArguments.getSelf(frame.getArguments());
final Object classname = context.getCoreLibrary().getLogicalClass(self);
final Object id = context.getSymbol(RubyArguments.getMethod(frame.getArguments()).getName());

final DynamicObject binding = Layouts.BINDING.createBinding(
context.getCoreLibrary().getBindingFactory(),
frame.materialize());

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

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

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

if (callNode.isInlinable()) {
callNode.forceInlining();
}
}

isInTraceFunc = true;

callNode.call(frame, RubyArguments.pack(
Layouts.PROC.getMethod(traceFunc),
Layouts.PROC.getDeclarationFrame(traceFunc),
null,
Layouts.PROC.getSelf(traceFunc),
Layouts.PROC.getBlock(traceFunc),
DeclarationContext.METHOD,
new Object[]{event, file, line, id, binding, classname}));

isInTraceFunc = false;
}

return null;
}

@Override
public String instrumentationInfo() {
return "set_trace_func";
}

};
return new CallEventInstrumentListener(context, traceFunc, event);
}

};

final AdvancedInstrumentRootFactory classEventFactory = new AdvancedInstrumentRootFactory() {

final TraceFuncEventFactory classEventFactory = new TraceFuncEventFactory() {
@Override
public AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node) {
final DynamicObject event = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist("class", UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null);

final SourceSection sourceSection = node.getEncapsulatingSourceSection();

final DynamicObject file = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist(sourceSection.getSource().getName(), UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null);
final int line = sourceSection.getStartLine();
public StandardInstrumentListener createInstrumentListener(RubyContext context, DynamicObject traceFunc) {
final DynamicObject event = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist("class", UTF8Encoding.INSTANCE), StringSupport.CR_7BIT, null);

return new BaseAdvancedIntrumentRoot(traceFunc, event, file, line);
return new BaseEventInstrumentListener(context, traceFunc, event);
}

};

eventFactories.put(RubySyntaxTag.LINE, lineEventFactory);
@@ -186,9 +92,9 @@ public AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node) {

instruments = new ArrayList<>();

for (Map.Entry<SyntaxTag, AdvancedInstrumentRootFactory> entry : eventFactories.entrySet()) {
for (Map.Entry<SyntaxTag, TraceFuncEventFactory> entry : eventFactories.entrySet()) {
for (Probe probe : context.getEnv().instrumenter().findProbesTaggedAs(entry.getKey())) {
instruments.add(context.getEnv().instrumenter().attach(probe, listener, entry.getValue(), null, "set_trace_func"));
instruments.add(context.getEnv().instrumenter().attach(probe, entry.getValue().createInstrumentListener(context, traceFunc), "set_trace_func"));
}
}

@@ -205,7 +111,7 @@ public void newProbeInserted(Probe probe) {
@Override
public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
if (eventFactories.containsKey(tag)) {
instruments.add(context.getEnv().instrumenter().attach(probe, listener, eventFactories.get(tag), null, "set_trace_func"));
instruments.add(context.getEnv().instrumenter().attach(probe, eventFactories.get(tag).createInstrumentListener(context, traceFunc), "set_trace_func"));
}
}

@@ -216,68 +122,134 @@ public void endASTProbing(RootNode rootNode) {
});
}

private final class BaseAdvancedIntrumentRoot extends AdvancedInstrumentRoot {
@Child private DirectCallNode callNode;
private abstract class TraceFuncEventFactory {

public abstract StandardInstrumentListener createInstrumentListener(RubyContext context, DynamicObject traceFunc);

}

private final class BaseEventInstrumentListener implements StandardInstrumentListener {

private final ConditionProfile inTraceFuncProfile = ConditionProfile.createBinaryProfile();

private final RubyContext context;
private final DynamicObject traceFunc;
private final Object event;
private final Object file;
private final int line;

public BaseAdvancedIntrumentRoot(DynamicObject traceFunc, Object event, Object file, int line) {
public BaseEventInstrumentListener(RubyContext context, DynamicObject traceFunc, Object event) {
this.context = context;
this.traceFunc = traceFunc;
this.event = event;
this.file = file;
this.line = line;
}

@Override
public Object executeRoot(Node node, VirtualFrame frame) {
public void onEnter(Probe probe, Node node, VirtualFrame frame) {
if (!inTraceFuncProfile.profile(isInTraceFunc)) {
final SourceSection sourceSection = node.getEncapsulatingSourceSection();

final DynamicObject file = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist(sourceSection.getSource().getName(), UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null);
final int line = sourceSection.getStartLine();

final Object classname = context.getCoreLibrary().getNilObject();
final Object id = context.getCoreLibrary().getNilObject();

final DynamicObject binding = Layouts.BINDING.createBinding(
context.getCoreLibrary().getBindingFactory(),
frame.materialize());

if (callNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
isInTraceFunc = true;

try {
context.inlineRubyHelper(node, frame, "traceFunc.call(event, file, line, id, binding, classname)",
"traceFunc", traceFunc,
"event", event,
"file", file,
"line", line,
"id", id,
"binding", binding,
"classname", classname);
} finally {
isInTraceFunc = false;
}
}
}

@Override
public void onReturnVoid(Probe probe, Node node, VirtualFrame frame) {
}

@Override
public void onReturnValue(Probe probe, Node node, VirtualFrame frame, Object result) {
}

@Override
public void onReturnExceptional(Probe probe, Node node, VirtualFrame frame, Exception exception) {
}
}

private final class CallEventInstrumentListener implements StandardInstrumentListener {

private final ConditionProfile inTraceFuncProfile = ConditionProfile.createBinaryProfile();

private final RubyContext context;
private final DynamicObject traceFunc;
private final Object event;

callNode = insert(Truffle.getRuntime().createDirectCallNode(Layouts.PROC.getCallTargetForType(traceFunc)));
public CallEventInstrumentListener(RubyContext context, DynamicObject traceFunc, Object event) {
this.context = context;
this.traceFunc = traceFunc;
this.event = event;
}

if (callNode.isCallTargetCloningAllowed()) {
callNode.cloneCallTarget();
}
@Override
public void onEnter(Probe probe, Node node, VirtualFrame frame) {
if (!inTraceFuncProfile.profile(isInTraceFunc)) {
// set_trace_func reports the file and line of the call site.
final SourceSection sourceSection = Truffle.getRuntime().getCallerFrame().getCallNode().getEncapsulatingSourceSection();
final String filename = sourceSection.getSource().getName();
final DynamicObject file = Layouts.STRING.createString(context.getCoreLibrary().getStringFactory(), RubyString.encodeBytelist(filename, UTF8Encoding.INSTANCE), StringSupport.CR_UNKNOWN, null);

if (callNode.isInlinable()) {
callNode.forceInlining();
}
if (!context.getOptions().INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC && filename.startsWith(SourceLoader.TRUFFLE_SCHEME)) {
return;
}

isInTraceFunc = true;
final int line = sourceSection.getStartLine();

callNode.call(frame, RubyArguments.pack(
Layouts.PROC.getMethod(traceFunc),
Layouts.PROC.getDeclarationFrame(traceFunc),
null,
Layouts.PROC.getSelf(traceFunc),
Layouts.PROC.getBlock(traceFunc),
DeclarationContext.METHOD,
new Object[]{event, file, line, id, binding, classname}));
final Object self = RubyArguments.getSelf(frame.getArguments());
final Object classname = context.getCoreLibrary().getLogicalClass(self);
final Object id = context.getSymbol(RubyArguments.getMethod(frame.getArguments()).getName());

isInTraceFunc = false;
final DynamicObject binding = Layouts.BINDING.createBinding(
context.getCoreLibrary().getBindingFactory(),
frame.materialize());

isInTraceFunc = true;

try {
context.inlineRubyHelper(node, frame, "traceFunc.call(event, file, line, id, binding, classname)",
"traceFunc", traceFunc,
"event", event,
"file", file,
"line", line,
"id", id,
"binding", binding,
"classname", classname);
} finally {
isInTraceFunc = false;
}
}
}

return null;
@Override
public void onReturnVoid(Probe probe, Node node, VirtualFrame frame) {
}

@Override
public String instrumentationInfo() {
return "set_trace_func";
public void onReturnValue(Probe probe, Node node, VirtualFrame frame, Object result) {
}
}

@Override
public void onReturnExceptional(Probe probe, Node node, VirtualFrame frame, Exception exception) {
}
}
}
5 changes: 5 additions & 0 deletions truffle/src/test/java/org/jruby/truffle/tck/RubyTckTest.java
Original file line number Diff line number Diff line change
@@ -117,4 +117,9 @@ protected String identity() {
return "identity";
}

@Override
protected String globalObject() {
return null;
}

}

0 comments on commit 6ba1606

Please sign in to comment.