com.oracle.truffle.api.instrumentation.TruffleInstrument Maven / Gradle / Ivy
Show all versions of truffle-api Show documentation
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.api.instrumentation;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.source.Source;
/**
*
* The service provider interface (SPI) for instruments: clients of Truffle instrumentation
* that may observe and inject behavior into interpreters written using the Truffle framework. A
* registered instrument may be created and disposed multiple times; only one instance is ever
* active per {@linkplain com.oracle.truffle.api.vm.PolyglotEngine engine}.
*
* Registration
*
* Instrument implementation classes must use the {@link Registration} annotation to provide
* required metadata and to enable automatic discovery of the implementation.
*
* Instrument Creation
*
* - A newly created instrument is notified once via {@link #onCreate(Env)}.
* - The {@link Instrumenter} instance available in the provided {@linkplain Env environment}
* allows the instrument to bind listeners and node factories to guest language code locations.
*
* Instrument Disposal
*
* - An instrument that will no longer be used is notified once via {@link #onDispose(Env)}.
* - Any active bindings created by the disposed instrument will be disposed automatically by the
* framework.
* - The {@link Instrumenter} instance available in the provided {@linkplain Env environment} may
* not be used after disposal.
*
* Example
*
* Example for a simple expression coverage instrument:
*
*
* @Registration(name = Coverage.NAME, version = Coverage.VERSION, instrumentType = Coverage.TYPE)
* @RequiredTags("EXPRESSION")
* public final class Coverage extends TruffleInstrument {
*
* public static final String NAME = "sample-coverage";
* public static final String TYPE = "coverage";
* public static final String VERSION = "coverage";
*
* private final Set<SourceSection> coverage = new HashSet<>();
*
* @Override
* protected void onCreate(Env env, Instrumenter instrumenter) {
* instrumenter.attachFactory(SourceSectionFilter.newBuilder() //
* .tagIs("EXPRESSION").build(), new EventNodeFactory() {
* public EventNode create(final EventContext context) {
* return new EventNode() {
* @CompilationFinal private boolean visited;
*
* @Override
* public void onReturnValue(VirtualFrame vFrame, Object result) {
* if (!visited) {
* CompilerDirectives.transferToInterpreterAndInvalidate();
* visited = true;
* coverage.add(context.getInstrumentedSourceSection());
* }
* }
* };
* }
* });
* }
*
* @Override
* protected void onDispose(Env env) {
* // print result
* }
*
* }
*
*
* @since 0.12
*/
public abstract class TruffleInstrument {
/**
* Constructor for subclasses.
*
* @since 0.12
*/
protected TruffleInstrument() {
}
/**
* Invoked once on each newly allocated {@link TruffleInstrument} instance.
*
* The method may {@link Env#registerService(java.lang.Object) register} additional
* services - e.g. objects to be exposed via
* {@link com.oracle.truffle.api.vm.PolyglotEngine.Instrument#lookup} query. For example to
* expose a debugger one could define an abstract debugger controller:
*
*
* {@codesnippet DebuggerController}
*
* and then implement it, instantiate and @link Env#registerService(java.lang.Object) register}
* in own's instrument
* {@link #onCreate(com.oracle.truffle.api.instrumentation.TruffleInstrument.Env) onCreate}
* method:
*
* {@codesnippet DebuggerExample}
*
* @param env environment information for the instrument
*
* @see Env#getInstrumenter()
* @since 0.12
*/
protected abstract void onCreate(Env env);
/**
* Invoked once on an {@linkplain TruffleInstrument instance} when it is no longer needed,
* possibly because the underlying {@linkplain com.oracle.truffle.api.vm.PolyglotEngine engine}
* has been disposed. A disposed instance is no longer usable. If the instrument is re-enabled,
* the engine will create a new instance.
*
* @param env environment information for the instrument
* @since 0.12
*/
protected void onDispose(Env env) {
// default implementation does nothing
}
/**
* Provides ways and means to access input, output and error streams. Also allows to parse
* arbitrary code from other Truffle languages.
*
* @since 0.12
*/
public static final class Env {
private final Instrumenter instrumenter;
private final InputStream in;
private final OutputStream err;
private final OutputStream out;
private List