8138882: Performance regression due to anonymous classloading
Reviewed-by: attila, sundar
This commit is contained in:
parent
c1fa6e31e8
commit
26fc600426
@ -140,7 +140,7 @@ public final class Context {
|
|||||||
|
|
||||||
private static final LongAdder NAMED_INSTALLED_SCRIPT_COUNT = new LongAdder();
|
private static final LongAdder NAMED_INSTALLED_SCRIPT_COUNT = new LongAdder();
|
||||||
private static final LongAdder ANONYMOUS_INSTALLED_SCRIPT_COUNT = new LongAdder();
|
private static final LongAdder ANONYMOUS_INSTALLED_SCRIPT_COUNT = new LongAdder();
|
||||||
private static final boolean DISABLE_VM_ANONYMOUS_CLASSES = Options.getBooleanProperty("nashorn.disableVmAnonymousClasses");
|
|
||||||
/**
|
/**
|
||||||
* Should scripts use only object slots for fields, or dual long/object slots? The default
|
* Should scripts use only object slots for fields, or dual long/object slots? The default
|
||||||
* behaviour is to couple this to optimistic types, using dual representation if optimistic types are enabled
|
* behaviour is to couple this to optimistic types, using dual representation if optimistic types are enabled
|
||||||
@ -775,7 +775,7 @@ public final class Context {
|
|||||||
* @return reusable compiled script across many global scopes.
|
* @return reusable compiled script across many global scopes.
|
||||||
*/
|
*/
|
||||||
public MultiGlobalCompiledScript compileScript(final Source source) {
|
public MultiGlobalCompiledScript compileScript(final Source source) {
|
||||||
final Class<?> clazz = compile(source, this.errors, this._strict);
|
final Class<?> clazz = compile(source, this.errors, this._strict, false);
|
||||||
final MethodHandle createProgramFunctionHandle = getCreateProgramFunctionHandle(clazz);
|
final MethodHandle createProgramFunctionHandle = getCreateProgramFunctionHandle(clazz);
|
||||||
|
|
||||||
return new MultiGlobalCompiledScript() {
|
return new MultiGlobalCompiledScript() {
|
||||||
@ -829,7 +829,7 @@ public final class Context {
|
|||||||
|
|
||||||
Class<?> clazz = null;
|
Class<?> clazz = null;
|
||||||
try {
|
try {
|
||||||
clazz = compile(source, new ThrowErrorManager(), strictFlag);
|
clazz = compile(source, new ThrowErrorManager(), strictFlag, true);
|
||||||
} catch (final ParserException e) {
|
} catch (final ParserException e) {
|
||||||
e.throwAsEcmaException(global);
|
e.throwAsEcmaException(global);
|
||||||
return null;
|
return null;
|
||||||
@ -1379,10 +1379,10 @@ public final class Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
|
private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
|
||||||
return getProgramFunction(compile(source, errMan, this._strict), scope);
|
return getProgramFunction(compile(source, errMan, this._strict, false), scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict) {
|
private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict, final boolean isEval) {
|
||||||
// start with no errors, no warnings.
|
// start with no errors, no warnings.
|
||||||
errMan.reset();
|
errMan.reset();
|
||||||
|
|
||||||
@ -1434,7 +1434,7 @@ public final class Context {
|
|||||||
final URL url = source.getURL();
|
final URL url = source.getURL();
|
||||||
final CodeSource cs = new CodeSource(url, (CodeSigner[])null);
|
final CodeSource cs = new CodeSource(url, (CodeSigner[])null);
|
||||||
final CodeInstaller installer;
|
final CodeInstaller installer;
|
||||||
if (DISABLE_VM_ANONYMOUS_CLASSES || env._persistent_cache || !env._lazy_compilation) {
|
if (!env.useAnonymousClasses(isEval) || env._persistent_cache || !env._lazy_compilation) {
|
||||||
// Persistent code cache and eager compilation preclude use of VM anonymous classes
|
// Persistent code cache and eager compilation preclude use of VM anonymous classes
|
||||||
final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
|
final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
|
||||||
installer = new NamedContextCodeInstaller(this, cs, loader);
|
installer = new NamedContextCodeInstaller(this, cs, loader);
|
||||||
|
@ -213,6 +213,14 @@ public final class ScriptEnvironment {
|
|||||||
/** Timing */
|
/** Timing */
|
||||||
public final Timing _timing;
|
public final Timing _timing;
|
||||||
|
|
||||||
|
/** Whether to use anonymous classes. See {@link #useAnonymousClasses(boolean)}. */
|
||||||
|
private final AnonymousClasses _anonymousClasses;
|
||||||
|
private enum AnonymousClasses {
|
||||||
|
AUTO,
|
||||||
|
OFF,
|
||||||
|
ON
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -279,6 +287,18 @@ public final class ScriptEnvironment {
|
|||||||
_version = options.getBoolean("version");
|
_version = options.getBoolean("version");
|
||||||
_verify_code = options.getBoolean("verify.code");
|
_verify_code = options.getBoolean("verify.code");
|
||||||
|
|
||||||
|
final String anonClasses = options.getString("anonymous.classes");
|
||||||
|
if (anonClasses == null || anonClasses.equals("auto")) {
|
||||||
|
_anonymousClasses = AnonymousClasses.AUTO;
|
||||||
|
} else if (anonClasses.equals("true")) {
|
||||||
|
_anonymousClasses = AnonymousClasses.ON;
|
||||||
|
} else if (anonClasses.equals("false")) {
|
||||||
|
_anonymousClasses = AnonymousClasses.OFF;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unsupported value for anonymous classes: " + anonClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
final String language = options.getString("language");
|
final String language = options.getString("language");
|
||||||
if (language == null || language.equals("es5")) {
|
if (language == null || language.equals("es5")) {
|
||||||
_es6 = false;
|
_es6 = false;
|
||||||
@ -411,4 +431,13 @@ public final class ScriptEnvironment {
|
|||||||
return _timing != null ? _timing.isEnabled() : false;
|
return _timing != null ? _timing.isEnabled() : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if compilation should use anonymous classes.
|
||||||
|
* @param isEval true if compilation is an eval call.
|
||||||
|
* @return true if anonymous classes should be used
|
||||||
|
*/
|
||||||
|
public boolean useAnonymousClasses(final boolean isEval) {
|
||||||
|
return _anonymousClasses == AnonymousClasses.ON || (_anonymousClasses == AnonymousClasses.AUTO && isEval);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -380,6 +380,15 @@ nashorn.option.trace.callsites = {
|
|||||||
enterexit [trace callsite enter/exit], objects [print object properties]." \
|
enterexit [trace callsite enter/exit], objects [print object properties]." \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nashorn.option.anonymous.classes = { \
|
||||||
|
name="--anonymous-classes", \
|
||||||
|
is_undocumented=true, \
|
||||||
|
params=[auto|true|false], \
|
||||||
|
default=auto, \
|
||||||
|
type=string, \
|
||||||
|
desc="Use VM anonymous classes for compiled scripts." \
|
||||||
|
}
|
||||||
|
|
||||||
nashorn.option.verify.code = { \
|
nashorn.option.verify.code = { \
|
||||||
name="--verify-code", \
|
name="--verify-code", \
|
||||||
is_undocumented=true, \
|
is_undocumented=true, \
|
||||||
|
@ -126,12 +126,12 @@ var booleanCls = Java.type("java.lang.Boolean").TYPE;
|
|||||||
|
|
||||||
// private compile method of Context class
|
// private compile method of Context class
|
||||||
var compileMethod = Context.class.getDeclaredMethod("compile",
|
var compileMethod = Context.class.getDeclaredMethod("compile",
|
||||||
sourceCls, errorMgrCls, booleanCls);
|
sourceCls, errorMgrCls, booleanCls, booleanCls);
|
||||||
compileMethod.accessible = true;
|
compileMethod.accessible = true;
|
||||||
|
|
||||||
var scriptCls = compileMethod.invoke(Context.context,
|
var scriptCls = compileMethod.invoke(Context.context,
|
||||||
Source.sourceFor("test", "print('hello')"),
|
Source.sourceFor("test", "print('hello')"),
|
||||||
new Context.ThrowErrorManager(), false);
|
new Context.ThrowErrorManager(), false, false);
|
||||||
|
|
||||||
var SCRIPT_CLASS_NAME_PREFIX = "jdk.nashorn.internal.scripts.Script$";
|
var SCRIPT_CLASS_NAME_PREFIX = "jdk.nashorn.internal.scripts.Script$";
|
||||||
print("script class name pattern satisfied? " +
|
print("script class name pattern satisfied? " +
|
||||||
|
Loading…
Reference in New Issue
Block a user