< prev index next >

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

Print this page

        

@@ -26,10 +26,12 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 
 import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import java.lang.ref.Reference;
 import java.lang.ref.SoftReference;

@@ -98,11 +100,11 @@
     /**
      * Cached form of the AST. Either a {@code SerializedAst} object used by split functions as they can't be
      * reparsed from source, or a soft reference to a {@code FunctionNode} for other functions (it is safe
      * to be cleared as they can be reparsed).
      */
-    private volatile Object cachedAst;
+    private volatile transient Object cachedAst;
 
     /** Token of this function within the source. */
     private final long token;
 
     /**

@@ -287,10 +289,13 @@
      */
     public void initTransients(final Source src, final CodeInstaller inst) {
         if (this.source == null && this.installer == null) {
             this.source    = src;
             this.installer = inst;
+            for (final RecompilableScriptFunctionData nested : nestedFunctions.values()) {
+                nested.initTransients(src, inst);
+            }
         } else if (this.source != src || !this.installer.isCompatibleWith(inst)) {
             // Existing values must be same as those passed as parameters
             throw new IllegalArgumentException();
         }
     }

@@ -422,11 +427,11 @@
             }
         // Are we strongly caching a serialized AST (for split functions only)?
         } else if (lCachedAst instanceof SerializedAst) {
             final SerializedAst serializedAst = (SerializedAst)lCachedAst;
             // Even so, are we also softly caching the AST?
-            final FunctionNode cachedFn = serializedAst.cachedAst.get();
+            final FunctionNode cachedFn = serializedAst.cachedAst == null ? null : serializedAst.cachedAst.get();
             if (cachedFn != null) {
                 // Yes we are - this is fast
                 return cloneSymbols(cachedFn);
             }
             final FunctionNode deserializedFn = deserialize(serializedAst.serializedAst);

@@ -490,13 +495,15 @@
      * functions. Since split functions are altered from their source form, they can't be reparsed from
      * source. While we could just use the {@code byte[]} representation in {@link RecompilableScriptFunctionData#cachedAst}
      * we're using this tuple instead to also keep a deserialized AST around in memory to cut down on
      * deserialization costs.
      */
-    private static class SerializedAst {
+    private static class SerializedAst implements Serializable {
         private final byte[] serializedAst;
-        private volatile Reference<FunctionNode> cachedAst;
+        private volatile transient Reference<FunctionNode> cachedAst;
+
+        private static final long serialVersionUID = 1L;
 
         SerializedAst(final FunctionNode fn, final Reference<FunctionNode> cachedAst) {
             this.serializedAst = AstSerializer.serialize(fn);
             this.cachedAst = cachedAst;
         }

@@ -1036,12 +1043,24 @@
             }
         }
         return true;
     }
 
+    private void writeObject(final ObjectOutputStream out) throws IOException {
+        final Object localCachedAst = cachedAst;
+        out.defaultWriteObject();
+        // We need to persist SerializedAst for split functions as they can't reparse the source code.
+        if (localCachedAst instanceof SerializedAst) {
+            out.writeObject(localCachedAst);
+        } else {
+            out.writeObject(null);
+        }
+    }
+
     private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject();
+        cachedAst = in.readObject();
         createLogger();
     }
 
     private void createLogger() {
         log = initLogger(Context.getContextTrusted());
< prev index next >