This commit is contained in:
Lana Steuck 2014-10-09 12:17:10 -07:00
commit 0bc4b4cef4
11 changed files with 283 additions and 136 deletions

View file

@ -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

View file

@ -78,7 +78,7 @@
<istrue value="${jfr}"/> <istrue value="${jfr}"/>
</condition> </condition>
</target> </target>
<target name="init" depends="init-conditions, init-cc"> <target name="init" depends="init-conditions, init-cc">
<!-- extends jvm args --> <!-- extends jvm args -->
<property name="run.test.jvmargs" value="${run.test.jvmargs.main} ${run.test.cc.jvmargs} ${jfr.options}"/> <property name="run.test.jvmargs" value="${run.test.jvmargs.main} ${run.test.cc.jvmargs} ${jfr.options}"/>
@ -420,6 +420,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" {
<propertyref prefix="test-sys-prop-no-security."/> <propertyref prefix="test-sys-prop-no-security."/>
<mapper from="test-sys-prop-no-security.*" to="*" type="glob"/> <mapper from="test-sys-prop-no-security.*" to="*" type="glob"/>
</propertyset> </propertyset>
<sysproperty key="optimistic.override" value="${optimistic}"/>
<classpath> <classpath>
<pathelement path="${run.test.classpath}"/> <pathelement path="${run.test.classpath}"/>
</classpath> </classpath>
@ -431,7 +432,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" {
<delete dir="${build.dir}/nashorn_code_cache"/> <delete dir="${build.dir}/nashorn_code_cache"/>
<property name="debug.test.jvmargs" value=""/> <property name="debug.test.jvmargs" value=""/>
<testng outputdir="${build.test.results.dir}" classfilesetref="test.classes" <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="${ext.class.path}"/>
<jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/> <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
<jvmarg line="${debug.test.jvmargs}"/> <jvmarg line="${debug.test.jvmargs}"/>
@ -442,6 +443,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" {
<propertyref prefix="test-sys-prop."/> <propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/> <mapper from="test-sys-prop.*" to="*" type="glob"/>
</propertyset> </propertyset>
<sysproperty key="optimistic.override" value="${optimistic}"/>
<sysproperty key="test.js.excludes.file" value="${exclude.list}"/> <sysproperty key="test.js.excludes.file" value="${exclude.list}"/>
<classpath> <classpath>
<pathelement path="${run.test.classpath}"/> <pathelement path="${run.test.classpath}"/>
@ -449,7 +451,27 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" {
</testng> </testng>
</target> </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"> <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."/> <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."/>

View file

@ -286,7 +286,8 @@ run.test.jvmargs.common=\
# turn on assertions for tests # turn on assertions for tests
run.test.jvmargs.main=${run.test.jvmargs.common} -ea 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 # -XX:+UnlockDiagnosticVMOptions
# #
@ -304,9 +305,25 @@ run.test.jvmargs.main=${run.test.jvmargs.common} -ea
# #
# print all compiled nmethods with oopmaps and lots of other info # print all compiled nmethods with oopmaps and lots of other info
# -XX:+PrintNMethods # -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 # 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 # 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 run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${build.dir}/nashorn.policy

View file

@ -458,12 +458,16 @@ public final class Compiler implements Loggable {
@Override @Override
public DebugLogger initLogger(final Context ctxt) { 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>() { return ctxt.getLogger(this.getClass(), new Consumer<DebugLogger>() {
@Override @Override
public void accept(final DebugLogger newLogger) { 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("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 @@ public final class Compiler implements Loggable {
* @throws CompilationException if error occurs during compilation * @throws CompilationException if error occurs during compilation
*/ */
public FunctionNode compile(final FunctionNode functionNode, final CompilationPhases phases) throws CompilationException { public FunctionNode compile(final FunctionNode functionNode, final CompilationPhases phases) throws CompilationException {
if (log.isEnabled()) {
log.finest("Starting compile job for ", DebugLogger.quote(functionNode.getName()), " phases=", quote(phases.getDesc())); log.info(">> Starting compile job for ", DebugLogger.quote(functionNode.getName()), " phases=", quote(phases.getDesc()));
log.indent(); log.indent();
}
final String name = DebugLogger.quote(functionNode.getName()); final String name = DebugLogger.quote(functionNode.getName());
@ -560,7 +565,7 @@ public final class Compiler implements Loggable {
long time = 0L; long time = 0L;
for (final CompilationPhase phase : phases) { for (final CompilationPhase phase : phases) {
log.fine(phase, " starting for ", quote(name)); log.fine(phase, " starting for ", name);
try { try {
newFunctionNode = phase.apply(this, phases, newFunctionNode); newFunctionNode = phase.apply(this, phases, newFunctionNode);
@ -588,8 +593,11 @@ public final class Compiler implements Loggable {
log.unindent(); log.unindent();
if (info) { if (info) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder("<< Finished compile job for ");
sb.append("Compile job for ").append(newFunctionNode.getSource()).append(':').append(quote(newFunctionNode.getName())).append(" finished"); sb.append(newFunctionNode.getSource()).
append(':').
append(quote(newFunctionNode.getName()));
if (time > 0L && timeLogger != null) { if (time > 0L && timeLogger != null) {
assert env.isTimingEnabled(); assert env.isTimingEnabled();
sb.append(" in ").append(time).append(" ms"); sb.append(" in ").append(time).append(" ms");

View file

@ -33,7 +33,6 @@ import static jdk.nashorn.internal.runtime.CodeStore.newCodeStore;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.Source.sourceFor; import static jdk.nashorn.internal.runtime.Source.sourceFor;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
@ -1138,6 +1137,9 @@ public final class Context {
StoredScript storedScript = null; StoredScript storedScript = null;
FunctionNode functionNode = 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 boolean useCodeStore = env._persistent_cache && !env._parse_only && !env._optimistic_types;
final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null; final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null;
@ -1224,7 +1226,7 @@ public final class Context {
final String mainClassName = storedScript.getMainClassName(); final String mainClassName = storedScript.getMainClassName();
final byte[] mainClassBytes = classBytes.get(mainClassName); final byte[] mainClassBytes = classBytes.get(mainClassName);
final Class<?> mainClass = installer.install(mainClassName, mainClassBytes); 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); installedClasses.put(mainClassName, mainClass);
@ -1244,8 +1246,8 @@ public final class Context {
if (constant instanceof RecompilableScriptFunctionData) { if (constant instanceof RecompilableScriptFunctionData) {
final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant; final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
data.initTransients(source, installer); data.initTransients(source, installer);
if (initialzers != null) { final FunctionInitializer initializer = initializers.get(data.getFunctionNodeId());
final FunctionInitializer initializer = initialzers.get(data.getFunctionNodeId()); if (initializer != null) {
initializer.setCode(installedClasses.get(initializer.getClassName())); initializer.setCode(installedClasses.get(initializer.getClassName()));
data.initializeCode(initializer); data.initializeCode(initializer);
} }

View file

@ -203,9 +203,9 @@ nashorn.option.lazy.compilation = {
nashorn.option.optimistic.types = { \ nashorn.option.optimistic.types = { \
name="--optimistic-types", \ name="--optimistic-types", \
is_undocumented=true, \ short_name="-ot", \
desc="Use optimistic type assumptions with deoptimizing recompilation.", \ 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 \ default=true \
} }
nashorn.option.loader.per.compile = { \ nashorn.option.loader.per.compile = { \

View file

@ -40,7 +40,7 @@ var tests = [
{name:"gbemu", files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"}, {name:"gbemu", files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"},
{name:"mandreel", files:["mandreel.js"], suite:"MandreelBenchmark"}, {name:"mandreel", files:["mandreel.js"], suite:"MandreelBenchmark"},
{name:"navier-stokes", files:["navier-stokes.js"], suite:"NavierStokes"}, {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:"raytrace", files:["raytrace.js"], suite:"RayTrace"},
{name:"regexp", files:["regexp.js"], suite:"RegExpSuite"}, {name:"regexp", files:["regexp.js"], suite:"RegExpSuite"},
{name:"richards", files:["richards.js"], suite:"Richards"}, {name:"richards", files:["richards.js"], suite:"Richards"},

View file

@ -24,8 +24,8 @@
/** /**
* @subtest * @subtest
*/ */
var payload = __DIR__ + "octane-payload.js"; var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
load(payload); load(dir + "octane-payload.js");
var runtime = undefined; var runtime = undefined;
var verbose = false; var verbose = false;
@ -43,27 +43,27 @@ function should_compile_only(name) {
function load_bench(arg) { function load_bench(arg) {
for (var idx = 0; idx < arg.files.length; idx++) { for (var idx = 0; idx < arg.files.length; idx++) {
var f = arg.files[idx]; var f = arg.files[idx];
var file = f.split('/'); var file = f.split('/');
var file_name = path + file[file.length - 1]; var file_name = path + file[file.length - 1];
var compile_and_return = should_compile_only(file_name); var compile_and_return = should_compile_only(file_name);
if (compile_and_return) { if (compile_and_return) {
if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them
return true; return true;
}
} }
}
print_verbose(arg, "loading '" + arg.name + "' [" + f + "]... " + file_name); print_verbose(arg, "loading '" + arg.name + "' [" + f + "]... " + file_name);
load(file_name); load(file_name);
} }
if (typeof arg.before !== 'undefined') { if (typeof arg.before !== 'undefined') {
arg.before(); arg.before();
} }
if (compile_and_return) { if (compile_and_return) {
print_always(arg, "Compiled OK"); print_always(arg, "Compiled OK");
} }
return !compile_and_return; return !compile_and_return;
@ -73,16 +73,16 @@ function load_bench(arg) {
function run_one_benchmark(arg, iters) { function run_one_benchmark(arg, iters) {
if (!load_bench(arg)) { if (!load_bench(arg)) {
return; return;
} }
var success = true; var success = true;
var current_name; var current_name;
if (iters == undefined) { if (iters == undefined) {
iters = numberOfIterations; iters = numberOfIterations;
} else { } else {
numberOfIterations = iters; numberOfIterations = iters;
} }
var benchmarks = eval(arg.suite + ".benchmarks"); var benchmarks = eval(arg.suite + ".benchmarks");
@ -91,64 +91,69 @@ function run_one_benchmark(arg, iters) {
var mean_score = 0; var mean_score = 0;
try { try {
for (var x = 0; x < benchmarks.length ; x++) { for (var x = 0; x < benchmarks.length ; x++) {
//do warmup run //do warmup run
//reset random number generator needed as of octane 9 before each run //reset random number generator needed as of octane 9 before each run
BenchmarkSuite.ResetRNG(); BenchmarkSuite.ResetRNG();
benchmarks[x].Setup(); 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
} }
ops += len; BenchmarkSuite.ResetRNG();
elapsed = new Date - start; print_verbose(arg, "running '" + arg.name + "' for " + iters + " iterations of no less than " + min_time + " seconds");
} while (elapsed < min_time * 1000);
var score = ops / elapsed * 1000 * 60; var scores = [];
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++) { var min_time_ms = min_time * 1000;
benchmarks[x].TearDown(); var len = benchmarks.length;
}
for (var x = 1; x < iters + 1 ; x++) { for (var it = 0; it < iters + 1; it++) {
mean_score += scores[x]; //every iteration must take a minimum of 10 secs
min_score = Math.min(min_score, scores[x]); var ops = 0;
max_score = Math.max(max_score, scores[x]); var elapsed = 0;
} var start = new Date;
mean_score /= iters; 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);
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) { } catch (e) {
print_always(arg, "*** Aborted and setting score to zero. Reason: " + e); print_always(arg, "*** Aborted and setting score to zero. Reason: " + e);
if (is_this_nashorn() && e instanceof java.lang.Throwable) { if (is_this_nashorn() && e instanceof java.lang.Throwable) {
e.printStackTrace(); e.printStackTrace();
} }
mean_score = min_score = max_score = 0; mean_score = min_score = max_score = 0;
scores = [0]; scores = [0];
} }
var res = mean_score.toFixed(0); var res = mean_score.toFixed(0);
if (verbose) { 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); print_always(arg, res);
} }
@ -163,13 +168,13 @@ function print_always(arg, x) {
function print_verbose(arg, x) { function print_verbose(arg, x) {
if (verbose) { if (verbose) {
print_always(arg, x) print_always(arg, x)
} }
} }
function run_suite(tests, iters) { function run_suite(tests, iters) {
for (var idx = 0; idx < tests.length; idx++) { for (var idx = 0; idx < tests.length; idx++) {
run_one_benchmark(tests[idx], iters); run_one_benchmark(tests[idx], iters);
} }
} }
@ -184,13 +189,13 @@ if (typeof $ARGS !== 'undefined') {
var new_args = []; var new_args = [];
for (i in args) { for (i in args) {
if (args[i].toString().indexOf(' ') != -1) { if (args[i].toString().indexOf(' ') != -1) {
args[i] = args[i].replace(/\/$/, ''); args[i] = args[i].replace(/\/$/, '');
var s = args[i].split(' '); var s = args[i].split(' ');
for (j in s) { for (j in s) {
new_args.push(s[j]); new_args.push(s[j]);
} }
} else { } else {
new_args.push(args[i]); new_args.push(args[i]);
} }
} }
@ -205,46 +210,46 @@ var min_time = 5;
for (var i = 0; i < args.length; i++) { for (var i = 0; i < args.length; i++) {
arg = args[i]; arg = args[i];
if (arg == "--iterations") { if (arg == "--iterations") {
iters = +args[++i]; iters = +args[++i];
if (isNaN(iters)) { if (isNaN(iters)) {
throw "'--iterations' must be followed by integer"; throw "'--iterations' must be followed by integer";
} }
} else if (arg == "--runtime") { } else if (arg == "--runtime") {
runtime = args[++i]; runtime = args[++i];
} else if (arg == "--verbose") { } else if (arg == "--verbose") {
verbose = true; verbose = true;
} else if (arg == "--min-time") { } else if (arg == "--min-time") {
min_time = +args[++i]; min_time = +args[++i];
if (isNaN(iters)) { if (isNaN(iters)) {
throw "'--min-time' must be followed by integer"; throw "'--min-time' must be followed by integer";
} }
} else if (arg == "") { } else if (arg == "") {
continue; //skip continue; //skip
} else { } else {
var found = false; 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) { for (j in tests) {
if (j != 0) { if (tests[j].name === arg) {
str += ", "; tests_found.push(tests[j]);
found = true;
break;
}
} }
str += "'" + tests[j].name + "'"; 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;
} }
throw str;
}
} }
} }
if (tests_found.length == 0) { if (tests_found.length == 0) {
for (i in tests) { for (i in tests) {
tests_found.push(tests[i]); tests_found.push(tests[i]);
} }
} }
@ -255,21 +260,21 @@ function is_this_nashorn() {
if (is_this_nashorn()) { if (is_this_nashorn()) {
try { try {
read = readFully; read = readFully;
} catch (e) { } catch (e) {
print("ABORTING: Cannot find 'readFully'. You must have scripting enabled to use this test harness. (-scripting)"); print("ABORTING: Cannot find 'readFully'. You must have scripting enabled to use this test harness. (-scripting)");
throw e; throw e;
} }
} }
// run tests in alphabetical order by name // run tests in alphabetical order by name
tests_found.sort(function(a, b) { tests_found.sort(function(a, b) {
if (a.name < b.name) { if (a.name < b.name) {
return -1; return -1;
} else if (a.name > b.name) { } else if (a.name > b.name) {
return 1; return 1;
} else { } else {
return 0; return 0;
} }
}); });

View file

@ -25,10 +25,10 @@
package jdk.nashorn.internal.runtime; package jdk.nashorn.internal.runtime;
import jdk.nashorn.api.scripting.ClassFilter; import jdk.nashorn.api.scripting.ClassFilter;
import jdk.nashorn.api.scripting.NashornScriptEngineFactory; import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
import jdk.nashorn.api.scripting.URLReader; import jdk.nashorn.api.scripting.URLReader;
import jdk.nashorn.internal.test.framework.TestFinder;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import javax.script.ScriptEngine; import javax.script.ScriptEngine;
@ -126,9 +126,9 @@ public class ClassFilterTest {
private void persistentCacheTestImpl() { private void persistentCacheTestImpl() {
NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
ScriptEngine engine = factory.getScriptEngine( ScriptEngine engine = factory.getScriptEngine(
new String[]{"--persistent-code-cache"}, TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}),
getClass().getClassLoader(), getClass().getClassLoader(),
getClassFilter() getClassFilter()
); );
String testScript = "var a = Java.type('java.lang.String');" + generateCodeForPersistentStore(); String testScript = "var a = Java.type('java.lang.String');" + generateCodeForPersistentStore();
try { try {
@ -137,7 +137,7 @@ public class ClassFilterTest {
fail(exc.getMessage()); fail(exc.getMessage());
} }
ScriptEngine engineSafe = factory.getScriptEngine( ScriptEngine engineSafe = factory.getScriptEngine(
new String[]{"--persistent-code-cache"}, TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}),
getClass().getClassLoader(), getClass().getClassLoader(),
new ClassFilter() { new ClassFilter() {
@Override @Override
@ -151,7 +151,7 @@ public class ClassFilterTest {
fail("ClassNotFoundException should have been thrown"); fail("ClassNotFoundException should have been thrown");
} catch (final Exception exc) { } catch (final Exception exc) {
if (!(exc.getCause() instanceof ClassNotFoundException)) { if (!(exc.getCause() instanceof ClassNotFoundException)) {
fail("ClassNotFoundException expected"); fail("ClassNotFoundException expected, got " + exc.getClass());
} }
} }
} }

View file

@ -179,7 +179,7 @@ public final class ScriptRunnable extends AbstractScriptRunnable implements ITes
for (final String str : forkJVMOptions) { for (final String str : forkJVMOptions) {
if(!str.isEmpty()) { if(!str.isEmpty()) {
cmd.add(str); cmd.add(str);
} }
} }
cmd.add(Shell.class.getName()); cmd.add(Shell.class.getName());
// now add the rest of the "in process" runtime arguments // now add the rest of the "in process" runtime arguments

View file

@ -56,6 +56,7 @@ import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor; import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
@ -75,7 +76,7 @@ import org.xml.sax.InputSource;
* Utility class to find/parse script test files and to create 'test' instances. * Utility class to find/parse script test files and to create 'test' instances.
* Actual 'test' object type is decided by clients of this class. * Actual 'test' object type is decided by clients of this class.
*/ */
final class TestFinder { public final class TestFinder {
private TestFinder() {} private TestFinder() {}
interface TestFactory<T> { interface TestFactory<T> {
@ -215,6 +216,8 @@ final class TestFinder {
final List<String> scriptArguments = new ArrayList<>(); final List<String> scriptArguments = new ArrayList<>();
boolean inComment = false; boolean inComment = false;
boolean explicitOptimistic = false;
try (Scanner scanner = new Scanner(testFile)) { try (Scanner scanner = new Scanner(testFile)) {
while (scanner.hasNext()) { while (scanner.hasNext()) {
// TODO: Scan for /ref=file qualifiers, etc, to determine run // TODO: Scan for /ref=file qualifiers, etc, to determine run
@ -287,7 +290,11 @@ final class TestFinder {
scriptArguments.add(scanner.next()); scriptArguments.add(scanner.next());
break; break;
case "@option": case "@option":
engineOptions.add(scanner.next()); final String next = scanner.next();
engineOptions.add(next);
if (next.startsWith("--optimistic-types")) {
explicitOptimistic = true;
}
break; break;
case "@fork": case "@fork":
fork = true; fork = true;
@ -336,12 +343,61 @@ final class TestFinder {
testOptions.put(OPTIONS_FORK, "true"); 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)); tests.add(factory.createTest(framework, testFile.toFile(), engineOptions, testOptions, scriptArguments));
} else if (!isNotTest) { } else if (!isNotTest) {
orphans.add(name); 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() { private static boolean strictModeEnabled() {
return Boolean.getBoolean(TEST_JS_ENABLE_STRICT_MODE); return Boolean.getBoolean(TEST_JS_ENABLE_STRICT_MODE);
} }