< 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 >