/*
 * Copyright (c) 2010, 2013, 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 jdk.nashorn.internal.runtime;

import static jdk.internal.org.objectweb.asm.Opcodes.V1_7;
import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
import static jdk.nashorn.internal.runtime.CodeStore.newCodeStore;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.Source.sourceFor;

import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.SwitchPoint;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReader;
import java.lang.module.ModuleReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.script.ScriptEngine;
import jdk.dynalink.DynamicLinker;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
import jdk.nashorn.api.scripting.ClassFilter;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.WeakValueCache;
import jdk.nashorn.internal.codegen.Compiler;
import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.debug.ASTWriter;
import jdk.nashorn.internal.ir.debug.PrintVisitor;
import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.Parser;
import jdk.nashorn.internal.runtime.events.RuntimeEvent;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
import jdk.nashorn.internal.runtime.options.Options;
import jdk.internal.misc.Unsafe;

/**
 * This class manages the global state of execution. Context is immutable.
 */
public final class Context {
    // nashorn specific security runtime access permission names
    /**
     * Permission needed to pass arbitrary nashorn command line options when creating Context.
     */
    public static final String NASHORN_SET_CONFIG      = "nashorn.setConfig";

    /**
     * Permission needed to create Nashorn Context instance.
     */
    public static final String NASHORN_CREATE_CONTEXT  = "nashorn.createContext";

    /**
     * Permission needed to create Nashorn Global instance.
     */
    public static final String NASHORN_CREATE_GLOBAL   = "nashorn.createGlobal";

    /**
     * Permission to get current Nashorn Context from thread local storage.
     */
    public static final String NASHORN_GET_CONTEXT     = "nashorn.getContext";

    /**
     * Permission to use Java reflection/jsr292 from script code.
     */
    public static final String NASHORN_JAVA_REFLECTION = "nashorn.JavaReflection";

    /**
     * Permission to enable nashorn debug mode.
     */
    public static final String NASHORN_DEBUG_MODE = "nashorn.debugMode";

    // nashorn load psuedo URL prefixes
    private static final String LOAD_CLASSPATH = "classpath:";
    private static final String LOAD_FX = "fx:";
    private static final String LOAD_NASHORN = "nashorn:";

    private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
    private static final MethodType CREATE_PROGRAM_FUNCTION_TYPE = MethodType.methodType(ScriptFunction.class, ScriptObject.class);

    private static final LongAdder NAMED_INSTALLED_SCRIPT_COUNT = new LongAdder();
    private static final LongAdder ANONYMOUS_INSTALLED_SCRIPT_COUNT = new LongAdder();

    /**
     * Should scripts use only object slots for fields, or dual long/object slots? The default
     * behaviour is to couple this to optimistic types, using dual representation if optimistic types are enabled
     * and single field representation otherwise. This can be overridden by setting either the "nashorn.fields.objects"
     * or "nashorn.fields.dual" system property.
     */
    private final FieldMode fieldMode;

    private static enum FieldMode {
        /** Value for automatic field representation depending on optimistic types setting */
        AUTO,
        /** Value for object field representation regardless of optimistic types setting */
        OBJECTS,
        /** Value for dual primitive/object field representation regardless of optimistic types setting */
        DUAL
    }

    /**
     * Keeps track of which builtin prototypes and properties have been relinked
     * Currently we are conservative and associate the name of a builtin class with all
     * its properties, so it's enough to invalidate a property to break all assumptions
     * about a prototype. This can be changed to a more fine grained approach, but no one
     * ever needs this, given the very rare occurrence of swapping out only parts of
     * a builtin v.s. the entire builtin object
     */
    private final Map<String, SwitchPoint> builtinSwitchPoints = new HashMap<>();

    /* Force DebuggerSupport to be loaded. */
    static {
        DebuggerSupport.FORCELOAD = true;
    }

    static long getNamedInstalledScriptCount() {
        return NAMED_INSTALLED_SCRIPT_COUNT.sum();
    }

    static long getAnonymousInstalledScriptCount() {
        return ANONYMOUS_INSTALLED_SCRIPT_COUNT.sum();
    }

    /**
     * ContextCodeInstaller that has the privilege of installing classes in the Context.
     * Can only be instantiated from inside the context and is opaque to other classes
     */
    private abstract static class ContextCodeInstaller implements CodeInstaller {
        final Context context;
        final CodeSource codeSource;

        ContextCodeInstaller(final Context context, final CodeSource codeSource) {
            this.context = context;
            this.codeSource = codeSource;
        }

        @Override
        public Context getContext() {
            return context;
        }

        @Override
        public void initialize(final Collection<Class<?>> classes, final Source source, final Object[] constants) {
            try {
                AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
                    @Override
                    public Void run() throws Exception {
                        for (final Class<?> clazz : classes) {
                            //use reflection to write source and constants table to installed classes
                            final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName());
                            sourceField.setAccessible(true);
                            sourceField.set(null, source);

                            final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName());
                            constantsField.setAccessible(true);
                            constantsField.set(null, constants);
                        }
                        return null;
                    }
                });
            } catch (final PrivilegedActionException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void verify(final byte[] code) {
            context.verify(code);
        }

        @Override
        public long getUniqueScriptId() {
            return context.getUniqueScriptId();
        }

        @Override
        public void storeScript(final String cacheKey, final Source source, final String mainClassName,
                                final Map<String,byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers,
                                final Object[] constants, final int compilationId) {
            if (context.codeStore != null) {
                context.codeStore.store(cacheKey, source, mainClassName, classBytes, initializers, constants, compilationId);
            }
        }

        @Override
        public StoredScript loadScript(final Source source, final String functionKey) {
            if (context.codeStore != null) {
                return context.codeStore.load(source, functionKey);
            }
            return null;
        }

        @Override
        public boolean isCompatibleWith(final CodeInstaller other) {
            if (other instanceof ContextCodeInstaller) {
                final ContextCodeInstaller cci = (ContextCodeInstaller)other;
                return cci.context == context && cci.codeSource == codeSource;
            }
            return false;
        }
    }

    private static class NamedContextCodeInstaller extends ContextCodeInstaller {
        private final ScriptLoader loader;
        private int usageCount = 0;
        private int bytesDefined = 0;

        // We reuse this installer for 10 compilations or 200000 defined bytes. Usually the first condition
        // will occur much earlier, the second is a safety measure for very large scripts/functions.
        private final static int MAX_USAGES = 10;
        private final static int MAX_BYTES_DEFINED = 200_000;

        private NamedContextCodeInstaller(final Context context, final CodeSource codeSource, final ScriptLoader loader) {
            super(context, codeSource);
            this.loader = loader;
        }

        @Override
        public Class<?> install(final String className, final byte[] bytecode) {
            usageCount++;
            bytesDefined += bytecode.length;
            NAMED_INSTALLED_SCRIPT_COUNT.increment();
            return loader.installClass(Compiler.binaryName(className), bytecode, codeSource);
        }

        @Override
        public CodeInstaller getOnDemandCompilationInstaller() {
            // Reuse this installer if we're within our limits.
            if (usageCount < MAX_USAGES && bytesDefined < MAX_BYTES_DEFINED) {
                return this;
            }
            return new NamedContextCodeInstaller(context, codeSource, context.createNewLoader());
        }

        @Override
        public CodeInstaller getMultiClassCodeInstaller() {
            // This installer is perfectly suitable for installing multiple classes that reference each other
            // as it produces classes with resolvable names, all defined in a single class loader.
            return this;
        }
    }

    private final WeakValueCache<CodeSource, Class<?>> anonymousHostClasses = new WeakValueCache<>();

    private static final class AnonymousContextCodeInstaller extends ContextCodeInstaller {
        private static final Unsafe UNSAFE = Unsafe.getUnsafe();
        private static final String ANONYMOUS_HOST_CLASS_NAME = Compiler.SCRIPTS_PACKAGE.replace('/', '.') + ".AnonymousHost";
        private static final byte[] ANONYMOUS_HOST_CLASS_BYTES = getAnonymousHostClassBytes();

        private final Class<?> hostClass;

        private AnonymousContextCodeInstaller(final Context context, final CodeSource codeSource, final Class<?> hostClass) {
            super(context, codeSource);
            this.hostClass = hostClass;
        }

        @Override
        public Class<?> install(final String className, final byte[] bytecode) {
            ANONYMOUS_INSTALLED_SCRIPT_COUNT.increment();
            return UNSAFE.defineAnonymousClass(hostClass, bytecode, null);
        }

        @Override
        public CodeInstaller getOnDemandCompilationInstaller() {
            // This code loader can be indefinitely reused for on-demand recompilations for the same code source.
            return this;
        }

        @Override
        public CodeInstaller getMultiClassCodeInstaller() {
            // This code loader can not be used to install multiple classes that reference each other, as they
            // would have no resolvable names. Therefore, in such situation we must revert to an installer that
            // produces named classes.
            return new NamedContextCodeInstaller(context, codeSource, context.createNewLoader());
        }

        private static byte[] getAnonymousHostClassBytes() {
            final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
            cw.visit(V1_7, Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT, ANONYMOUS_HOST_CLASS_NAME.replace('.', '/'), null, "java/lang/Object", null);
            cw.visitEnd();
            return cw.toByteArray();
        }
    }

    /** Is Context global debug mode enabled ? */
    public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");

    private static final ThreadLocal<Global> currentGlobal = new ThreadLocal<>();

    // in-memory cache for loaded classes
    private ClassCache classCache;

    // persistent code store
    private CodeStore codeStore;

    // A factory for linking global properties as constant method handles. It is created when the first Global
    // is created, and invalidated forever once the second global is created.
    private final AtomicReference<GlobalConstants> globalConstantsRef = new AtomicReference<>();

    // Are java.sql, java.sql.rowset modules found in the system?
    static final boolean javaSqlFound, javaSqlRowsetFound;

    static {
        final ModuleLayer boot = ModuleLayer.boot();
        javaSqlFound = boot.findModule("java.sql").isPresent();
        javaSqlRowsetFound = boot.findModule("java.sql.rowset").isPresent();
    }

    /**
     * Get the current global scope
     * @return the current global scope
     */
    public static Global getGlobal() {
        // This class in a package.access protected package.
        // Trusted code only can call this method.
        return currentGlobal.get();
    }

    /**
     * Set the current global scope
     * @param global the global scope
     */
    public static void setGlobal(final ScriptObject global) {
        if (global != null && !(global instanceof Global)) {
            throw new IllegalArgumentException("not a global!");
        }
        setGlobal((Global)global);
    }

    /**
     * Set the current global scope
     * @param global the global scope
     */
    public static void setGlobal(final Global global) {
        // This class in a package.access protected package.
        // Trusted code only can call this method.
        assert getGlobal() != global;
        //same code can be cached between globals, then we need to invalidate method handle constants
        if (global != null) {
            final GlobalConstants globalConstants = getContext(global).getGlobalConstants();
            if (globalConstants != null) {
                globalConstants.invalidateAll();
            }
        }
        currentGlobal.set(global);
    }

    /**
     * Get context of the current global
     * @return current global scope's context.
     */
    public static Context getContext() {
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission(NASHORN_GET_CONTEXT));
        }
        return getContextTrusted();
    }

    /**
     * Get current context's error writer
     *
     * @return error writer of the current context
     */
    public static PrintWriter getCurrentErr() {
        final ScriptObject global = getGlobal();
        return (global != null)? global.getContext().getErr() : new PrintWriter(System.err);
    }

    /**
     * Output text to this Context's error stream
     * @param str text to write
     */
    public static void err(final String str) {
        err(str, true);
    }

    /**
     * Output text to this Context's error stream, optionally with
     * a newline afterwards
     *
     * @param str  text to write
     * @param crlf write a carriage return/new line after text
     */
    public static void err(final String str, final boolean crlf) {
        final PrintWriter err = Context.getCurrentErr();
        if (err != null) {
            if (crlf) {
                err.println(str);
            } else {
                err.print(str);
            }
        }
    }

    /** Current environment. */
    private final ScriptEnvironment env;

    /** is this context in strict mode? Cached from env. as this is used heavily. */
    final boolean _strict;

    /** class loader to resolve classes from script. */
    private final ClassLoader appLoader;

    /*package-private*/
    ClassLoader getAppLoader() {
        return appLoader;
    }

    /** Class loader to load classes compiled from scripts. */
    private final ScriptLoader scriptLoader;

    /** Dynamic linker for linking call sites in script code loaded by this context */
    private final DynamicLinker dynamicLinker;

    /** Current error manager. */
    private final ErrorManager errors;

    /** Unique id for script. Used only when --loader-per-compile=false */
    private final AtomicLong uniqueScriptId;

    /** Optional class filter to use for Java classes. Can be null. */
    private final ClassFilter classFilter;

    /** Process-wide singleton structure loader */
    private static final StructureLoader theStructLoader;
    private static final ConcurrentMap<String, Class<?>> structureClasses = new ConcurrentHashMap<>();

    /*package-private*/ @SuppressWarnings("static-method")
    StructureLoader getStructLoader() {
        return theStructLoader;
    }

    private static AccessControlContext createNoPermAccCtxt() {
        return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, new Permissions()) });
    }

    private static AccessControlContext createPermAccCtxt(final String permName) {
        final Permissions perms = new Permissions();
        perms.add(new RuntimePermission(permName));
        return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
    }

    private static final AccessControlContext NO_PERMISSIONS_ACC_CTXT = createNoPermAccCtxt();
    private static final AccessControlContext CREATE_LOADER_ACC_CTXT  = createPermAccCtxt("createClassLoader");
    private static final AccessControlContext CREATE_GLOBAL_ACC_CTXT  = createPermAccCtxt(NASHORN_CREATE_GLOBAL);
    private static final AccessControlContext GET_LOADER_ACC_CTXT     = createPermAccCtxt("getClassLoader");

    static {
        final ClassLoader myLoader = Context.class.getClassLoader();
        theStructLoader = AccessController.doPrivileged(new PrivilegedAction<StructureLoader>() {
            @Override
            public StructureLoader run() {
                return new StructureLoader(myLoader);
            }
        }, CREATE_LOADER_ACC_CTXT);
    }

    /**
     * ThrowErrorManager that throws ParserException upon error conditions.
     */
    public static class ThrowErrorManager extends ErrorManager {
        @Override
        public void error(final String message) {
            throw new ParserException(message);
        }

        @Override
        public void error(final ParserException e) {
            throw e;
        }
    }

    /**
     * Constructor
     *
     * @param options options from command line or Context creator
     * @param errors  error manger
     * @param appLoader application class loader
     */
    public Context(final Options options, final ErrorManager errors, final ClassLoader appLoader) {
        this(options, errors, appLoader, null);
    }

    /**
     * Constructor
     *
     * @param options options from command line or Context creator
     * @param errors  error manger
     * @param appLoader application class loader
     * @param classFilter class filter to use
     */
    public Context(final Options options, final ErrorManager errors, final ClassLoader appLoader, final ClassFilter classFilter) {
        this(options, errors, new PrintWriter(System.out, true), new PrintWriter(System.err, true), appLoader, classFilter);
    }

    /**
     * Constructor
     *
     * @param options options from command line or Context creator
     * @param errors  error manger
     * @param out     output writer for this Context
     * @param err     error writer for this Context
     * @param appLoader application class loader
     */
    public Context(final Options options, final ErrorManager errors, final PrintWriter out, final PrintWriter err, final ClassLoader appLoader) {
        this(options, errors, out, err, appLoader, (ClassFilter)null);
    }

    /**
     * Constructor
     *
     * @param options options from command line or Context creator
     * @param errors  error manger
     * @param out     output writer for this Context
     * @param err     error writer for this Context
     * @param appLoader application class loader
     * @param classFilter class filter to use
     */
    public Context(final Options options, final ErrorManager errors, final PrintWriter out, final PrintWriter err, final ClassLoader appLoader, final ClassFilter classFilter) {
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission(NASHORN_CREATE_CONTEXT));
        }

        this.classFilter = classFilter;
        this.env       = new ScriptEnvironment(options, out, err);
        this._strict   = env._strict;
        if (env._loader_per_compile) {
            this.scriptLoader = null;
            this.uniqueScriptId = null;
        } else {
            this.scriptLoader = createNewLoader();
            this.uniqueScriptId = new AtomicLong();
        }
        this.errors    = errors;

        // if user passed --module-path, we create a module class loader with
        // passed appLoader as the parent.
        final String modulePath = env._module_path;
        ClassLoader appCl = null;
        if (!env._compile_only && modulePath != null && !modulePath.isEmpty()) {
            // make sure that caller can create a class loader.
            if (sm != null) {
                sm.checkCreateClassLoader();
            }
            appCl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
                @Override
                public ClassLoader run() {
                    return createModuleLoader(appLoader, modulePath, env._add_modules);
                }
            });
        } else {
            appCl = appLoader;
        }

        // if user passed -classpath option, make a URLClassLoader with that and
        // the app loader or module app loader as the parent.
        final String classPath = env._classpath;
        if (!env._compile_only && classPath != null && !classPath.isEmpty()) {
            // make sure that caller can create a class loader.
            if (sm != null) {
                sm.checkCreateClassLoader();
            }
            appCl = NashornLoader.createClassLoader(classPath, appCl);
        }

        this.appLoader = appCl;
        this.dynamicLinker = Bootstrap.createDynamicLinker(this.appLoader, env._unstable_relink_threshold);

        final int cacheSize = env._class_cache_size;
        if (cacheSize > 0) {
            classCache = new ClassCache(this, cacheSize);
        }

        if (env._persistent_cache) {
            codeStore = newCodeStore(this);
        }

        // print version info if asked.
        if (env._version) {
            getErr().println("nashorn " + Version.version());
        }

        if (env._fullversion) {
            getErr().println("nashorn full version " + Version.fullVersion());
        }

        if (Options.getBooleanProperty("nashorn.fields.dual")) {
            fieldMode = FieldMode.DUAL;
        } else if (Options.getBooleanProperty("nashorn.fields.objects")) {
            fieldMode = FieldMode.OBJECTS;
        } else {
            fieldMode = FieldMode.AUTO;
        }

        initLoggers();
    }


    /**
     * Get the class filter for this context
     * @return class filter
     */
    public ClassFilter getClassFilter() {
        return classFilter;
    }

    /**
     * Returns the factory for constant method handles for global properties. The returned factory can be
     * invalidated if this Context has more than one Global.
     * @return the factory for constant method handles for global properties.
     */
    GlobalConstants getGlobalConstants() {
        return globalConstantsRef.get();
    }

    /**
     * Get the error manager for this context
     * @return error manger
     */
    public ErrorManager getErrorManager() {
        return errors;
    }

    /**
     * Get the script environment for this context
     * @return script environment
     */
    public ScriptEnvironment getEnv() {
        return env;
    }

    /**
     * Get the output stream for this context
     * @return output print writer
     */
    public PrintWriter getOut() {
        return env.getOut();
    }

    /**
     * Get the error stream for this context
     * @return error print writer
     */
    public PrintWriter getErr() {
        return env.getErr();
    }

    /**
     * Should scripts compiled by this context use dual field representation?
     * @return true if using dual fields, false for object-only fields
     */
    public boolean useDualFields() {
        return fieldMode == FieldMode.DUAL || (fieldMode == FieldMode.AUTO && env._optimistic_types);
    }

    /**
     * Get the PropertyMap of the current global scope
     * @return the property map of the current global scope
     */
    public static PropertyMap getGlobalMap() {
        return Context.getGlobal().getMap();
    }

    /**
     * Compile a top level script.
     *
     * @param source the source
     * @param scope  the scope
     *
     * @return top level function for script
     */
    public ScriptFunction compileScript(final Source source, final ScriptObject scope) {
        return compileScript(source, scope, this.errors);
    }

    /**
     * Interface to represent compiled code that can be re-used across many
     * global scope instances
     */
    public static interface MultiGlobalCompiledScript {
        /**
         * Obtain script function object for a specific global scope object.
         *
         * @param newGlobal global scope for which function object is obtained
         * @return script function for script level expressions
         */
        public ScriptFunction getFunction(final Global newGlobal);
    }

    /**
     * Compile a top level script.
     *
     * @param source the script source
     * @return reusable compiled script across many global scopes.
     */
    public MultiGlobalCompiledScript compileScript(final Source source) {
        final Class<?> clazz = compile(source, this.errors, this._strict, false);
        final MethodHandle createProgramFunctionHandle = getCreateProgramFunctionHandle(clazz);

        return new MultiGlobalCompiledScript() {
            @Override
            public ScriptFunction getFunction(final Global newGlobal) {
                return invokeCreateProgramFunctionHandle(createProgramFunctionHandle, newGlobal);
            }
        };
    }

    /**
     * Entry point for {@code eval}
     *
     * @param initialScope The scope of this eval call
     * @param string       Evaluated code as a String
     * @param callThis     "this" to be passed to the evaluated code
     * @param location     location of the eval call
     * @return the return value of the {@code eval}
     */
    public Object eval(final ScriptObject initialScope, final String string,
            final Object callThis, final Object location) {
        return eval(initialScope, string, callThis, location, false, false);
    }

    /**
     * Entry point for {@code eval}
     *
     * @param initialScope The scope of this eval call
     * @param string       Evaluated code as a String
     * @param callThis     "this" to be passed to the evaluated code
     * @param location     location of the eval call
     * @param strict       is this {@code eval} call from a strict mode code?
     * @param evalCall     is this called from "eval" builtin?
     *
     * @return the return value of the {@code eval}
     */
    public Object eval(final ScriptObject initialScope, final String string,
            final Object callThis, final Object location, final boolean strict, final boolean evalCall) {
        final String  file       = location == UNDEFINED || location == null ? "<eval>" : location.toString();
        final Source  source     = sourceFor(file, string, evalCall);
        // is this direct 'eval' builtin call?
        final boolean directEval = evalCall && (location != UNDEFINED);
        final Global  global = Context.getGlobal();
        ScriptObject scope = initialScope;

        // ECMA section 10.1.1 point 2 says eval code is strict if it begins
        // with "use strict" directive or eval direct call itself is made
        // from from strict mode code. We are passed with caller's strict mode.
        // Nashorn extension: any 'eval' is unconditionally strict when -strict is specified.
        boolean strictFlag = strict || this._strict;

        Class<?> clazz;
        try {
            clazz = compile(source, new ThrowErrorManager(), strictFlag, true);
        } catch (final ParserException e) {
            e.throwAsEcmaException(global);
            return null;
        }

        if (!strictFlag) {
            // We need to get strict mode flag from compiled class. This is
            // because eval code may start with "use strict" directive.
            try {
                strictFlag = clazz.getField(STRICT_MODE.symbolName()).getBoolean(null);
            } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
                //ignored
                strictFlag = false;
            }
        }

        // In strict mode, eval does not instantiate variables and functions
        // in the caller's environment. A new environment is created!
        if (strictFlag) {
            // Create a new scope object with given scope as its prototype
            scope = newScope(scope);
        }

        final ScriptFunction func = getProgramFunction(clazz, scope);
        Object evalThis;
        if (directEval) {
            evalThis = (callThis != UNDEFINED && callThis != null) || strictFlag ? callThis : global;
        } else {
            // either indirect evalCall or non-eval (Function, engine.eval, ScriptObjectMirror.eval..)
            evalThis = callThis;
        }

        return ScriptRuntime.apply(func, evalThis);
    }

    private static ScriptObject newScope(final ScriptObject callerScope) {
        return new Scope(callerScope, PropertyMap.newMap(Scope.class));
    }

    private static Source loadInternal(final String srcStr, final String prefix, final String resourcePath) {
        if (srcStr.startsWith(prefix)) {
            final String resource = resourcePath + srcStr.substring(prefix.length());
            // NOTE: even sandbox scripts should be able to load scripts in nashorn: scheme
            // These scripts are always available and are loaded from nashorn.jar's resources.
            return AccessController.doPrivileged(
                    new PrivilegedAction<Source>() {
                        @Override
                        public Source run() {
                            try {
                                final InputStream resStream = Context.class.getResourceAsStream(resource);
                                return resStream != null ? sourceFor(srcStr, Source.readFully(resStream)) : null;
                            } catch (final IOException exp) {
                                return null;
                            }
                        }
                    });
        }

        return null;
    }

    /**
     * Implementation of {@code load} Nashorn extension. Load a script file from a source
     * expression
     *
     * @param scope  the scope
     * @param from   source expression for script
     *
     * @return return value for load call (undefined)
     *
     * @throws IOException if source cannot be found or loaded
     */
    public Object load(final Object scope, final Object from) throws IOException {
        final Object src = from instanceof ConsString ? from.toString() : from;
        Source source = null;

        // load accepts a String (which could be a URL or a file name), a File, a URL
        // or a ScriptObject that has "name" and "source" (string valued) properties.
        if (src instanceof String) {
            final String srcStr = (String)src;
            if (srcStr.startsWith(LOAD_CLASSPATH)) {
                final URL url = getResourceURL(srcStr.substring(LOAD_CLASSPATH.length()));
                source = url != null ? sourceFor(url.toString(), url) : null;
            } else {
                final File file = new File(srcStr);
                if (srcStr.indexOf(':') != -1) {
                    if ((source = loadInternal(srcStr, LOAD_NASHORN, "resources/")) == null &&
                        (source = loadInternal(srcStr, LOAD_FX, "resources/fx/")) == null) {
                        URL url;
                        try {
                            //check for malformed url. if malformed, it may still be a valid file
                            url = new URL(srcStr);
                        } catch (final MalformedURLException e) {
                            url = file.toURI().toURL();
                        }
                        source = sourceFor(url.toString(), url);
                    }
                } else if (file.isFile()) {
                    source = sourceFor(srcStr, file);
                }
            }
        } else if (src instanceof File && ((File)src).isFile()) {
            final File file = (File)src;
            source = sourceFor(file.getName(), file);
        } else if (src instanceof URL) {
            final URL url = (URL)src;
            source = sourceFor(url.toString(), url);
        } else if (src instanceof ScriptObject) {
            final ScriptObject sobj = (ScriptObject)src;
            if (sobj.has("script") && sobj.has("name")) {
                final String script = JSType.toString(sobj.get("script"));
                final String name   = JSType.toString(sobj.get("name"));
                source = sourceFor(name, script);
            }
        } else if (src instanceof Map) {
            final Map<?,?> map = (Map<?,?>)src;
            if (map.containsKey("script") && map.containsKey("name")) {
                final String script = JSType.toString(map.get("script"));
                final String name   = JSType.toString(map.get("name"));
                source = sourceFor(name, script);
            }
        }

        if (source != null) {
            if (scope instanceof ScriptObject && ((ScriptObject)scope).isScope()) {
                final ScriptObject sobj = (ScriptObject)scope;
                // passed object is a script object
                // Global is the only user accessible scope ScriptObject
                assert sobj.isGlobal() : "non-Global scope object!!";
                return evaluateSource(source, sobj, sobj);
            } else if (scope == null || scope == UNDEFINED) {
                // undefined or null scope. Use current global instance.
                final Global global = getGlobal();
                return evaluateSource(source, global, global);
            } else {
                /*
                 * Arbitrary object passed for scope.
                 * Indirect load that is equivalent to:
                 *
                 *    (function(scope, source) {
                 *        with (scope) {
                 *            eval(<script_from_source>);
                 *        }
                 *    })(scope, source);
                 */
                final Global global = getGlobal();
                // Create a new object. This is where all declarations
                // (var, function) from the evaluated code go.
                // make global to be its __proto__ so that global
                // definitions are accessible to the evaluated code.
                final ScriptObject evalScope = newScope(global);

                // finally, make a WithObject around user supplied scope object
                // so that it's properties are accessible as variables.
                final ScriptObject withObj = ScriptRuntime.openWith(evalScope, scope);

                // evaluate given source with 'withObj' as scope
                // but use global object as "this".
                return evaluateSource(source, withObj, global);
            }
        }

        throw typeError("cant.load.script", ScriptRuntime.safeToString(from));
    }

    /**
     * Implementation of {@code loadWithNewGlobal} Nashorn extension. Load a script file from a source
     * expression, after creating a new global scope.
     *
     * @param from source expression for script
     * @param args (optional) arguments to be passed to the loaded script
     *
     * @return return value for load call (undefined)
     *
     * @throws IOException if source cannot be found or loaded
     */
    public Object loadWithNewGlobal(final Object from, final Object...args) throws IOException {
        final Global oldGlobal = getGlobal();
        final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
           @Override
           public Global run() {
               try {
                   return newGlobal();
               } catch (final RuntimeException e) {
                   if (Context.DEBUG) {
                       e.printStackTrace();
                   }
                   throw e;
               }
           }
        }, CREATE_GLOBAL_ACC_CTXT);
        // initialize newly created Global instance
        initGlobal(newGlobal);
        setGlobal(newGlobal);

        final Object[] wrapped = args == null? ScriptRuntime.EMPTY_ARRAY :  ScriptObjectMirror.wrapArray(args, oldGlobal);
        newGlobal.put("arguments", newGlobal.wrapAsObject(wrapped), env._strict);

        try {
            // wrap objects from newGlobal's world as mirrors - but if result
            // is from oldGlobal's world, unwrap it!
            return ScriptObjectMirror.unwrap(ScriptObjectMirror.wrap(load(newGlobal, from), newGlobal), oldGlobal);
        } finally {
            setGlobal(oldGlobal);
        }
    }

    /**
     * Load or get a structure class. Structure class names are based on the number of parameter fields
     * and {@link AccessorProperty} fields in them. Structure classes are used to represent ScriptObjects
     *
     * @see ObjectClassGenerator
     * @see AccessorProperty
     * @see ScriptObject
     *
     * @param fullName  full name of class, e.g. jdk.nashorn.internal.objects.JO2P1 contains 2 fields and 1 parameter.
     *
     * @return the {@code Class<?>} for this structure
     *
     * @throws ClassNotFoundException if structure class cannot be resolved
     */
    @SuppressWarnings("unchecked")
    public static Class<? extends ScriptObject> forStructureClass(final String fullName) throws ClassNotFoundException {
        if (System.getSecurityManager() != null && !StructureLoader.isStructureClass(fullName)) {
            throw new ClassNotFoundException(fullName);
        }
        return (Class<? extends ScriptObject>)structureClasses.computeIfAbsent(fullName, (name) -> {
            try {
                return Class.forName(name, true, theStructLoader);
            } catch (final ClassNotFoundException e) {
                throw new AssertionError(e);
            }
        });
    }

    /**
     * Is {@code className} the name of a structure class?
     *
     * @param className a class name
     * @return true if className is a structure class name
     */
    public static boolean isStructureClass(final String className) {
        return StructureLoader.isStructureClass(className);
    }

    /**
     * Checks that the given Class can be accessed from no permissions context.
     *
     * @param clazz Class object
     * @throws SecurityException if not accessible
     */
    public static void checkPackageAccess(final Class<?> clazz) {
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            Class<?> bottomClazz = clazz;
            while (bottomClazz.isArray()) {
                bottomClazz = bottomClazz.getComponentType();
            }
            checkPackageAccess(sm, bottomClazz.getName());
        }
    }

    /**
     * Checks that the given package name can be accessed from no permissions context.
     *
     * @param pkgName package name
     * @throws SecurityException if not accessible
     */
    public static void checkPackageAccess(final String pkgName) {
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkPackageAccess(sm, pkgName.endsWith(".") ? pkgName : pkgName + ".");
        }
    }

    /**
     * Checks that the given package can be accessed from no permissions context.
     *
     * @param sm current security manager instance
     * @param fullName fully qualified package name
     * @throw SecurityException if not accessible
     */
    private static void checkPackageAccess(final SecurityManager sm, final String fullName) {
        Objects.requireNonNull(sm);
        final int index = fullName.lastIndexOf('.');
        if (index != -1) {
            final String pkgName = fullName.substring(0, index);
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                @Override
                public Void run() {
                    sm.checkPackageAccess(pkgName);
                    return null;
                }
            }, NO_PERMISSIONS_ACC_CTXT);
        }
    }

    /**
     * Checks that the given Class can be accessed from no permissions context.
     *
     * @param clazz Class object
     * @return true if package is accessible, false otherwise
     */
    private static boolean isAccessiblePackage(final Class<?> clazz) {
        try {
            checkPackageAccess(clazz);
            return true;
        } catch (final SecurityException se) {
            return false;
        }
    }

    /**
     * Checks that the given Class is public and it can be accessed from no permissions context.
     *
     * @param clazz Class object to check
     * @return true if Class is accessible, false otherwise
     */
    public static boolean isAccessibleClass(final Class<?> clazz) {
        return Modifier.isPublic(clazz.getModifiers()) && Context.isAccessiblePackage(clazz);
    }

    /**
     * Lookup a Java class. This is used for JSR-223 stuff linking in from
     * {@code jdk.nashorn.internal.objects.NativeJava} and {@code jdk.nashorn.internal.runtime.NativeJavaPackage}
     *
     * @param fullName full name of class to load
     *
     * @return the {@code Class<?>} for the name
     *
     * @throws ClassNotFoundException if class cannot be resolved
     */
    public Class<?> findClass(final String fullName) throws ClassNotFoundException {
        if (fullName.indexOf('[') != -1 || fullName.indexOf('/') != -1) {
            // don't allow array class names or internal names.
            throw new ClassNotFoundException(fullName);
        }

        // give chance to ClassFilter to filter out, if present
        if (classFilter != null && !classFilter.exposeToScripts(fullName)) {
            throw new ClassNotFoundException(fullName);
        }

        // check package access as soon as possible!
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkPackageAccess(sm, fullName);
        }

        // Try finding using the "app" loader.
        if (appLoader != null) {
            return Class.forName(fullName, true, appLoader);
        } else {
            final Class<?> cl = Class.forName(fullName);
            // return the Class only if it was loaded by boot loader
            if (cl.getClassLoader() == null) {
                return cl;
            } else {
                throw new ClassNotFoundException(fullName);
            }
        }
    }

    /**
     * Hook to print stack trace for a {@link Throwable} that occurred during
     * execution
     *
     * @param t throwable for which to dump stack
     */
    public static void printStackTrace(final Throwable t) {
        if (Context.DEBUG) {
            t.printStackTrace(Context.getCurrentErr());
        }
    }

    /**
     * Verify generated bytecode before emission. This is called back from the
     * {@link ObjectClassGenerator} or the {@link Compiler}. If the "--verify-code" parameter
     * hasn't been given, this is a nop
     *
     * Note that verification may load classes -- we don't want to do that unless
     * user specified verify option. We check it here even though caller
     * may have already checked that flag
     *
     * @param bytecode bytecode to verify
     */
    public void verify(final byte[] bytecode) {
        if (env._verify_code) {
            // No verification when security manager is around as verifier
            // may load further classes - which should be avoided.
            if (System.getSecurityManager() == null) {
                CheckClassAdapter.verify(new ClassReader(bytecode), theStructLoader, false, new PrintWriter(System.err, true));
            }
        }
    }

    /**
     * Create and initialize a new global scope object.
     *
     * @return the initialized global scope object.
     */
    public Global createGlobal() {
        return initGlobal(newGlobal());
    }

    /**
     * Create a new uninitialized global scope object
     * @return the global script object
     */
    public Global newGlobal() {
        createOrInvalidateGlobalConstants();
        return new Global(this);
    }

    private void createOrInvalidateGlobalConstants() {
        for (;;) {
            final GlobalConstants currentGlobalConstants = getGlobalConstants();
            if (currentGlobalConstants != null) {
                // Subsequent invocation; we're creating our second or later Global. GlobalConstants is not safe to use
                // with more than one Global, as the constant method handle linkages it creates create a coupling
                // between the Global and the call sites in the compiled code.
                currentGlobalConstants.invalidateForever();
                return;
            }
            final GlobalConstants newGlobalConstants = new GlobalConstants(getLogger(GlobalConstants.class));
            if (globalConstantsRef.compareAndSet(null, newGlobalConstants)) {
                // First invocation; we're creating the first Global in this Context. Create the GlobalConstants object
                // for this Context.
                return;
            }

            // If we reach here, then we started out as the first invocation, but another concurrent invocation won the
            // CAS race. We'll just let the loop repeat and invalidate the CAS race winner.
        }
    }

    /**
     * Initialize given global scope object.
     *
     * @param global the global
     * @param engine the associated ScriptEngine instance, can be null
     * @return the initialized global scope object.
     */
    public Global initGlobal(final Global global, final ScriptEngine engine) {
        // Need only minimal global object, if we are just compiling.
        if (!env._compile_only) {
            final Global oldGlobal = Context.getGlobal();
            try {
                Context.setGlobal(global);
                // initialize global scope with builtin global objects
                global.initBuiltinObjects(engine);
            } finally {
                Context.setGlobal(oldGlobal);
            }
        }

        return global;
    }

    /**
     * Initialize given global scope object.
     *
     * @param global the global
     * @return the initialized global scope object.
     */
    public Global initGlobal(final Global global) {
        return initGlobal(global, null);
    }

    /**
     * Return the current global's context
     * @return current global's context
     */
    static Context getContextTrusted() {
        return getContext(getGlobal());
    }

    /**
     * Gets the Nashorn dynamic linker for the specified class. If the class is
     * a script class, the dynamic linker associated with its context is
     * returned. Otherwise the dynamic linker associated with the current
     * context is returned.
     * @param clazz the class for which we want to retrieve a dynamic linker.
     * @return the Nashorn dynamic linker for the specified class.
     */
    public static DynamicLinker getDynamicLinker(final Class<?> clazz) {
        return fromClass(clazz).dynamicLinker;
    }

    /**
     * Gets the Nashorn dynamic linker associated with the current context.
     * @return the Nashorn dynamic linker for the current context.
     */
    public static DynamicLinker getDynamicLinker() {
        return getContextTrusted().dynamicLinker;
    }

    /**
     * Creates a module layer with one module that is defined to the given class
     * loader.
     *
     * @param descriptor the module descriptor for the newly created module
     * @param loader the class loader of the module
     * @return the new Module
     */
    static Module createModuleTrusted(final ModuleDescriptor descriptor, final ClassLoader loader) {
        return createModuleTrusted(ModuleLayer.boot(), descriptor, loader);
    }

    /**
     * Creates a module layer with one module that is defined to the given class
     * loader.
     *
     * @param parent the parent layer of the new module
     * @param descriptor the module descriptor for the newly created module
     * @param loader the class loader of the module
     * @return the new Module
     */
    static Module createModuleTrusted(final ModuleLayer parent, final ModuleDescriptor descriptor, final ClassLoader loader) {
        final String mn = descriptor.name();

        final ModuleReference mref = new ModuleReference(descriptor, null) {
            @Override
            public ModuleReader open() {
                throw new UnsupportedOperationException();
            }
        };

        final ModuleFinder finder = new ModuleFinder() {
            @Override
            public Optional<ModuleReference> find(final String name) {
                if (name.equals(mn)) {
                    return Optional.of(mref);
                } else {
                    return Optional.empty();
                }
            }
            @Override
            public Set<ModuleReference> findAll() {
                return Set.of(mref);
            }
        };

        final Configuration cf = parent.configuration()
                .resolve(finder, ModuleFinder.of(), Set.of(mn));

        final PrivilegedAction<ModuleLayer> pa = () -> parent.defineModules(cf, name -> loader);
        final ModuleLayer layer = AccessController.doPrivileged(pa, GET_LOADER_ACC_CTXT);

        final Module m = layer.findModule(mn).get();
        assert m.getLayer() == layer;

        return m;
    }

    static Context getContextTrustedOrNull() {
        final Global global = Context.getGlobal();
        return global == null ? null : getContext(global);
    }

    private static Context getContext(final Global global) {
        // We can't invoke Global.getContext() directly, as it's a protected override, and Global isn't in our package.
        // In order to access the method, we must cast it to ScriptObject first (which is in our package) and then let
        // virtual invocation do its thing.
        return ((ScriptObject)global).getContext();
    }

    /**
     * Try to infer Context instance from the Class. If we cannot,
     * then get it from the thread local variable.
     *
     * @param clazz the class
     * @return context
     */
    static Context fromClass(final Class<?> clazz) {
        ClassLoader loader = null;
        try {
            loader = clazz.getClassLoader();
        } catch (final SecurityException ignored) {
            // This could fail because of anonymous classes being used.
            // Accessing loader of anonymous class fails (for extension
            // loader class too?). In any case, for us fetching Context
            // from class loader is just an optimization. We can always
            // get Context from thread local storage (below).
        }

        if (loader instanceof ScriptLoader) {
            return ((ScriptLoader)loader).getContext();
        }

        return Context.getContextTrusted();
    }

    private URL getResourceURL(final String resName) {
        if (appLoader != null) {
            return appLoader.getResource(resName);
        }
        return ClassLoader.getSystemResource(resName);
    }

    private Object evaluateSource(final Source source, final ScriptObject scope, final ScriptObject thiz) {
        ScriptFunction script = null;

        try {
            script = compileScript(source, scope, new Context.ThrowErrorManager());
        } catch (final ParserException e) {
            e.throwAsEcmaException();
        }

        return ScriptRuntime.apply(script, thiz);
    }

    private static ScriptFunction getProgramFunction(final Class<?> script, final ScriptObject scope) {
        if (script == null) {
            return null;
        }
        return invokeCreateProgramFunctionHandle(getCreateProgramFunctionHandle(script), scope);
    }

    private static MethodHandle getCreateProgramFunctionHandle(final Class<?> script) {
        try {
            return LOOKUP.findStatic(script, CREATE_PROGRAM_FUNCTION.symbolName(), CREATE_PROGRAM_FUNCTION_TYPE);
        } catch (NoSuchMethodException | IllegalAccessException e) {
            throw new AssertionError("Failed to retrieve a handle for the program function for " + script.getName(), e);
        }
    }

    private static ScriptFunction invokeCreateProgramFunctionHandle(final MethodHandle createProgramFunctionHandle, final ScriptObject scope) {
        try {
            return (ScriptFunction)createProgramFunctionHandle.invokeExact(scope);
        } catch (final RuntimeException|Error e) {
            throw e;
        } catch (final Throwable t) {
            throw new AssertionError("Failed to create a program function", t);
        }
    }

    private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
        return getProgramFunction(compile(source, errMan, this._strict, false), scope);
    }

    private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict, final boolean isEval) {
        // start with no errors, no warnings.
        errMan.reset();

        Class<?> script = findCachedClass(source);
        if (script != null) {
            final DebugLogger log = getLogger(Compiler.class);
            if (log.isEnabled()) {
                log.fine(new RuntimeEvent<>(Level.INFO, source), "Code cache hit for ", source, " avoiding recompile.");
            }
            return script;
        }

        StoredScript storedScript = null;
        FunctionNode functionNode = null;
        // Don't use code store if optimistic types is enabled but lazy compilation is not.
        // This would store a full script compilation with many wrong optimistic assumptions that would
        // do more harm than good on later runs with both optimistic types and lazy compilation enabled.
        final boolean useCodeStore = codeStore != null && !env._parse_only && (!env._optimistic_types || env._lazy_compilation);
        final String cacheKey = useCodeStore ? CodeStore.getCacheKey("script", null) : null;

        if (useCodeStore) {
            storedScript = codeStore.load(source, cacheKey);
        }

        if (storedScript == null) {
            if (env._dest_dir != null) {
                source.dump(env._dest_dir);
            }

            functionNode = new Parser(env, source, errMan, strict, getLogger(Parser.class)).parse();

            if (errMan.hasErrors()) {
                return null;
            }

            if (env._print_ast || functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) {
                getErr().println(new ASTWriter(functionNode));
            }

            if (env._print_parse || functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) {
                getErr().println(new PrintVisitor(functionNode, true, false));
            }
        }

        if (env._parse_only) {
            return null;
        }

        final URL          url    = source.getURL();
        final CodeSource   cs     = new CodeSource(url, (CodeSigner[])null);
        final CodeInstaller installer;
        if (!env.useAnonymousClasses(source.getLength()) || env._persistent_cache || !env._lazy_compilation) {
            // Persistent code cache and eager compilation preclude use of VM anonymous classes
            final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
            installer = new NamedContextCodeInstaller(this, cs, loader);
        } else {
            installer = new AnonymousContextCodeInstaller(this, cs,
                    anonymousHostClasses.getOrCreate(cs, (key) ->
                            createNewLoader().installClass(
                                    // NOTE: we're defining these constants in AnonymousContextCodeInstaller so they are not
                                    // initialized if we don't use AnonymousContextCodeInstaller. As this method is only ever
                                    // invoked from AnonymousContextCodeInstaller, this is okay.
                                    AnonymousContextCodeInstaller.ANONYMOUS_HOST_CLASS_NAME,
                                    AnonymousContextCodeInstaller.ANONYMOUS_HOST_CLASS_BYTES, cs)));
        }

        if (storedScript == null) {
            final CompilationPhases phases = Compiler.CompilationPhases.COMPILE_ALL;

            final Compiler compiler = Compiler.forInitialCompilation(
                    installer,
                    source,
                    errMan,
                    strict | functionNode.isStrict());

            final FunctionNode compiledFunction = compiler.compile(functionNode, phases);
            if (errMan.hasErrors()) {
                return null;
            }
            script = compiledFunction.getRootClass();
            compiler.persistClassInfo(cacheKey, compiledFunction);
        } else {
            Compiler.updateCompilationId(storedScript.getCompilationId());
            script = storedScript.installScript(source, installer);
        }

        cacheClass(source, script);
        return script;
    }

    private ScriptLoader createNewLoader() {
        return AccessController.doPrivileged(
             new PrivilegedAction<ScriptLoader>() {
                @Override
                public ScriptLoader run() {
                    return new ScriptLoader(Context.this);
                }
             }, CREATE_LOADER_ACC_CTXT);
    }

    private long getUniqueScriptId() {
        return uniqueScriptId.getAndIncrement();
    }

    /**
     * Cache for compiled script classes.
     */
    @SuppressWarnings("serial")
    @Logger(name="classcache")
    private static class ClassCache extends LinkedHashMap<Source, ClassReference> implements Loggable {
        private final int size;
        private final ReferenceQueue<Class<?>> queue;
        private final DebugLogger log;

        ClassCache(final Context context, final int size) {
            super(size, 0.75f, true);
            this.size = size;
            this.queue = new ReferenceQueue<>();
            this.log   = initLogger(context);
        }

        void cache(final Source source, final Class<?> clazz) {
            if (log.isEnabled()) {
                log.info("Caching ", source, " in class cache");
            }
            put(source, new ClassReference(clazz, queue, source));
        }

        @Override
        protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) {
            return size() > size;
        }

        @Override
        public ClassReference get(final Object key) {
            for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
                final Source source = ref.source;
                if (log.isEnabled()) {
                    log.info("Evicting ", source, " from class cache.");
                }
                remove(source);
            }

            final ClassReference ref = super.get(key);
            if (ref != null && log.isEnabled()) {
                log.info("Retrieved class reference for ", ref.source, " from class cache");
            }
            return ref;
        }

        @Override
        public DebugLogger initLogger(final Context context) {
            return context.getLogger(getClass());
        }

        @Override
        public DebugLogger getLogger() {
            return log;
        }

    }

    private static class ClassReference extends SoftReference<Class<?>> {
        private final Source source;

        ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) {
            super(clazz, queue);
            this.source = source;
        }
    }

    // Class cache management
    private Class<?> findCachedClass(final Source source) {
        final ClassReference ref = classCache == null ? null : classCache.get(source);
        return ref != null ? ref.get() : null;
    }

    private void cacheClass(final Source source, final Class<?> clazz) {
        if (classCache != null) {
            classCache.cache(source, clazz);
        }
    }

    // logging
    private final Map<String, DebugLogger> loggers = new HashMap<>();

    private void initLoggers() {
        ((Loggable)MethodHandleFactory.getFunctionality()).initLogger(this);
    }

    /**
     * Get a logger, given a loggable class
     * @param clazz a Loggable class
     * @return debuglogger associated with that class
     */
    public DebugLogger getLogger(final Class<? extends Loggable> clazz) {
        return getLogger(clazz, null);
    }

    /**
     * Get a logger, given a loggable class
     * @param clazz a Loggable class
     * @param initHook an init hook - if this is the first time the logger is created in the context, run the init hook
     * @return debuglogger associated with that class
     */
    public DebugLogger getLogger(final Class<? extends Loggable> clazz, final Consumer<DebugLogger> initHook) {
        final String name = getLoggerName(clazz);
        DebugLogger logger = loggers.get(name);
        if (logger == null) {
            if (!env.hasLogger(name)) {
                return DebugLogger.DISABLED_LOGGER;
            }
            final LoggerInfo info = env._loggers.get(name);
            logger = new DebugLogger(name, info.getLevel(), info.isQuiet());
            if (initHook != null) {
                initHook.accept(logger);
            }
            loggers.put(name, logger);
        }
        return logger;
    }

    /**
     * Given a Loggable class, weave debug info info a method handle for that logger.
     * Level.INFO is used
     *
     * @param clazz loggable
     * @param mh    method handle
     * @param text  debug printout to add
     *
     * @return instrumented method handle, or null if logger not enabled
     */
    public MethodHandle addLoggingToHandle(final Class<? extends Loggable> clazz, final MethodHandle mh, final Supplier<String> text) {
        return addLoggingToHandle(clazz, Level.INFO, mh, Integer.MAX_VALUE, false, text);
    }

    /**
     * Given a Loggable class, weave debug info info a method handle for that logger.
     *
     * @param clazz            loggable
     * @param level            log level
     * @param mh               method handle
     * @param paramStart       first parameter to print
     * @param printReturnValue should we print the return value?
     * @param text             debug printout to add
     *
     * @return instrumented method handle, or null if logger not enabled
     */
    public MethodHandle addLoggingToHandle(final Class<? extends Loggable> clazz, final Level level, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Supplier<String> text) {
        final DebugLogger log = getLogger(clazz);
        if (log.isEnabled()) {
            return MethodHandleFactory.addDebugPrintout(log, level, mh, paramStart, printReturnValue, text.get());
        }
        return mh;
    }

    private static String getLoggerName(final Class<?> clazz) {
        Class<?> current = clazz;
        while (current != null) {
            final Logger log = current.getAnnotation(Logger.class);
            if (log != null) {
                assert !"".equals(log.name());
                return log.name();
            }
            current = current.getSuperclass();
        }
        assert false;
        return null;
    }

    /**
     * This is a special kind of switchpoint used to guard builtin
     * properties and prototypes. In the future it might contain
     * logic to e.g. multiple switchpoint classes.
     */
    public static final class BuiltinSwitchPoint extends SwitchPoint {
        //empty
    }

    /**
     * Create a new builtin switchpoint and return it
     * @param name key name
     * @return new builtin switchpoint
     */
    public SwitchPoint newBuiltinSwitchPoint(final String name) {
        assert builtinSwitchPoints.get(name) == null;
        final SwitchPoint sp = new BuiltinSwitchPoint();
        builtinSwitchPoints.put(name, sp);
        return sp;
    }

    /**
     * Return the builtin switchpoint for a particular key name
     * @param name key name
     * @return builtin switchpoint or null if none
     */
    public SwitchPoint getBuiltinSwitchPoint(final String name) {
        return builtinSwitchPoints.get(name);
    }

    private static ClassLoader createModuleLoader(final ClassLoader cl,
            final String modulePath, final String addModules) {
        if (addModules == null) {
            throw new IllegalArgumentException("--module-path specified with no --add-modules");
        }

        final Path[] paths = Stream.of(modulePath.split(File.pathSeparator)).
            map(s -> Paths.get(s)).
            toArray(sz -> new Path[sz]);
        final ModuleFinder mf = ModuleFinder.of(paths);
        final Set<ModuleReference> mrefs = mf.findAll();
        if (mrefs.isEmpty()) {
            throw new RuntimeException("No modules in script --module-path: " + modulePath);
        }

        final Set<String> rootMods;
        if (addModules.equals("ALL-MODULE-PATH")) {
            rootMods = mrefs.stream().
                map(mr->mr.descriptor().name()).
                collect(Collectors.toSet());
        } else {
            rootMods = Stream.of(addModules.split(",")).
                map(String::trim).
                collect(Collectors.toSet());
        }

        final ModuleLayer boot = ModuleLayer.boot();
        final Configuration conf = boot.configuration().
            resolve(mf, ModuleFinder.of(), rootMods);
        final String firstMod = rootMods.iterator().next();
        return boot.defineModulesWithOneLoader(conf, cl).findLoader(firstMod);
    }
}
