Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 6d1ed38b9c52
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: d686a67983c9
Choose a head ref
  • 4 commits
  • 2 files changed
  • 1 contributor

Commits on Aug 17, 2015

  1. Copy the full SHA
    cdb43d4 View commit details
  2. Copy the full SHA
    1389bdf View commit details
  3. Copy the full SHA
    940632e View commit details
  4. Copy the full SHA
    d686a67 View commit details
Original file line number Diff line number Diff line change
@@ -16,6 +16,10 @@
import com.oracle.truffle.api.nodes.NodeVisitor;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.RubyRootNode;
import org.jruby.truffle.nodes.methods.SetMethodDeclarationContext;
import org.jruby.truffle.nodes.objects.DefineOrGetClassNode;
import org.jruby.truffle.nodes.objects.DefineOrGetModuleNode;
import org.jruby.truffle.nodes.objects.OpenModuleNode;
import org.jruby.truffle.runtime.RubySyntaxTag;

public class RubyDefaultASTProber implements NodeVisitor, ASTProber {
@@ -32,17 +36,18 @@ public boolean visit(Node node) {
rubyNode.probe().tagAs(RubySyntaxTag.LINE, null);
}

if (rubyNode.getParent() instanceof RubyRootNode) {
if (rubyNode instanceof OpenModuleNode) {
rubyNode.probe().tagAs(RubySyntaxTag.CLASS, null);
}
// A RubyRootNode can't have a probe because it doesn't have a parent. So, we do the next best thing and
// tag its immediate child. The trace instrument will know to look at the parent (RubyRootNode) based upon
// the context implied by the tag. We need to tag at the RubyRootNode because the semantics of set_trace_func
// are such that the receiver must be resolved, so we have to push as far into the callee as we can to have
// a properly constructed frame.
else if ((rubyNode.getParent() instanceof RubyRootNode) && !(rubyNode instanceof SetMethodDeclarationContext)) {
rubyNode.probe().tagAs(RubySyntaxTag.CALL, null);
}

// A RubyRootNode can't have a probe because it doesn't have a parent. So, we do the next best thing and
// tag its immediate child. The trace instrument will know to look at the parent (RubyRootNode) based upon
// the context implied by the tag. We need to tag at the RubyRootNode because the semantics of set_trace_func
// are such that the receiver must be resolved, so we have to push as far into the callee as we can to have
// a properly constructed frame.
} else if (node.getParent() instanceof RubyRootNode) {
node.probe().tagAs(RubySyntaxTag.CALL, null);
}
}

Original file line number Diff line number Diff line change
@@ -84,59 +84,7 @@ public AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node) {
final RubyBasicObject file = StringNodes.createString(context.getCoreLibrary().getStringClass(), sourceSection.getSource().getName());
final int line = sourceSection.getStartLine();

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)) {
final Object self = context.getCoreLibrary().getNilObject();
final Object classname = self;
final Object id = context.getCoreLibrary().getNilObject();

final RubyBinding binding = new RubyBinding(
context.getCoreLibrary().getBindingClass(),
self,
frame.materialize());

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

callNode = insert(Truffle.getRuntime().createDirectCallNode(ProcNodes.getCallTargetForBlocks(traceFunc)));

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

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

isInTraceFunc = true;

callNode.call(frame, RubyArguments.pack(
ProcNodes.getMethod(traceFunc),
ProcNodes.getDeclarationFrame(traceFunc),
ProcNodes.getSelfCapturedInScope(traceFunc),
ProcNodes.getBlockCapturedInScope(traceFunc),
new Object[]{event, file, line, id, binding, classname}));

isInTraceFunc = false;
}

return null;
}

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

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

};
@@ -215,8 +163,25 @@ public String instrumentationInfo() {

};

final AdvancedInstrumentRootFactory classEventFactory = new AdvancedInstrumentRootFactory() {

@Override
public AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node) {
final RubyBasicObject event = StringNodes.createString(context.getCoreLibrary().getStringClass(), "class");

final SourceSection sourceSection = node.getEncapsulatingSourceSection();

final RubyBasicObject file = StringNodes.createString(context.getCoreLibrary().getStringClass(), sourceSection.getSource().getName());
final int line = sourceSection.getStartLine();

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

};

eventFactories.put(RubySyntaxTag.LINE, lineEventFactory);
eventFactories.put(RubySyntaxTag.CALL, callEventFactory);
eventFactories.put(RubySyntaxTag.CLASS, classEventFactory);

instruments = new ArrayList<>();

@@ -252,4 +217,68 @@ public void endASTProbing(Source source) {
});
}

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

private final ConditionProfile inTraceFuncProfile = ConditionProfile.createBinaryProfile();

private final RubyBasicObject traceFunc;
private final Object event;
private final Object file;
private final int line;

public BaseAdvancedIntrumentRoot(RubyBasicObject traceFunc, Object event, Object file, int line) {
this.traceFunc = traceFunc;
this.event = event;
this.file = file;
this.line = line;
}

@Override
public Object executeRoot(Node node, VirtualFrame frame) {
if (!inTraceFuncProfile.profile(isInTraceFunc)) {
final Object self = context.getCoreLibrary().getNilObject();
final Object classname = context.getCoreLibrary().getNilObject();
final Object id = context.getCoreLibrary().getNilObject();

final RubyBinding binding = new RubyBinding(
context.getCoreLibrary().getBindingClass(),
self,
frame.materialize());

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

callNode = insert(Truffle.getRuntime().createDirectCallNode(ProcNodes.getCallTargetForBlocks(traceFunc)));

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

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

isInTraceFunc = true;

callNode.call(frame, RubyArguments.pack(
ProcNodes.getMethod(traceFunc),
ProcNodes.getDeclarationFrame(traceFunc),
ProcNodes.getSelfCapturedInScope(traceFunc),
ProcNodes.getBlockCapturedInScope(traceFunc),
new Object[]{event, file, line, id, binding, classname}));

isInTraceFunc = false;
}

return null;
}

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

}