# HG changeset patch # User lagergren # Date 1363268995 -3600 # Node ID 390d44ba90cf422ebf895d932cded19d0c6b60ea # Parent 60684aeba89cf0fdcd11883da4df8bbf8ce73d30 8009982: Lazy execution bugfix. Added lazy sunspider unit test. Added mandreel to compile-octane test. Fixed warnings Reviewed-by: sundar, jlaskey diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java --- a/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Thu Mar 14 14:49:55 2013 +0100 @@ -176,7 +176,7 @@ // -- Internals only below this point - private void checkConfigPermission() { + private static void checkConfigPermission() { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission("nashorn.setConfig")); diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Mar 14 14:49:55 2013 +0100 @@ -3230,8 +3230,7 @@ } private void newFunctionObject(final FunctionNode functionNode) { - final boolean isLazy = functionNode.isLazy(); - final Class[] cparams = new Class[] { RecompilableScriptFunctionData.class, ScriptObject.class }; + final boolean isLazy = functionNode.isLazy(); new ObjectCreator(this, new ArrayList(), new ArrayList(), false, false) { @Override @@ -3246,7 +3245,7 @@ } else { m.loadNull(); } - m.invoke(constructorNoLookup(className, cparams)); + m.invoke(constructorNoLookup(className, RecompilableScriptFunctionData.class, ScriptObject.class)); } }.makeObject(method); } diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/codegen/Compiler.java --- a/src/jdk/nashorn/internal/codegen/Compiler.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java Thu Mar 14 14:49:55 2013 +0100 @@ -217,8 +217,6 @@ append(safeSourceName(functionNode.getSource())); this.scriptName = sb.toString(); - - LOG.info("Initializing compiler for '" + functionNode.getName() + "' scriptName = " + scriptName + ", root function: '" + functionNode.getName() + "' lazy=" + functionNode.isLazy()); } /** @@ -361,7 +359,10 @@ final Map> installedClasses = new HashMap<>(); final String rootClassName = firstCompileUnitName(); - final Class rootClass = install(rootClassName, bytecode.get(rootClassName)); + final byte[] rootByteCode = bytecode.get(rootClassName); + final Class rootClass = install(rootClassName, rootByteCode); + + int length = rootByteCode.length; installedClasses.put(rootClassName, rootClass); @@ -370,7 +371,10 @@ if (className.equals(rootClassName)) { continue; } - installedClasses.put(className, install(className, entry.getValue())); + final byte[] code = entry.getValue(); + length += code.length; + + installedClasses.put(className, install(className, code)); } for (final CompileUnit unit : compileUnits) { @@ -388,12 +392,32 @@ } }); - LOG.info("Installed root class: " + rootClass + " and " + bytecode.size() + " compile unit classes"); + final StringBuilder sb; + if (LOG.isEnabled()) { + sb = new StringBuilder(); + sb.append("Installed class '"). + append(rootClass.getSimpleName()). + append('\''). + append(" bytes="). + append(length). + append('.'); + if (bytecode.size() > 1) { + sb.append(' ').append(bytecode.size()).append(" compile units."); + } + } else { + sb = null; + } if (Timing.isEnabled()) { final long duration = System.currentTimeMillis() - t0; Timing.accumulateTime("[Code Installation]", duration); - LOG.info("Installation time: " + duration + " ms"); + if (sb != null) { + sb.append(" Install time: ").append(duration).append(" ms"); + } + } + + if (sb != null) { + LOG.info(sb.toString()); } return rootClass; diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/ir/FunctionNode.java --- a/src/jdk/nashorn/internal/ir/FunctionNode.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java Thu Mar 14 14:49:55 2013 +0100 @@ -218,8 +218,9 @@ private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_WITH_OR_EVAL | IS_SPLIT | HAS_LAZY_CHILDREN; /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */ private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL; - /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep with or eval. */ - private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_WITH_OR_EVAL; + /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep with or eval. + * We also pessimistically need a parent scope if we have lazy children that have not yet been compiled */ + private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_WITH_OR_EVAL | HAS_LAZY_CHILDREN; /** What is the return type of this function? */ private Type returnType = Type.UNKNOWN; @@ -724,13 +725,10 @@ * their parent scope, functions that reference themselves, and non-strict functions that need an Arguments object * (since it exposes {@code arguments.callee} property) will need to have a callee parameter. * - * We also conservatively need a callee if we have lazy children, i.e. nested function nodes that have not yet - * been evaluated. _They_ may need the callee and we don't know it - * * @return true if the function's generated Java method needs a {@code callee} parameter. */ public boolean needsCallee() { - return hasLazyChildren() || needsParentScope() || needsSelfSymbol() || (needsArguments() && !isStrictMode()); + return needsParentScope() || needsSelfSymbol() || (needsArguments() && !isStrictMode()); } /** @@ -1076,7 +1074,7 @@ } else { this.flags |= USES_ANCESTOR_SCOPE; final FunctionNode parentFn = findParentFunction(); - if(parentFn != null) { + if (parentFn != null) { parentFn.setUsesScopeSymbol(symbol); } } diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/objects/Global.java --- a/src/jdk/nashorn/internal/objects/Global.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/objects/Global.java Thu Mar 14 14:49:55 2013 +0100 @@ -1528,8 +1528,9 @@ addOwnProperty(ScriptingFunctions.EXIT_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); } - private void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) { + private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) { AccessController.doPrivileged(new PrivilegedAction() { + @Override public Void run() { for (Field f : scriptEnv.getClass().getFields()) { try { diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/parser/Parser.java --- a/src/jdk/nashorn/internal/parser/Parser.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/parser/Parser.java Thu Mar 14 14:49:55 2013 +0100 @@ -126,7 +126,7 @@ /** Namespace for function names where not explicitly given */ private final Namespace namespace; - private static DebugLogger LOG = new DebugLogger("parser"); + private static final DebugLogger LOG = new DebugLogger("parser"); /** * Constructor diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/runtime/Context.java --- a/src/jdk/nashorn/internal/runtime/Context.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/Context.java Thu Mar 14 14:49:55 2013 +0100 @@ -744,6 +744,7 @@ global = (GlobalObject)Context.getGlobalTrusted(); script = global.findCachedClass(source); if (script != null) { + Compiler.LOG.fine("Code cache hit for " + source + " avoiding recompile."); return script; } } diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/runtime/ScriptLoader.java --- a/src/jdk/nashorn/internal/runtime/ScriptLoader.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/ScriptLoader.java Thu Mar 14 14:49:55 2013 +0100 @@ -60,8 +60,7 @@ synchronized Class installClass(final String name, final byte[] data, final CodeSource cs) { if (cs == null) { return defineClass(name, data, 0, data.length, new ProtectionDomain(null, getPermissions(null))); - } else { - return defineClass(name, data, 0, data.length, cs); } + return defineClass(name, data, 0, data.length, cs); } } diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Thu Mar 14 14:49:55 2013 +0100 @@ -412,6 +412,7 @@ public static MethodHandle getConstructor(final Class sourceType, final Class targetType) throws Exception { final StaticClass adapterClass = getAdapterClassFor(new Class[] { targetType }); return AccessController.doPrivileged(new PrivilegedExceptionAction() { + @Override public MethodHandle run() throws Exception { return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new LinkRequestImpl(NashornCallSiteDescriptor.get( "dyn:new", MethodType.methodType(targetType, StaticClass.class, sourceType), 0), false, diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/runtime/regexp/DefaultRegExp.java --- a/src/jdk/nashorn/internal/runtime/regexp/DefaultRegExp.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/regexp/DefaultRegExp.java Thu Mar 14 14:49:55 2013 +0100 @@ -95,14 +95,14 @@ return null; // never matches or similar, e.g. a[] } - RegExpMatcher matcher = this.matcher; + RegExpMatcher currentMatcher = this.matcher; - if (matcher == null || matcher.getInput() != str) { - matcher = new DefaultMatcher(str); - this.matcher = matcher; + if (currentMatcher == null || matcher.getInput() != str) { + currentMatcher = new DefaultMatcher(str); + this.matcher = currentMatcher; } - return matcher; + return currentMatcher; } class DefaultMatcher implements RegExpMatcher { diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java --- a/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java Thu Mar 14 14:49:55 2013 +0100 @@ -97,14 +97,14 @@ return null; } - RegExpMatcher matcher = this.matcher; + RegExpMatcher currentMatcher = this.matcher; - if (matcher == null || input != matcher.getInput()) { - matcher = new JoniMatcher(input); - this.matcher = matcher; + if (currentMatcher == null || input != currentMatcher.getInput()) { + currentMatcher = new JoniMatcher(input); + this.matcher = currentMatcher; } - return matcher; + return currentMatcher; } /** diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/runtime/regexp/RegExp.java --- a/src/jdk/nashorn/internal/runtime/regexp/RegExp.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExp.java Thu Mar 14 14:49:55 2013 +0100 @@ -156,7 +156,7 @@ * * @param key the message key * @param str string argument - * @throws jdk.nashorn.internal.runtime.ParserException + * @throws jdk.nashorn.internal.runtime.ParserException unconditionally */ protected static void throwParserException(final String key, final String str) throws ParserException { throw new ParserException(ECMAErrors.getMessage("parser.error.regex." + key, str)); diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java --- a/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java Thu Mar 14 14:49:55 2013 +0100 @@ -25,7 +25,6 @@ package jdk.nashorn.internal.runtime.regexp; -import jdk.nashorn.internal.parser.Lexer; import jdk.nashorn.internal.runtime.ParserException; import jdk.nashorn.internal.runtime.options.Options; @@ -35,7 +34,6 @@ */ public class RegExpFactory { - private final static RegExpFactory instance; private final static String JDK = "jdk"; @@ -60,7 +58,8 @@ * Creates a Regular expression from the given {@code pattern} and {@code flags} strings. * * @param pattern RegExp pattern string - * @param flags RegExp flags string + * @param flags RegExp flags string + * @return new RegExp * @throws ParserException if flags is invalid or pattern string has syntax error. */ protected RegExp compile(final String pattern, final String flags) throws ParserException { @@ -71,8 +70,8 @@ * Compile a regexp with the given {@code source} and {@code flags}. * * @param pattern RegExp pattern string - * @param flags flag string - * + * @param flags flag string + * @return new RegExp * @throws ParserException if invalid source or flags */ public static RegExp create(final String pattern, final String flags) { diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/runtime/regexp/RegExpResult.java --- a/src/jdk/nashorn/internal/runtime/regexp/RegExpResult.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpResult.java Thu Mar 14 14:49:55 2013 +0100 @@ -80,11 +80,11 @@ /** * Get the group with the given index or the empty string if group index is not valid. - * @param index the group index + * @param groupIndex the group index * @return the group or "" */ - public Object getGroup(int index) { - return index >= 0 && index < groups.length ? groups[index] : ""; + public Object getGroup(final int groupIndex) { + return groupIndex >= 0 && groupIndex < groups.length ? groups[groupIndex] : ""; } /** diff -r 60684aeba89c -r 390d44ba90cf src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java --- a/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java Tue Mar 12 21:17:47 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java Thu Mar 14 14:49:55 2013 +0100 @@ -182,8 +182,6 @@ * @return Committed token */ private boolean commit(final int n) { - final int startIn = position; - switch (n) { case 1: sb.append(ch0); diff -r 60684aeba89c -r 390d44ba90cf test/script/basic/compile-octane.js.EXPECTED --- a/test/script/basic/compile-octane.js.EXPECTED Tue Mar 12 21:17:47 2013 +0530 +++ b/test/script/basic/compile-octane.js.EXPECTED Thu Mar 14 14:49:55 2013 +0100 @@ -16,6 +16,9 @@ Compiling... gbemu.js Compiled OK: gbemu.js +Compiling... mandreel.js +Compiled OK: mandreel.js + Compiling... navier-stokes.js Compiled OK: navier-stokes.js diff -r 60684aeba89c -r 390d44ba90cf test/script/basic/run-octane.js --- a/test/script/basic/run-octane.js Tue Mar 12 21:17:47 2013 +0530 +++ b/test/script/basic/run-octane.js Thu Mar 14 14:49:55 2013 +0100 @@ -31,7 +31,8 @@ "crypto.js", "deltablue.js", "earley-boyer.js", - "gbemu.js", + "gbemu.js", + "mandreel.js", "navier-stokes.js", "pdfjs.js", "raytrace.js", @@ -49,6 +50,12 @@ { name: "gbemu.js" }, ]; + +//TODO mandreel can be compiled as a test, but not run multiple times unless modified to not have global state +var compileOnly = { + "mandreel.js" : true +}; + var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__; // TODO: why is this path hard coded when it's defined in project properties? @@ -63,6 +70,10 @@ return str.indexOf(suffix, str.length - suffix.length) !== -1; } +function should_compile_only(name) { + return (typeof compile_only !== 'undefined') || compileOnly[name] === true; +} + function run_one_benchmark(arg, iters) { var file_name; @@ -77,14 +88,18 @@ } file_name = file[file.length - 1]; - if (typeof compile_only !== 'undefined') { + 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; + } print("Compiling... " + file_name); } load(path + 'base.js'); load(arg); - if (typeof compile_only !== 'undefined') { + if (compile_and_return) { print("Compiled OK: " + file_name); print(""); return; @@ -164,7 +179,7 @@ function run_suite(tests, iters) { for (var idx = 0; idx < tests.length; idx++) { - run_one_benchmark(tests[idx], iters, false); + run_one_benchmark(tests[idx], iters); } } diff -r 60684aeba89c -r 390d44ba90cf test/script/basic/runsunspider-eager.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/runsunspider-eager.js Thu Mar 14 14:49:55 2013 +0100 @@ -0,0 +1,33 @@ +/* + * 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. + */ + +/** + * runsunspider : runs the sunspider tests and checks for compliance + * + * @test + * @option -timezone=PST + * @runif external.sunspider + */ + +load(__DIR__ + "runsunspider.js"); + diff -r 60684aeba89c -r 390d44ba90cf test/script/basic/runsunspider-lazy.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/runsunspider-lazy.js Thu Mar 14 14:49:55 2013 +0100 @@ -0,0 +1,34 @@ +/* + * 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. + */ + +/** + * runsunspider : runs the sunspider tests and checks for compliance + * + * @test + * @option -timezone=PST + * @option --lazy-compilation + * @runif external.sunspider + */ + +load(__DIR__ + "runsunspider.js"); + diff -r 60684aeba89c -r 390d44ba90cf test/script/basic/runsunspider.js --- a/test/script/basic/runsunspider.js Tue Mar 12 21:17:47 2013 +0530 +++ b/test/script/basic/runsunspider.js Thu Mar 14 14:49:55 2013 +0100 @@ -24,39 +24,11 @@ /** * runsunspider : runs the sunspider tests and checks for compliance * - * @test - * @option -timezone=PST - * @runif external.sunspider - */ - -/* - * Copyright (c) 2010-2011, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. + * @subtest */ /** * This is not a test, but a test "framework" for running sunspider tests. - * */ function assertEq(a, b) {