8053905: Eager code generation fails for earley boyer with split threshold set to 1000

Mon, 27 Apr 2015 12:50:21 +0200

author
hannesw
date
Mon, 27 Apr 2015 12:50:21 +0200
changeset 1337
248dc4f11e5b
parent 1336
5ed57fe26f13
child 1338
24e7c53c5716

8053905: Eager code generation fails for earley boyer with split threshold set to 1000
Reviewed-by: attila, lagergren

src/jdk/nashorn/internal/codegen/CodeGenerator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CompilationPhase.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CompileUnit.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/Compiler.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/TypeEvaluator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Context.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/FunctionInitializer.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/StoredScript.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8053905.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8053905.js.EXPECTED file | annotate | diff | comparison | revisions
test/script/basic/compile-octane-splitter.js file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Mon Apr 27 12:27:33 2015 +0200
     1.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Mon Apr 27 12:50:21 2015 +0200
     1.3 @@ -4526,7 +4526,7 @@
     1.4          }
     1.5  
     1.6          if (addInitializer && !compiler.isOnDemandCompilation()) {
     1.7 -            compiler.addFunctionInitializer(data, functionNode);
     1.8 +            functionNode.getCompileUnit().addFunctionInitializer(data, functionNode);
     1.9          }
    1.10  
    1.11          // We don't emit a ScriptFunction on stack for the outermost compiled function (as there's no code being
     2.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Mon Apr 27 12:27:33 2015 +0200
     2.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Mon Apr 27 12:50:21 2015 +0200
     2.3 @@ -57,7 +57,6 @@
     2.4  import jdk.nashorn.internal.ir.debug.PrintVisitor;
     2.5  import jdk.nashorn.internal.ir.visitor.NodeVisitor;
     2.6  import jdk.nashorn.internal.runtime.CodeInstaller;
     2.7 -import jdk.nashorn.internal.runtime.FunctionInitializer;
     2.8  import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
     2.9  import jdk.nashorn.internal.runtime.ScriptEnvironment;
    2.10  import jdk.nashorn.internal.runtime.logging.DebugLogger;
    2.11 @@ -581,18 +580,7 @@
    2.12                      continue;
    2.13                  }
    2.14                  unit.setCode(installedClasses.get(unit.getUnitClassName()));
    2.15 -            }
    2.16 -
    2.17 -            if (!compiler.isOnDemandCompilation()) {
    2.18 -                // Initialize functions
    2.19 -                final Map<Integer, FunctionInitializer> initializers = compiler.getFunctionInitializers();
    2.20 -                if (initializers != null) {
    2.21 -                    for (final Entry<Integer, FunctionInitializer> entry : initializers.entrySet()) {
    2.22 -                        final FunctionInitializer initializer = entry.getValue();
    2.23 -                        initializer.setCode(installedClasses.get(initializer.getClassName()));
    2.24 -                        compiler.getScriptFunctionData(entry.getKey()).initializeCode(initializer);
    2.25 -                    }
    2.26 -                }
    2.27 +                unit.initializeFunctionsCode();
    2.28              }
    2.29  
    2.30              if (log.isEnabled()) {
     3.1 --- a/src/jdk/nashorn/internal/codegen/CompileUnit.java	Mon Apr 27 12:27:33 2015 +0200
     3.2 +++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java	Mon Apr 27 12:50:21 2015 +0200
     3.3 @@ -26,10 +26,16 @@
     3.4  package jdk.nashorn.internal.codegen;
     3.5  
     3.6  import java.io.Serializable;
     3.7 +import java.util.Collection;
     3.8 +import java.util.Collections;
     3.9 +import java.util.IdentityHashMap;
    3.10 +import java.util.Map;
    3.11  import java.util.Objects;
    3.12  import java.util.Set;
    3.13  import java.util.TreeSet;
    3.14  import jdk.nashorn.internal.ir.CompileUnitHolder;
    3.15 +import jdk.nashorn.internal.ir.FunctionNode;
    3.16 +import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
    3.17  
    3.18  /**
    3.19    * Used to track split class compilation. Note that instances of the class are serializable, but all fields are
    3.20 @@ -50,6 +56,8 @@
    3.21  
    3.22      private transient Class<?> clazz;
    3.23  
    3.24 +    private transient Map<FunctionNode, RecompilableScriptFunctionData> functions = new IdentityHashMap<>();
    3.25 +
    3.26      private transient boolean isUsed;
    3.27  
    3.28      private static int emittedUnitCount;
    3.29 @@ -121,6 +129,32 @@
    3.30          this.classEmitter = null;
    3.31      }
    3.32  
    3.33 +    void addFunctionInitializer(final RecompilableScriptFunctionData data, final FunctionNode functionNode) {
    3.34 +        functions.put(functionNode, data);
    3.35 +    }
    3.36 +
    3.37 +    /**
    3.38 +     * Returns true if this compile unit is responsible for initializing the specified function data with specified
    3.39 +     * function node.
    3.40 +     * @param data the function data to check
    3.41 +     * @param functionNode the function node to check
    3.42 +     * @return true if this unit is responsible for initializing the function data with the function node, otherwise
    3.43 +     * false
    3.44 +     */
    3.45 +    public boolean isInitializing(final RecompilableScriptFunctionData data, final FunctionNode functionNode) {
    3.46 +        return functions.get(functionNode) == data;
    3.47 +    }
    3.48 +
    3.49 +    void initializeFunctionsCode() {
    3.50 +        for(final Map.Entry<FunctionNode, RecompilableScriptFunctionData> entry : functions.entrySet()) {
    3.51 +            entry.getValue().initializeCode(entry.getKey());
    3.52 +        }
    3.53 +    }
    3.54 +
    3.55 +    Collection<FunctionNode> getFunctionNodes() {
    3.56 +        return Collections.unmodifiableCollection(functions.keySet());
    3.57 +    }
    3.58 +
    3.59      /**
    3.60       * Add weight to this compile unit
    3.61       * @param w weight to add
     4.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java	Mon Apr 27 12:27:33 2015 +0200
     4.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java	Mon Apr 27 12:50:21 2015 +0200
     4.3 @@ -565,7 +565,7 @@
     4.4       * @return a copy of this compiler's current mapping of invalidated optimistic program points to their types.
     4.5       */
     4.6      public Map<Integer, Type> getInvalidatedProgramPoints() {
     4.7 -        return invalidatedProgramPoints == null ? null : new TreeMap<>(invalidatedProgramPoints);
     4.8 +        return invalidatedProgramPoints.isEmpty() ? null : new TreeMap<>(invalidatedProgramPoints);
     4.9      }
    4.10  
    4.11      TypeMap getTypeMap() {
    4.12 @@ -704,21 +704,6 @@
    4.13          return sb.toString();
    4.14      }
    4.15  
    4.16 -    Map<Integer, FunctionInitializer> functionInitializers;
    4.17 -
    4.18 -    void addFunctionInitializer(final RecompilableScriptFunctionData functionData, final FunctionNode functionNode) {
    4.19 -        if (functionInitializers == null) {
    4.20 -            functionInitializers = new HashMap<>();
    4.21 -        }
    4.22 -        if (!functionInitializers.containsKey(functionData)) {
    4.23 -            functionInitializers.put(functionData.getFunctionNodeId(), new FunctionInitializer(functionNode));
    4.24 -        }
    4.25 -    }
    4.26 -
    4.27 -    Map<Integer, FunctionInitializer> getFunctionInitializers() {
    4.28 -        return functionInitializers;
    4.29 -    }
    4.30 -
    4.31      /**
    4.32       * Persist current compilation with the given {@code cacheKey}.
    4.33       * @param cacheKey cache key
    4.34 @@ -726,15 +711,17 @@
    4.35       */
    4.36      public void persistClassInfo(final String cacheKey, final FunctionNode functionNode) {
    4.37          if (cacheKey != null && env._persistent_cache) {
    4.38 -            Map<Integer, FunctionInitializer> initializers;
    4.39              // If this is an on-demand compilation create a function initializer for the function being compiled.
    4.40              // Otherwise use function initializer map generated by codegen.
    4.41 -            if (functionInitializers == null) {
    4.42 -                initializers = new HashMap<>();
    4.43 -                final FunctionInitializer initializer = new FunctionInitializer(functionNode, getInvalidatedProgramPoints());
    4.44 -                initializers.put(functionNode.getId(), initializer);
    4.45 +            Map<Integer, FunctionInitializer> initializers = new HashMap<>();
    4.46 +            if (isOnDemandCompilation()) {
    4.47 +                initializers.put(functionNode.getId(), new FunctionInitializer(functionNode, getInvalidatedProgramPoints()));
    4.48              } else {
    4.49 -                initializers = functionInitializers;
    4.50 +                for (final CompileUnit compileUnit : getCompileUnits()) {
    4.51 +                    for (final FunctionNode fn : compileUnit.getFunctionNodes()) {
    4.52 +                        initializers.put(fn.getId(), new FunctionInitializer(fn));
    4.53 +                    }
    4.54 +                }
    4.55              }
    4.56              final String mainClassName = getFirstCompileUnit().getUnitClassName();
    4.57              installer.storeScript(cacheKey, source, mainClassName, bytecode, initializers, constantData.toArray(), compilationId);
     5.1 --- a/src/jdk/nashorn/internal/codegen/TypeEvaluator.java	Mon Apr 27 12:27:33 2015 +0200
     5.2 +++ b/src/jdk/nashorn/internal/codegen/TypeEvaluator.java	Mon Apr 27 12:50:21 2015 +0200
     5.3 @@ -227,7 +227,8 @@
     5.4              // gradually introduce them as needed. An easy one would be to do the same for .call(this) idiom.
     5.5              final CallNode callExpr = (CallNode)expr;
     5.6              final Expression fnExpr = callExpr.getFunction();
     5.7 -            if (fnExpr instanceof FunctionNode) {
     5.8 +            // Skip evaluation if running with eager compilation as we may violate constraints in RecompilableScriptFunctionData
     5.9 +            if (fnExpr instanceof FunctionNode && compiler.getContext().getEnv()._lazy_compilation) {
    5.10                  final FunctionNode fn = (FunctionNode)fnExpr;
    5.11                  if (callExpr.getArgs().isEmpty()) {
    5.12                      final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(fn.getId());
     6.1 --- a/src/jdk/nashorn/internal/runtime/Context.java	Mon Apr 27 12:27:33 2015 +0200
     6.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java	Mon Apr 27 12:50:21 2015 +0200
     6.3 @@ -1281,7 +1281,7 @@
     6.4              compiler.persistClassInfo(cacheKey, compiledFunction);
     6.5          } else {
     6.6              Compiler.updateCompilationId(storedScript.getCompilationId());
     6.7 -            script = install(storedScript, source, installer);
     6.8 +            script = storedScript.installScript(source, installer);
     6.9          }
    6.10  
    6.11          cacheClass(source, script);
    6.12 @@ -1303,51 +1303,6 @@
    6.13      }
    6.14  
    6.15      /**
    6.16 -     * Install a previously compiled class from the code cache.
    6.17 -     *
    6.18 -     * @param storedScript cached script containing class bytes and constants
    6.19 -     * @return main script class
    6.20 -     */
    6.21 -    private static Class<?> install(final StoredScript storedScript, final Source source, final CodeInstaller<ScriptEnvironment> installer) {
    6.22 -
    6.23 -        final Map<String, Class<?>> installedClasses = new HashMap<>();
    6.24 -        final Map<String, byte[]>   classBytes       = storedScript.getClassBytes();
    6.25 -        final Object[] constants       = storedScript.getConstants();
    6.26 -        final String   mainClassName   = storedScript.getMainClassName();
    6.27 -        final byte[]   mainClassBytes  = classBytes.get(mainClassName);
    6.28 -        final Class<?> mainClass       = installer.install(mainClassName, mainClassBytes);
    6.29 -        final Map<Integer, FunctionInitializer> initializers = storedScript.getInitializers();
    6.30 -
    6.31 -        installedClasses.put(mainClassName, mainClass);
    6.32 -
    6.33 -        for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
    6.34 -            final String className = entry.getKey();
    6.35 -            if (className.equals(mainClassName)) {
    6.36 -                continue;
    6.37 -            }
    6.38 -            final byte[] code = entry.getValue();
    6.39 -
    6.40 -            installedClasses.put(className, installer.install(className, code));
    6.41 -        }
    6.42 -
    6.43 -        installer.initialize(installedClasses.values(), source, constants);
    6.44 -
    6.45 -        for (final Object constant : constants) {
    6.46 -            if (constant instanceof RecompilableScriptFunctionData) {
    6.47 -                final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
    6.48 -                data.initTransients(source, installer);
    6.49 -                final FunctionInitializer initializer = initializers.get(data.getFunctionNodeId());
    6.50 -                if (initializer != null) {
    6.51 -                    initializer.setCode(installedClasses.get(initializer.getClassName()));
    6.52 -                    data.initializeCode(initializer);
    6.53 -                }
    6.54 -            }
    6.55 -        }
    6.56 -
    6.57 -        return mainClass;
    6.58 -    }
    6.59 -
    6.60 -    /**
    6.61       * Cache for compiled script classes.
    6.62       */
    6.63      @SuppressWarnings("serial")
     7.1 --- a/src/jdk/nashorn/internal/runtime/FunctionInitializer.java	Mon Apr 27 12:27:33 2015 +0200
     7.2 +++ b/src/jdk/nashorn/internal/runtime/FunctionInitializer.java	Mon Apr 27 12:50:21 2015 +0200
     7.3 @@ -60,17 +60,6 @@
     7.4      }
     7.5  
     7.6      /**
     7.7 -     * Copy constructor.
     7.8 -     *
     7.9 -     * @param init original initializer
    7.10 -     */
    7.11 -    FunctionInitializer(final FunctionInitializer init) {
    7.12 -        this.className = init.getClassName();
    7.13 -        this.methodType = init.getMethodType();
    7.14 -        this.flags = init.getFlags();
    7.15 -    }
    7.16 -
    7.17 -    /**
    7.18       * Constructor.
    7.19       *
    7.20       * @param functionNode the function node
    7.21 @@ -130,7 +119,7 @@
    7.22       * Set the class implementing the function
    7.23       * @param code the class
    7.24       */
    7.25 -    public void setCode(final Class<?> code) {
    7.26 +    void setCode(final Class<?> code) {
    7.27          // Make sure code has not been set and has expected class name
    7.28          if (this.code != null) {
    7.29              throw new IllegalStateException("code already set");
     8.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Mon Apr 27 12:27:33 2015 +0200
     8.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Mon Apr 27 12:50:21 2015 +0200
     8.3 @@ -32,7 +32,6 @@
     8.4  import java.lang.invoke.MethodType;
     8.5  import java.util.Collection;
     8.6  import java.util.Collections;
     8.7 -import java.util.HashMap;
     8.8  import java.util.HashSet;
     8.9  import java.util.Map;
    8.10  import java.util.Set;
    8.11 @@ -503,7 +502,7 @@
    8.12  
    8.13              if (script != null) {
    8.14                  Compiler.updateCompilationId(script.getCompilationId());
    8.15 -                return installStoredScript(script, newInstaller);
    8.16 +                return script.installFunction(this, newInstaller);
    8.17              }
    8.18          }
    8.19  
    8.20 @@ -518,56 +517,6 @@
    8.21          return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints());
    8.22      }
    8.23  
    8.24 -    private static Map<String, Class<?>> installStoredScriptClasses(final StoredScript script, final CodeInstaller<ScriptEnvironment> installer) {
    8.25 -        final Map<String, Class<?>> installedClasses = new HashMap<>();
    8.26 -        final Map<String, byte[]>   classBytes       = script.getClassBytes();
    8.27 -        final String   mainClassName   = script.getMainClassName();
    8.28 -        final byte[]   mainClassBytes  = classBytes.get(mainClassName);
    8.29 -
    8.30 -        final Class<?> mainClass       = installer.install(mainClassName, mainClassBytes);
    8.31 -
    8.32 -        installedClasses.put(mainClassName, mainClass);
    8.33 -
    8.34 -        for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
    8.35 -            final String className = entry.getKey();
    8.36 -            final byte[] bytecode = entry.getValue();
    8.37 -
    8.38 -            if (className.equals(mainClassName)) {
    8.39 -                continue;
    8.40 -            }
    8.41 -
    8.42 -            installedClasses.put(className, installer.install(className, bytecode));
    8.43 -        }
    8.44 -        return installedClasses;
    8.45 -    }
    8.46 -
    8.47 -    /**
    8.48 -     * Install this script using the given {@code installer}.
    8.49 -     *
    8.50 -     * @param script the compiled script
    8.51 -     * @return the function initializer
    8.52 -     */
    8.53 -    private FunctionInitializer installStoredScript(final StoredScript script, final CodeInstaller<ScriptEnvironment> newInstaller) {
    8.54 -        final Map<String, Class<?>> installedClasses = installStoredScriptClasses(script, newInstaller);
    8.55 -
    8.56 -        final Map<Integer, FunctionInitializer> initializers = script.getInitializers();
    8.57 -        assert initializers != null;
    8.58 -        assert initializers.size() == 1;
    8.59 -        final FunctionInitializer initializer = initializers.values().iterator().next();
    8.60 -
    8.61 -        final Object[] constants = script.getConstants();
    8.62 -        for (int i = 0; i < constants.length; i++) {
    8.63 -            if (constants[i] instanceof RecompilableScriptFunctionData) {
    8.64 -                // replace deserialized function data with the ones we already have
    8.65 -                constants[i] = getScriptFunctionData(((RecompilableScriptFunctionData) constants[i]).getFunctionNodeId());
    8.66 -            }
    8.67 -        }
    8.68 -
    8.69 -        newInstaller.initialize(installedClasses.values(), source, constants);
    8.70 -        initializer.setCode(installedClasses.get(initializer.getClassName()));
    8.71 -        return initializer;
    8.72 -    }
    8.73 -
    8.74      boolean usePersistentCodeCache() {
    8.75          final ScriptEnvironment env = installer.getOwner();
    8.76          return env._persistent_cache && env._optimistic_types;
    8.77 @@ -645,13 +594,21 @@
    8.78       * by the compiler internals in Nashorn and is public for implementation reasons only. Attempting to invoke it
    8.79       * externally will result in an exception.
    8.80       *
    8.81 -     * @param initializer FunctionInitializer for this data
    8.82 +     * @param functionNode FunctionNode for this data
    8.83       */
    8.84 -    public void initializeCode(final FunctionInitializer initializer) {
    8.85 +    public void initializeCode(final FunctionNode functionNode) {
    8.86          // Since the method is public, we double-check that we aren't invoked with an inappropriate compile unit.
    8.87 -        if(!code.isEmpty()) {
    8.88 +        if (!code.isEmpty() || functionNode.getId() != functionNodeId || !functionNode.getCompileUnit().isInitializing(this, functionNode)) {
    8.89              throw new IllegalStateException(name);
    8.90          }
    8.91 +        addCode(lookup(functionNode), null, null, functionNode.getFlags());
    8.92 +    }
    8.93 +
    8.94 +    /**
    8.95 +     * Initializes this function with the given function code initializer.
    8.96 +     * @param initializer function code initializer
    8.97 +     */
    8.98 +    void initializeCode(final FunctionInitializer initializer) {
    8.99          addCode(lookup(initializer, true), null, null, initializer.getFlags());
   8.100      }
   8.101  
     9.1 --- a/src/jdk/nashorn/internal/runtime/StoredScript.java	Mon Apr 27 12:27:33 2015 +0200
     9.2 +++ b/src/jdk/nashorn/internal/runtime/StoredScript.java	Mon Apr 27 12:50:21 2015 +0200
     9.3 @@ -27,7 +27,7 @@
     9.4  
     9.5  import java.io.Serializable;
     9.6  import java.util.Arrays;
     9.7 -import java.util.LinkedHashMap;
     9.8 +import java.util.HashMap;
     9.9  import java.util.Map;
    9.10  
    9.11  /**
    9.12 @@ -77,44 +77,70 @@
    9.13          return compilationId;
    9.14      }
    9.15  
    9.16 -    /**
    9.17 -     * Returns the main class name.
    9.18 -     * @return the main class name
    9.19 -     */
    9.20 -    public String getMainClassName() {
    9.21 -        return mainClassName;
    9.22 +    private Map<String, Class<?>> installClasses(final Source source, final CodeInstaller<ScriptEnvironment> installer) {
    9.23 +        final Map<String, Class<?>> installedClasses = new HashMap<>();
    9.24 +        final byte[]   mainClassBytes = classBytes.get(mainClassName);
    9.25 +        final Class<?> mainClass      = installer.install(mainClassName, mainClassBytes);
    9.26 +
    9.27 +        installedClasses.put(mainClassName, mainClass);
    9.28 +
    9.29 +        for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
    9.30 +            final String className = entry.getKey();
    9.31 +
    9.32 +            if (!className.equals(mainClassName)) {
    9.33 +                installedClasses.put(className, installer.install(className, entry.getValue()));
    9.34 +            }
    9.35 +        }
    9.36 +
    9.37 +        installer.initialize(installedClasses.values(), source, constants);
    9.38 +        return installedClasses;
    9.39 +    }
    9.40 +
    9.41 +    FunctionInitializer installFunction(final RecompilableScriptFunctionData data, final CodeInstaller<ScriptEnvironment> installer) {
    9.42 +        final Map<String, Class<?>> installedClasses = installClasses(data.getSource(), installer);
    9.43 +
    9.44 +        assert initializers != null;
    9.45 +        assert initializers.size() == 1;
    9.46 +        final FunctionInitializer initializer = initializers.values().iterator().next();
    9.47 +
    9.48 +        for (int i = 0; i < constants.length; i++) {
    9.49 +            if (constants[i] instanceof RecompilableScriptFunctionData) {
    9.50 +                // replace deserialized function data with the ones we already have
    9.51 +                final RecompilableScriptFunctionData newData = data.getScriptFunctionData(((RecompilableScriptFunctionData) constants[i]).getFunctionNodeId());
    9.52 +                assert newData != null;
    9.53 +                newData.initTransients(data.getSource(), installer);
    9.54 +                constants[i] = newData;
    9.55 +            }
    9.56 +        }
    9.57 +
    9.58 +        initializer.setCode(installedClasses.get(initializer.getClassName()));
    9.59 +        return initializer;
    9.60      }
    9.61  
    9.62      /**
    9.63 -     * Returns a map of class names to class bytes.
    9.64 -     * @return map of class bytes
    9.65 +     * Install as script.
    9.66 +     *
    9.67 +     * @param source the source
    9.68 +     * @param installer the installer
    9.69 +     * @return main script class
    9.70       */
    9.71 -    public Map<String, byte[]> getClassBytes() {
    9.72 -        final Map<String, byte[]> clonedMap = new LinkedHashMap<>();
    9.73 -        for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
    9.74 -            clonedMap.put(entry.getKey(), entry.getValue().clone());
    9.75 +    Class<?> installScript(final Source source, final CodeInstaller<ScriptEnvironment> installer) {
    9.76 +
    9.77 +        final Map<String, Class<?>> installedClasses = installClasses(source, installer);
    9.78 +
    9.79 +        for (final Object constant : constants) {
    9.80 +            if (constant instanceof RecompilableScriptFunctionData) {
    9.81 +                final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
    9.82 +                data.initTransients(source, installer);
    9.83 +                final FunctionInitializer initializer = initializers.get(data.getFunctionNodeId());
    9.84 +                if (initializer != null) {
    9.85 +                    initializer.setCode(installedClasses.get(initializer.getClassName()));
    9.86 +                    data.initializeCode(initializer);
    9.87 +                }
    9.88 +            }
    9.89          }
    9.90 -        return clonedMap;
    9.91 -    }
    9.92  
    9.93 -    /**
    9.94 -     * Returns the constants array.
    9.95 -     * @return constants array
    9.96 -     */
    9.97 -    public Object[] getConstants() {
    9.98 -        return constants.clone();
    9.99 -    }
   9.100 -
   9.101 -    /**
   9.102 -     * Returns the function initializers map.
   9.103 -     * @return The initializers map.
   9.104 -     */
   9.105 -    public Map<Integer, FunctionInitializer> getInitializers() {
   9.106 -        final Map<Integer, FunctionInitializer> clonedMap = new LinkedHashMap<>();
   9.107 -        for (final Map.Entry<Integer, FunctionInitializer> entry : initializers.entrySet()) {
   9.108 -            clonedMap.put(entry.getKey(), new FunctionInitializer(entry.getValue()));
   9.109 -        }
   9.110 -        return clonedMap;
   9.111 +        return installedClasses.get(mainClassName);
   9.112      }
   9.113  
   9.114      @Override
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/test/script/basic/JDK-8053905.js	Mon Apr 27 12:50:21 2015 +0200
    10.3 @@ -0,0 +1,38 @@
    10.4 +/*
    10.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
    10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 + * 
    10.8 + * This code is free software; you can redistribute it and/or modify it
    10.9 + * under the terms of the GNU General Public License version 2 only, as
   10.10 + * published by the Free Software Foundation.
   10.11 + * 
   10.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   10.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.15 + * version 2 for more details (a copy is included in the LICENSE file that
   10.16 + * accompanied this code).
   10.17 + * 
   10.18 + * You should have received a copy of the GNU General Public License version
   10.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   10.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.21 + * 
   10.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   10.23 + * or visit www.oracle.com if you need additional information or have any
   10.24 + * questions.
   10.25 + */
   10.26 +
   10.27 +/**
   10.28 + * JDK-8053905: Eager code generation fails for earley boyer with split threshold set to 1000
   10.29 + *
   10.30 + * @test
   10.31 + * @runif external.octane
   10.32 + * @fork
   10.33 + * @option -Dnashorn.compiler.splitter.threshold=1000
   10.34 + * @option -scripting
   10.35 + * @option --lazy-compilation=false
   10.36 + */
   10.37 +
   10.38 +var fn  = __DIR__ + 'compile-octane.js';
   10.39 +arguments.push("earley-boyer"); // run only earley-boyer
   10.40 +var url = new java.io.File(fn).toURL();
   10.41 +load(url);
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/test/script/basic/JDK-8053905.js.EXPECTED	Mon Apr 27 12:50:21 2015 +0200
    11.3 @@ -0,0 +1,2 @@
    11.4 +Compiling 'earley-boyer'...
    11.5 +Done.
    12.1 --- a/test/script/basic/compile-octane-splitter.js	Mon Apr 27 12:27:33 2015 +0200
    12.2 +++ b/test/script/basic/compile-octane-splitter.js	Mon Apr 27 12:50:21 2015 +0200
    12.3 @@ -29,11 +29,10 @@
    12.4   * forever, so make this test future safe, we specify them explicitly
    12.5   *
    12.6   * @test
    12.7 + * @runif external.octane
    12.8   * @fork
    12.9 + * @option -scripting
   12.10   * @option -Dnashorn.compiler.splitter.threshold=1000
   12.11 - * @fork
   12.12 - * @runif external.octane
   12.13 - * @option -scripting
   12.14   * @option -Dnashorn.typeInfo.disabled=true
   12.15   * @option --class-cache-size=0
   12.16   * @option --persistent-code-cache=false

mercurial