Class Instrument

java.lang.Object
com.oracle.truffle.api.instrument.Instrument

public final class Instrument extends Object
A dynamically added/removed binding between a Probe, which provides notification of execution events taking place at a Node in a Guest Language (GL) Truffle AST, and a receiver, which consumes notifications on behalf of an external tool.

Summary: How to "instrument" an AST location:

  1. Create an implementation of TruffleEventReceiver that responds to events on behalf of a tool.
  2. Create an Instrument via factory method create(TruffleEventReceiver).
  3. "Attach" the Instrument to a Probe via Probe.attach(Instrument), at which point event notifications begin to arrive at the receiver.
  4. When no longer needed, "detach" the Instrument via dispose(), at which point event notifications to the receiver cease, and the Instrument becomes unusable.

Options for creating receivers:

  1. Implement the interface TruffleEventReceiver. The event handling methods account for both the entry into an AST node (about to call) and several possible kinds of exit from an AST node (just returned).
  2. Extend DefaultEventReceiver, which provides a no-op implementation of every TruffleEventReceiver method; override the methods of interest.
  3. Extend SimpleEventReceiver, where return values are ignored so only two methods (for "enter" and "return") will notify all events.

General guidelines for receiver implementation:

When an Instrument is attached to a Probe, the receiver effectively becomes part of the executing GL program; performance can be affected by the receiver's implementation.

  • Do not store Frame or Node references in fields.
  • Prefer final fields and (where performance is important) short methods.
  • If needed, pass along the VirtualFrame reference from an event notification as far as possible through code that is expected to be inlined, since this incurs no runtime overhead. When access to frame data is needed, substitute a more expensive materialized representation of the frame.
  • If a receiver calls back to its tool during event handling, and if performance is an issue, then this should be through a final "callback" field in the instrument, and the called methods should be minimal.
  • On the other hand, implementations should prevent Truffle from inlining beyond a reasonable point with the method annotation CompilerDirectives.TruffleBoundary.
  • The implicit "outer" pointer in a non-static inner class is a useful way to implement callbacks to owner tools.
  • Primitive-valued return events are boxed for notification, but Truffle will eliminate the boxing if they are cast back to their primitive values quickly (in particular before crossing any CompilerDirectives.TruffleBoundary annotations).

Allowing for AST cloning:

Truffle routinely clones ASTs, which has consequences for receiver implementation.

  • Even though a Probe is uniquely associated with a particular location in the executing Guest Language program, execution events at that location will in general be implemented by different Node instances, i.e. clones of the originally probed node.
  • Because of cloning the Node supplied with notifications to a particular receiver will vary, but because they all represent the same GL program location the events should be treated as equivalent for most purposes.

Access to execution state:

  • Event notification arguments provide primary access to the GL program's execution states:
    • Node: the concrete node (in one of the AST's clones) from which the event originated.
    • VirtualFrame: the current execution frame.
  • Some global information is available, for example the execution stack.
  • Additional information needed by a receiver could be stored when created, preferably final of course. For example, a reference to the Probe to which the receiver's Instrument has been attached would give access to its corresponding source location or to the collection of tags currently applied to the Probe.

Activating and deactivating Instruments:

Instruments are single-use:

  • An instrument becomes active only when attached to a Probe via Probe.attach(Instrument), and it may only be attached to a single Probe. It is a runtime error to attempt attaching a previously attached instrument.
  • Attaching an instrument modifies every existing clone of the AST to which it is being attached, which can trigger deoptimization.
  • The method dispose() makes an instrument inactive by removing it from the Probe to which it was attached and rendering it permanently inert.
  • Disposal removes the implementation of an instrument from all ASTs to which it was attached, which can trigger deoptimization.

Sharing receivers:

Although an Instrument may only be attached to a single Probe, a receiver can be shared among multiple Instruments. This can be useful for observing events that might happen at different locations in a single AST, for example all assignments to a particular variable. In this case a new Instrument would be created and attached at each assignment node, but all the Instruments would be created with the same receiver.

Disclaimer: experimental; under development.

See Also:
  • Method Details

    • create

      public static Instrument create(TruffleEventReceiver receiver, String instrumentInfo)
      Creates an instrument that will route execution events to a receiver.
      Parameters:
      receiver - a receiver for event generated by the instrument
      instrumentInfo - optional description of the instrument's role
      Returns:
      a new instrument, ready for attachment at a probe
    • create

      public static Instrument create(TruffleEventReceiver receiver)
      Creates an instrument that will route execution events to a receiver.
    • dispose

      public void dispose() throws IllegalStateException
      Removes this instrument (and any clones) from the probe to which it attached and renders the instrument inert.
      Throws:
      IllegalStateException - if this instrument has already been disposed