src/jdk/nashorn/internal/codegen/Compiler.java

Print this page

        

@@ -60,12 +60,15 @@
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.TemporarySymbols;
 import jdk.nashorn.internal.ir.debug.ClassHistogramElement;
 import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
+import jdk.nashorn.internal.runtime.CodeCache;
 import jdk.nashorn.internal.runtime.CodeInstaller;
 import jdk.nashorn.internal.runtime.DebugLogger;
+import jdk.nashorn.internal.runtime.PersistentCodeCache;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.Timing;
 import jdk.nashorn.internal.runtime.options.Options;
 

@@ -403,17 +406,16 @@
         }
 
         return newFunctionNode;
     }
 
-    private Class<?> install(final String className, final byte[] code) {
+    private Class<?> install(final String className, final byte[] code, final Object[] constants) {
         LOG.fine("Installing class ", className);
 
         final Class<?> clazz = installer.install(Compiler.binaryName(className), code);
 
         try {
-            final Object[] constants = getConstantData().toArray();
             // Need doPrivileged because these fields are private
             AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
                 @Override
                 public Void run() throws Exception {
                     //use reflection to write source and constants table to installed classes

@@ -442,14 +444,24 @@
         final long t0 = Timing.isEnabled() ? System.currentTimeMillis() : 0L;
 
         assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " has no bytecode and cannot be installed";
 
         final Map<String, Class<?>> installedClasses = new HashMap<>();
+        final Object[] constants = getConstantData().toArray();
 
         final String   rootClassName = firstCompileUnitName();
         final byte[]   rootByteCode  = bytecode.get(rootClassName);
-        final Class<?> rootClass     = install(rootClassName, rootByteCode);
+        final Class<?> rootClass     = install(rootClassName, rootByteCode, constants);
+
+        final CodeCache codeCache = installer.getCodeCache();
+        if (!isLazy() && codeCache != null) {
+            try {
+                codeCache.putScript(source, rootClassName, bytecode, constants);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
 
         int length = rootByteCode.length;
 
         installedClasses.put(rootClassName, rootClass);
 

@@ -459,11 +471,11 @@
                 continue;
             }
             final byte[] code = entry.getValue();
             length += code.length;
 
-            installedClasses.put(className, install(className, code));
+            installedClasses.put(className, install(className, code, constants));
         }
 
         for (final CompileUnit unit : compileUnits) {
             unit.setCode(installedClasses.get(unit.getUnitClassName()));
         }

@@ -497,10 +509,46 @@
         }
 
         return rootClass;
     }
 
+    /**
+     * Install a previously compiled class from the code cache.
+     *
+     * @param cachedScript cached script containing class bytes and constants
+     * @return main script class
+     */
+    public Class<?> install(final PersistentCodeCache.CachedScript cachedScript) {
+        this.source = cachedScript.getSource();
+
+        final Map<String, Class<?>> installedClasses = new HashMap<>();
+        final Object[] constants = cachedScript.getConstants();
+
+        final String   rootClassName = cachedScript.getMainClassName();
+        final byte[]   rootByteCode  = cachedScript.getClassBytes().get(rootClassName);
+        final Class<?> rootClass     = install(rootClassName, rootByteCode, constants);
+
+        installedClasses.put(rootClassName, rootClass);
+
+        for (final Entry<String, byte[]> entry : cachedScript.getClassBytes().entrySet()) {
+            final String className = entry.getKey();
+            if (className.equals(rootClassName)) {
+                continue;
+            }
+            final byte[] code = entry.getValue();
+
+            installedClasses.put(className, install(className, code, constants));
+        }
+        for (Object constant : constants) {
+            if (constant instanceof RecompilableScriptFunctionData) {
+                ((RecompilableScriptFunctionData) constant).setCodeAndSource(installedClasses, source);
+            }
+        }
+
+        return rootClass;
+    }
+
     Set<CompileUnit> getCompileUnits() {
         return compileUnits;
     }
 
     boolean getStrictMode() {