8059321: Decrease warmup time by caching common structures that were reused during parse

Mon, 29 Sep 2014 14:39:58 -0700

author
lagergren
date
Mon, 29 Sep 2014 14:39:58 -0700
changeset 1029
70597fd25c61
parent 1028
d79265f2fa92
child 1030
7eba45a08557

8059321: Decrease warmup time by caching common structures that were reused during parse
Reviewed-by: attila, hannesw

src/jdk/nashorn/internal/codegen/Compiler.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/Label.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/MethodEmitter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/types/Type.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/parser/AbstractParser.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java	Thu Sep 25 15:53:47 2014 +0200
     1.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java	Mon Sep 29 14:39:58 2014 -0700
     1.3 @@ -32,7 +32,6 @@
     1.4  import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
     1.5  import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
     1.6  import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
     1.7 -
     1.8  import java.io.File;
     1.9  import java.lang.invoke.MethodType;
    1.10  import java.util.Arrays;
    1.11 @@ -154,6 +153,13 @@
    1.12      private RecompilableScriptFunctionData compiledFunction;
    1.13  
    1.14      /**
    1.15 +     * Most compile unit names are longer than the default StringBuilder buffer,
    1.16 +     * worth startup performance when massive class generation is going on to increase
    1.17 +     * this
    1.18 +     */
    1.19 +    private static final int COMPILE_UNIT_NAME_BUFFER_SIZE = 32;
    1.20 +
    1.21 +    /**
    1.22       * Compilation phases that a compilation goes through
    1.23       */
    1.24      public static class CompilationPhases implements Iterable<CompilationPhase> {
    1.25 @@ -631,7 +637,8 @@
    1.26      }
    1.27  
    1.28      String nextCompileUnitName() {
    1.29 -        final StringBuilder sb = new StringBuilder(firstCompileUnitName);
    1.30 +        final StringBuilder sb = new StringBuilder(COMPILE_UNIT_NAME_BUFFER_SIZE);
    1.31 +        sb.append(firstCompileUnitName);
    1.32          final int cuid = nextCompileUnitId.getAndIncrement();
    1.33          if (cuid > 0) {
    1.34              sb.append("$cu").append(cuid);
     2.1 --- a/src/jdk/nashorn/internal/codegen/Label.java	Thu Sep 25 15:53:47 2014 +0200
     2.2 +++ b/src/jdk/nashorn/internal/codegen/Label.java	Mon Sep 29 14:39:58 2014 -0700
     2.3 @@ -590,8 +590,13 @@
     2.4          return label.getOffset() > other.label.getOffset();
     2.5      }
     2.6  
     2.7 +    private String str;
     2.8 +
     2.9      @Override
    2.10      public String toString() {
    2.11 -        return name + '_' + id;
    2.12 +        if (str == null) {
    2.13 +            str = name + '_' + id;
    2.14 +        }
    2.15 +        return str;
    2.16      }
    2.17  }
     3.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Thu Sep 25 15:53:47 2014 +0200
     3.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Mon Sep 29 14:39:58 2014 -0700
     3.3 @@ -2586,12 +2586,55 @@
     3.4       *
     3.5       * @param args debug information to print
     3.6       */
     3.7 +    @SuppressWarnings("unused")
     3.8      private void debug(final Object... args) {
     3.9          if (debug) {
    3.10              debug(30, args);
    3.11          }
    3.12      }
    3.13  
    3.14 +    private void debug(final String arg) {
    3.15 +        if (debug) {
    3.16 +            debug(30, arg);
    3.17 +        }
    3.18 +    }
    3.19 +
    3.20 +    private void debug(final Object arg0, final Object arg1) {
    3.21 +        if (debug) {
    3.22 +            debug(30, new Object[] { arg0, arg1 });
    3.23 +        }
    3.24 +    }
    3.25 +
    3.26 +    private void debug(final Object arg0, final Object arg1, final Object arg2) {
    3.27 +        if (debug) {
    3.28 +            debug(30, new Object[] { arg0, arg1, arg2 });
    3.29 +        }
    3.30 +    }
    3.31 +
    3.32 +    private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3) {
    3.33 +        if (debug) {
    3.34 +            debug(30, new Object[] { arg0, arg1, arg2, arg3 });
    3.35 +        }
    3.36 +    }
    3.37 +
    3.38 +    private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4) {
    3.39 +        if (debug) {
    3.40 +            debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4 });
    3.41 +        }
    3.42 +    }
    3.43 +
    3.44 +    private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5) {
    3.45 +        if (debug) {
    3.46 +            debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5 });
    3.47 +        }
    3.48 +    }
    3.49 +
    3.50 +    private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5, final Object arg6) {
    3.51 +        if (debug) {
    3.52 +            debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6 });
    3.53 +        }
    3.54 +    }
    3.55 +
    3.56      /**
    3.57       * Debug function that outputs generated bytecode and stack contents
    3.58       * for a label - indentation is currently the only thing that differs
     4.1 --- a/src/jdk/nashorn/internal/codegen/types/Type.java	Thu Sep 25 15:53:47 2014 +0200
     4.2 +++ b/src/jdk/nashorn/internal/codegen/types/Type.java	Mon Sep 29 14:39:58 2014 -0700
     4.3 @@ -54,8 +54,10 @@
     4.4  import java.lang.invoke.MethodHandle;
     4.5  import java.lang.invoke.MethodHandles;
     4.6  import java.lang.invoke.MethodType;
     4.7 +import java.util.Collections;
     4.8  import java.util.Map;
     4.9  import java.util.TreeMap;
    4.10 +import java.util.WeakHashMap;
    4.11  import java.util.concurrent.ConcurrentHashMap;
    4.12  import java.util.concurrent.ConcurrentMap;
    4.13  import jdk.internal.org.objectweb.asm.Handle;
    4.14 @@ -103,6 +105,16 @@
    4.15      /** The class for this type */
    4.16      private final Class<?> clazz;
    4.17  
    4.18 +    /**
    4.19 +     * Cache for internal types - this is a query that requires complex stringbuilding inside
    4.20 +     * ASM and it saves startup time to cache the type mappings
    4.21 +     */
    4.22 +    private static final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> INTERNAL_TYPE_CACHE =
    4.23 +            Collections.synchronizedMap(new WeakHashMap<Class<?>, jdk.internal.org.objectweb.asm.Type>());
    4.24 +
    4.25 +    /** Internal ASM type for this Type - computed once at construction */
    4.26 +    private final jdk.internal.org.objectweb.asm.Type internalType;
    4.27 +
    4.28      /** Weights are used to decide which types are "wider" than other types */
    4.29      protected static final int MIN_WEIGHT = -1;
    4.30  
    4.31 @@ -121,12 +133,13 @@
    4.32       * @param slots       how many bytecode slots the type takes up
    4.33       */
    4.34      Type(final String name, final Class<?> clazz, final int weight, final int slots) {
    4.35 -        this.name       = name;
    4.36 -        this.clazz      = clazz;
    4.37 -        this.descriptor = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz);
    4.38 -        this.weight     = weight;
    4.39 +        this.name         = name;
    4.40 +        this.clazz        = clazz;
    4.41 +        this.descriptor   = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz);
    4.42 +        this.weight       = weight;
    4.43          assert weight >= MIN_WEIGHT && weight <= MAX_WEIGHT : "illegal type weight: " + weight;
    4.44 -        this.slots      = slots;
    4.45 +        this.slots        = slots;
    4.46 +        this.internalType = getInternalType(clazz);
    4.47      }
    4.48  
    4.49      /**
    4.50 @@ -356,11 +369,22 @@
    4.51      }
    4.52  
    4.53      private jdk.internal.org.objectweb.asm.Type getInternalType() {
    4.54 -        return jdk.internal.org.objectweb.asm.Type.getType(getTypeClass());
    4.55 +        return internalType;
    4.56 +    }
    4.57 +
    4.58 +    private static jdk.internal.org.objectweb.asm.Type lookupInternalType(final Class<?> type) {
    4.59 +        final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> cache = INTERNAL_TYPE_CACHE;
    4.60 +        jdk.internal.org.objectweb.asm.Type itype = cache.get(type);
    4.61 +        if (itype != null) {
    4.62 +            return itype;
    4.63 +        }
    4.64 +        itype = jdk.internal.org.objectweb.asm.Type.getType(type);
    4.65 +        cache.put(type, itype);
    4.66 +        return itype;
    4.67      }
    4.68  
    4.69      private static jdk.internal.org.objectweb.asm.Type getInternalType(final Class<?> type) {
    4.70 -        return jdk.internal.org.objectweb.asm.Type.getType(type);
    4.71 +        return lookupInternalType(type);
    4.72      }
    4.73  
    4.74      static void invokestatic(final MethodVisitor method, final Call call) {
     5.1 --- a/src/jdk/nashorn/internal/parser/AbstractParser.java	Thu Sep 25 15:53:47 2014 +0200
     5.2 +++ b/src/jdk/nashorn/internal/parser/AbstractParser.java	Mon Sep 29 14:39:58 2014 -0700
     5.3 @@ -30,7 +30,6 @@
     5.4  import static jdk.nashorn.internal.parser.TokenType.EOF;
     5.5  import static jdk.nashorn.internal.parser.TokenType.EOL;
     5.6  import static jdk.nashorn.internal.parser.TokenType.IDENT;
     5.7 -
     5.8  import java.util.HashMap;
     5.9  import java.util.Map;
    5.10  import jdk.nashorn.internal.ir.IdentNode;
     6.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Thu Sep 25 15:53:47 2014 +0200
     6.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Mon Sep 29 14:39:58 2014 -0700
     6.3 @@ -589,7 +589,9 @@
     6.4      }
     6.5  
     6.6      MethodHandle lookupCodeMethod(final Class<?> codeClass, final MethodType targetType) {
     6.7 -        log.info("Looking up ", DebugLogger.quote(name), " type=", targetType);
     6.8 +        if (log.isEnabled()) {
     6.9 +            log.info("Looking up ", DebugLogger.quote(name), " type=", targetType);
    6.10 +        }
    6.11          return MH.findStatic(LOOKUP, codeClass, functionName, targetType);
    6.12      }
    6.13  
     7.1 --- a/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Thu Sep 25 15:53:47 2014 +0200
     7.2 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Mon Sep 29 14:39:58 2014 -0700
     7.3 @@ -25,6 +25,9 @@
     7.4  
     7.5  package jdk.nashorn.internal.runtime.regexp;
     7.6  
     7.7 +import java.util.Collections;
     7.8 +import java.util.Set;
     7.9 +import java.util.WeakHashMap;
    7.10  import jdk.nashorn.internal.runtime.ParserException;
    7.11  import jdk.nashorn.internal.runtime.options.Options;
    7.12  
    7.13 @@ -39,6 +42,15 @@
    7.14      private final static String JDK  = "jdk";
    7.15      private final static String JONI = "joni";
    7.16  
    7.17 +    /** Weak cache of already validated regexps - when reparsing, we don't, for example
    7.18 +     *  need to recompile (reverify) all regexps that have previously been parsed by this
    7.19 +     *  RegExpFactory in a previous compilation. This saves significant time in e.g. avatar
    7.20 +     *  startup */
    7.21 +    private static final Set<String> VALID_CACHE_SET =
    7.22 +            Collections.newSetFromMap(
    7.23 +                    Collections.synchronizedMap(
    7.24 +                            new WeakHashMap<String, Boolean>()));
    7.25 +
    7.26      static {
    7.27          final String impl = Options.getStringProperty("nashorn.regexp.impl", JONI);
    7.28          switch (impl) {
    7.29 @@ -88,7 +100,9 @@
    7.30       */
    7.31      // @SuppressWarnings({"unused"})
    7.32      public static void validate(final String pattern, final String flags) throws ParserException {
    7.33 -        instance.compile(pattern, flags);
    7.34 +        if (VALID_CACHE_SET.add(pattern + flags)) {
    7.35 +            instance.compile(pattern, flags);
    7.36 +        }
    7.37      }
    7.38  
    7.39      /**

mercurial