8059346: Single class loader is used to load compiled bytecode
Reviewed-by: hannesw, lagergren
This commit is contained in:
parent
e97393b108
commit
c7df19bca4
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime
@ -100,4 +100,21 @@ public interface CodeInstaller<T> {
|
||||
* @return compiled script data
|
||||
*/
|
||||
public StoredScript loadScript(Source source, String functionKey);
|
||||
|
||||
/**
|
||||
* Returns a new code installer that shares most of the functionality of this code installer, but uses a
|
||||
* new, independent class loader.
|
||||
* @return a new code installer with a new independent class loader.
|
||||
*/
|
||||
public CodeInstaller<T> withNewLoader();
|
||||
|
||||
/**
|
||||
* Returns true if this code installer is compatible with the other code installer. Compatibility is expected to be
|
||||
* an equivalence relation, and installers are supposed to be compatible with those they create using
|
||||
* {@link #withNewLoader()}.
|
||||
* @param other the other code installer tested for compatibility with this code installer.
|
||||
* @return true if this code installer is compatible with the other code installer.
|
||||
*/
|
||||
public boolean isCompatibleWith(CodeInstaller<T> other);
|
||||
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import static jdk.nashorn.internal.runtime.CodeStore.newCodeStore;
|
||||
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
|
||||
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||
import static jdk.nashorn.internal.runtime.Source.sourceFor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
@ -158,7 +159,7 @@ public final class Context {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the context for this installer
|
||||
* Return the script environment for this installer
|
||||
* @return ScriptEnvironment
|
||||
*/
|
||||
@Override
|
||||
@ -222,6 +223,20 @@ public final class Context {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeInstaller<ScriptEnvironment> withNewLoader() {
|
||||
return new ContextCodeInstaller(context, context.createNewLoader(), codeSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompatibleWith(final CodeInstaller<ScriptEnvironment> other) {
|
||||
if (other instanceof ContextCodeInstaller) {
|
||||
final ContextCodeInstaller cci = (ContextCodeInstaller)other;
|
||||
return cci.context == context && cci.codeSource == codeSource;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Is Context global debug mode enabled ? */
|
||||
|
@ -26,6 +26,7 @@
|
||||
package jdk.nashorn.internal.runtime;
|
||||
|
||||
import static jdk.nashorn.internal.lookup.Lookup.MH;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
@ -268,7 +269,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
if (this.source == null && this.installer == null) {
|
||||
this.source = src;
|
||||
this.installer = inst;
|
||||
} else if (this.source != src || this.installer != inst) {
|
||||
} else if (this.source != src || !this.installer.isCompatibleWith(inst)) {
|
||||
// Existing values must be same as those passed as parameters
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
@ -407,6 +408,17 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
return getCompiler(fn, actualCallSiteType, newLocals(runtimeScope), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a code installer for installing new code. If we're using either optimistic typing or loader-per-compile,
|
||||
* then asks for a code installer with a new class loader; otherwise just uses the current installer. We use
|
||||
* a new class loader with optimistic typing so that deoptimized code can get reclaimed by GC.
|
||||
* @return a code installer for installing new code.
|
||||
*/
|
||||
private CodeInstaller<ScriptEnvironment> getInstallerForNewCode() {
|
||||
final ScriptEnvironment env = installer.getOwner();
|
||||
return env._optimistic_types || env._loader_per_compile ? installer.withNewLoader() : installer;
|
||||
}
|
||||
|
||||
Compiler getCompiler(final FunctionNode functionNode, final MethodType actualCallSiteType,
|
||||
final ScriptObject runtimeScope, final Map<Integer, Type> invalidatedProgramPoints,
|
||||
final int[] continuationEntryPoints) {
|
||||
@ -417,7 +429,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
return new Compiler(
|
||||
context,
|
||||
context.getEnv(),
|
||||
installer,
|
||||
getInstallerForNewCode(),
|
||||
functionNode.getSource(), // source
|
||||
context.getErrorManager(),
|
||||
isStrict() | functionNode.isStrict(), // is strict
|
||||
@ -463,11 +475,12 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
final TypeMap typeMap = typeMap(actualCallSiteType);
|
||||
final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
|
||||
cacheKey = CodeStore.getCacheKey(functionNodeId, paramTypes);
|
||||
final StoredScript script = installer.loadScript(source, cacheKey);
|
||||
final CodeInstaller<ScriptEnvironment> newInstaller = getInstallerForNewCode();
|
||||
final StoredScript script = newInstaller.loadScript(source, cacheKey);
|
||||
|
||||
if (script != null) {
|
||||
Compiler.updateCompilationId(script.getCompilationId());
|
||||
return install(script);
|
||||
return installStoredScript(script, newInstaller);
|
||||
}
|
||||
}
|
||||
|
||||
@ -481,15 +494,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Install this script using the given {@code installer}.
|
||||
*
|
||||
* @param script the compiled script
|
||||
* @return the function initializer
|
||||
*/
|
||||
private FunctionInitializer install(final StoredScript script) {
|
||||
|
||||
private static Map<String, Class<?>> installStoredScriptClasses(final StoredScript script, final CodeInstaller<ScriptEnvironment> installer) {
|
||||
final Map<String, Class<?>> installedClasses = new HashMap<>();
|
||||
final Map<String, byte[]> classBytes = script.getClassBytes();
|
||||
final String mainClassName = script.getMainClassName();
|
||||
@ -509,6 +514,17 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
|
||||
installedClasses.put(className, installer.install(className, bytecode));
|
||||
}
|
||||
return installedClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install this script using the given {@code installer}.
|
||||
*
|
||||
* @param script the compiled script
|
||||
* @return the function initializer
|
||||
*/
|
||||
private FunctionInitializer installStoredScript(final StoredScript script, final CodeInstaller<ScriptEnvironment> newInstaller) {
|
||||
final Map<String, Class<?>> installedClasses = installStoredScriptClasses(script, newInstaller);
|
||||
|
||||
final Map<Integer, FunctionInitializer> initializers = script.getInitializers();
|
||||
assert initializers != null;
|
||||
@ -523,7 +539,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
}
|
||||
}
|
||||
|
||||
installer.initialize(installedClasses.values(), source, constants);
|
||||
newInstaller.initialize(installedClasses.values(), source, constants);
|
||||
initializer.setCode(installedClasses.get(initializer.getClassName()));
|
||||
return initializer;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user