changeset 1257:bc8e67bec2f9 jdk9-b63

Merge
author lana
date Thu, 30 Apr 2015 17:21:20 -0700
parents e866be0f51ac b275aac76cdd
children 26901244399e 811bbe3c6959
files
diffstat 14 files changed, 223 insertions(+), 197 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Apr 30 13:02:10 2015 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Apr 30 17:21:20 2015 -0700
@@ -4526,7 +4526,7 @@
         }
 
         if (addInitializer && !compiler.isOnDemandCompilation()) {
-            compiler.addFunctionInitializer(data, functionNode);
+            functionNode.getCompileUnit().addFunctionInitializer(data, functionNode);
         }
 
         // We don't emit a ScriptFunction on stack for the outermost compiled function (as there's no code being
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Apr 30 13:02:10 2015 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Apr 30 17:21:20 2015 -0700
@@ -57,7 +57,6 @@
 import jdk.nashorn.internal.ir.debug.PrintVisitor;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.runtime.CodeInstaller;
-import jdk.nashorn.internal.runtime.FunctionInitializer;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -581,18 +580,7 @@
                     continue;
                 }
                 unit.setCode(installedClasses.get(unit.getUnitClassName()));
-            }
-
-            if (!compiler.isOnDemandCompilation()) {
-                // Initialize functions
-                final Map<Integer, FunctionInitializer> initializers = compiler.getFunctionInitializers();
-                if (initializers != null) {
-                    for (final Entry<Integer, FunctionInitializer> entry : initializers.entrySet()) {
-                        final FunctionInitializer initializer = entry.getValue();
-                        initializer.setCode(installedClasses.get(initializer.getClassName()));
-                        compiler.getScriptFunctionData(entry.getKey()).initializeCode(initializer);
-                    }
-                }
+                unit.initializeFunctionsCode();
             }
 
             if (log.isEnabled()) {
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java	Thu Apr 30 13:02:10 2015 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java	Thu Apr 30 17:21:20 2015 -0700
@@ -26,10 +26,16 @@
 package jdk.nashorn.internal.codegen;
 
 import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.TreeSet;
 import jdk.nashorn.internal.ir.CompileUnitHolder;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 
 /**
   * Used to track split class compilation. Note that instances of the class are serializable, but all fields are
@@ -50,6 +56,8 @@
 
     private transient Class<?> clazz;
 
+    private transient Map<FunctionNode, RecompilableScriptFunctionData> functions = new IdentityHashMap<>();
+
     private transient boolean isUsed;
 
     private static int emittedUnitCount;
@@ -121,6 +129,32 @@
         this.classEmitter = null;
     }
 
+    void addFunctionInitializer(final RecompilableScriptFunctionData data, final FunctionNode functionNode) {
+        functions.put(functionNode, data);
+    }
+
+    /**
+     * Returns true if this compile unit is responsible for initializing the specified function data with specified
+     * function node.
+     * @param data the function data to check
+     * @param functionNode the function node to check
+     * @return true if this unit is responsible for initializing the function data with the function node, otherwise
+     * false
+     */
+    public boolean isInitializing(final RecompilableScriptFunctionData data, final FunctionNode functionNode) {
+        return functions.get(functionNode) == data;
+    }
+
+    void initializeFunctionsCode() {
+        for(final Map.Entry<FunctionNode, RecompilableScriptFunctionData> entry : functions.entrySet()) {
+            entry.getValue().initializeCode(entry.getKey());
+        }
+    }
+
+    Collection<FunctionNode> getFunctionNodes() {
+        return Collections.unmodifiableCollection(functions.keySet());
+    }
+
     /**
      * Add weight to this compile unit
      * @param w weight to add
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java	Thu Apr 30 13:02:10 2015 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java	Thu Apr 30 17:21:20 2015 -0700
@@ -565,7 +565,7 @@
      * @return a copy of this compiler's current mapping of invalidated optimistic program points to their types.
      */
     public Map<Integer, Type> getInvalidatedProgramPoints() {
-        return invalidatedProgramPoints == null ? null : new TreeMap<>(invalidatedProgramPoints);
+        return invalidatedProgramPoints.isEmpty() ? null : new TreeMap<>(invalidatedProgramPoints);
     }
 
     TypeMap getTypeMap() {
@@ -704,21 +704,6 @@
         return sb.toString();
     }
 
-    Map<Integer, FunctionInitializer> functionInitializers;
-
-    void addFunctionInitializer(final RecompilableScriptFunctionData functionData, final FunctionNode functionNode) {
-        if (functionInitializers == null) {
-            functionInitializers = new HashMap<>();
-        }
-        if (!functionInitializers.containsKey(functionData)) {
-            functionInitializers.put(functionData.getFunctionNodeId(), new FunctionInitializer(functionNode));
-        }
-    }
-
-    Map<Integer, FunctionInitializer> getFunctionInitializers() {
-        return functionInitializers;
-    }
-
     /**
      * Persist current compilation with the given {@code cacheKey}.
      * @param cacheKey cache key
@@ -726,15 +711,17 @@
      */
     public void persistClassInfo(final String cacheKey, final FunctionNode functionNode) {
         if (cacheKey != null && env._persistent_cache) {
-            Map<Integer, FunctionInitializer> initializers;
             // If this is an on-demand compilation create a function initializer for the function being compiled.
             // Otherwise use function initializer map generated by codegen.
-            if (functionInitializers == null) {
-                initializers = new HashMap<>();
-                final FunctionInitializer initializer = new FunctionInitializer(functionNode, getInvalidatedProgramPoints());
-                initializers.put(functionNode.getId(), initializer);
+            Map<Integer, FunctionInitializer> initializers = new HashMap<>();
+            if (isOnDemandCompilation()) {
+                initializers.put(functionNode.getId(), new FunctionInitializer(functionNode, getInvalidatedProgramPoints()));
             } else {
-                initializers = functionInitializers;
+                for (final CompileUnit compileUnit : getCompileUnits()) {
+                    for (final FunctionNode fn : compileUnit.getFunctionNodes()) {
+                        initializers.put(fn.getId(), new FunctionInitializer(fn));
+                    }
+                }
             }
             final String mainClassName = getFirstCompileUnit().getUnitClassName();
             installer.storeScript(cacheKey, source, mainClassName, bytecode, initializers, constantData.toArray(), compilationId);
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java	Thu Apr 30 13:02:10 2015 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java	Thu Apr 30 17:21:20 2015 -0700
@@ -227,7 +227,8 @@
             // gradually introduce them as needed. An easy one would be to do the same for .call(this) idiom.
             final CallNode callExpr = (CallNode)expr;
             final Expression fnExpr = callExpr.getFunction();
-            if (fnExpr instanceof FunctionNode) {
+            // Skip evaluation if running with eager compilation as we may violate constraints in RecompilableScriptFunctionData
+            if (fnExpr instanceof FunctionNode && compiler.getContext().getEnv()._lazy_compilation) {
                 final FunctionNode fn = (FunctionNode)fnExpr;
                 if (callExpr.getArgs().isEmpty()) {
                     final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(fn.getId());
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Thu Apr 30 13:02:10 2015 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Thu Apr 30 17:21:20 2015 -0700
@@ -1281,7 +1281,7 @@
             compiler.persistClassInfo(cacheKey, compiledFunction);
         } else {
             Compiler.updateCompilationId(storedScript.getCompilationId());
-            script = install(storedScript, source, installer);
+            script = storedScript.installScript(source, installer);
         }
 
         cacheClass(source, script);
@@ -1303,51 +1303,6 @@
     }
 
     /**
-     * Install a previously compiled class from the code cache.
-     *
-     * @param storedScript cached script containing class bytes and constants
-     * @return main script class
-     */
-    private static Class<?> install(final StoredScript storedScript, final Source source, final CodeInstaller<ScriptEnvironment> installer) {
-
-        final Map<String, Class<?>> installedClasses = new HashMap<>();
-        final Map<String, byte[]>   classBytes       = storedScript.getClassBytes();
-        final Object[] constants       = storedScript.getConstants();
-        final String   mainClassName   = storedScript.getMainClassName();
-        final byte[]   mainClassBytes  = classBytes.get(mainClassName);
-        final Class<?> mainClass       = installer.install(mainClassName, mainClassBytes);
-        final Map<Integer, FunctionInitializer> initializers = storedScript.getInitializers();
-
-        installedClasses.put(mainClassName, mainClass);
-
-        for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
-            final String className = entry.getKey();
-            if (className.equals(mainClassName)) {
-                continue;
-            }
-            final byte[] code = entry.getValue();
-
-            installedClasses.put(className, installer.install(className, code));
-        }
-
-        installer.initialize(installedClasses.values(), source, constants);
-
-        for (final Object constant : constants) {
-            if (constant instanceof RecompilableScriptFunctionData) {
-                final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
-                data.initTransients(source, installer);
-                final FunctionInitializer initializer = initializers.get(data.getFunctionNodeId());
-                if (initializer != null) {
-                    initializer.setCode(installedClasses.get(initializer.getClassName()));
-                    data.initializeCode(initializer);
-                }
-            }
-        }
-
-        return mainClass;
-    }
-
-    /**
      * Cache for compiled script classes.
      */
     @SuppressWarnings("serial")
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FunctionInitializer.java	Thu Apr 30 13:02:10 2015 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FunctionInitializer.java	Thu Apr 30 17:21:20 2015 -0700
@@ -60,17 +60,6 @@
     }
 
     /**
-     * Copy constructor.
-     *
-     * @param init original initializer
-     */
-    FunctionInitializer(final FunctionInitializer init) {
-        this.className = init.getClassName();
-        this.methodType = init.getMethodType();
-        this.flags = init.getFlags();
-    }
-
-    /**
      * Constructor.
      *
      * @param functionNode the function node
@@ -130,7 +119,7 @@
      * Set the class implementing the function
      * @param code the class
      */
-    public void setCode(final Class<?> code) {
+    void setCode(final Class<?> code) {
         // Make sure code has not been set and has expected class name
         if (this.code != null) {
             throw new IllegalStateException("code already set");
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Thu Apr 30 13:02:10 2015 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Thu Apr 30 17:21:20 2015 -0700
@@ -32,7 +32,6 @@
 import java.lang.invoke.MethodType;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -503,7 +502,7 @@
 
             if (script != null) {
                 Compiler.updateCompilationId(script.getCompilationId());
-                return installStoredScript(script, newInstaller);
+                return script.installFunction(this, newInstaller);
             }
         }
 
@@ -518,56 +517,6 @@
         return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints());
     }
 
-    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();
-        final byte[]   mainClassBytes  = classBytes.get(mainClassName);
-
-        final Class<?> mainClass       = installer.install(mainClassName, mainClassBytes);
-
-        installedClasses.put(mainClassName, mainClass);
-
-        for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
-            final String className = entry.getKey();
-            final byte[] bytecode = entry.getValue();
-
-            if (className.equals(mainClassName)) {
-                continue;
-            }
-
-            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;
-        assert initializers.size() == 1;
-        final FunctionInitializer initializer = initializers.values().iterator().next();
-
-        final Object[] constants = script.getConstants();
-        for (int i = 0; i < constants.length; i++) {
-            if (constants[i] instanceof RecompilableScriptFunctionData) {
-                // replace deserialized function data with the ones we already have
-                constants[i] = getScriptFunctionData(((RecompilableScriptFunctionData) constants[i]).getFunctionNodeId());
-            }
-        }
-
-        newInstaller.initialize(installedClasses.values(), source, constants);
-        initializer.setCode(installedClasses.get(initializer.getClassName()));
-        return initializer;
-    }
-
     boolean usePersistentCodeCache() {
         final ScriptEnvironment env = installer.getOwner();
         return env._persistent_cache && env._optimistic_types;
@@ -645,13 +594,21 @@
      * by the compiler internals in Nashorn and is public for implementation reasons only. Attempting to invoke it
      * externally will result in an exception.
      *
-     * @param initializer FunctionInitializer for this data
+     * @param functionNode FunctionNode for this data
      */
-    public void initializeCode(final FunctionInitializer initializer) {
+    public void initializeCode(final FunctionNode functionNode) {
         // Since the method is public, we double-check that we aren't invoked with an inappropriate compile unit.
-        if(!code.isEmpty()) {
+        if (!code.isEmpty() || functionNode.getId() != functionNodeId || !functionNode.getCompileUnit().isInitializing(this, functionNode)) {
             throw new IllegalStateException(name);
         }
+        addCode(lookup(functionNode), null, null, functionNode.getFlags());
+    }
+
+    /**
+     * Initializes this function with the given function code initializer.
+     * @param initializer function code initializer
+     */
+    void initializeCode(final FunctionInitializer initializer) {
         addCode(lookup(initializer, true), null, null, initializer.getFlags());
     }
 
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StoredScript.java	Thu Apr 30 13:02:10 2015 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StoredScript.java	Thu Apr 30 17:21:20 2015 -0700
@@ -27,7 +27,7 @@
 
 import java.io.Serializable;
 import java.util.Arrays;
-import java.util.LinkedHashMap;
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -77,44 +77,70 @@
         return compilationId;
     }
 
-    /**
-     * Returns the main class name.
-     * @return the main class name
-     */
-    public String getMainClassName() {
-        return mainClassName;
+    private Map<String, Class<?>> installClasses(final Source source, final CodeInstaller<ScriptEnvironment> installer) {
+        final Map<String, Class<?>> installedClasses = new HashMap<>();
+        final byte[]   mainClassBytes = classBytes.get(mainClassName);
+        final Class<?> mainClass      = installer.install(mainClassName, mainClassBytes);
+
+        installedClasses.put(mainClassName, mainClass);
+
+        for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
+            final String className = entry.getKey();
+
+            if (!className.equals(mainClassName)) {
+                installedClasses.put(className, installer.install(className, entry.getValue()));
+            }
+        }
+
+        installer.initialize(installedClasses.values(), source, constants);
+        return installedClasses;
+    }
+
+    FunctionInitializer installFunction(final RecompilableScriptFunctionData data, final CodeInstaller<ScriptEnvironment> installer) {
+        final Map<String, Class<?>> installedClasses = installClasses(data.getSource(), installer);
+
+        assert initializers != null;
+        assert initializers.size() == 1;
+        final FunctionInitializer initializer = initializers.values().iterator().next();
+
+        for (int i = 0; i < constants.length; i++) {
+            if (constants[i] instanceof RecompilableScriptFunctionData) {
+                // replace deserialized function data with the ones we already have
+                final RecompilableScriptFunctionData newData = data.getScriptFunctionData(((RecompilableScriptFunctionData) constants[i]).getFunctionNodeId());
+                assert newData != null;
+                newData.initTransients(data.getSource(), installer);
+                constants[i] = newData;
+            }
+        }
+
+        initializer.setCode(installedClasses.get(initializer.getClassName()));
+        return initializer;
     }
 
     /**
-     * Returns a map of class names to class bytes.
-     * @return map of class bytes
+     * Install as script.
+     *
+     * @param source the source
+     * @param installer the installer
+     * @return main script class
      */
-    public Map<String, byte[]> getClassBytes() {
-        final Map<String, byte[]> clonedMap = new LinkedHashMap<>();
-        for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
-            clonedMap.put(entry.getKey(), entry.getValue().clone());
+    Class<?> installScript(final Source source, final CodeInstaller<ScriptEnvironment> installer) {
+
+        final Map<String, Class<?>> installedClasses = installClasses(source, installer);
+
+        for (final Object constant : constants) {
+            if (constant instanceof RecompilableScriptFunctionData) {
+                final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
+                data.initTransients(source, installer);
+                final FunctionInitializer initializer = initializers.get(data.getFunctionNodeId());
+                if (initializer != null) {
+                    initializer.setCode(installedClasses.get(initializer.getClassName()));
+                    data.initializeCode(initializer);
+                }
+            }
         }
-        return clonedMap;
-    }
 
-    /**
-     * Returns the constants array.
-     * @return constants array
-     */
-    public Object[] getConstants() {
-        return constants.clone();
-    }
-
-    /**
-     * Returns the function initializers map.
-     * @return The initializers map.
-     */
-    public Map<Integer, FunctionInitializer> getInitializers() {
-        final Map<Integer, FunctionInitializer> clonedMap = new LinkedHashMap<>();
-        for (final Map.Entry<Integer, FunctionInitializer> entry : initializers.entrySet()) {
-            clonedMap.put(entry.getKey(), new FunctionInitializer(entry.getValue()));
-        }
-        return clonedMap;
+        return installedClasses.get(mainClassName);
     }
 
     @Override
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Thu Apr 30 13:02:10 2015 -0700
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Thu Apr 30 17:21:20 2015 -0700
@@ -26,7 +26,7 @@
 package jdk.nashorn.internal.runtime.regexp;
 
 import java.util.Collections;
-import java.util.Set;
+import java.util.Map;
 import java.util.WeakHashMap;
 import jdk.nashorn.internal.runtime.ParserException;
 import jdk.nashorn.internal.runtime.options.Options;
@@ -45,11 +45,10 @@
     /** 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>()));
+     *  startup
+     */
+    private static final Map<String, RegExp> REGEXP_CACHE =
+            Collections.synchronizedMap(new WeakHashMap<String, RegExp>());
 
     static {
         final String impl = Options.getStringProperty("nashorn.regexp.impl", JONI);
@@ -87,7 +86,13 @@
      * @throws ParserException if invalid source or flags
      */
     public static RegExp create(final String pattern, final String flags) {
-        return instance.compile(pattern,  flags);
+        final String key = pattern + "/" + flags;
+        RegExp regexp = REGEXP_CACHE.get(key);
+        if (regexp == null) {
+            regexp = instance.compile(pattern,  flags);
+            REGEXP_CACHE.put(key, regexp);
+        }
+        return regexp;
     }
 
     /**
@@ -98,11 +103,8 @@
      *
      * @throws ParserException if invalid source or flags
      */
-    // @SuppressWarnings({"unused"})
     public static void validate(final String pattern, final String flags) throws ParserException {
-        if (VALID_CACHE_SET.add(pattern + flags)) {
-            instance.compile(pattern, flags);
-        }
+        create(pattern, flags);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8053905.js	Thu Apr 30 17:21:20 2015 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8053905: Eager code generation fails for earley boyer with split threshold set to 1000
+ *
+ * @test
+ * @runif external.octane
+ * @fork
+ * @option -Dnashorn.compiler.splitter.threshold=1000
+ * @option -scripting
+ * @option --lazy-compilation=false
+ */
+
+var fn  = __DIR__ + 'compile-octane.js';
+arguments.push("earley-boyer"); // run only earley-boyer
+var url = new java.io.File(fn).toURL();
+load(url);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8053905.js.EXPECTED	Thu Apr 30 17:21:20 2015 -0700
@@ -0,0 +1,2 @@
+Compiling 'earley-boyer'...
+Done.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8066407.js	Thu Apr 30 17:21:20 2015 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066407: Function with same body not reparsed after SyntaxError
+ *
+ * @test
+ * @run
+ */
+
+function testFunction(body) {
+    try {
+        Function(body);
+        Assert.fail("Should have thrown");
+    } catch (e) {
+        Assert.assertEquals(e.name, "SyntaxError");
+        count++;
+    }
+
+}
+
+var count = 0;
+
+testFunction("/a/r");
+testFunction("/a/r");
+testFunction("/a/r");
+
+Assert.assertTrue(count === 3);
--- a/test/script/basic/compile-octane-splitter.js	Thu Apr 30 13:02:10 2015 -0700
+++ b/test/script/basic/compile-octane-splitter.js	Thu Apr 30 17:21:20 2015 -0700
@@ -29,11 +29,10 @@
  * forever, so make this test future safe, we specify them explicitly
  *
  * @test
+ * @runif external.octane
  * @fork
+ * @option -scripting
  * @option -Dnashorn.compiler.splitter.threshold=1000
- * @fork
- * @runif external.octane
- * @option -scripting
  * @option -Dnashorn.typeInfo.disabled=true
  * @option --class-cache-size=0
  * @option --persistent-code-cache=false