Mercurial > people > rkennke > jdk9-shenandoah-final > nashorn
changeset 1045:11925a82ad9f
8059346: Single class loader is used to load compiled bytecode
Reviewed-by: hannesw, lagergren
author | attila |
---|---|
date | Thu, 02 Oct 2014 16:30:49 +0200 |
parents | 26c0435ffe0b |
children | 6008e2ea42c2 |
files | src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeInstaller.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java |
diffstat | 3 files changed, 63 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeInstaller.java Wed Oct 01 12:22:12 2014 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeInstaller.java Thu Oct 02 16:30:49 2014 +0200 @@ -100,4 +100,21 @@ * @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); + }
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Wed Oct 01 12:22:12 2014 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Thu Oct 02 16:30:49 2014 +0200 @@ -33,6 +33,7 @@ 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 @@ } /** - * Return the context for this installer + * Return the script environment for this installer * @return ScriptEnvironment */ @Override @@ -222,6 +223,20 @@ } 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 ? */
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Oct 01 12:22:12 2014 +0200 +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Thu Oct 02 16:30:49 2014 +0200 @@ -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 @@ 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 @@ 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 @@ return new Compiler( context, context.getEnv(), - installer, + getInstallerForNewCode(), functionNode.getSource(), // source context.getErrorManager(), isStrict() | functionNode.isStrict(), // is strict @@ -463,11 +475,12 @@ 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 @@ 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 @@ 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 @@ } } - installer.initialize(installedClasses.values(), source, constants); + newInstaller.initialize(installedClasses.values(), source, constants); initializer.setCode(installedClasses.get(initializer.getClassName())); return initializer; }