OpenJDK / jdk / jdk10
changeset 26887:f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
Reviewed-by: attila, shade
line wrap: on
line diff
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java Fri Sep 26 18:47:20 2014 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java Mon Sep 29 14:39:58 2014 -0700 @@ -32,7 +32,6 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.THIS; import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS; import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote; - import java.io.File; import java.lang.invoke.MethodType; import java.util.Arrays; @@ -154,6 +153,13 @@ private RecompilableScriptFunctionData compiledFunction; /** + * Most compile unit names are longer than the default StringBuilder buffer, + * worth startup performance when massive class generation is going on to increase + * this + */ + private static final int COMPILE_UNIT_NAME_BUFFER_SIZE = 32; + + /** * Compilation phases that a compilation goes through */ public static class CompilationPhases implements Iterable<CompilationPhase> { @@ -631,7 +637,8 @@ } String nextCompileUnitName() { - final StringBuilder sb = new StringBuilder(firstCompileUnitName); + final StringBuilder sb = new StringBuilder(COMPILE_UNIT_NAME_BUFFER_SIZE); + sb.append(firstCompileUnitName); final int cuid = nextCompileUnitId.getAndIncrement(); if (cuid > 0) { sb.append("$cu").append(cuid);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Label.java Fri Sep 26 18:47:20 2014 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Label.java Mon Sep 29 14:39:58 2014 -0700 @@ -590,8 +590,13 @@ return label.getOffset() > other.label.getOffset(); } + private String str; + @Override public String toString() { - return name + '_' + id; + if (str == null) { + str = name + '_' + id; + } + return str; } }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Fri Sep 26 18:47:20 2014 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Mon Sep 29 14:39:58 2014 -0700 @@ -2576,12 +2576,55 @@ * * @param args debug information to print */ + @SuppressWarnings("unused") private void debug(final Object... args) { if (debug) { debug(30, args); } } + private void debug(final String arg) { + if (debug) { + debug(30, arg); + } + } + + private void debug(final Object arg0, final Object arg1) { + if (debug) { + debug(30, new Object[] { arg0, arg1 }); + } + } + + private void debug(final Object arg0, final Object arg1, final Object arg2) { + if (debug) { + debug(30, new Object[] { arg0, arg1, arg2 }); + } + } + + private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3) { + if (debug) { + debug(30, new Object[] { arg0, arg1, arg2, arg3 }); + } + } + + private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4) { + if (debug) { + debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4 }); + } + } + + private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5) { + if (debug) { + debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5 }); + } + } + + private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5, final Object arg6) { + if (debug) { + debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6 }); + } + } + /** * Debug function that outputs generated bytecode and stack contents * for a label - indentation is currently the only thing that differs
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java Fri Sep 26 18:47:20 2014 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java Mon Sep 29 14:39:58 2014 -0700 @@ -54,8 +54,10 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.util.Collections; import java.util.Map; import java.util.TreeMap; +import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import jdk.internal.org.objectweb.asm.Handle; @@ -103,6 +105,16 @@ /** The class for this type */ private final Class<?> clazz; + /** + * Cache for internal types - this is a query that requires complex stringbuilding inside + * ASM and it saves startup time to cache the type mappings + */ + private static final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> INTERNAL_TYPE_CACHE = + Collections.synchronizedMap(new WeakHashMap<Class<?>, jdk.internal.org.objectweb.asm.Type>()); + + /** Internal ASM type for this Type - computed once at construction */ + private final jdk.internal.org.objectweb.asm.Type internalType; + /** Weights are used to decide which types are "wider" than other types */ protected static final int MIN_WEIGHT = -1; @@ -121,12 +133,13 @@ * @param slots how many bytecode slots the type takes up */ Type(final String name, final Class<?> clazz, final int weight, final int slots) { - this.name = name; - this.clazz = clazz; - this.descriptor = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz); - this.weight = weight; + this.name = name; + this.clazz = clazz; + this.descriptor = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz); + this.weight = weight; assert weight >= MIN_WEIGHT && weight <= MAX_WEIGHT : "illegal type weight: " + weight; - this.slots = slots; + this.slots = slots; + this.internalType = getInternalType(clazz); } /** @@ -356,11 +369,22 @@ } private jdk.internal.org.objectweb.asm.Type getInternalType() { - return jdk.internal.org.objectweb.asm.Type.getType(getTypeClass()); + return internalType; + } + + private static jdk.internal.org.objectweb.asm.Type lookupInternalType(final Class<?> type) { + final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> cache = INTERNAL_TYPE_CACHE; + jdk.internal.org.objectweb.asm.Type itype = cache.get(type); + if (itype != null) { + return itype; + } + itype = jdk.internal.org.objectweb.asm.Type.getType(type); + cache.put(type, itype); + return itype; } private static jdk.internal.org.objectweb.asm.Type getInternalType(final Class<?> type) { - return jdk.internal.org.objectweb.asm.Type.getType(type); + return lookupInternalType(type); } static void invokestatic(final MethodVisitor method, final Call call) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java Fri Sep 26 18:47:20 2014 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java Mon Sep 29 14:39:58 2014 -0700 @@ -30,7 +30,6 @@ import static jdk.nashorn.internal.parser.TokenType.EOF; import static jdk.nashorn.internal.parser.TokenType.EOL; import static jdk.nashorn.internal.parser.TokenType.IDENT; - import java.util.HashMap; import java.util.Map; import jdk.nashorn.internal.ir.IdentNode;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Fri Sep 26 18:47:20 2014 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Mon Sep 29 14:39:58 2014 -0700 @@ -589,7 +589,9 @@ } MethodHandle lookupCodeMethod(final Class<?> codeClass, final MethodType targetType) { - log.info("Looking up ", DebugLogger.quote(name), " type=", targetType); + if (log.isEnabled()) { + log.info("Looking up ", DebugLogger.quote(name), " type=", targetType); + } return MH.findStatic(LOOKUP, codeClass, functionName, targetType); }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java Fri Sep 26 18:47:20 2014 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java Mon Sep 29 14:39:58 2014 -0700 @@ -25,6 +25,9 @@ package jdk.nashorn.internal.runtime.regexp; +import java.util.Collections; +import java.util.Set; +import java.util.WeakHashMap; import jdk.nashorn.internal.runtime.ParserException; import jdk.nashorn.internal.runtime.options.Options; @@ -39,6 +42,15 @@ private final static String JDK = "jdk"; private final static String JONI = "joni"; + /** Weak cache of already validated regexps - when reparsing, we don't, for example + * need to recompile (reverify) all regexps that have previously been parsed by this + * RegExpFactory in a previous compilation. This saves significant time in e.g. avatar + * startup */ + private static final Set<String> VALID_CACHE_SET = + Collections.newSetFromMap( + Collections.synchronizedMap( + new WeakHashMap<String, Boolean>())); + static { final String impl = Options.getStringProperty("nashorn.regexp.impl", JONI); switch (impl) { @@ -88,7 +100,9 @@ */ // @SuppressWarnings({"unused"}) public static void validate(final String pattern, final String flags) throws ParserException { - instance.compile(pattern, flags); + if (VALID_CACHE_SET.add(pattern + flags)) { + instance.compile(pattern, flags); + } } /**