Merge
authorlana
Thu, 09 Oct 2014 12:17:10 -0700
changeset 26983 b5cd0f03efc4
parent 26978 81dc2e398a6c (current diff)
parent 26982 ff5dd57a40f2 (diff)
child 26984 77577c0a22cb
Merge
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/bin/fixwhitespace.sh	Thu Oct 09 12:17:10 2014 -0700
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# Copyright (c) 2010, 2013, 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.
+#
+
+fix() {
+    #convert tabs to spaces
+    find . -name $1 -exec sed -i "" 's/	/    /g' {} \;
+    #remove trailing whitespace
+    find . -name $1 -exec sed -i "" 's/[ 	]*$//' \{} \;
+}
+
+if [ ! -z $1 ]; then 
+    fix $1;
+else
+    fix "*.java"
+    fix "*.js"
+fi
--- a/nashorn/make/build.xml	Thu Oct 09 11:24:22 2014 -0700
+++ b/nashorn/make/build.xml	Thu Oct 09 12:17:10 2014 -0700
@@ -78,7 +78,7 @@
       <istrue value="${jfr}"/>
     </condition>
   </target>
-
+  
   <target name="init" depends="init-conditions, init-cc">
     <!-- extends jvm args -->
     <property name="run.test.jvmargs" value="${run.test.jvmargs.main} ${run.test.cc.jvmargs} ${jfr.options}"/>
@@ -420,6 +420,7 @@
         <propertyref prefix="test-sys-prop-no-security."/>
         <mapper from="test-sys-prop-no-security.*" to="*" type="glob"/>
       </propertyset>
+      <sysproperty key="optimistic.override" value="${optimistic}"/>
       <classpath>
           <pathelement path="${run.test.classpath}"/>
       </classpath>
@@ -431,7 +432,7 @@
     <delete dir="${build.dir}/nashorn_code_cache"/>
     <property name="debug.test.jvmargs" value=""/>
     <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes"
-       verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
+	    verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
       <jvmarg line="${ext.class.path}"/>
       <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
       <jvmarg line="${debug.test.jvmargs}"/>
@@ -442,6 +443,7 @@
         <propertyref prefix="test-sys-prop."/>
         <mapper from="test-sys-prop.*" to="*" type="glob"/>
       </propertyset>
+      <sysproperty key="optimistic.override" value="${optimistic}"/>
       <sysproperty key="test.js.excludes.file" value="${exclude.list}"/>
       <classpath>
           <pathelement path="${run.test.classpath}"/>
@@ -449,7 +451,27 @@
     </testng>
   </target>
 
-  <target name="test" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file, -test-security, -test-nosecurity" if="testng.available"/>
+  <target name="test" depends="test-pessimistic, test-optimistic"/>
+
+  <target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+    <echo message="Running test suite in OPTIMISTIC mode..."/>
+    <antcall target="-test-nosecurity" inheritRefs="true">
+      <param name="optimistic" value="true"/>
+    </antcall>    
+    <antcall target="-test-security" inheritRefs="true">
+      <param name="optimistic" value="true"/>
+    </antcall>
+  </target>
+
+  <target name="test-pessimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+    <echo message="Running test suite in PESSIMISTIC mode..."/>
+    <antcall target="-test-nosecurity" inheritRefs="true">
+      <param name="optimistic" value="false"/>
+    </antcall>    
+    <antcall target="-test-security" inheritRefs="true">
+      <param name="optimistic" value="false"/>
+    </antcall>
+  </target>
 
   <target name="check-jemmy.jfx.testng" unless="jemmy.jfx.testng.available">
     <echo message="WARNING: Jemmy or JavaFX or TestNG not available, will not run tests. Please copy testng.jar, JemmyCore.jar, JemmyFX.jar, JemmyAWTInput.jar under test${file.separator}lib directory. And make sure you have jfxrt.jar in ${java.home}${file.separator}lib${file.separator}ext dir."/>
--- a/nashorn/make/project.properties	Thu Oct 09 11:24:22 2014 -0700
+++ b/nashorn/make/project.properties	Thu Oct 09 12:17:10 2014 -0700
@@ -286,7 +286,8 @@
 # turn on assertions for tests
 run.test.jvmargs.main=${run.test.jvmargs.common} -ea
 
-# extra jvmargs that might be useful for debugging
+# Extra jvmargs that might be useful for debugging
+# and performance improvements/monitoring
 #
 # -XX:+UnlockDiagnosticVMOptions 
 #
@@ -304,9 +305,25 @@
 #
 # print all compiled nmethods with oopmaps and lots of other info
 # -XX:+PrintNMethods
+#
+# activate the generic "UseNewCode" flag to test whatever functionality
+# lies behind it. This is the preferred way to test a, yet flagless,
+# feature in HotSpot - for example, the uncommon trap placement fix
+# was hidden behind this flag before it became the default
+#
+# -XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode 
+#
+# Crank up the type profile level to 222, which has some warmup
+# penalties, but produces much better code for JavaScript, where better
+# and more intrusive type profiling is required to get rid of
+# a large amount of unnecessary guard code, that could not otherwise
+# be eliminated
+#
+# -XX:TypeProfileLevel=222
+#
 
 # Use best known performance options for octane
-run.test.jvmargs.octane.main=${run.test.jvmargs.common} -XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode -XX:TypeProfileLevel=222
+run.test.jvmargs.octane.main=${run.test.jvmargs.common} -XX:TypeProfileLevel=222
 
 # Security manager args - make sure that we run with the nashorn.policy that the build creates
 run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${build.dir}/nashorn.policy
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java	Thu Oct 09 11:24:22 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java	Thu Oct 09 12:17:10 2014 -0700
@@ -458,12 +458,16 @@
 
     @Override
     public DebugLogger initLogger(final Context ctxt) {
+        final boolean optimisticTypes = env._optimistic_types;
+        final boolean lazyCompilation = env._lazy_compilation;
+
         return ctxt.getLogger(this.getClass(), new Consumer<DebugLogger>() {
             @Override
             public void accept(final DebugLogger newLogger) {
-                if (!Compiler.this.getScriptEnvironment()._lazy_compilation) {
+                if (!lazyCompilation) {
                     newLogger.warning("WARNING: Running with lazy compilation switched off. This is not a default setting.");
                 }
+                newLogger.warning("Optimistic types are ", optimisticTypes ? "ENABLED." : "DISABLED.");
             }
         });
     }
@@ -541,9 +545,10 @@
      * @throws CompilationException if error occurs during compilation
      */
     public FunctionNode compile(final FunctionNode functionNode, final CompilationPhases phases) throws CompilationException {
-
-        log.finest("Starting compile job for ", DebugLogger.quote(functionNode.getName()), " phases=", quote(phases.getDesc()));
-        log.indent();
+        if (log.isEnabled()) {
+            log.info(">> Starting compile job for ", DebugLogger.quote(functionNode.getName()), " phases=", quote(phases.getDesc()));
+            log.indent();
+        }
 
         final String name = DebugLogger.quote(functionNode.getName());
 
@@ -560,7 +565,7 @@
         long time = 0L;
 
         for (final CompilationPhase phase : phases) {
-            log.fine(phase, " starting for ", quote(name));
+            log.fine(phase, " starting for ", name);
 
             try {
                 newFunctionNode = phase.apply(this, phases, newFunctionNode);
@@ -588,8 +593,11 @@
         log.unindent();
 
         if (info) {
-            final StringBuilder sb = new StringBuilder();
-            sb.append("Compile job for ").append(newFunctionNode.getSource()).append(':').append(quote(newFunctionNode.getName())).append(" finished");
+            final StringBuilder sb = new StringBuilder("<< Finished compile job for ");
+            sb.append(newFunctionNode.getSource()).
+                append(':').
+                append(quote(newFunctionNode.getName()));
+
             if (time > 0L && timeLogger != null) {
                 assert env.isTimingEnabled();
                 sb.append(" in ").append(time).append(" ms");
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Thu Oct 09 11:24:22 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Thu Oct 09 12:17:10 2014 -0700
@@ -33,7 +33,6 @@
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
-
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -1138,6 +1137,9 @@
 
         StoredScript storedScript = null;
         FunctionNode functionNode = null;
+        // We only use the code store here if optimistic types are disabled. With optimistic types,
+        // code is stored per function in RecompilableScriptFunctionData.
+        // TODO: This should really be triggered by lazy compilation, not optimistic types.
         final boolean useCodeStore = env._persistent_cache && !env._parse_only && !env._optimistic_types;
         final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null;
 
@@ -1224,7 +1226,7 @@
         final String   mainClassName   = storedScript.getMainClassName();
         final byte[]   mainClassBytes  = classBytes.get(mainClassName);
         final Class<?> mainClass       = installer.install(mainClassName, mainClassBytes);
-        final Map<Integer, FunctionInitializer> initialzers = storedScript.getInitializers();
+        final Map<Integer, FunctionInitializer> initializers = storedScript.getInitializers();
 
         installedClasses.put(mainClassName, mainClass);
 
@@ -1244,8 +1246,8 @@
             if (constant instanceof RecompilableScriptFunctionData) {
                 final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
                 data.initTransients(source, installer);
-                if (initialzers != null) {
-                    final FunctionInitializer initializer = initialzers.get(data.getFunctionNodeId());
+                final FunctionInitializer initializer = initializers.get(data.getFunctionNodeId());
+                if (initializer != null) {
                     initializer.setCode(installedClasses.get(initializer.getClassName()));
                     data.initializeCode(initializer);
                 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Options.properties	Thu Oct 09 11:24:22 2014 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Options.properties	Thu Oct 09 12:17:10 2014 -0700
@@ -203,9 +203,9 @@
 
 nashorn.option.optimistic.types = {                                                                      \
     name="--optimistic-types",                                                                           \
-    is_undocumented=true,                                                                                \
-    desc="Use optimistic type assumptions with deoptimizing recompilation.", \
-    default=true                                   \
+    short_name="-ot",                                                                                    \
+    desc="Use optimistic type assumptions with deoptimizing recompilation. This makes the compiler try, for any program symbol whose type cannot be proven at compile time, to type it as narrow and primitive as possible. If the runtime encounters an error because symbol type is too narrow, a wider method will be generated until steady stage is reached. While this produces as optimal Java Bytecode as possible, erroneous type guesses will lead to longer warmup. Optimistic typing is currently enabled by default, but can be disabled for faster startup performance.",                     \
+    default=true                                                                                         \
 }
 
 nashorn.option.loader.per.compile = {              \
--- a/nashorn/test/script/basic/octane-payload.js	Thu Oct 09 11:24:22 2014 -0700
+++ b/nashorn/test/script/basic/octane-payload.js	Thu Oct 09 12:17:10 2014 -0700
@@ -40,7 +40,7 @@
     {name:"gbemu",         files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"},
     {name:"mandreel",      files:["mandreel.js"],                      suite:"MandreelBenchmark"},
     {name:"navier-stokes", files:["navier-stokes.js"],                 suite:"NavierStokes"},
-    {name:"pdfjs",         files:["pdfjs.js"],                         suite:"PdfJS"},
+    {name:"pdfjs",         files:["pdfjs.js"],                         suite:"PdfJS",                cleanUpIteration: function() { canvas_logs = []; }},
     {name:"raytrace",      files:["raytrace.js"],                      suite:"RayTrace"},
     {name:"regexp",        files:["regexp.js"],                        suite:"RegExpSuite"},
     {name:"richards",      files:["richards.js"],                      suite:"Richards"},
--- a/nashorn/test/script/basic/run-octane.js	Thu Oct 09 11:24:22 2014 -0700
+++ b/nashorn/test/script/basic/run-octane.js	Thu Oct 09 12:17:10 2014 -0700
@@ -24,8 +24,8 @@
 /**
  * @subtest
  */
-var payload = __DIR__ + "octane-payload.js";
-load(payload);
+var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
+load(dir + "octane-payload.js");
 
 var runtime = undefined;
 var verbose = false;
@@ -43,27 +43,27 @@
 function load_bench(arg) {
 
     for (var idx = 0; idx < arg.files.length; idx++) {
-    var f = arg.files[idx];
-    var file = f.split('/');
-    var file_name = path + file[file.length - 1];
+        var f = arg.files[idx];
+        var file = f.split('/');
+        var file_name = path + file[file.length - 1];
 
-    var compile_and_return = should_compile_only(file_name);
-    if (compile_and_return) {
-        if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them
-        return true;
+        var compile_and_return = should_compile_only(file_name);
+        if (compile_and_return) {
+            if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them
+                return true;
+            }
         }
-    }
 
-    print_verbose(arg, "loading '" + arg.name + "' [" + f + "]... " + file_name);
-    load(file_name);
+        print_verbose(arg, "loading '" + arg.name + "' [" + f + "]... " + file_name);
+        load(file_name);
     }
 
     if (typeof arg.before !== 'undefined') {
-    arg.before();
+        arg.before();
     }
 
     if (compile_and_return) {
-    print_always(arg, "Compiled OK");
+        print_always(arg, "Compiled OK");
     }
     return !compile_and_return;
 
@@ -73,16 +73,16 @@
 function run_one_benchmark(arg, iters) {
 
     if (!load_bench(arg)) {
-    return;
+        return;
     }
 
     var success = true;
     var current_name;
 
     if (iters == undefined) {
-    iters = numberOfIterations;
+        iters = numberOfIterations;
     } else {
-    numberOfIterations = iters;
+        numberOfIterations = iters;
     }
 
     var benchmarks = eval(arg.suite + ".benchmarks");
@@ -91,64 +91,69 @@
     var mean_score = 0;
 
     try {
-    for (var x = 0; x < benchmarks.length ; x++) {
-        //do warmup run
-        //reset random number generator needed as of octane 9 before each run
-        BenchmarkSuite.ResetRNG();
-        benchmarks[x].Setup();
-    }
-    BenchmarkSuite.ResetRNG();
-    print_verbose(arg, "running '" + arg.name + "' for " + iters + " iterations of no less than " + min_time + " seconds");
-
-    var scores = [];
-
-    var min_time_ms = min_time * 1000;
-    var len = benchmarks.length;
-
-    for (var it = 0; it < iters + 1; it++) {
-        //every iteration must take a minimum of 10 secs
-        var ops = 0;
-        var elapsed = 0;
-        var start = new Date;
-        do {
-        for (var i = 0; i < len; i++) {
-            benchmarks[i].run();
-            //important - no timing here like elapsed = new Date() - start, as in the
-            //original harness. This will make timing very non-deterministic.
-            //NOTHING else must live in this loop
+        for (var x = 0; x < benchmarks.length ; x++) {
+            //do warmup run
+            //reset random number generator needed as of octane 9 before each run
+            BenchmarkSuite.ResetRNG();
+            benchmarks[x].Setup();
         }
-        ops += len;
-        elapsed = new Date - start;
-        } while (elapsed < min_time * 1000);
+        BenchmarkSuite.ResetRNG();
+        print_verbose(arg, "running '" + arg.name + "' for " + iters + " iterations of no less than " + min_time + " seconds");
+
+        var scores = [];
+
+        var min_time_ms = min_time * 1000;
+        var len = benchmarks.length;
 
-        var score = ops / elapsed * 1000 * 60;
-        scores.push(score);
-        var name = it == 0 ? "warmup" : "iteration " + it;
-        print_verbose(arg, name + " finished " + score.toFixed(0) + " ops/minute");
-    }
-
-    for (var x = 0; x < benchmarks.length ; x++) {
-        benchmarks[x].TearDown();
-    }
+        for (var it = 0; it < iters + 1; it++) {
+            //every iteration must take a minimum of 10 secs
+            var ops = 0;
+            var elapsed = 0;
+            var start = new Date;
+            do {
+                for (var i = 0; i < len; i++) {
+                    benchmarks[i].run();
+                    //important - no timing here like elapsed = new Date() - start, as in the
+                    //original harness. This will make timing very non-deterministic.
+                    //NOTHING else must live in this loop
+                }
+                ops += len;
+                elapsed = new Date - start;
+            } while (elapsed < min_time * 1000);
 
-    for (var x = 1; x < iters + 1 ; x++) {
-        mean_score += scores[x];
-        min_score = Math.min(min_score, scores[x]);
-        max_score = Math.max(max_score, scores[x]);
-    }
-    mean_score /= iters;
+            var score = ops / elapsed * 1000 * 60;
+            scores.push(score);
+            var name = it == 0 ? "warmup" : "iteration " + it;
+            print_verbose(arg, name + " finished " + score.toFixed(0) + " ops/minute");
+
+            // optional per-iteration cleanup hook
+            if (typeof arg.cleanUpIteration == "function") {
+                arg.cleanUpIteration();
+            }
+        }
+
+        for (var x = 0; x < benchmarks.length ; x++) {
+            benchmarks[x].TearDown();
+        }
+
+        for (var x = 1; x < iters + 1 ; x++) {
+            mean_score += scores[x];
+            min_score = Math.min(min_score, scores[x]);
+            max_score = Math.max(max_score, scores[x]);
+        }
+        mean_score /= iters;
     } catch (e) {
-    print_always(arg, "*** Aborted and setting score to zero. Reason: " + e);
-    if (is_this_nashorn() && e instanceof java.lang.Throwable) {
-        e.printStackTrace();
-    }
-    mean_score = min_score = max_score = 0;
-    scores = [0];
+        print_always(arg, "*** Aborted and setting score to zero. Reason: " + e);
+        if (is_this_nashorn() && e instanceof java.lang.Throwable) {
+            e.printStackTrace();
+        }
+        mean_score = min_score = max_score = 0;
+        scores = [0];
     }
 
     var res = mean_score.toFixed(0);
     if (verbose) {
-	res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0);
+        res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0);
     }
     print_always(arg, res);
 }
@@ -163,13 +168,13 @@
 
 function print_verbose(arg, x) {
     if (verbose) {
-    print_always(arg, x)
+        print_always(arg, x)
     }
 }
 
 function run_suite(tests, iters) {
     for (var idx = 0; idx < tests.length; idx++) {
-    run_one_benchmark(tests[idx], iters);
+        run_one_benchmark(tests[idx], iters);
     }
 }
 
@@ -184,13 +189,13 @@
 var new_args = [];
 for (i in args) {
     if (args[i].toString().indexOf(' ') != -1) {
-    args[i] = args[i].replace(/\/$/, '');
-    var s = args[i].split(' ');
-    for (j in s) {
-        new_args.push(s[j]);
-    }
+        args[i] = args[i].replace(/\/$/, '');
+        var s = args[i].split(' ');
+        for (j in s) {
+            new_args.push(s[j]);
+        }
     } else {
-    new_args.push(args[i]);
+        new_args.push(args[i]);
     }
 }
 
@@ -205,46 +210,46 @@
 for (var i = 0; i < args.length; i++) {
     arg = args[i];
     if (arg == "--iterations") {
-    iters = +args[++i];
-    if (isNaN(iters)) {
-        throw "'--iterations' must be followed by integer";
-    }
+        iters = +args[++i];
+        if (isNaN(iters)) {
+            throw "'--iterations' must be followed by integer";
+        }
     } else if (arg == "--runtime") {
-    runtime = args[++i];
+        runtime = args[++i];
     } else if (arg == "--verbose") {
-    verbose = true;
+        verbose = true;
     } else if (arg == "--min-time") {
-    min_time = +args[++i];
-    if (isNaN(iters)) {
-        throw "'--min-time' must be followed by integer";
-    }
+        min_time = +args[++i];
+        if (isNaN(iters)) {
+            throw "'--min-time' must be followed by integer";
+        }
     } else if (arg == "") {
-    continue; //skip
+        continue; //skip
     } else {
-    var found = false;
-    for (j in tests) {
-        if (tests[j].name === arg) {
-        tests_found.push(tests[j]);
-        found = true;
-        break;
+        var found = false;
+        for (j in tests) {
+            if (tests[j].name === arg) {
+                tests_found.push(tests[j]);
+                found = true;
+                break;
+            }
         }
-    }
-    if (!found) {
-        var str = "unknown test name: '" + arg + "' -- valid names are: ";
-        for (j in tests) {
-        if (j != 0) {
-            str += ", ";
+        if (!found) {
+            var str = "unknown test name: '" + arg + "' -- valid names are: ";
+            for (j in tests) {
+                if (j != 0) {
+                    str += ", ";
+                }
+                str += "'" + tests[j].name + "'";
+            }
+            throw str;
         }
-        str += "'" + tests[j].name + "'";
-        }
-        throw str;
-    }
     }
 }
 
 if (tests_found.length == 0) {
     for (i in tests) {
-    tests_found.push(tests[i]);
+        tests_found.push(tests[i]);
     }
 }
 
@@ -255,21 +260,21 @@
 
 if (is_this_nashorn()) {
     try {
-    read = readFully;
+        read = readFully;
     } catch (e) {
-    print("ABORTING: Cannot find 'readFully'. You must have scripting enabled to use this test harness. (-scripting)");
-    throw e;
+        print("ABORTING: Cannot find 'readFully'. You must have scripting enabled to use this test harness. (-scripting)");
+        throw e;
     }
 }
 
 // run tests in alphabetical order by name
 tests_found.sort(function(a, b) {
     if (a.name < b.name) {
-    return -1;
+        return -1;
     } else if (a.name > b.name) {
-    return 1;
+        return 1;
     } else {
-    return 0;
+        return 0;
     }
 });
 
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java	Thu Oct 09 11:24:22 2014 -0700
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java	Thu Oct 09 12:17:10 2014 -0700
@@ -25,10 +25,10 @@
 
 package jdk.nashorn.internal.runtime;
 
-
 import jdk.nashorn.api.scripting.ClassFilter;
 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
 import jdk.nashorn.api.scripting.URLReader;
+import jdk.nashorn.internal.test.framework.TestFinder;
 import org.testng.annotations.Test;
 
 import javax.script.ScriptEngine;
@@ -126,9 +126,9 @@
     private void persistentCacheTestImpl() {
         NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
         ScriptEngine engine = factory.getScriptEngine(
-                new String[]{"--persistent-code-cache"},
-                getClass().getClassLoader(),
-                getClassFilter()
+              TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}),
+                  getClass().getClassLoader(),
+                  getClassFilter()
         );
         String testScript = "var a = Java.type('java.lang.String');" + generateCodeForPersistentStore();
         try {
@@ -137,7 +137,7 @@
             fail(exc.getMessage());
         }
         ScriptEngine engineSafe = factory.getScriptEngine(
-                new String[]{"--persistent-code-cache"},
+                TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}),
                 getClass().getClassLoader(),
                 new ClassFilter() {
                     @Override
@@ -151,7 +151,7 @@
             fail("ClassNotFoundException should have been thrown");
         } catch (final Exception exc) {
             if (!(exc.getCause() instanceof ClassNotFoundException)) {
-                fail("ClassNotFoundException expected");
+                fail("ClassNotFoundException expected, got " + exc.getClass());
             }
         }
     }
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java	Thu Oct 09 11:24:22 2014 -0700
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java	Thu Oct 09 12:17:10 2014 -0700
@@ -179,7 +179,7 @@
         for (final String str : forkJVMOptions) {
             if(!str.isEmpty()) {
                 cmd.add(str);
-            }
+        }
         }
         cmd.add(Shell.class.getName());
         // now add the rest of the "in process" runtime arguments
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java	Thu Oct 09 11:24:22 2014 -0700
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java	Thu Oct 09 12:17:10 2014 -0700
@@ -56,6 +56,7 @@
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
@@ -75,7 +76,7 @@
  * Utility class to find/parse script test files and to create 'test' instances.
  * Actual 'test' object type is decided by clients of this class.
  */
-final class TestFinder {
+public final class TestFinder {
     private TestFinder() {}
 
     interface TestFactory<T> {
@@ -215,6 +216,8 @@
         final List<String> scriptArguments = new ArrayList<>();
         boolean inComment = false;
 
+        boolean explicitOptimistic = false;
+
         try (Scanner scanner = new Scanner(testFile)) {
             while (scanner.hasNext()) {
                 // TODO: Scan for /ref=file qualifiers, etc, to determine run
@@ -287,7 +290,11 @@
                     scriptArguments.add(scanner.next());
                     break;
                 case "@option":
-                    engineOptions.add(scanner.next());
+                    final String next = scanner.next();
+                    engineOptions.add(next);
+                    if (next.startsWith("--optimistic-types")) {
+                        explicitOptimistic = true;
+                    }
                     break;
                 case "@fork":
                     fork = true;
@@ -336,12 +343,61 @@
                 testOptions.put(OPTIONS_FORK, "true");
             }
 
+            //if there are explicit optimistic type settings, use those - do not override
+            //the test might only work with optimistic types on or off.
+            if (!explicitOptimistic) {
+                addExplicitOptimisticTypes(engineOptions);
+            }
+
             tests.add(factory.createTest(framework, testFile.toFile(), engineOptions, testOptions, scriptArguments));
         } else if (!isNotTest) {
             orphans.add(name);
         }
     }
 
+    //the reverse of the default setting for optimistic types, if enabled, false, otherwise true
+    //thus, true for 8u40, false for 9
+    private static final boolean OPTIMISTIC_OVERRIDE = false;
+
+    /**
+     * Check if there is an optimistic override, that disables the default
+     * false optimistic types and sets them to true, for testing purposes
+     *
+     * @return true if optimistic type override has been set by test suite
+     */
+    public static boolean hasOptimisticOverride() {
+        return Boolean.valueOf(OPTIMISTIC_OVERRIDE).toString().equals(System.getProperty("optimistic.override"));
+    }
+
+    /**
+     * Add an optimistic-types=true option to an argument list if this
+     * is set to override the default false. Add an optimistic-types=true
+     * options to an argument list if this is set to override the default
+     * true
+     *
+     * @args new argument list array
+     */
+    public static String[] addExplicitOptimisticTypes(String[] args) {
+        if (hasOptimisticOverride()) {
+            final List<String> newList = new ArrayList<>(Arrays.asList(args));
+            newList.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE));
+            return newList.toArray(new String[0]);
+        }
+        return args;
+    }
+
+    /**
+     * Add an optimistic-types=true option to an argument list if this
+     * is set to override the default false
+     *
+     * @args argument list
+     */
+    public static void addExplicitOptimisticTypes(List<String> args) {
+        if (hasOptimisticOverride()) {
+            args.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE));
+        }
+    }
+
     private static boolean strictModeEnabled() {
         return Boolean.getBoolean(TEST_JS_ENABLE_STRICT_MODE);
     }