/*
* Copyright (c) 2014, 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.impl;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.InstrumentInfo;
import com.oracle.truffle.api.RootCallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.TruffleLanguage.Env;
import com.oracle.truffle.api.TruffleOptions;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.nodes.LanguageInfo;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
/**
* Communication between PolyglotEngine, TruffleLanguage API/SPI, and other services.
*/
public abstract class Accessor {
@SuppressWarnings("all")
protected final Collection<ClassLoader> loaders() {
return TruffleLocator.loaders();
}
public abstract static class Nodes {
public abstract boolean isInstrumentable(RootNode rootNode);
public abstract boolean isTaggedWith(Node node, Class<?> tag);
public abstract boolean isCloneUninitializedSupported(RootNode rootNode);
public abstract RootNode cloneUninitialized(RootNode rootNode);
public abstract Object getEngineObject(LanguageInfo languageInfo);
public abstract TruffleLanguage<?> getLanguageSpi(LanguageInfo languageInfo);
public abstract void setLanguageSpi(LanguageInfo languageInfo, TruffleLanguage<?> spi);
public abstract LanguageInfo createLanguage(Object vmObject, String name, String version, Set<String> mimeTypes);
}
public abstract static class DumpSupport {
public abstract void dump(Node newNode, Node newChild, CharSequence reason);
}
public abstract static class InteropSupport {
public abstract boolean canHandle(Object foreignAccess, Object receiver);
public abstract CallTarget canHandleTarget(Object access);
}
public abstract static class JavaInteropSupport {
public abstract Node createToJavaNode();
public abstract Object toJava(Node toJavaNode, Class<?> type, Object value);
}
public abstract static class EngineSupport {
public static final int EXECUTION_EVENT = 1;
public static final int SUSPENDED_EVENT = 2;
@SuppressWarnings("deprecation")
public abstract <C> com.oracle.truffle.api.impl.FindContextNode<C> createFindContextNode(TruffleLanguage<C> lang);
@SuppressWarnings("rawtypes")
public abstract Env findEnv(Object vm, Class<? extends TruffleLanguage> languageClass, boolean failIfNotFound);
public abstract Object getInstrumentationHandler(Object languageShared);
public abstract Iterable<? extends Object> importSymbols(Object languageShared, Env env, String globalName);
public abstract boolean isMimeTypeSupported(Object languageShared, String mimeType);
public abstract void registerDebugger(Object vm, Object debugger);
public abstract boolean isEvalRoot(RootNode target);
public abstract Object findOriginalObject(Object truffleObject);
public abstract CallTarget lookupOrRegisterComputation(Object truffleObject, RootNode symbolNode, Object... keyOrKeys);
@SuppressWarnings("static-method")
public final void attachOutputConsumer(DispatchOutputStream dos, OutputStream out) {
dos.attach(out);
}
@SuppressWarnings("static-method")
public final void detachOutputConsumer(DispatchOutputStream dos, OutputStream out) {
dos.detach(out);
}
public abstract Object getCurrentVM();
public abstract Env getEnvForLanguage(Object languageShared, String mimeType);
public abstract Env getEnvForInstrument(Object vm, String mimeType);
public abstract Env getEnvForInstrument(LanguageInfo language);
public abstract Object contextReferenceGet(Object reference);
public abstract boolean isDisposed(Object vmInstance);
public abstract Map<String, LanguageInfo> getLanguages(Object vmInstance);
public abstract Map<String, InstrumentInfo> getInstruments(Object vmInstance);
public abstract <T> T lookup(InstrumentInfo info, Class<T> serviceClass);
public abstract <S> S lookup(LanguageInfo language, Class<S> type);
}
public abstract static class LanguageSupport {
public abstract void initializeLanguage(LanguageInfo language, TruffleLanguage<?> impl, boolean legacyLanguage);
public abstract Env createEnv(Object vmObject, LanguageInfo info, OutputStream stdOut, OutputStream stdErr, InputStream stdIn, Map<String, Object> config);
public abstract void postInitEnv(Env env);
public abstract Object evalInContext(Object sourceVM, String code, Node node, MaterializedFrame frame);
public abstract Object findExportedSymbol(TruffleLanguage.Env env, String globalName, boolean onlyExplicit);
public abstract Object languageGlobal(TruffleLanguage.Env env);
public abstract void dispose(Env env);
public abstract LanguageInfo getLanguageInfo(TruffleLanguage.Env env);
public abstract LanguageInfo getLanguageInfo(TruffleLanguage<?> language);
public abstract LanguageInfo getLegacyLanguageInfo(@SuppressWarnings("rawtypes") Class<? extends TruffleLanguage> languageClass);
public abstract CallTarget parse(Env env, Source code, Node context, String... argumentNames);
public abstract String toStringIfVisible(Env env, Object obj, boolean checkVisibility);
public abstract Object findMetaObject(Env env, Object value);
public abstract SourceSection findSourceLocation(Env env, Object value);
public abstract Object getContext(Env env);
public abstract InstrumentInfo createInstrument(Object vmObject, String id, String name, String version);
public abstract Object getVMObject(InstrumentInfo info);
public abstract <S> S lookup(LanguageInfo languageEnsureInitialized, Class<S> type);
public abstract boolean isContextInitialized(Env env);
}
public abstract static class InstrumentSupport {
public abstract void addInstrument(Object instrumentationHandler, Object key, Class<?> instrumentClass, String[] expectedServices);
public abstract void disposeInstrument(Object instrumentationHandler, Object key, boolean cleanupRequired);
public abstract <T> T getInstrumentationHandlerService(Object handler, Object key, Class<T> type);
public abstract Object createInstrumentationHandler(Object vm, DispatchOutputStream out, DispatchOutputStream err, InputStream in);
public abstract void collectEnvServices(Set<Object> collectTo, Object languageShared, LanguageInfo languageInfo);
public abstract void onFirstExecution(RootNode rootNode);
public abstract void onLoad(RootNode rootNode);
@SuppressWarnings("static-method")
public final DispatchOutputStream createDispatchOutput(OutputStream out) {
if (out instanceof DispatchOutputStream) {
return (DispatchOutputStream) out;
}
return new DispatchOutputStream(out);
}
}
protected abstract static class Frames {
protected abstract void markMaterializeCalled(FrameDescriptor descriptor);
protected abstract boolean getMaterializeCalled(FrameDescriptor descriptor);
}
private static Accessor.LanguageSupport API;
private static Accessor.EngineSupport SPI;
private static Accessor.Nodes NODES;
private static Accessor.InstrumentSupport INSTRUMENTHANDLER;
private static Accessor.DumpSupport DUMP;
private static Accessor.InteropSupport INTEROP;
private static Accessor.JavaInteropSupport JAVAINTEROP;
private static Accessor.Frames FRAMES;
@SuppressWarnings("unused") private static Accessor SOURCE;
static {
TruffleLanguage<?> lng = new TruffleLanguage<Object>() {
@Override
protected Object findExportedSymbol(Object context, String globalName, boolean onlyExplicit) {
return null;
}
@Override
protected Object getLanguageGlobal(Object context) {
return null;
}
@Override
protected boolean isObjectOfLanguage(Object object) {
return false;
}
@Override
protected Object createContext(TruffleLanguage.Env env) {
return null;
}
};
lng.hashCode();
new Node() {
}.getRootNode();
conditionallyInitDebugger();
conditionallyInitEngine();
conditionallyInitJavaInterop();
if (TruffleOptions.TraceASTJSON) {
try {
Class.forName("com.oracle.truffle.api.utilities.JSONHelper", true, Accessor.class.getClassLoader());
} catch (ClassNotFoundException ex) {
throw new IllegalStateException(ex);
}
}
}
@SuppressWarnings("all")
private static void conditionallyInitDebugger() throws IllegalStateException {
try {
Class.forName("com.oracle.truffle.api.debug.Debugger", true, Accessor.class.getClassLoader());
} catch (ClassNotFoundException ex) {
boolean assertOn = false;
assert assertOn = true;
if (!assertOn) {
throw new IllegalStateException(ex);
}
}
}
@SuppressWarnings("all")
private static void conditionallyInitEngine() throws IllegalStateException {
try {
Class.forName("com.oracle.truffle.api.vm.PolyglotEngine", true, Accessor.class.getClassLoader());
} catch (ClassNotFoundException ex) {
boolean assertOn = false;
assert assertOn = true;
if (!assertOn) {
throw new IllegalStateException(ex);
}
}
}
@SuppressWarnings("all")
private static void conditionallyInitJavaInterop() throws IllegalStateException {
try {
Class.forName("com.oracle.truffle.api.interop.java.JavaInterop", true, Accessor.class.getClassLoader());
} catch (ClassNotFoundException ex) {
boolean assertOn = false;
assert assertOn = true;
if (!assertOn) {
throw new IllegalStateException(ex);
}
}
}
protected Accessor() {
if (!this.getClass().getName().startsWith("com.oracle.truffle.api")) {
throw new IllegalStateException();
}
if (this.getClass().getSimpleName().endsWith("API")) {
if (API != null) {
throw new IllegalStateException();
}
API = this.languageSupport();
} else if (this.getClass().getSimpleName().endsWith("Nodes")) {
if (NODES != null) {
throw new IllegalStateException();
}
NODES = this.nodes();
} else if (this.getClass().getSimpleName().endsWith("InstrumentHandler")) {
if (INSTRUMENTHANDLER != null) {
throw new IllegalStateException();
}
INSTRUMENTHANDLER = this.instrumentSupport();
} else if (this.getClass().getSimpleName().endsWith("Frames")) {
if (FRAMES != null) {
throw new IllegalStateException();
}
FRAMES = this.framesSupport();
} else if (this.getClass().getSimpleName().endsWith("SourceAccessor")) {
SOURCE = this;
} else if (this.getClass().getSimpleName().endsWith("DumpAccessor")) {
DUMP = this.dumpSupport();
} else if (this.getClass().getSimpleName().endsWith("JavaInteropAccessor")) {
JAVAINTEROP = this.javaInteropSupport();
} else if (this.getClass().getSimpleName().endsWith("InteropAccessor")) {
INTEROP = this.interopSupport();
} else if (this.getClass().getSimpleName().endsWith("ScopeAccessor")) {
// O.K.
} else {
if (SPI != null) {
throw new IllegalStateException();
}
SPI = this.engineSupport();
}
}
protected Accessor.Nodes nodes() {
return NODES;
}
protected LanguageSupport languageSupport() {
return API;
}
protected DumpSupport dumpSupport() {
return DUMP;
}
protected EngineSupport engineSupport() {
return SPI;
}
protected InstrumentSupport instrumentSupport() {
return INSTRUMENTHANDLER;
}
protected InteropSupport interopSupport() {
return INTEROP;
}
protected JavaInteropSupport javaInteropSupport() {
return JAVAINTEROP;
}
static InstrumentSupport instrumentAccess() {
return INSTRUMENTHANDLER;
}
static LanguageSupport languageAccess() {
return API;
}
static EngineSupport engineAccess() {
return SPI;
}
static Accessor.Nodes nodesAccess() {
return NODES;
}
protected Accessor.Frames framesSupport() {
return FRAMES;
}
static Accessor.Frames framesAccess() {
return FRAMES;
}
/**
* Don't call me. I am here only to let NetBeans debug any Truffle project.
*
* @param args
*/
public static void main(String... args) {
throw new IllegalStateException();
}
private static final TVMCI SUPPORT = Truffle.getRuntime().getCapability(TVMCI.class);
@SuppressWarnings("deprecation")
protected void onLoopCount(Node source, int iterations) {
if (SUPPORT != null) {
SUPPORT.onLoopCount(source, iterations);
} else {
// needs an additional compatibility check so older graal runtimes
// still run with newer truffle versions
RootNode root = source.getRootNode();
if (root != null) {
RootCallTarget target = root.getCallTarget();
if (target instanceof com.oracle.truffle.api.LoopCountReceiver) {
((com.oracle.truffle.api.LoopCountReceiver) target).reportLoopCount(iterations);
}
}
}
}
/*
* Do not remove: This is accessed reflectively in AccessorTest
*/
static <T extends TruffleLanguage<?>> T findLanguageByClass(Object vm, Class<T> languageClass) {
Env env = SPI.findEnv(vm, languageClass, true);
TruffleLanguage<?> language = NODES.getLanguageSpi(API.getLanguageInfo(env));
return languageClass.cast(language);
}
}