src/jdk/nashorn/internal/runtime/Context.java

Fri, 03 May 2013 16:01:33 +0200

author
lagergren
date
Fri, 03 May 2013 16:01:33 +0200
changeset 248
829b06307fb2
parent 247
5a3f7867e19c
child 253
fb1d7ea3e1b6
permissions
-rw-r--r--

8013871: mem usage histograms enabled with compiler logging level set to more specific than or equals to info when --print-mem-usage flag is used
Reviewed-by: jlaskey, hannesw

     1 /*
     2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package jdk.nashorn.internal.runtime;
    28 import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
    29 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
    30 import static jdk.nashorn.internal.lookup.Lookup.MH;
    31 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    32 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
    34 import java.io.File;
    35 import java.io.IOException;
    36 import java.io.PrintWriter;
    37 import java.lang.invoke.MethodHandle;
    38 import java.lang.invoke.MethodHandles;
    39 import java.lang.reflect.Constructor;
    40 import java.net.MalformedURLException;
    41 import java.net.URL;
    42 import java.security.AccessControlContext;
    43 import java.security.AccessController;
    44 import java.security.CodeSigner;
    45 import java.security.CodeSource;
    46 import java.security.Permissions;
    47 import java.security.PrivilegedAction;
    48 import java.security.ProtectionDomain;
    49 import jdk.internal.org.objectweb.asm.ClassReader;
    50 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
    51 import jdk.nashorn.internal.codegen.Compiler;
    52 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
    53 import jdk.nashorn.internal.ir.FunctionNode;
    54 import jdk.nashorn.internal.ir.debug.ASTWriter;
    55 import jdk.nashorn.internal.ir.debug.PrintVisitor;
    56 import jdk.nashorn.internal.parser.Parser;
    57 import jdk.nashorn.internal.runtime.options.Options;
    59 /**
    60  * This class manages the global state of execution. Context is immutable.
    61  */
    62 public final class Context {
    64     /**
    65      * ContextCodeInstaller that has the privilege of installing classes in the Context.
    66      * Can only be instantiated from inside the context and is opaque to other classes
    67      */
    68     public static class ContextCodeInstaller implements CodeInstaller<ScriptEnvironment> {
    69         private final Context      context;
    70         private final ScriptLoader loader;
    71         private final CodeSource   codeSource;
    73         private ContextCodeInstaller(final Context context, final ScriptLoader loader, final CodeSource codeSource) {
    74             this.context    = context;
    75             this.loader     = loader;
    76             this.codeSource = codeSource;
    77         }
    79         /**
    80          * Return the context for this installer
    81          * @return ScriptEnvironment
    82          */
    83         @Override
    84         public ScriptEnvironment getOwner() {
    85             return context.env;
    86         }
    88         @Override
    89         public Class<?> install(final String className, final byte[] bytecode) {
    90             return loader.installClass(className, bytecode, codeSource);
    91         }
    93         @Override
    94         public void verify(final byte[] code) {
    95             context.verify(code);
    96         }
    97     }
    99     /** Is Context global debug mode enabled ? */
   100     public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
   102     private static final ThreadLocal<ScriptObject> currentGlobal =
   103         new ThreadLocal<ScriptObject>() {
   104             @Override
   105             protected ScriptObject initialValue() {
   106                  return null;
   107             }
   108         };
   110     /**
   111      * Get the current global scope
   112      * @return the current global scope
   113      */
   114     public static ScriptObject getGlobal() {
   115         // This class in a package.access protected package.
   116         // Trusted code only can call this method.
   117         return getGlobalTrusted();
   118     }
   120     /**
   121      * Set the current global scope
   122      * @param global the global scope
   123      */
   124     public static void setGlobal(final ScriptObject global) {
   125         final SecurityManager sm = System.getSecurityManager();
   126         if (sm != null) {
   127             sm.checkPermission(new RuntimePermission("nashorn.setGlobal"));
   128         }
   130         if (global != null && !(global instanceof GlobalObject)) {
   131             throw new IllegalArgumentException("global does not implement GlobalObject!");
   132         }
   134         setGlobalTrusted(global);
   135     }
   137     /**
   138      * Get context of the current global
   139      * @return current global scope's context.
   140      */
   141     public static Context getContext() {
   142         final SecurityManager sm = System.getSecurityManager();
   143         if (sm != null) {
   144             sm.checkPermission(new RuntimePermission("nashorn.getContext"));
   145         }
   146         return getContextTrusted();
   147     }
   149     /**
   150      * Get current context's error writer
   151      *
   152      * @return error writer of the current context
   153      */
   154     public static PrintWriter getCurrentErr() {
   155         final ScriptObject global = getGlobalTrusted();
   156         return (global != null)? global.getContext().getErr() : new PrintWriter(System.err);
   157     }
   159     /**
   160      * Output text to this Context's error stream
   161      * @param str text to write
   162      */
   163     public static void err(final String str) {
   164         err(str, true);
   165     }
   167     /**
   168      * Output text to this Context's error stream, optionally with
   169      * a newline afterwards
   170      *
   171      * @param str  text to write
   172      * @param crlf write a carriage return/new line after text
   173      */
   174     public static void err(final String str, final boolean crlf) {
   175         final PrintWriter err = Context.getCurrentErr();
   176         if (err != null) {
   177             if (crlf) {
   178                 err.println(str);
   179             } else {
   180                 err.print(str);
   181             }
   182         }
   183     }
   185     /** Current environment. */
   186     private final ScriptEnvironment env;
   188     /** is this context in strict mode? Cached from env. as this is used heavily. */
   189     public final boolean _strict;
   191     /** class loader to resolve classes from script. */
   192     private final ClassLoader  appLoader;
   194     /** Class loader to load classes from -classpath option, if set. */
   195     private final ClassLoader  classPathLoader;
   197     /** Class loader to load classes compiled from scripts. */
   198     private final ScriptLoader scriptLoader;
   200     /** Current error manager. */
   201     private final ErrorManager errors;
   203     private static final ClassLoader myLoader = Context.class.getClassLoader();
   204     private static final StructureLoader sharedLoader;
   206     static {
   207         sharedLoader = AccessController.doPrivileged(new PrivilegedAction<StructureLoader>() {
   208             @Override
   209             public StructureLoader run() {
   210                 return new StructureLoader(myLoader, null);
   211             }
   212         });
   213     }
   215     /**
   216      * ThrowErrorManager that throws ParserException upon error conditions.
   217      */
   218     public static class ThrowErrorManager extends ErrorManager {
   219         @Override
   220         public void error(final String message) {
   221             throw new ParserException(message);
   222         }
   224         @Override
   225         public void error(final ParserException e) {
   226             throw e;
   227         }
   228     }
   230     /**
   231      * Constructor
   232      *
   233      * @param options options from command line or Context creator
   234      * @param errors  error manger
   235      * @param appLoader application class loader
   236      */
   237     public Context(final Options options, final ErrorManager errors, final ClassLoader appLoader) {
   238         this(options, errors, new PrintWriter(System.out, true), new PrintWriter(System.err, true), appLoader);
   239     }
   241     /**
   242      * Constructor
   243      *
   244      * @param options options from command line or Context creator
   245      * @param errors  error manger
   246      * @param out     output writer for this Context
   247      * @param err     error writer for this Context
   248      * @param appLoader application class loader
   249      */
   250     public Context(final Options options, final ErrorManager errors, final PrintWriter out, final PrintWriter err, final ClassLoader appLoader) {
   251         final SecurityManager sm = System.getSecurityManager();
   252         if (sm != null) {
   253             sm.checkPermission(new RuntimePermission("nashorn.createContext"));
   254         }
   256         this.env       = new ScriptEnvironment(options, out, err);
   257         this._strict   = env._strict;
   258         this.appLoader = appLoader;
   259         this.scriptLoader = (ScriptLoader)AccessController.doPrivileged(
   260              new PrivilegedAction<ClassLoader>() {
   261                 @Override
   262                 public ClassLoader run() {
   263                     final StructureLoader structureLoader = new StructureLoader(sharedLoader, Context.this);
   264                     return new ScriptLoader(structureLoader, Context.this);
   265                 }
   266              });
   267         this.errors    = errors;
   269         // if user passed -classpath option, make a class loader with that and set it as
   270         // thread context class loader so that script can access classes from that path.
   271         final String classPath = options.getString("classpath");
   272         if (! env._compile_only && classPath != null && !classPath.isEmpty()) {
   273             // make sure that caller can create a class loader.
   274             if (sm != null) {
   275                 sm.checkPermission(new RuntimePermission("createClassLoader"));
   276             }
   277             this.classPathLoader = NashornLoader.createClassLoader(classPath);
   278         } else {
   279             this.classPathLoader = null;
   280         }
   282         // print version info if asked.
   283         if (env._version) {
   284             getErr().println("nashorn " + Version.version());
   285         }
   287         if (env._fullversion) {
   288             getErr().println("nashorn full version " + Version.fullVersion());
   289         }
   290     }
   292     /**
   293      * Get the error manager for this context
   294      * @return error manger
   295      */
   296     public ErrorManager getErrorManager() {
   297         return errors;
   298     }
   300     /**
   301      * Get the script environment for this context
   302      * @return script environment
   303      */
   304     public ScriptEnvironment getEnv() {
   305         return env;
   306     }
   308     /**
   309      * Get the output stream for this context
   310      * @return output print writer
   311      */
   312     public PrintWriter getOut() {
   313         return env.getOut();
   314     }
   316     /**
   317      * Get the error stream for this context
   318      * @return error print writer
   319      */
   320     public PrintWriter getErr() {
   321         return env.getErr();
   322     }
   324     /**
   325      * Get the PropertyMap of the current global scope
   326      * @return the property map of the current global scope
   327      */
   328     public static PropertyMap getGlobalMap() {
   329         return Context.getGlobalTrusted().getMap();
   330     }
   332     /**
   333      * Compile a top level script.
   334      *
   335      * @param source the source
   336      * @param scope  the scope
   337      *
   338      * @return top level function for script
   339      */
   340     public ScriptFunction compileScript(final Source source, final ScriptObject scope) {
   341         return compileScript(source, scope, this.errors);
   342     }
   344     /**
   345      * Entry point for {@code eval}
   346      *
   347      * @param initialScope The scope of this eval call
   348      * @param string       Evaluated code as a String
   349      * @param callThis     "this" to be passed to the evaluated code
   350      * @param location     location of the eval call
   351      * @param strict       is this {@code eval} call from a strict mode code?
   352      *
   353      * @return the return value of the {@code eval}
   354      */
   355     public Object eval(final ScriptObject initialScope, final String string, final Object callThis, final Object location, final boolean strict) {
   356         final String  file       = (location == UNDEFINED || location == null) ? "<eval>" : location.toString();
   357         final Source  source     = new Source(file, string);
   358         final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval?
   359         final ScriptObject global = Context.getGlobalTrusted();
   361         ScriptObject scope = initialScope;
   363         // ECMA section 10.1.1 point 2 says eval code is strict if it begins
   364         // with "use strict" directive or eval direct call itself is made
   365         // from from strict mode code. We are passed with caller's strict mode.
   366         boolean strictFlag = directEval && strict;
   368         Class<?> clazz = null;
   369         try {
   370             clazz = compile(source, new ThrowErrorManager(), strictFlag);
   371         } catch (final ParserException e) {
   372             e.throwAsEcmaException(global);
   373             return null;
   374         }
   376         if (!strictFlag) {
   377             // We need to get strict mode flag from compiled class. This is
   378             // because eval code may start with "use strict" directive.
   379             try {
   380                 strictFlag = clazz.getField(STRICT_MODE.symbolName()).getBoolean(null);
   381             } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
   382                 //ignored
   383                 strictFlag = false;
   384             }
   385         }
   387         // In strict mode, eval does not instantiate variables and functions
   388         // in the caller's environment. A new environment is created!
   389         if (strictFlag) {
   390             // Create a new scope object
   391             final ScriptObject strictEvalScope = ((GlobalObject)global).newObject();
   393             // bless it as a "scope"
   394             strictEvalScope.setIsScope();
   396             // set given scope to be it's proto so that eval can still
   397             // access caller environment vars in the new environment.
   398             strictEvalScope.setProto(scope);
   399             scope = strictEvalScope;
   400         }
   402         ScriptFunction func = getRunScriptFunction(clazz, scope);
   403         Object evalThis;
   404         if (directEval) {
   405             evalThis = (callThis instanceof ScriptObject || strictFlag) ? callThis : global;
   406         } else {
   407             evalThis = global;
   408         }
   410         return ScriptRuntime.apply(func, evalThis);
   411     }
   413     private static Source loadInternal(final String srcStr, final String prefix, final String resourcePath) {
   414         if (srcStr.startsWith(prefix)) {
   415             final String resource = resourcePath + srcStr.substring(prefix.length());
   416             // NOTE: even sandbox scripts should be able to load scripts in nashorn: scheme
   417             // These scripts are always available and are loaded from nashorn.jar's resources.
   418             return AccessController.doPrivileged(
   419                     new PrivilegedAction<Source>() {
   420                         @Override
   421                         public Source run() {
   422                             try {
   423                                 final URL resURL = Context.class.getResource(resource);
   424                                 return (resURL != null)? new Source(srcStr, resURL) : null;
   425                             } catch (final IOException exp) {
   426                                 return null;
   427                             }
   428                         }
   429                     });
   430         }
   432         return null;
   433     }
   435     /**
   436      * Implementation of {@code load} Nashorn extension. Load a script file from a source
   437      * expression
   438      *
   439      * @param scope  the scope
   440      * @param from   source expression for script
   441      *
   442      * @return return value for load call (undefined)
   443      *
   444      * @throws IOException if source cannot be found or loaded
   445      */
   446     public Object load(final ScriptObject scope, final Object from) throws IOException {
   447         final Object src = (from instanceof ConsString)?  from.toString() : from;
   448         Source source = null;
   450         // load accepts a String (which could be a URL or a file name), a File, a URL
   451         // or a ScriptObject that has "name" and "source" (string valued) properties.
   452         if (src instanceof String) {
   453             final String srcStr = (String)src;
   454             final File file = new File(srcStr);
   455             if (srcStr.indexOf(':') != -1) {
   456                 if ((source = loadInternal(srcStr, "nashorn:", "resources/")) == null &&
   457                     (source = loadInternal(srcStr, "fx:", "resources/fx/")) == null) {
   458                     URL url;
   459                     try {
   460                         //check for malformed url. if malformed, it may still be a valid file
   461                         url = new URL(srcStr);
   462                     } catch (final MalformedURLException e) {
   463                         url = file.toURI().toURL();
   464                     }
   465                     source = new Source(url.toString(), url);
   466                 }
   467             } else if (file.isFile()) {
   468                 source = new Source(srcStr, file);
   469             }
   470         } else if (src instanceof File && ((File)src).isFile()) {
   471             final File file = (File)src;
   472             source = new Source(file.getName(), file);
   473         } else if (src instanceof URL) {
   474             final URL url = (URL)src;
   475             source = new Source(url.toString(), url);
   476         } else if (src instanceof ScriptObject) {
   477             final ScriptObject sobj = (ScriptObject)src;
   478             if (sobj.has("script") && sobj.has("name")) {
   479                 final String script = JSType.toString(sobj.get("script"));
   480                 final String name   = JSType.toString(sobj.get("name"));
   481                 source = new Source(name, script);
   482             }
   483         }
   485         if (source != null) {
   486             return evaluateSource(source, scope, scope);
   487         }
   489         throw typeError("cant.load.script", ScriptRuntime.safeToString(from));
   490     }
   492     /**
   493      * Load or get a structure class. Structure class names are based on the number of parameter fields
   494      * and {@link AccessorProperty} fields in them. Structure classes are used to represent ScriptObjects
   495      *
   496      * @see ObjectClassGenerator
   497      * @see AccessorProperty
   498      * @see ScriptObject
   499      *
   500      * @param fullName  full name of class, e.g. jdk.nashorn.internal.objects.JO2P1 contains 2 fields and 1 parameter.
   501      *
   502      * @return the {@code Class<?>} for this structure
   503      *
   504      * @throws ClassNotFoundException if structure class cannot be resolved
   505      */
   506     public static Class<?> forStructureClass(final String fullName) throws ClassNotFoundException {
   507         return Class.forName(fullName, true, sharedLoader);
   508     }
   510     /**
   511      * Lookup a Java class. This is used for JSR-223 stuff linking in from
   512      * {@link jdk.nashorn.internal.objects.NativeJava} and {@link jdk.nashorn.internal.runtime.NativeJavaPackage}
   513      *
   514      * @param fullName full name of class to load
   515      *
   516      * @return the {@code Class<?>} for the name
   517      *
   518      * @throws ClassNotFoundException if class cannot be resolved
   519      */
   520     public Class<?> findClass(final String fullName) throws ClassNotFoundException {
   521         // check package access as soon as possible!
   522         final int index = fullName.lastIndexOf('.');
   523         if (index != -1) {
   524             final SecurityManager sm = System.getSecurityManager();
   525             if (sm != null) {
   526                 AccessController.doPrivileged(new PrivilegedAction<Void>() {
   527                     @Override
   528                     public Void run() {
   529                         sm.checkPackageAccess(fullName.substring(0, index));
   530                         return null;
   531                     }
   532                 }, createNoPermissionsContext());
   533             }
   534         }
   536         // try the script -classpath loader, if that is set
   537         if (classPathLoader != null) {
   538             try {
   539                 return Class.forName(fullName, true, classPathLoader);
   540             } catch (final ClassNotFoundException ignored) {
   541                 // ignore, continue search
   542             }
   543         }
   545         // Try finding using the "app" loader.
   546         return Class.forName(fullName, true, appLoader);
   547     }
   549     /**
   550      * Hook to print stack trace for a {@link Throwable} that occurred during
   551      * execution
   552      *
   553      * @param t throwable for which to dump stack
   554      */
   555     public static void printStackTrace(final Throwable t) {
   556         if (Context.DEBUG) {
   557             t.printStackTrace(Context.getCurrentErr());
   558         }
   559     }
   561     /**
   562      * Verify generated bytecode before emission. This is called back from the
   563      * {@link ObjectClassGenerator} or the {@link Compiler}. If the "--verify-code" parameter
   564      * hasn't been given, this is a nop
   565      *
   566      * Note that verification may load classes -- we don't want to do that unless
   567      * user specified verify option. We check it here even though caller
   568      * may have already checked that flag
   569      *
   570      * @param bytecode bytecode to verify
   571      */
   572     public void verify(final byte[] bytecode) {
   573         if (env._verify_code) {
   574             // No verification when security manager is around as verifier
   575             // may load further classes - which should be avoided.
   576             if (System.getSecurityManager() == null) {
   577                 CheckClassAdapter.verify(new ClassReader(bytecode), scriptLoader, false, new PrintWriter(System.err, true));
   578             }
   579         }
   580     }
   582     /**
   583      * Create and initialize a new global scope object.
   584      *
   585      * @return the initialized global scope object.
   586      */
   587     public ScriptObject createGlobal() {
   588         return initGlobal(newGlobal());
   589     }
   591     /**
   592      * Create a new uninitialized global scope object
   593      * @return the global script object
   594      */
   595     public ScriptObject newGlobal() {
   596         final SecurityManager sm = System.getSecurityManager();
   597         if (sm != null) {
   598             sm.checkPermission(new RuntimePermission("nashorn.newGlobal"));
   599         }
   601         return newGlobalTrusted();
   602     }
   604     /**
   605      * Initialize given global scope object.
   606      *
   607      * @param global the global
   608      * @return the initialized global scope object.
   609      */
   610     public ScriptObject initGlobal(final ScriptObject global) {
   611         if (! (global instanceof GlobalObject)) {
   612             throw new IllegalArgumentException("not a global object!");
   613         }
   615         // Need only minimal global object, if we are just compiling.
   616         if (!env._compile_only) {
   617             final ScriptObject oldGlobal = Context.getGlobalTrusted();
   618             try {
   619                 Context.setGlobalTrusted(global);
   620                 // initialize global scope with builtin global objects
   621                 ((GlobalObject)global).initBuiltinObjects();
   622             } finally {
   623                 Context.setGlobalTrusted(oldGlobal);
   624             }
   625         }
   627         return global;
   628     }
   630     /**
   631      * Trusted variants - package-private
   632      */
   634     /**
   635      * Return the current global scope
   636      * @return current global scope
   637      */
   638     static ScriptObject getGlobalTrusted() {
   639         return currentGlobal.get();
   640     }
   642     /**
   643      * Set the current global scope
   644      */
   645     static void setGlobalTrusted(ScriptObject global) {
   646          currentGlobal.set(global);
   647     }
   649     /**
   650      * Return the current global's context
   651      * @return current global's context
   652      */
   653     static Context getContextTrusted() {
   654         return Context.getGlobalTrusted().getContext();
   655     }
   657     /**
   658      * Try to infer Context instance from the Class. If we cannot,
   659      * then get it from the thread local variable.
   660      *
   661      * @param clazz the class
   662      * @return context
   663      */
   664     static Context fromClass(final Class<?> clazz) {
   665         final ClassLoader loader = clazz.getClassLoader();
   667         Context context = null;
   668         if (loader instanceof NashornLoader) {
   669             context = ((NashornLoader)loader).getContext();
   670         }
   672         return (context != null) ? context : Context.getContextTrusted();
   673     }
   675     private static AccessControlContext createNoPermissionsContext() {
   676         return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, new Permissions()) });
   677     }
   679     private Object evaluateSource(final Source source, final ScriptObject scope, final ScriptObject thiz) {
   680         ScriptFunction script = null;
   682         try {
   683             script = compileScript(source, scope, new Context.ThrowErrorManager());
   684         } catch (final ParserException e) {
   685             e.throwAsEcmaException();
   686         }
   688         return ScriptRuntime.apply(script, thiz);
   689     }
   691     private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) {
   692         if (script == null) {
   693             return null;
   694         }
   696         // Get run method - the entry point to the script
   697         final MethodHandle runMethodHandle =
   698                 MH.findStatic(
   699                     MethodHandles.lookup(),
   700                     script,
   701                     RUN_SCRIPT.symbolName(),
   702                     MH.type(
   703                         Object.class,
   704                         ScriptFunction.class,
   705                         Object.class));
   707         boolean strict;
   709         try {
   710             strict = script.getField(STRICT_MODE.symbolName()).getBoolean(null);
   711         } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
   712             strict = false;
   713         }
   715         // Package as a JavaScript function and pass function back to shell.
   716         return ((GlobalObject)Context.getGlobalTrusted()).newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
   717     }
   719     private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
   720         return getRunScriptFunction(compile(source, errMan, this._strict), scope);
   721     }
   723     private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict) {
   724         // start with no errors, no warnings.
   725         errMan.reset();
   727         GlobalObject global = null;
   728         Class<?> script;
   730         if (env._class_cache_size > 0) {
   731             global = (GlobalObject)Context.getGlobalTrusted();
   732             script = global.findCachedClass(source);
   733             if (script != null) {
   734                 Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
   735                 return script;
   736             }
   737         }
   739         final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse();
   740         if (errors.hasErrors()) {
   741             return null;
   742         }
   744         if (env._print_ast) {
   745             getErr().println(new ASTWriter(functionNode));
   746         }
   748         if (env._print_parse) {
   749             getErr().println(new PrintVisitor(functionNode));
   750         }
   752         if (env._parse_only) {
   753             return null;
   754         }
   756         final URL          url    = source.getURL();
   757         final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
   758         final CodeSource   cs     = url == null ? null : new CodeSource(url, (CodeSigner[])null);
   759         final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
   761         final Compiler compiler = new Compiler(installer, strict);
   763         final FunctionNode newFunctionNode = compiler.compile(functionNode);
   764         script = compiler.install(newFunctionNode);
   766         if (global != null) {
   767             global.cacheClass(source, script);
   768         }
   770         return script;
   771     }
   773     private ScriptLoader createNewLoader() {
   774         return AccessController.doPrivileged(
   775              new PrivilegedAction<ScriptLoader>() {
   776                 @Override
   777                 public ScriptLoader run() {
   778                     // Generated code won't refer to any class generated by context
   779                     // script loader and so parent loader can be the structure
   780                     // loader -- which is parent of the context script loader.
   781                     return new ScriptLoader((StructureLoader)scriptLoader.getParent(), Context.this);
   782                 }
   783              });
   784     }
   786     private ScriptObject newGlobalTrusted() {
   787         try {
   788             final Class<?> clazz = Class.forName("jdk.nashorn.internal.objects.Global", true, scriptLoader);
   789             final Constructor<?> cstr = clazz.getConstructor(Context.class);
   790             return (ScriptObject) cstr.newInstance(this);
   791         } catch (final Exception e) {
   792             printStackTrace(e);
   793             if (e instanceof RuntimeException) {
   794                 throw (RuntimeException)e;
   795             }
   796             throw new RuntimeException(e);
   797         }
   798     }
   799 }

mercurial