Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2017, 2018, 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.polyglot;
import static com.oracle.truffle.polyglot.VMAccessor.LANGUAGE;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Engine;
import org.graalvm.polyglot.Value;
import org.graalvm.polyglot.impl.AbstractPolyglotImpl.AbstractContextImpl;
import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.TruffleContext;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.TruffleOptions;
import com.oracle.truffle.polyglot.HostLanguage.HostContext;
final class PolyglotContextImpl extends AbstractContextImpl implements com.oracle.truffle.polyglot.PolyglotImpl.VMObject {
/**
* This class isolates static state to optimize when only a single context is used. This
* simplifies resetting state in AOT mode during native image generation.
*/
static final class SingleContextState {
private final ContextThreadLocal contextThreadLocal = new ContextThreadLocal();
private final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("Single Context");
@CompilationFinal private volatile PolyglotContextImpl singleContext;
}
@CompilationFinal private static SingleContextState singleContextState = new SingleContextState();
/*
* Used from testing using reflection. Its invalid to call it anywhere else than testing. Used
* in ContextLookupCompilationTest.
*/
static void resetSingleContextState() {
singleContextState = new SingleContextState();
}
private static final Object NO_ENTER = new Object();
private final Assumption singleThreaded = Truffle.getRuntime().createAssumption("Single threaded");
private final Assumption singleThreadedConstant = Truffle.getRuntime().createAssumption("Single threaded constant thread");
private final Map threads = new HashMap<>();
private volatile PolyglotThreadInfo currentThreadInfo = PolyglotThreadInfo.NULL;
@CompilationFinal private volatile PolyglotThreadInfo constantCurrentThreadInfo = PolyglotThreadInfo.NULL;
/*
* While canceling the context can no longer be entered. The context goes from canceling into
* closed state.
*/
volatile boolean cancelling;
private volatile Thread closingThread;
/*
* If the context is closed all operations should fail with IllegalStateException.
*/
volatile boolean closed;
final PolyglotEngineImpl engine;
@CompilationFinal(dimensions = 1) final PolyglotLanguageContext[] contexts;
Context creatorApi; // effectively final
Context currentApi; // effectively final
final TruffleContext truffleContext;
final PolyglotContextImpl parent;
final Map polyglotBindings; // for direct legacy access
final Value polyglotHostBindings; // for accesses from the polyglot api
final PolyglotLanguage creator; // creator for internal contexts
final Map creatorArguments; // special arguments for internal contexts
@CompilationFinal PolyglotContextConfig config; // effectively final
// map from class to language index
@CompilationFinal private FinalIntMap languageIndexMap;
private final List childContexts = new ArrayList<>();
boolean inContextPreInitialization; // effectively final
/* Constructor for testing. */
private PolyglotContextImpl() {
super(null);
this.engine = null;
this.contexts = null;
this.truffleContext = null;
this.parent = null;
this.polyglotHostBindings = null;
this.polyglotBindings = null;
this.creator = null;
this.creatorArguments = null;
}
/*
* Constructor for outer contexts.
*/
PolyglotContextImpl(PolyglotEngineImpl engine, PolyglotContextConfig config) {
super(engine.impl);
this.parent = null;
this.engine = engine;
this.config = config;
this.creator = null;
this.creatorArguments = Collections.emptyMap();
this.truffleContext = VMAccessor.LANGUAGE.createTruffleContext(this);
this.polyglotBindings = new ConcurrentHashMap<>();
this.contexts = createContextArray();
if (!config.logLevels.isEmpty()) {
VMAccessor.LANGUAGE.configureLoggers(this, config.logLevels);
}
PolyglotLanguageContext hostContext = getContextInitialized(engine.hostLanguage, null);
this.polyglotHostBindings = getAPIAccess().newValue(polyglotBindings, new PolyglotBindingsValue(hostContext));
notifyContextCreated();
PolyglotContextImpl.initializeStaticContext(this);
}
/*
* Constructor for inner contexts.
*/
@SuppressWarnings("hiding")
PolyglotContextImpl(PolyglotLanguageContext creator, Map langConfig, TruffleContext spiContext) {
super(creator.getEngine().impl);
PolyglotContextImpl parent = creator.context;
this.parent = parent;
this.config = parent.config;
this.engine = parent.engine;
this.creator = creator.language;
this.creatorArguments = langConfig;
this.parent.addChildContext(this);
this.truffleContext = spiContext;
this.polyglotBindings = new ConcurrentHashMap<>();
if (!parent.config.logLevels.isEmpty()) {
VMAccessor.LANGUAGE.configureLoggers(this, parent.config.logLevels);
}
this.contexts = createContextArray();
this.polyglotHostBindings = getAPIAccess().newValue(polyglotBindings, new PolyglotBindingsValue(getHostContext()));
// notifyContextCreated() is called after spiContext.impl is set to this.
initializeStaticContext(this);
}
private PolyglotLanguageContext[] createContextArray() {
Collection languages = engine.idToLanguage.values();
PolyglotLanguageContext[] newContexts = new PolyglotLanguageContext[languages.size() + (PolyglotEngineImpl.HOST_LANGUAGE_INDEX + 1)];
Iterator languageIterator = languages.iterator();
PolyglotLanguageContext hostContext = new PolyglotLanguageContext(this, engine.hostLanguage);
newContexts[PolyglotEngineImpl.HOST_LANGUAGE_INDEX] = hostContext;
for (int i = (PolyglotEngineImpl.HOST_LANGUAGE_INDEX + 1); i < languages.size() + 1; i++) {
PolyglotLanguage language = languageIterator.next();
newContexts[i] = new PolyglotLanguageContext(this, language);
}
hostContext.ensureInitialized(null);
((HostContext) hostContext.getContextImpl()).internalContext = hostContext;
return newContexts;
}
/**
* Marks a context used globally. Potentially invalidating the global single context assumption.
*/
static void initializeStaticContext(PolyglotContextImpl context) {
SingleContextState state = singleContextState;
if (state.singleContextAssumption.isValid()) {
synchronized (state) {
if (state.singleContextAssumption.isValid()) {
if (state.singleContext != null) {
state.singleContextAssumption.invalidate();
state.singleContext = null;
} else {
state.singleContext = context;
}
}
}
}
}
/**
* Marks all code from this context as unusable. Its important that a context is only disposed
* there is no code that could rely on the singleContextAssumption.
*/
static void disposeStaticContext(PolyglotContextImpl context) {
SingleContextState state = singleContextState;
if (state.singleContextAssumption.isValid()) {
synchronized (state) {
if (state.singleContextAssumption.isValid()) {
assert state.singleContext == context;
state.singleContext = null;
}
}
}
}
PolyglotLanguageContext getContext(PolyglotLanguage language) {
return contexts[language.index];
}
PolyglotLanguageContext getContextInitialized(PolyglotLanguage language, PolyglotLanguage accessingLanguage) {
PolyglotLanguageContext context = getContext(language);
context.ensureInitialized(accessingLanguage);
return context;
}
void notifyContextCreated() {
VMAccessor.INSTRUMENT.notifyContextCreated(engine, truffleContext);
}
private synchronized void addChildContext(PolyglotContextImpl child) {
if (closingThread != null) {
throw new IllegalStateException("Adding child context into a closing context.");
}
childContexts.add(child);
}
static PolyglotContextImpl current() {
if (singleContextState.singleContextAssumption.isValid()) {
if (singleContextState.contextThreadLocal.isSet()) {
return singleContextState.singleContext;
} else {
CompilerDirectives.transferToInterpreter();
return null;
}
} else {
return (PolyglotContextImpl) singleContextState.contextThreadLocal.get();
}
}
static PolyglotContextImpl requireContext() {
PolyglotContextImpl context = current();
if (context == null) {
CompilerDirectives.transferToInterpreter();
context = current();
if (context == null) {
throw new AssertionError("No current context available.");
}
}
return context;
}
@Override
public synchronized void explicitEnter(Context sourceContext) {
checkCreatorAccess(sourceContext, "entered");
Object prev = enter();
PolyglotThreadInfo current = getCurrentThreadInfo();
assert current.thread == Thread.currentThread();
current.explicitContextStack.addLast(prev);
}
@Override
public synchronized void explicitLeave(Context sourceContext) {
checkCreatorAccess(sourceContext, "left");
PolyglotThreadInfo current = getCurrentThreadInfo();
LinkedList