src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java

Print this page




  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  */
  25 
  26 package jdk.nashorn.internal.runtime;
  27 
  28 import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
  29 import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
  30 import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
  31 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;

  32 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  33 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  34 import static jdk.nashorn.internal.runtime.Source.sourceFor;
  35 
  36 import java.io.File;
  37 import java.io.IOException;
  38 import java.io.PrintWriter;
  39 import java.lang.invoke.MethodHandle;
  40 import java.lang.invoke.MethodHandles;
  41 import java.lang.invoke.MethodType;
  42 import java.lang.ref.ReferenceQueue;
  43 import java.lang.ref.SoftReference;
  44 import java.lang.reflect.Field;
  45 import java.lang.reflect.Modifier;
  46 import java.net.MalformedURLException;
  47 import java.net.URL;
  48 import java.security.AccessControlContext;
  49 import java.security.AccessController;
  50 import java.security.CodeSigner;
  51 import java.security.CodeSource;


 183             } catch (final PrivilegedActionException e) {
 184                 throw new RuntimeException(e);
 185             }
 186         }
 187 
 188         @Override
 189         public void verify(final byte[] code) {
 190             context.verify(code);
 191         }
 192 
 193         @Override
 194         public long getUniqueScriptId() {
 195             return context.getUniqueScriptId();
 196         }
 197 
 198         @Override
 199         public void storeScript(final String cacheKey, final Source source, final String mainClassName,
 200                                 final Map<String,byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers,
 201                                 final Object[] constants, final int compilationId) {
 202             if (context.codeStore != null) {
 203                 context.codeStore.storeScript(cacheKey, source, mainClassName, classBytes, initializers, constants, compilationId);
 204             }
 205         }
 206 
 207         @Override
 208         public StoredScript loadScript(final Source source, final String functionKey) {
 209             if (context.codeStore != null) {
 210                 return context.codeStore.loadScript(source, functionKey);
 211             }
 212             return null;
 213         }
 214     }
 215 
 216     /** Is Context global debug mode enabled ? */
 217     public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
 218 
 219     private static final ThreadLocal<Global> currentGlobal = new ThreadLocal<>();
 220 
 221     // in-memory cache for loaded classes
 222     private ClassCache classCache;
 223 
 224     // persistent code store
 225     private CodeStore codeStore;
 226 
 227     /**
 228      * Get the current global scope
 229      * @return the current global scope
 230      */


 446         // if user passed -classpath option, make a class loader with that and set it as
 447         // thread context class loader so that script can access classes from that path.
 448         final String classPath = options.getString("classpath");
 449         if (!env._compile_only && classPath != null && !classPath.isEmpty()) {
 450             // make sure that caller can create a class loader.
 451             if (sm != null) {
 452                 sm.checkPermission(new RuntimePermission("createClassLoader"));
 453             }
 454             this.classPathLoader = NashornLoader.createClassLoader(classPath);
 455         } else {
 456             this.classPathLoader = null;
 457         }
 458 
 459         final int cacheSize = env._class_cache_size;
 460         if (cacheSize > 0) {
 461             classCache = new ClassCache(cacheSize);
 462         }
 463 
 464         if (env._persistent_cache) {
 465             try {
 466                 final String cacheDir = Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache");
 467                 codeStore = new CodeStore(this, cacheDir);
 468             } catch (final IOException e) {
 469                 throw new RuntimeException("Error initializing code cache", e);
 470             }
 471         }
 472 
 473         // print version info if asked.
 474         if (env._version) {
 475             getErr().println("nashorn " + Version.version());
 476         }
 477 
 478         if (env._fullversion) {
 479             getErr().println("nashorn full version " + Version.fullVersion());
 480         }
 481 
 482         initLoggers();
 483     }
 484 
 485 
 486     /**
 487      * Get the class filter for this context


1100 
1101     private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict) {
1102         // start with no errors, no warnings.
1103         errMan.reset();
1104 
1105         Class<?> script = findCachedClass(source);
1106         if (script != null) {
1107             final DebugLogger log = getLogger(Compiler.class);
1108             if (log.isEnabled()) {
1109                 log.fine(new RuntimeEvent<>(Level.INFO, source), "Code cache hit for ", source, " avoiding recompile.");
1110             }
1111             return script;
1112         }
1113 
1114         StoredScript storedScript = null;
1115         FunctionNode functionNode = null;
1116         final boolean useCodeStore = env._persistent_cache && !env._parse_only && !env._optimistic_types;
1117         final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null;
1118 
1119         if (useCodeStore) {
1120             storedScript = codeStore.loadScript(source, cacheKey);
1121         }
1122 
1123         if (storedScript == null) {
1124             functionNode = new Parser(env, source, errMan, strict, getLogger(Parser.class)).parse();
1125 
1126             if (errMan.hasErrors()) {
1127                 return null;
1128             }
1129 
1130             if (env._print_ast || functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
1131                 getErr().println(new ASTWriter(functionNode));
1132             }
1133 
1134             if (env._print_parse || functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
1135                 getErr().println(new PrintVisitor(functionNode, true, false));
1136             }
1137         }
1138 
1139         if (env._parse_only) {
1140             return null;


1177                 @Override
1178                 public ScriptLoader run() {
1179                     return new ScriptLoader(appLoader, Context.this);
1180                 }
1181              }, CREATE_LOADER_ACC_CTXT);
1182     }
1183 
1184     private long getUniqueScriptId() {
1185         return uniqueScriptId.getAndIncrement();
1186     }
1187 
1188     /**
1189      * Install a previously compiled class from the code cache.
1190      *
1191      * @param storedScript cached script containing class bytes and constants
1192      * @return main script class
1193      */
1194     private static Class<?> install(final StoredScript storedScript, final Source source, final CodeInstaller<ScriptEnvironment> installer) {
1195 
1196         final Map<String, Class<?>> installedClasses = new HashMap<>();

1197         final Object[] constants       = storedScript.getConstants();
1198         final String   mainClassName   = storedScript.getMainClassName();
1199         final byte[]   mainClassBytes  = storedScript.getClassBytes().get(mainClassName);
1200         final Class<?> mainClass       = installer.install(mainClassName, mainClassBytes);
1201         final Map<Integer, FunctionInitializer> initialzers = storedScript.getInitializers();
1202 
1203         installedClasses.put(mainClassName, mainClass);
1204 
1205         for (final Map.Entry<String, byte[]> entry : storedScript.getClassBytes().entrySet()) {
1206             final String className = entry.getKey();
1207             if (className.equals(mainClassName)) {
1208                 continue;
1209             }
1210             final byte[] code = entry.getValue();
1211 
1212             installedClasses.put(className, installer.install(className, code));
1213         }
1214 
1215         installer.initialize(installedClasses.values(), source, constants);
1216 
1217         for (final Object constant : constants) {
1218             if (constant instanceof RecompilableScriptFunctionData) {
1219                 final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
1220                 data.initTransients(source, installer);
1221                 if (initialzers != null) {
1222                     final FunctionInitializer initializer = initialzers.get(data.getFunctionNodeId());
1223                     initializer.setCode(installedClasses.get(initializer.getClassName()));
1224                     data.initializeCode(initializer);
1225                 }




  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  */
  25 
  26 package jdk.nashorn.internal.runtime;
  27 
  28 import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
  29 import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
  30 import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
  31 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
  32 import static jdk.nashorn.internal.runtime.CodeStore.newCodeStore;
  33 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  34 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  35 import static jdk.nashorn.internal.runtime.Source.sourceFor;
  36 
  37 import java.io.File;
  38 import java.io.IOException;
  39 import java.io.PrintWriter;
  40 import java.lang.invoke.MethodHandle;
  41 import java.lang.invoke.MethodHandles;
  42 import java.lang.invoke.MethodType;
  43 import java.lang.ref.ReferenceQueue;
  44 import java.lang.ref.SoftReference;
  45 import java.lang.reflect.Field;
  46 import java.lang.reflect.Modifier;
  47 import java.net.MalformedURLException;
  48 import java.net.URL;
  49 import java.security.AccessControlContext;
  50 import java.security.AccessController;
  51 import java.security.CodeSigner;
  52 import java.security.CodeSource;


 184             } catch (final PrivilegedActionException e) {
 185                 throw new RuntimeException(e);
 186             }
 187         }
 188 
 189         @Override
 190         public void verify(final byte[] code) {
 191             context.verify(code);
 192         }
 193 
 194         @Override
 195         public long getUniqueScriptId() {
 196             return context.getUniqueScriptId();
 197         }
 198 
 199         @Override
 200         public void storeScript(final String cacheKey, final Source source, final String mainClassName,
 201                                 final Map<String,byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers,
 202                                 final Object[] constants, final int compilationId) {
 203             if (context.codeStore != null) {
 204                 context.codeStore.store(cacheKey, source, mainClassName, classBytes, initializers, constants, compilationId);
 205             }
 206         }
 207 
 208         @Override
 209         public StoredScript loadScript(final Source source, final String functionKey) {
 210             if (context.codeStore != null) {
 211                 return context.codeStore.load(source, functionKey);
 212             }
 213             return null;
 214         }
 215     }
 216 
 217     /** Is Context global debug mode enabled ? */
 218     public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
 219 
 220     private static final ThreadLocal<Global> currentGlobal = new ThreadLocal<>();
 221 
 222     // in-memory cache for loaded classes
 223     private ClassCache classCache;
 224 
 225     // persistent code store
 226     private CodeStore codeStore;
 227 
 228     /**
 229      * Get the current global scope
 230      * @return the current global scope
 231      */


 447         // if user passed -classpath option, make a class loader with that and set it as
 448         // thread context class loader so that script can access classes from that path.
 449         final String classPath = options.getString("classpath");
 450         if (!env._compile_only && classPath != null && !classPath.isEmpty()) {
 451             // make sure that caller can create a class loader.
 452             if (sm != null) {
 453                 sm.checkPermission(new RuntimePermission("createClassLoader"));
 454             }
 455             this.classPathLoader = NashornLoader.createClassLoader(classPath);
 456         } else {
 457             this.classPathLoader = null;
 458         }
 459 
 460         final int cacheSize = env._class_cache_size;
 461         if (cacheSize > 0) {
 462             classCache = new ClassCache(cacheSize);
 463         }
 464 
 465         if (env._persistent_cache) {
 466             try {
 467                 codeStore = newCodeStore(this);

 468             } catch (final IOException e) {
 469                 throw new RuntimeException("Error initializing code cache", e);
 470             }
 471         }
 472 
 473         // print version info if asked.
 474         if (env._version) {
 475             getErr().println("nashorn " + Version.version());
 476         }
 477 
 478         if (env._fullversion) {
 479             getErr().println("nashorn full version " + Version.fullVersion());
 480         }
 481 
 482         initLoggers();
 483     }
 484 
 485 
 486     /**
 487      * Get the class filter for this context


1100 
1101     private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict) {
1102         // start with no errors, no warnings.
1103         errMan.reset();
1104 
1105         Class<?> script = findCachedClass(source);
1106         if (script != null) {
1107             final DebugLogger log = getLogger(Compiler.class);
1108             if (log.isEnabled()) {
1109                 log.fine(new RuntimeEvent<>(Level.INFO, source), "Code cache hit for ", source, " avoiding recompile.");
1110             }
1111             return script;
1112         }
1113 
1114         StoredScript storedScript = null;
1115         FunctionNode functionNode = null;
1116         final boolean useCodeStore = env._persistent_cache && !env._parse_only && !env._optimistic_types;
1117         final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null;
1118 
1119         if (useCodeStore) {
1120             storedScript = codeStore.load(source, cacheKey);
1121         }
1122 
1123         if (storedScript == null) {
1124             functionNode = new Parser(env, source, errMan, strict, getLogger(Parser.class)).parse();
1125 
1126             if (errMan.hasErrors()) {
1127                 return null;
1128             }
1129 
1130             if (env._print_ast || functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
1131                 getErr().println(new ASTWriter(functionNode));
1132             }
1133 
1134             if (env._print_parse || functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
1135                 getErr().println(new PrintVisitor(functionNode, true, false));
1136             }
1137         }
1138 
1139         if (env._parse_only) {
1140             return null;


1177                 @Override
1178                 public ScriptLoader run() {
1179                     return new ScriptLoader(appLoader, Context.this);
1180                 }
1181              }, CREATE_LOADER_ACC_CTXT);
1182     }
1183 
1184     private long getUniqueScriptId() {
1185         return uniqueScriptId.getAndIncrement();
1186     }
1187 
1188     /**
1189      * Install a previously compiled class from the code cache.
1190      *
1191      * @param storedScript cached script containing class bytes and constants
1192      * @return main script class
1193      */
1194     private static Class<?> install(final StoredScript storedScript, final Source source, final CodeInstaller<ScriptEnvironment> installer) {
1195 
1196         final Map<String, Class<?>> installedClasses = new HashMap<>();
1197         final Map<String, byte[]>   classBytes       = storedScript.getClassBytes();
1198         final Object[] constants       = storedScript.getConstants();
1199         final String   mainClassName   = storedScript.getMainClassName();
1200         final byte[]   mainClassBytes  = classBytes.get(mainClassName);
1201         final Class<?> mainClass       = installer.install(mainClassName, mainClassBytes);
1202         final Map<Integer, FunctionInitializer> initialzers = storedScript.getInitializers();
1203 
1204         installedClasses.put(mainClassName, mainClass);
1205 
1206         for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
1207             final String className = entry.getKey();
1208             if (className.equals(mainClassName)) {
1209                 continue;
1210             }
1211             final byte[] code = entry.getValue();
1212 
1213             installedClasses.put(className, installer.install(className, code));
1214         }
1215 
1216         installer.initialize(installedClasses.values(), source, constants);
1217 
1218         for (final Object constant : constants) {
1219             if (constant instanceof RecompilableScriptFunctionData) {
1220                 final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
1221                 data.initTransients(source, installer);
1222                 if (initialzers != null) {
1223                     final FunctionInitializer initializer = initialzers.get(data.getFunctionNodeId());
1224                     initializer.setCode(installedClasses.get(initializer.getClassName()));
1225                     data.initializeCode(initializer);
1226                 }