Skip to content

Commit

Permalink
[Truffle] Restore instrumentation support.
Browse files Browse the repository at this point in the history
Contains code written by Michael Van de Vanter.
  • Loading branch information
chrisseaton committed Jan 4, 2015
1 parent b1e646a commit 6327ad1
Show file tree
Hide file tree
Showing 2 changed files with 293 additions and 1 deletion.
50 changes: 49 additions & 1 deletion core/src/main/java/org/jruby/truffle/nodes/RubyNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.dsl.TypeSystemReference;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrument.Probe;
import com.oracle.truffle.api.instrument.ProbeNode;
import com.oracle.truffle.api.instrument.TruffleEventReceiver;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.dispatch.Dispatch;
import org.jruby.truffle.nodes.instrument.RubyWrapperNode;
import org.jruby.truffle.nodes.yield.YieldDispatchNode;
import org.jruby.truffle.runtime.LexicalScope;
import org.jruby.truffle.runtime.RubyContext;
Expand All @@ -30,7 +34,7 @@
* @see YieldDispatchNode
*/
@TypeSystemReference(RubyTypes.class)
public abstract class RubyNode extends Node {
public abstract class RubyNode extends Node implements ProbeNode.Instrumentable {

private final RubyContext context;

Expand Down Expand Up @@ -218,6 +222,50 @@ public RubyBignum bignum(BigInteger value) {
return new RubyBignum(getContext().getCoreLibrary().getBignumClass(), value);
}

public RubyNode getNonWrapperNode() {
return this;
}

public Probe probe() {
final Node parent = getParent();

if (parent == null) {
throw new IllegalStateException("Cannot call probe() on a node without a parent.");
}

if (parent instanceof RubyWrapperNode) {
return ((RubyWrapperNode) parent).getProbe();
}

// Create a new wrapper/probe with this node as its child.
final RubyWrapperNode wrapper = new RubyWrapperNode(this);

// Connect it to a Probe
final Probe probe = ProbeNode.insertProbe(wrapper);

// Replace this node in the AST with the wrapper
this.replace(wrapper);

return probe;
}

public void probeLite(TruffleEventReceiver eventReceiver) {
final Node parent = getParent();

if (parent == null) {
throw new IllegalStateException("Cannot call probeLite() on a node without a parent");
}

if (parent instanceof RubyWrapperNode) {
throw new IllegalStateException("Cannot call probeLite() on a node that already has a wrapper.");
}

final RubyWrapperNode wrapper = new RubyWrapperNode(this);
ProbeNode.insertProbeLite(wrapper, eventReceiver);

this.replace(wrapper);
}

// Copied from RubyTypesGen

@SuppressWarnings("static-method")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
/*
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.instrument;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrument.KillException;
import com.oracle.truffle.api.instrument.Probe;
import com.oracle.truffle.api.instrument.ProbeNode;
import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
import com.oracle.truffle.api.instrument.TruffleEventReceiver;
import com.oracle.truffle.api.nodes.NodeCost;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyBignum;
import org.jruby.truffle.runtime.core.RubyString;

@NodeInfo(cost = NodeCost.NONE)
public final class RubyWrapperNode extends RubyNode implements WrapperNode {

@Child private RubyNode child;
@Child private ProbeNode probeNode;

public RubyWrapperNode(RubyNode child) {
super(child.getContext(), child.getSourceSection());
assert !(child instanceof RubyWrapperNode);
this.child = child;
}

public String instrumentationInfo() {
return "Wrapper node for Ruby";
}

@Override
public RubyNode getNonWrapperNode() {
return child;
}

public void insertProbe(ProbeNode newProbeNode) {
this.probeNode = insert(newProbeNode);
}

public Probe getProbe() {
try {
return probeNode.getProbe();
} catch (IllegalStateException e) {
throw new UnsupportedOperationException("A lite-Probed wrapper has no explicit Probe");
}
}

public RubyNode getChild() {
return child;
}

@Override
public Object execute(VirtualFrame frame) {
probeNode.enter(child, frame);

Object result;

try {
result = child.execute(frame);
probeNode.returnValue(child, frame, result);
} catch (KillException e) {
throw e;
} catch (Exception e) {
probeNode.returnExceptional(child, frame, e);
throw e;
}

return result;
}

@Override
public RubyArray executeArray(VirtualFrame frame) throws UnexpectedResultException {
probeNode.enter(child, frame);

RubyArray result;

try {
result = child.executeArray(frame);
probeNode.returnValue(child, frame, result);
} catch (KillException e) {
throw e;
} catch (Exception e) {
probeNode.returnExceptional(child, frame, e);
throw e;
}

return result;
}

@Override
public RubyBignum executeBignum(VirtualFrame frame) throws UnexpectedResultException {
probeNode.enter(child, frame);

RubyBignum result;

try {
result = child.executeBignum(frame);
probeNode.returnValue(child, frame, result);
} catch (KillException e) {
throw e;
} catch (Exception e) {
probeNode.returnExceptional(child, frame, e);
throw e;
}

return result;
}

@Override
public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException {
probeNode.enter(child, frame);

boolean result;

try {
result = child.executeBoolean(frame);
probeNode.returnValue(child, frame, result);
} catch (KillException e) {
throw e;
} catch (Exception e) {
probeNode.returnExceptional(child, frame, e);
throw e;
}

return result;
}

@Override
public Object isDefined(VirtualFrame frame) {
return child.isDefined(frame);
}

@Override
public int executeIntegerFixnum(VirtualFrame frame) throws UnexpectedResultException {
probeNode.enter(child, frame);

int result;

try {
result = child.executeIntegerFixnum(frame);
probeNode.returnValue(child, frame, result);
} catch (KillException e) {
throw e;
} catch (Exception e) {
probeNode.returnExceptional(child, frame, e);
throw e;
}

return result;
}

@Override
public long executeLongFixnum(VirtualFrame frame) throws UnexpectedResultException {
probeNode.enter(child, frame);

long result;

try {
result = child.executeLongFixnum(frame);
probeNode.returnValue(child, frame, result);
} catch (KillException e) {
throw e;
} catch (Exception e) {
probeNode.returnExceptional(child, frame, e);
throw e;
}

return result;
}

@Override
public double executeFloat(VirtualFrame frame) throws UnexpectedResultException {
probeNode.enter(child, frame);

double result;

try {
result = child.executeFloat(frame);
probeNode.returnValue(child, frame, result);
} catch (KillException e) {
throw e;
} catch (Exception e) {
probeNode.returnExceptional(child, frame, e);
throw e;
}

return result;
}

@Override
public RubyString executeString(VirtualFrame frame) throws UnexpectedResultException {
probeNode.enter(child, frame);

RubyString result;

try {
result = child.executeString(frame);
probeNode.returnValue(child, frame, result);
} catch (KillException e) {
throw e;
} catch (Exception e) {
probeNode.returnExceptional(child, frame, e);
throw e;
}

return result;
}

@Override
public void executeVoid(VirtualFrame frame) {
probeNode.enter(child, frame);

try {
child.executeVoid(frame);
probeNode.returnVoid(child, frame);
} catch (KillException e) {
throw e;
} catch (Exception e) {
probeNode.returnExceptional(child, frame, e);
throw e;
}
}

@Override
public Probe probe() {
throw new UnsupportedOperationException("Cannot call probe() on a wrapper.");
}

@Override
public void probeLite(TruffleEventReceiver eventReceiver) {
throw new UnsupportedOperationException("Cannot call probeLite() on a wrapper.");
}
}

0 comments on commit 6327ad1

Please sign in to comment.