# HG changeset patch # User lana # Date 1415988228 28800 # Node ID fc37699ddc0ed41d4ab5da821211a6d2648c8883 # Parent 99f9e7a9cf0edf8ea17959839890d3ae90ce59c7# Parent 21bb83c7d7905ec42e4621f6918d8ebcef87197f Merge diff -r 99f9e7a9cf0e -r fc37699ddc0e docs/source/EvalFile.java --- a/docs/source/EvalFile.java Wed Nov 12 13:47:23 2014 -0800 +++ b/docs/source/EvalFile.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,14 +29,16 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import javax.script.*; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +@SuppressWarnings("javadoc") public class EvalFile { - public static void main(String[] args) throws Exception { + public static void main(final String[] args) throws Exception { // create a script engine manager - ScriptEngineManager factory = new ScriptEngineManager(); + final ScriptEngineManager factory = new ScriptEngineManager(); // create JavaScript engine - ScriptEngine engine = factory.getEngineByName("nashorn"); + final ScriptEngine engine = factory.getEngineByName("nashorn"); // evaluate JavaScript code from given file - specified by first argument engine.eval(new java.io.FileReader(args[0])); } diff -r 99f9e7a9cf0e -r fc37699ddc0e docs/source/EvalScript.java --- a/docs/source/EvalScript.java Wed Nov 12 13:47:23 2014 -0800 +++ b/docs/source/EvalScript.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,14 +29,16 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import javax.script.*; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +@SuppressWarnings("javadoc") public class EvalScript { - public static void main(String[] args) throws Exception { + public static void main(final String[] args) throws Exception { // create a script engine manager - ScriptEngineManager factory = new ScriptEngineManager(); + final ScriptEngineManager factory = new ScriptEngineManager(); // create a JavaScript engine - ScriptEngine engine = factory.getEngineByName("nashorn"); + final ScriptEngine engine = factory.getEngineByName("nashorn"); // evaluate JavaScript code from String engine.eval("print('Hello, World')"); } diff -r 99f9e7a9cf0e -r fc37699ddc0e docs/source/InvokeScriptFunction.java --- a/docs/source/InvokeScriptFunction.java Wed Nov 12 13:47:23 2014 -0800 +++ b/docs/source/InvokeScriptFunction.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,22 +29,25 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import javax.script.*; +import javax.script.Invocable; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +@SuppressWarnings("javadoc") public class InvokeScriptFunction { - public static void main(String[] args) throws Exception { - ScriptEngineManager manager = new ScriptEngineManager(); - ScriptEngine engine = manager.getEngineByName("nashorn"); + public static void main(final String[] args) throws Exception { + final ScriptEngineManager manager = new ScriptEngineManager(); + final ScriptEngine engine = manager.getEngineByName("nashorn"); // JavaScript code in a String - String script = "function hello(name) { print('Hello, ' + name); }"; + final String script = "function hello(name) { print('Hello, ' + name); }"; // evaluate script engine.eval(script); // javax.script.Invocable is an optional interface. // Check whether your script engine implements or not! // Note that the JavaScript engine implements Invocable interface. - Invocable inv = (Invocable) engine; + final Invocable inv = (Invocable) engine; // invoke the global function named "hello" inv.invokeFunction("hello", "Scripting!!" ); diff -r 99f9e7a9cf0e -r fc37699ddc0e docs/source/InvokeScriptMethod.java --- a/docs/source/InvokeScriptMethod.java Wed Nov 12 13:47:23 2014 -0800 +++ b/docs/source/InvokeScriptMethod.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,26 +29,29 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import javax.script.*; +import javax.script.Invocable; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +@SuppressWarnings("javadoc") public class InvokeScriptMethod { - public static void main(String[] args) throws Exception { - ScriptEngineManager manager = new ScriptEngineManager(); - ScriptEngine engine = manager.getEngineByName("nashorn"); + public static void main(final String[] args) throws Exception { + final ScriptEngineManager manager = new ScriptEngineManager(); + final ScriptEngine engine = manager.getEngineByName("nashorn"); // JavaScript code in a String. This code defines a script object 'obj' // with one method called 'hello'. - String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }"; + final String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }"; // evaluate script engine.eval(script); // javax.script.Invocable is an optional interface. // Check whether your script engine implements or not! // Note that the JavaScript engine implements Invocable interface. - Invocable inv = (Invocable) engine; + final Invocable inv = (Invocable) engine; // get script object on which we want to call the method - Object obj = engine.get("obj"); + final Object obj = engine.get("obj"); // invoke the method named "hello" on the script object "obj" inv.invokeMethod(obj, "hello", "Script Method !!" ); diff -r 99f9e7a9cf0e -r fc37699ddc0e docs/source/MultiScopes.java --- a/docs/source/MultiScopes.java Wed Nov 12 13:47:23 2014 -0800 +++ b/docs/source/MultiScopes.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,12 +29,17 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import javax.script.*; +import javax.script.Bindings; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.SimpleScriptContext; +@SuppressWarnings("javadoc") public class MultiScopes { - public static void main(String[] args) throws Exception { - ScriptEngineManager manager = new ScriptEngineManager(); - ScriptEngine engine = manager.getEngineByName("nashorn"); + public static void main(final String[] args) throws Exception { + final ScriptEngineManager manager = new ScriptEngineManager(); + final ScriptEngine engine = manager.getEngineByName("nashorn"); engine.put("x", "hello"); // print global variable "x" @@ -42,9 +47,9 @@ // the above line prints "hello" // Now, pass a different script context - ScriptContext newContext = new SimpleScriptContext(); + final ScriptContext newContext = new SimpleScriptContext(); newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE); - Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE); + final Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE); // add new variable "x" to the new engineScope engineScope.put("x", "world"); diff -r 99f9e7a9cf0e -r fc37699ddc0e docs/source/RunnableImpl.java --- a/docs/source/RunnableImpl.java Wed Nov 12 13:47:23 2014 -0800 +++ b/docs/source/RunnableImpl.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,28 +29,31 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import javax.script.*; +import javax.script.Invocable; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +@SuppressWarnings("javadoc") public class RunnableImpl { - public static void main(String[] args) throws Exception { - ScriptEngineManager manager = new ScriptEngineManager(); - ScriptEngine engine = manager.getEngineByName("nashorn"); + public static void main(final String[] args) throws Exception { + final ScriptEngineManager manager = new ScriptEngineManager(); + final ScriptEngine engine = manager.getEngineByName("nashorn"); // JavaScript code in a String - String script = "function run() { print('run called'); }"; + final String script = "function run() { print('run called'); }"; // evaluate script engine.eval(script); - Invocable inv = (Invocable) engine; + final Invocable inv = (Invocable) engine; // get Runnable interface object from engine. This interface methods // are implemented by script functions with the matching name. - Runnable r = inv.getInterface(Runnable.class); + final Runnable r = inv.getInterface(Runnable.class); // start a new thread that runs the script implemented // runnable interface - Thread th = new Thread(r); + final Thread th = new Thread(r); th.start(); th.join(); } diff -r 99f9e7a9cf0e -r fc37699ddc0e docs/source/RunnableImplObject.java --- a/docs/source/RunnableImplObject.java Wed Nov 12 13:47:23 2014 -0800 +++ b/docs/source/RunnableImplObject.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,31 +29,34 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import javax.script.*; +import javax.script.Invocable; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +@SuppressWarnings("javadoc") public class RunnableImplObject { - public static void main(String[] args) throws Exception { - ScriptEngineManager manager = new ScriptEngineManager(); - ScriptEngine engine = manager.getEngineByName("nashorn"); + public static void main(final String[] args) throws Exception { + final ScriptEngineManager manager = new ScriptEngineManager(); + final ScriptEngine engine = manager.getEngineByName("nashorn"); // JavaScript code in a String - String script = "var obj = new Object(); obj.run = function() { print('run method called'); }"; + final String script = "var obj = new Object(); obj.run = function() { print('run method called'); }"; // evaluate script engine.eval(script); // get script object on which we want to implement the interface with - Object obj = engine.get("obj"); + final Object obj = engine.get("obj"); - Invocable inv = (Invocable) engine; + final Invocable inv = (Invocable) engine; // get Runnable interface object from engine. This interface methods // are implemented by script methods of object 'obj' - Runnable r = inv.getInterface(obj, Runnable.class); + final Runnable r = inv.getInterface(obj, Runnable.class); // start a new thread that runs the script implemented // runnable interface - Thread th = new Thread(r); + final Thread th = new Thread(r); th.start(); th.join(); } diff -r 99f9e7a9cf0e -r fc37699ddc0e docs/source/ScriptVars.java --- a/docs/source/ScriptVars.java Wed Nov 12 13:47:23 2014 -0800 +++ b/docs/source/ScriptVars.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,15 +29,17 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import javax.script.*; -import java.io.*; +import java.io.File; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +@SuppressWarnings("javadoc") public class ScriptVars { - public static void main(String[] args) throws Exception { - ScriptEngineManager manager = new ScriptEngineManager(); - ScriptEngine engine = manager.getEngineByName("nashorn"); + public static void main(final String[] args) throws Exception { + final ScriptEngineManager manager = new ScriptEngineManager(); + final ScriptEngine engine = manager.getEngineByName("nashorn"); - File f = new File("test.txt"); + final File f = new File("test.txt"); // expose File object as variable to script engine.put("file", f); diff -r 99f9e7a9cf0e -r fc37699ddc0e make/build.xml --- a/make/build.xml Wed Nov 12 13:47:23 2014 -0800 +++ b/make/build.xml Fri Nov 14 10:03:48 2014 -0800 @@ -155,6 +155,7 @@ + ${line.separator} diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/internal/dynalink/DynamicLinkerFactory.java --- a/src/jdk/internal/dynalink/DynamicLinkerFactory.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/internal/dynalink/DynamicLinkerFactory.java Fri Nov 14 10:03:48 2014 -0800 @@ -97,6 +97,7 @@ import jdk.internal.dynalink.linker.GuardingDynamicLinker; import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; import jdk.internal.dynalink.linker.LinkRequest; +import jdk.internal.dynalink.linker.MethodTypeConversionStrategy; import jdk.internal.dynalink.support.AutoDiscovery; import jdk.internal.dynalink.support.BottomGuardingDynamicLinker; import jdk.internal.dynalink.support.ClassLoaderGetterContextProvider; @@ -105,6 +106,7 @@ import jdk.internal.dynalink.support.DefaultPrelinkFilter; import jdk.internal.dynalink.support.LinkerServicesImpl; import jdk.internal.dynalink.support.TypeConverterFactory; +import jdk.internal.dynalink.support.TypeUtilities; /** * A factory class for creating {@link DynamicLinker}s. The most usual dynamic linker is a linker that is a composition @@ -115,7 +117,6 @@ * @author Attila Szegedi */ public class DynamicLinkerFactory { - /** * Default value for {@link #setUnstableRelinkThreshold(int) unstable relink threshold}. */ @@ -130,6 +131,7 @@ private boolean syncOnRelink = false; private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD; private GuardedInvocationFilter prelinkFilter; + private MethodTypeConversionStrategy autoConversionStrategy; /** * Sets the class loader for automatic discovery of available linkers. If not set explicitly, then the thread @@ -259,6 +261,29 @@ } /** + * Sets an object representing the conversion strategy for automatic type conversions. After + * {@link TypeConverterFactory#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has + * applied all custom conversions to a method handle, it still needs to effect + * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that + * can usually be automatically applied as per + * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}. + * However, sometimes language runtimes will want to customize even those conversions for their own call + * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by + * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom + * automatic conversion strategy, that can deal with null values. Note that when the strategy's + * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} + * is invoked, the custom language conversions will already have been applied to the method handle, so by + * design the difference between the handle's current method type and the desired final type will always + * only be ones that can be subjected to method invocation conversions. The strategy also doesn't need to + * invoke a final {@code MethodHandle.asType()} as the converter factory will do that as the final step. + * @param autoConversionStrategy the strategy for applying method invocation conversions for the linker + * created by this factory. + */ + public void setAutoConversionStrategy(final MethodTypeConversionStrategy autoConversionStrategy) { + this.autoConversionStrategy = autoConversionStrategy; + } + + /** * Creates a new dynamic linker consisting of all the prioritized, autodiscovered, and fallback linkers as well as * the pre-link filter. * @@ -324,8 +349,9 @@ prelinkFilter = new DefaultPrelinkFilter(); } - return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters), composite), - prelinkFilter, runtimeContextArgCount, syncOnRelink, unstableRelinkThreshold); + return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters, + autoConversionStrategy), composite), prelinkFilter, runtimeContextArgCount, syncOnRelink, + unstableRelinkThreshold); } private static ClassLoader getThreadContextClassLoader() { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/internal/dynalink/beans/AbstractJavaLinker.java --- a/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java Fri Nov 14 10:03:48 2014 -0800 @@ -287,10 +287,21 @@ */ private static SingleDynamicMethod createDynamicMethod(final AccessibleObject m) { if(CallerSensitiveDetector.isCallerSensitive(m)) { + // Method has @CallerSensitive annotation return new CallerSensitiveDynamicMethod(m); } + // Method has no @CallerSensitive annotation + final MethodHandle mh; + try { + mh = unreflectSafely(m); + } catch (final IllegalAccessError e) { + // java.lang.invoke can in some case conservatively treat as caller sensitive methods that aren't + // marked with the annotation. In this case, we'll fall back to treating it as caller sensitive. + return new CallerSensitiveDynamicMethod(m); + } + // Proceed with non-caller sensitive final Member member = (Member)m; - return new SimpleDynamicMethod(unreflectSafely(m), member.getDeclaringClass(), member.getName(), m instanceof Constructor); + return new SimpleDynamicMethod(mh, member.getDeclaringClass(), member.getName(), m instanceof Constructor); } /** diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java Fri Nov 14 10:03:48 2014 -0800 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 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. 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2014 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package jdk.internal.dynalink.linker; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; + +/** + * Interface for objects representing a strategy for converting a method handle to a new type. + */ +public interface MethodTypeConversionStrategy { + /** + * Converts a method handle to a new type. + * @param target target method handle + * @param newType new type + * @return target converted to the new type. + */ + public MethodHandle asType(final MethodHandle target, final MethodType newType); +} diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/internal/dynalink/support/TypeConverterFactory.java --- a/src/jdk/internal/dynalink/support/TypeConverterFactory.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/internal/dynalink/support/TypeConverterFactory.java Fri Nov 14 10:03:48 2014 -0800 @@ -97,6 +97,7 @@ import jdk.internal.dynalink.linker.GuardedTypeConversion; import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; import jdk.internal.dynalink.linker.LinkerServices; +import jdk.internal.dynalink.linker.MethodTypeConversionStrategy; /** * A factory for type converters. This class is the main implementation behind the @@ -109,6 +110,7 @@ private final GuardingTypeConverterFactory[] factories; private final ConversionComparator[] comparators; + private final MethodTypeConversionStrategy autoConversionStrategy; private final ClassValue> converterMap = new ClassValue>() { @Override @@ -177,8 +179,24 @@ * Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances. * * @param factories the {@link GuardingTypeConverterFactory} instances to compose. + * @param autoConversionStrategy conversion strategy for automatic type conversions. After + * {@link #asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has applied all custom + * conversions to a method handle, it still needs to effect + * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that + * can usually be automatically applied as per + * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}. + * However, sometimes language runtimes will want to customize even those conversions for their own call + * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by + * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom + * automatic conversion strategy, that can deal with null values. Note that when the strategy's + * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} + * is invoked, the custom language conversions will already have been applied to the method handle, so by + * design the difference between the handle's current method type and the desired final type will always + * only be ones that can be subjected to method invocation conversions. Can be null, in which case no + * custom strategy is employed. */ - public TypeConverterFactory(final Iterable factories) { + public TypeConverterFactory(final Iterable factories, + final MethodTypeConversionStrategy autoConversionStrategy) { final List l = new LinkedList<>(); final List c = new LinkedList<>(); for(final GuardingTypeConverterFactory factory: factories) { @@ -189,20 +207,24 @@ } this.factories = l.toArray(new GuardingTypeConverterFactory[l.size()]); this.comparators = c.toArray(new ConversionComparator[c.size()]); - + this.autoConversionStrategy = autoConversionStrategy; } /** * Similar to {@link MethodHandle#asType(MethodType)} except it also hooks in method handles produced by * {@link GuardingTypeConverterFactory} implementations, providing for language-specific type coercing of - * parameters. It will apply {@link MethodHandle#asType(MethodType)} for all primitive-to-primitive, - * wrapper-to-primitive, primitive-to-wrapper conversions as well as for all upcasts. For all other conversions, - * it'll insert {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters - * provided by {@link GuardingTypeConverterFactory} implementations. + * parameters. For all conversions that are not a JLS method invocation conversion it'll insert + * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters + * provided by {@link GuardingTypeConverterFactory} implementations. For the remaining JLS method invocation + * conversions, it will invoke {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)} first + * if an automatic conversion strategy was specified in the + * {@link #TypeConverterFactory(Iterable, MethodTypeConversionStrategy) constructor}, and finally apply + * {@link MethodHandle#asType(MethodType)} for any remaining conversions. * * @param handle target method handle * @param fromType the types of source arguments - * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)} and + * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)}, + * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}, and * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with * {@link GuardingTypeConverterFactory} produced type converters as filters. */ @@ -246,8 +268,12 @@ } } - // Take care of automatic conversions - return newHandle.asType(fromType); + // Give change to automatic conversion strategy, if one is present. + final MethodHandle autoConvertedHandle = + autoConversionStrategy != null ? autoConversionStrategy.asType(newHandle, fromType) : newHandle; + + // Do a final asType for any conversions that remain. + return autoConvertedHandle.asType(fromType); } private static MethodHandle applyConverters(final MethodHandle handle, final int pos, final List converters) { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/internal/dynalink/support/TypeUtilities.java --- a/src/jdk/internal/dynalink/support/TypeUtilities.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/internal/dynalink/support/TypeUtilities.java Fri Nov 14 10:03:48 2014 -0800 @@ -520,4 +520,13 @@ public static Class getWrapperType(final Class primitiveType) { return WRAPPER_TYPES.get(primitiveType); } + + /** + * Returns true if the passed type is a wrapper for a primitive type. + * @param type the examined type + * @return true if the passed type is a wrapper for a primitive type. + */ + public static boolean isWrapperType(final Class type) { + return PRIMITIVE_TYPES.containsKey(type); + } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/AssertsEnabled.java --- a/src/jdk/nashorn/internal/AssertsEnabled.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/AssertsEnabled.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,8 +27,8 @@ /** * Class that exposes the current state of asserts. - * */ +@SuppressWarnings("all") public final class AssertsEnabled { private static boolean assertsEnabled = false; static { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/codegen/ApplySpecialization.java --- a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,6 +29,7 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.EXPLODED_ARGUMENT_PREFIX; import java.lang.invoke.MethodType; +import java.net.URL; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; @@ -93,6 +94,8 @@ private final Deque> explodedArguments = new ArrayDeque<>(); + private final Deque callSiteTypes = new ArrayDeque<>(); + private static final String ARGUMENTS = ARGUMENTS_VAR.symbolName(); /** @@ -118,86 +121,113 @@ return context.getLogger(this.getClass()); } + @SuppressWarnings("serial") + private static class TransformFailedException extends RuntimeException { + TransformFailedException(final FunctionNode fn, final String message) { + super(massageURL(fn.getSource().getURL()) + '.' + fn.getName() + " => " + message, null, false, false); + } + } + + @SuppressWarnings("serial") + private static class AppliesFoundException extends RuntimeException { + AppliesFoundException() { + super("applies_found", null, false, false); + } + } + + private static final AppliesFoundException HAS_APPLIES = new AppliesFoundException(); + + private boolean hasApplies(final FunctionNode functionNode) { + try { + functionNode.accept(new NodeVisitor(new LexicalContext()) { + @Override + public boolean enterFunctionNode(final FunctionNode fn) { + return fn == functionNode; + } + + @Override + public boolean enterCallNode(final CallNode callNode) { + if (isApply(callNode)) { + throw HAS_APPLIES; + } + return true; + } + }); + } catch (final AppliesFoundException e) { + return true; + } + + log.fine("There are no applies in ", DebugLogger.quote(functionNode.getName()), " - nothing to do."); + return false; // no applies + } + /** * Arguments may only be used as args to the apply. Everything else is disqualified * We cannot control arguments if they escape from the method and go into an unknown * scope, thus we are conservative and treat any access to arguments outside the * apply call as a case of "we cannot apply the optimization". - * - * @return true if arguments escape */ - private boolean argumentsEscape(final FunctionNode functionNode) { - - @SuppressWarnings("serial") - final UnsupportedOperationException uoe = new UnsupportedOperationException() { - @Override - public synchronized Throwable fillInStackTrace() { - return null; - } - }; + private static void checkValidTransform(final FunctionNode functionNode) { final Set argumentsFound = new HashSet<>(); final Deque> stack = new ArrayDeque<>(); + //ensure that arguments is only passed as arg to apply - try { - functionNode.accept(new NodeVisitor(new LexicalContext()) { - private boolean isCurrentArg(final Expression expr) { - return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call - } + functionNode.accept(new NodeVisitor(new LexicalContext()) { + + private boolean isCurrentArg(final Expression expr) { + return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call + } - private boolean isArguments(final Expression expr) { - if (expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName())) { - argumentsFound.add(expr); + private boolean isArguments(final Expression expr) { + if (expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName())) { + argumentsFound.add(expr); + return true; + } + return false; + } + + private boolean isParam(final String name) { + for (final IdentNode param : functionNode.getParameters()) { + if (param.getName().equals(name)) { return true; } - return false; } + return false; + } - private boolean isParam(final String name) { - for (final IdentNode param : functionNode.getParameters()) { - if (param.getName().equals(name)) { - return true; - } - } - return false; + @Override + public Node leaveIdentNode(final IdentNode identNode) { + if (isParam(identNode.getName())) { + throw new TransformFailedException(lc.getCurrentFunction(), "parameter: " + identNode.getName()); } - - @Override - public Node leaveIdentNode(final IdentNode identNode) { - if (isParam(identNode.getName()) || isArguments(identNode) && !isCurrentArg(identNode)) { - throw uoe; //avoid filling in stack trace - } - return identNode; + // it's OK if 'argument' occurs as the current argument of an apply + if (isArguments(identNode) && !isCurrentArg(identNode)) { + throw new TransformFailedException(lc.getCurrentFunction(), "is 'arguments': " + identNode.getName()); } + return identNode; + } - @Override - public boolean enterCallNode(final CallNode callNode) { - final Set callArgs = new HashSet<>(); - if (isApply(callNode)) { - final List argList = callNode.getArgs(); - if (argList.size() != 2 || !isArguments(argList.get(argList.size() - 1))) { - throw new UnsupportedOperationException(); - } - callArgs.addAll(callNode.getArgs()); + @Override + public boolean enterCallNode(final CallNode callNode) { + final Set callArgs = new HashSet<>(); + if (isApply(callNode)) { + final List argList = callNode.getArgs(); + if (argList.size() != 2 || !isArguments(argList.get(argList.size() - 1))) { + throw new TransformFailedException(lc.getCurrentFunction(), "argument pattern not matched: " + argList); } - stack.push(callArgs); - return true; + callArgs.addAll(callNode.getArgs()); } + stack.push(callArgs); + return true; + } - @Override - public Node leaveCallNode(final CallNode callNode) { - stack.pop(); - return callNode; - } - }); - } catch (final UnsupportedOperationException e) { - if (!argumentsFound.isEmpty()) { - log.fine("'arguments' is used but escapes, or is reassigned in '" + functionNode.getName() + "'. Aborting"); + @Override + public Node leaveCallNode(final CallNode callNode) { + stack.pop(); + return callNode; } - return true; //bad - } - - return false; + }); } @Override @@ -224,12 +254,14 @@ final CallNode newCallNode = callNode.setArgs(newArgs).setIsApplyToCall(); - log.fine("Transformed ", - callNode, - " from apply to call => ", - newCallNode, - " in ", - DebugLogger.quote(lc.getCurrentFunction().getName())); + if (log.isEnabled()) { + log.fine("Transformed ", + callNode, + " from apply to call => ", + newCallNode, + " in ", + DebugLogger.quote(lc.getCurrentFunction().getName())); + } return newCallNode; } @@ -237,12 +269,12 @@ return callNode; } - private boolean pushExplodedArgs(final FunctionNode functionNode) { + private void pushExplodedArgs(final FunctionNode functionNode) { int start = 0; final MethodType actualCallSiteType = compiler.getCallSiteType(functionNode); if (actualCallSiteType == null) { - return false; + throw new TransformFailedException(lc.getCurrentFunction(), "No callsite type"); } assert actualCallSiteType.parameterType(actualCallSiteType.parameterCount() - 1) != Object[].class : "error vararg callsite passed to apply2call " + functionNode.getName() + " " + actualCallSiteType; @@ -264,8 +296,8 @@ } } + callSiteTypes.push(actualCallSiteType); explodedArguments.push(newParams); - return true; } @Override @@ -288,11 +320,30 @@ return false; } - if (argumentsEscape(functionNode)) { + if (!hasApplies(functionNode)) { return false; } - return pushExplodedArgs(functionNode); + if (log.isEnabled()) { + log.info("Trying to specialize apply to call in '", + functionNode.getName(), + "' params=", + functionNode.getParameters(), + " id=", + functionNode.getId(), + " source=", + massageURL(functionNode.getSource().getURL())); + } + + try { + checkValidTransform(functionNode); + pushExplodedArgs(functionNode); + } catch (final TransformFailedException e) { + log.info("Failure: ", e.getMessage()); + return false; + } + + return true; } /** @@ -300,8 +351,8 @@ * @return true if successful, false otherwise */ @Override - public Node leaveFunctionNode(final FunctionNode functionNode0) { - FunctionNode newFunctionNode = functionNode0; + public Node leaveFunctionNode(final FunctionNode functionNode) { + FunctionNode newFunctionNode = functionNode; final String functionName = newFunctionNode.getName(); if (changed.contains(newFunctionNode.getId())) { @@ -310,17 +361,18 @@ setParameters(lc, explodedArguments.peek()); if (log.isEnabled()) { - log.info("Successfully specialized apply to call in '", + log.info("Success: ", + massageURL(newFunctionNode.getSource().getURL()), + '.', functionName, - " params=", - explodedArguments.peek(), "' id=", newFunctionNode.getId(), - " source=", - newFunctionNode.getSource().getURL()); + " params=", + callSiteTypes.peek()); } } + callSiteTypes.pop(); explodedArguments.pop(); return newFunctionNode.setState(lc, CompilationState.BUILTINS_TRANSFORMED); @@ -331,4 +383,15 @@ return f instanceof AccessNode && "apply".equals(((AccessNode)f).getProperty()); } + private static String massageURL(final URL url) { + if (url == null) { + return ""; + } + final String str = url.toString(); + final int slash = str.lastIndexOf('/'); + if (slash == -1) { + return str; + } + return str.substring(slash + 1); + } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Nov 14 10:03:48 2014 -0800 @@ -615,7 +615,6 @@ static final TypeBounds UNBOUNDED = new TypeBounds(Type.UNKNOWN, Type.OBJECT); static final TypeBounds INT = exact(Type.INT); - static final TypeBounds NUMBER = exact(Type.NUMBER); static final TypeBounds OBJECT = exact(Type.OBJECT); static final TypeBounds BOOLEAN = exact(Type.BOOLEAN); @@ -3569,7 +3568,8 @@ operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT); } else { // Non-optimistic, non-FP +. Allow it to overflow. - operandBounds = new TypeBounds(binaryNode.getWidestOperandType(), Type.OBJECT); + operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest), + Type.OBJECT); forceConversionSeparation = binaryNode.getWidestOperationType().narrowerThan(resultBounds.widest); } loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false, forceConversionSeparation); @@ -3856,12 +3856,8 @@ operandBounds = numericBounds; } else { final boolean isOptimistic = isValid(getProgramPoint()); - if(isOptimistic) { + if(isOptimistic || node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) { operandBounds = new TypeBounds(node.getType(), Type.NUMBER); - } else if(node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) { - // Non-optimistic division must always take double arguments as its result must also be - // double. - operandBounds = TypeBounds.NUMBER; } else { // Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow. operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(), @@ -3897,7 +3893,7 @@ private static boolean isRhsZero(final BinaryNode binaryNode) { final Expression rhs = binaryNode.rhs(); - return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode)rhs).getValue()); + return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode)rhs).getValue()); } private void loadBIT_XOR(final BinaryNode binaryNode) { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java --- a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java Fri Nov 14 10:03:48 2014 -0800 @@ -31,7 +31,6 @@ import java.util.Deque; import java.util.HashMap; import java.util.Map; - import jdk.nashorn.internal.IntDeque; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.Block; @@ -250,7 +249,7 @@ static Type getTypeForSlotDescriptor(final char typeDesc) { // Recognizing both lowercase and uppercase as we're using both to signify symbol boundaries; see // MethodEmitter.markSymbolBoundariesInLvarTypesDescriptor(). - switch(typeDesc) { + switch (typeDesc) { case 'I': case 'i': return Type.INT; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/codegen/Compiler.java --- a/src/jdk/nashorn/internal/codegen/Compiler.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java Fri Nov 14 10:03:48 2014 -0800 @@ -389,6 +389,7 @@ * @param continuationEntryPoints continuation entry points for restof method * @param runtimeScope runtime scope for recompilation type lookup in {@code TypeEvaluator} */ + @SuppressWarnings("unused") public Compiler( final Context context, final ScriptEnvironment env, diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java --- a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Fri Nov 14 10:03:48 2014 -0800 @@ -28,7 +28,6 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN; import static jdk.nashorn.internal.ir.Expression.isAlwaysFalse; import static jdk.nashorn.internal.ir.Expression.isAlwaysTrue; - import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; @@ -236,12 +235,12 @@ private byte conversions; void recordConversion(final LvarType from, final LvarType to) { - switch(from) { + switch (from) { case UNDEFINED: return; case INT: case BOOLEAN: - switch(to) { + switch (to) { case LONG: recordConversion(I2L); return; @@ -256,7 +255,7 @@ return; } case LONG: - switch(to) { + switch (to) { case DOUBLE: recordConversion(L2D); return; @@ -1425,6 +1424,7 @@ * @param symbol the symbol representing the variable * @param type the type */ + @SuppressWarnings("unused") private void setType(final Symbol symbol, final LvarType type) { if(getLocalVariableTypeOrNull(symbol) == type) { return; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java --- a/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Fri Nov 14 10:03:48 2014 -0800 @@ -33,6 +33,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringWriter; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -221,11 +223,37 @@ private static void reportError(final String msg, final File file, final Exception e) { final long now = System.currentTimeMillis(); if(now - lastReportedError > ERROR_REPORT_THRESHOLD) { - getLogger().warning(String.format("Failed to %s %s", msg, file), e); + reportError(String.format("Failed to %s %s", msg, file), e); lastReportedError = now; } } + /** + * Logs an error message with warning severity (reasoning being that we're reporting an error that'll disable the + * type info cache, but it's only logged as a warning because that doesn't prevent Nashorn from running, it just + * disables a performance-enhancing cache). + * @param msg the message to log + * @param e the exception that represents the error. + */ + private static void reportError(final String msg, final Exception e) { + getLogger().warning(msg, "\n", exceptionToString(e)); + } + + /** + * A helper that prints an exception stack trace into a string. We have to do this as if we just pass the exception + * to {@link DebugLogger#warning(Object...)}, it will only log the exception message and not the stack, making + * problems harder to diagnose. + * @param e the exception + * @return the string representation of {@link Exception#printStackTrace()} output. + */ + private static String exceptionToString(final Exception e) { + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw, false); + e.printStackTrace(pw); + pw.flush(); + return sw.toString(); + } + private static File createBaseCacheDir() { if(MAX_FILES == 0 || Options.getBooleanProperty("nashorn.typeInfo.disabled")) { return null; @@ -233,7 +261,7 @@ try { return createBaseCacheDirPrivileged(); } catch(final Exception e) { - getLogger().warning("Failed to create cache dir", e); + reportError("Failed to create cache dir", e); return null; } } @@ -267,7 +295,7 @@ try { return createCacheDirPrivileged(baseDir); } catch(final Exception e) { - getLogger().warning("Failed to create cache dir", e); + reportError("Failed to create cache dir", e); return null; } } @@ -280,7 +308,7 @@ try { versionDirName = getVersionDirName(); } catch(final Exception e) { - getLogger().warning("Failed to calculate version dir name", e); + reportError("Failed to calculate version dir name", e); return null; } final File versionDir = new File(baseDir, versionDirName); @@ -323,10 +351,17 @@ * per-code-version directory. Normally, this will create the SHA-1 digest of the nashorn.jar. In case the classpath * for nashorn is local directory (e.g. during development), this will create the string "dev-" followed by the * timestamp of the most recent .class file. - * @return + * + * @return digest of currently running nashorn + * @throws Exception if digest could not be created */ - private static String getVersionDirName() throws Exception { - final URL url = OptimisticTypesPersistence.class.getResource(""); + public static String getVersionDirName() throws Exception { + // NOTE: getResource("") won't work if the JAR file doesn't have directory entries (and JAR files in JDK distro + // don't, or at least it's a bad idea counting on it). Alternatively, we could've tried + // getResource("OptimisticTypesPersistence.class") but behavior of getResource with regard to its willingness + // to hand out URLs to .class files is also unspecified. Therefore, the most robust way to obtain an URL to our + // package is to have a small non-class anchor file and start out from its URL. + final URL url = OptimisticTypesPersistence.class.getResource("anchor.properties"); final String protocol = url.getProtocol(); if (protocol.equals("jar")) { // Normal deployment: nashorn.jar diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/codegen/anchor.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/codegen/anchor.properties Fri Nov 14 10:03:48 2014 -0800 @@ -0,0 +1,27 @@ +# +# Copyright (c) 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. 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. +# + + +# This file exists only so OptimisticTypesPersistence.getVersionDirName() can take its URL. diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/codegen/types/IntType.java --- a/src/jdk/nashorn/internal/codegen/types/IntType.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/codegen/types/IntType.java Fri Nov 14 10:03:48 2014 -0800 @@ -55,6 +55,7 @@ import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.nashorn.internal.codegen.CompilerConstants; +import jdk.nashorn.internal.runtime.JSType; /** * Type class: INT @@ -230,19 +231,21 @@ @Override public Type div(final MethodVisitor method, final int programPoint) { - // Never perform non-optimistic integer division in JavaScript. - assert programPoint != INVALID_PROGRAM_POINT; - - method.visitInvokeDynamicInsn("idiv", "(II)I", MATHBOOTSTRAP, programPoint); + if (programPoint == INVALID_PROGRAM_POINT) { + JSType.DIV_ZERO.invoke(method); + } else { + method.visitInvokeDynamicInsn("idiv", "(II)I", MATHBOOTSTRAP, programPoint); + } return INT; } @Override public Type rem(final MethodVisitor method, final int programPoint) { - // Never perform non-optimistic integer remainder in JavaScript. - assert programPoint != INVALID_PROGRAM_POINT; - - method.visitInvokeDynamicInsn("irem", "(II)I", MATHBOOTSTRAP, programPoint); + if (programPoint == INVALID_PROGRAM_POINT) { + JSType.REM_ZERO.invoke(method); + } else { + method.visitInvokeDynamicInsn("irem", "(II)I", MATHBOOTSTRAP, programPoint); + } return INT; } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/codegen/types/LongType.java --- a/src/jdk/nashorn/internal/codegen/types/LongType.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/codegen/types/LongType.java Fri Nov 14 10:03:48 2014 -0800 @@ -170,19 +170,21 @@ @Override public Type div(final MethodVisitor method, final int programPoint) { - // Never perform non-optimistic integer division in JavaScript. - assert programPoint != INVALID_PROGRAM_POINT; - - method.visitInvokeDynamicInsn("ldiv", "(JJ)J", MATHBOOTSTRAP, programPoint); + if (programPoint == INVALID_PROGRAM_POINT) { + JSType.DIV_ZERO_LONG.invoke(method); + } else { + method.visitInvokeDynamicInsn("ldiv", "(JJ)J", MATHBOOTSTRAP, programPoint); + } return LONG; } @Override public Type rem(final MethodVisitor method, final int programPoint) { - // Never perform non-optimistic integer remainder in JavaScript. - assert programPoint != INVALID_PROGRAM_POINT; - - method.visitInvokeDynamicInsn("lrem", "(JJ)J", MATHBOOTSTRAP, programPoint); + if (programPoint == INVALID_PROGRAM_POINT) { + JSType.REM_ZERO_LONG.invoke(method); + } else { + method.visitInvokeDynamicInsn("lrem", "(JJ)J", MATHBOOTSTRAP, programPoint); + } return LONG; } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/codegen/types/Type.java --- a/src/jdk/nashorn/internal/codegen/types/Type.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/codegen/types/Type.java Fri Nov 14 10:03:48 2014 -0800 @@ -356,7 +356,7 @@ final int pp = input.readInt(); final int typeChar = input.readByte(); final Type type; - switch(typeChar) { + switch (typeChar) { case 'L': type = Type.OBJECT; break; case 'D': type = Type.NUMBER; break; case 'J': type = Type.LONG; break; @@ -376,13 +376,13 @@ } private static jdk.internal.org.objectweb.asm.Type lookupInternalType(final Class type) { - final Map, jdk.internal.org.objectweb.asm.Type> cache = INTERNAL_TYPE_CACHE; - jdk.internal.org.objectweb.asm.Type itype = cache.get(type); + final Map, jdk.internal.org.objectweb.asm.Type> c = INTERNAL_TYPE_CACHE; + jdk.internal.org.objectweb.asm.Type itype = c.get(type); if (itype != null) { return itype; } itype = jdk.internal.org.objectweb.asm.Type.getType(type); - cache.put(type, itype); + c.put(type, itype); return itype; } @@ -1155,6 +1155,10 @@ return type; } + /** + * Read resolve + * @return resolved type + */ protected final Object readResolve() { return Type.typeFor(clazz); } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/ir/BinaryNode.java --- a/src/jdk/nashorn/internal/ir/BinaryNode.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/ir/BinaryNode.java Fri Nov 14 10:03:48 2014 -0800 @@ -264,6 +264,10 @@ case COMMARIGHT: { return rhs.getType(localVariableTypes); } + case AND: + case OR:{ + return Type.widestReturnType(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes)); + } default: if (isComparison()) { return Type.BOOLEAN; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/objects/ArrayBufferView.java --- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java Fri Nov 14 10:03:48 2014 -0800 @@ -28,7 +28,6 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; - import java.nio.ByteBuffer; import java.nio.ByteOrder; import jdk.internal.dynalink.CallSiteDescriptor; @@ -44,6 +43,9 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.arrays.TypedArrayData; +/** + * ArrayBufferView, es6 class or TypedArray implementation + */ @ScriptClass("ArrayBufferView") public abstract class ArrayBufferView extends ScriptObject { private final NativeArrayBuffer buffer; @@ -71,6 +73,13 @@ setArray(data); } + /** + * Constructor + * + * @param buffer underlying NativeArrayBuffer + * @param byteOffset byte offset for buffer + * @param elementLength element length in bytes + */ protected ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) { this(buffer, byteOffset, elementLength, Global.instance()); } @@ -89,22 +98,42 @@ return factory().bytesPerElement; } + /** + * Buffer getter as per spec + * @param self ArrayBufferView instance + * @return buffer + */ @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE) public static Object buffer(final Object self) { return ((ArrayBufferView)self).buffer; } + /** + * Buffer offset getter as per spec + * @param self ArrayBufferView instance + * @return buffer offset + */ @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE) public static int byteOffset(final Object self) { return ((ArrayBufferView)self).byteOffset; } + /** + * Byte length getter as per spec + * @param self ArrayBufferView instance + * @return array buffer view length in bytes + */ @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE) public static int byteLength(final Object self) { final ArrayBufferView view = (ArrayBufferView)self; return ((TypedArrayData)view.getArray()).getElementLength() * view.bytesPerElement(); } + /** + * Length getter as per spec + * @param self ArrayBufferView instance + * @return length in elements + */ @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE) public static int length(final Object self) { return ((ArrayBufferView)self).elementLength(); @@ -119,15 +148,29 @@ return ((TypedArrayData)getArray()).getElementLength(); } + /** + * Factory class for byte ArrayBufferViews + */ protected static abstract class Factory { final int bytesPerElement; final int maxElementLength; + /** + * Constructor + * + * @param bytesPerElement number of bytes per element for this buffer + */ public Factory(final int bytesPerElement) { this.bytesPerElement = bytesPerElement; this.maxElementLength = Integer.MAX_VALUE / bytesPerElement; } + /** + * Factory method + * + * @param elementLength number of elements + * @return new ArrayBufferView + */ public final ArrayBufferView construct(final int elementLength) { if (elementLength > maxElementLength) { throw rangeError("inappropriate.array.buffer.length", JSType.toString(elementLength)); @@ -135,15 +178,47 @@ return construct(new NativeArrayBuffer(elementLength * bytesPerElement), 0, elementLength); } - public abstract ArrayBufferView construct(NativeArrayBuffer buffer, int byteOffset, int elementLength); + /** + * Factory method + * + * @param buffer underlying buffer + * @param byteOffset byte offset + * @param elementLength number of elements + * + * @return new ArrayBufferView + */ + public abstract ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength); - public abstract TypedArrayData createArrayData(ByteBuffer nb, int start, int end); + /** + * Factory method for array data + * + * @param nb underlying nativebuffer + * @param start start element + * @param end end element + * + * @return new array data + */ + public abstract TypedArrayData createArrayData(final ByteBuffer nb, final int start, final int end); + /** + * Get the class name for this type of buffer + * + * @return class name + */ public abstract String getClassName(); } + /** + * Get the factor for this kind of buffer + * @return Factory + */ protected abstract Factory factory(); + /** + * Get the prototype for this ArrayBufferView + * @param global global instance + * @return prototype + */ protected abstract ScriptObject getPrototype(final Global global); @Override @@ -151,10 +226,23 @@ return factory().getClassName(); } + /** + * Check if this array contains floats + * @return true if float array (or double) + */ protected boolean isFloatArray() { return false; } + /** + * Inheritable constructor implementation + * + * @param newObj is this a new constructor + * @param args arguments + * @param factory factory + * + * @return new ArrayBufferView + */ protected static ArrayBufferView constructorImpl(final boolean newObj, final Object[] args, final Factory factory) { final Object arg0 = args.length != 0 ? args[0] : 0; final ArrayBufferView dest; @@ -200,6 +288,15 @@ return dest; } + /** + * Inheritable implementation of set, if no efficient implementation is available + * + * @param self ArrayBufferView instance + * @param array array + * @param offset0 array offset + * + * @return result of setter + */ protected static Object setImpl(final Object self, final Object array, final Object offset0) { final ArrayBufferView dest = (ArrayBufferView)self; final int length; @@ -244,6 +341,15 @@ return (int)(length & Integer.MAX_VALUE); } + /** + * Implementation of subarray if no efficient override exists + * + * @param self ArrayBufferView instance + * @param begin0 begin index + * @param end0 end index + * + * @return sub array + */ protected static ScriptObject subarrayImpl(final Object self, final Object begin0, final Object end0) { final ArrayBufferView arrayView = (ArrayBufferView)self; final int byteOffset = arrayView.byteOffset; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/objects/Global.java --- a/src/jdk/nashorn/internal/objects/Global.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/objects/Global.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,6 +29,7 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; + import java.io.IOException; import java.io.PrintWriter; import java.lang.invoke.MethodHandle; @@ -41,7 +42,6 @@ import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; import javax.script.ScriptContext; import javax.script.ScriptEngine; import jdk.internal.dynalink.linker.GuardedInvocation; @@ -54,7 +54,6 @@ import jdk.nashorn.internal.objects.annotations.ScriptClass; import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.Context; -import jdk.nashorn.internal.runtime.GlobalConstants; import jdk.nashorn.internal.runtime.GlobalFunctions; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.NativeJavaPackage; @@ -438,9 +437,6 @@ this.scontext = scontext; } - // global constants for this global - they can be replaced with MethodHandle.constant until invalidated - private static AtomicReference gcsInstance = new AtomicReference<>(); - @Override protected Context getContext() { return context; @@ -470,11 +466,6 @@ super(checkAndGetMap(context)); this.context = context; this.setIsScope(); - //we can only share one instance of Global constants between globals, or we consume way too much - //memory - this is good enough for most programs - while (gcsInstance.get() == null) { - gcsInstance.compareAndSet(null, new GlobalConstants(context.getLogger(GlobalConstants.class))); - } } /** @@ -493,15 +484,6 @@ } /** - * Return the global constants map for fields that - * can be accessed as MethodHandle.constant - * @return constant map - */ - public static GlobalConstants getConstants() { - return gcsInstance.get(); - } - - /** * Check if we have a Global instance * @return true if one exists */ diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/objects/NativeArray.java --- a/src/jdk/nashorn/internal/objects/NativeArray.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Fri Nov 14 10:03:48 2014 -0800 @@ -35,7 +35,6 @@ import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT; import java.lang.invoke.MethodHandle; -import java.lang.invoke.SwitchPoint; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -93,17 +92,6 @@ private static final Object CALL_CMP = new Object(); private static final Object TO_LOCALE_STRING = new Object(); - private SwitchPoint lengthMadeNotWritableSwitchPoint; - private PushLinkLogic pushLinkLogic; - private PopLinkLogic popLinkLogic; - private ConcatLinkLogic concatLinkLogic; - - /** - * Index for the modification SwitchPoint that triggers when length - * becomes not writable - */ - private static final int LENGTH_NOT_WRITABLE_SWITCHPOINT = 0; - /* * Constructors. */ @@ -271,12 +259,83 @@ @Override public Object getLength() { final long length = JSType.toUint32(getArray().length()); - if(length < Integer.MAX_VALUE) { + if (length < Integer.MAX_VALUE) { return (int)length; } return length; } + private boolean defineLength(final long oldLen, final PropertyDescriptor oldLenDesc, final PropertyDescriptor desc, final boolean reject) { + // Step 3a + if (!desc.has(VALUE)) { + return super.defineOwnProperty("length", desc, reject); + } + + // Step 3b + final PropertyDescriptor newLenDesc = desc; + + // Step 3c and 3d - get new length and convert to long + final long newLen = NativeArray.validLength(newLenDesc.getValue(), true); + + // Step 3e + newLenDesc.setValue(newLen); + + // Step 3f + // increasing array length - just need to set new length value (and attributes if any) and return + if (newLen >= oldLen) { + return super.defineOwnProperty("length", newLenDesc, reject); + } + + // Step 3g + if (!oldLenDesc.isWritable()) { + if (reject) { + throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this)); + } + return false; + } + + // Step 3h and 3i + final boolean newWritable = !newLenDesc.has(WRITABLE) || newLenDesc.isWritable(); + if (!newWritable) { + newLenDesc.setWritable(true); + } + + // Step 3j and 3k + final boolean succeeded = super.defineOwnProperty("length", newLenDesc, reject); + if (!succeeded) { + return false; + } + + // Step 3l + // make sure that length is set till the point we can delete the old elements + long o = oldLen; + while (newLen < o) { + o--; + final boolean deleteSucceeded = delete(o, false); + if (!deleteSucceeded) { + newLenDesc.setValue(o + 1); + if (!newWritable) { + newLenDesc.setWritable(false); + } + super.defineOwnProperty("length", newLenDesc, false); + if (reject) { + throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this)); + } + return false; + } + } + + // Step 3m + if (!newWritable) { + // make 'length' property not writable + final ScriptObject newDesc = Global.newEmptyInstance(); + newDesc.set(WRITABLE, false, 0); + return super.defineOwnProperty("length", newDesc, false); + } + + return true; + } + /** * ECMA 15.4.5.1 [[DefineOwnProperty]] ( P, Desc, Throw ) */ @@ -290,82 +349,16 @@ // Step 2 // get old length and convert to long - long oldLen = NativeArray.validLength(oldLenDesc.getValue(), true); + final long oldLen = NativeArray.validLength(oldLenDesc.getValue(), true); // Step 3 if ("length".equals(key)) { // check for length being made non-writable + final boolean result = defineLength(oldLen, oldLenDesc, desc, reject); if (desc.has(WRITABLE) && !desc.isWritable()) { setIsLengthNotWritable(); } - - // Step 3a - if (!desc.has(VALUE)) { - return super.defineOwnProperty("length", desc, reject); - } - - // Step 3b - final PropertyDescriptor newLenDesc = desc; - - // Step 3c and 3d - get new length and convert to long - final long newLen = NativeArray.validLength(newLenDesc.getValue(), true); - - // Step 3e - newLenDesc.setValue(newLen); - - // Step 3f - // increasing array length - just need to set new length value (and attributes if any) and return - if (newLen >= oldLen) { - return super.defineOwnProperty("length", newLenDesc, reject); - } - - // Step 3g - if (!oldLenDesc.isWritable()) { - if (reject) { - throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this)); - } - return false; - } - - // Step 3h and 3i - final boolean newWritable = !newLenDesc.has(WRITABLE) || newLenDesc.isWritable(); - if (!newWritable) { - newLenDesc.setWritable(true); - } - - // Step 3j and 3k - final boolean succeeded = super.defineOwnProperty("length", newLenDesc, reject); - if (!succeeded) { - return false; - } - - // Step 3l - // make sure that length is set till the point we can delete the old elements - while (newLen < oldLen) { - oldLen--; - final boolean deleteSucceeded = delete(oldLen, false); - if (!deleteSucceeded) { - newLenDesc.setValue(oldLen + 1); - if (!newWritable) { - newLenDesc.setWritable(false); - } - super.defineOwnProperty("length", newLenDesc, false); - if (reject) { - throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this)); - } - return false; - } - } - - // Step 3m - if (!newWritable) { - // make 'length' property not writable - final ScriptObject newDesc = Global.newEmptyInstance(); - newDesc.set(WRITABLE, false, 0); - return super.defineOwnProperty("length", newDesc, false); - } - - return true; + return result; } // Step 4a @@ -441,23 +434,7 @@ @Override public void setIsLengthNotWritable() { super.setIsLengthNotWritable(); - /* - * Switchpoints are created lazily. If we link any push or pop site, - * we need to create the "length made not writable" switchpoint, if it - * doesn't exist. - * - * If the switchpoint already exists, we will find it here, and invalidate - * it, invalidating all previous callsites that use it. - * - * If the switchpoint doesn't exist, no push/pop has been linked so far, - * because that would create it too. We invalidate it immediately and the - * check link logic for all future callsites will fail immediately at link - * time - */ - if (lengthMadeNotWritableSwitchPoint == null) { - lengthMadeNotWritableSwitchPoint = new SwitchPoint(); - } - SwitchPoint.invalidateAll(new SwitchPoint[] { lengthMadeNotWritableSwitchPoint }); + setArray(ArrayData.setIsLengthNotWritable(getArray())); } /** @@ -494,7 +471,7 @@ @Setter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) public static void length(final Object self, final Object length) { if (isArray(self)) { - ((ScriptObject) self).setLength(validLength(length, true)); + ((ScriptObject)self).setLength(validLength(length, true)); } } @@ -1306,10 +1283,13 @@ // Get only non-missing elements. Missing elements go at the end // of the sorted array. So, just don't copy these to sort input. final ArrayList src = new ArrayList<>(); - for (long i = 0; i < len; i = array.nextIndex(i)) { - if (array.has((int) i)) { - src.add(array.getObject((int) i)); + + for (final Iterator iter = array.indexIterator(); iter.hasNext(); ) { + final long index = iter.next(); + if (index >= len) { + break; } + src.add(array.getObject((int)index)); } final Object[] sorted = sort(src.toArray(), comparefn); @@ -1767,11 +1747,11 @@ @Override public SpecializedFunction.LinkLogic getLinkLogic(final Class clazz) { if (clazz == PushLinkLogic.class) { - return pushLinkLogic == null ? new PushLinkLogic(this) : pushLinkLogic; + return PushLinkLogic.INSTANCE; } else if (clazz == PopLinkLogic.class) { - return popLinkLogic == null ? new PopLinkLogic(this) : pushLinkLogic; + return PopLinkLogic.INSTANCE; } else if (clazz == ConcatLinkLogic.class) { - return concatLinkLogic == null ? new ConcatLinkLogic(this) : concatLinkLogic; + return ConcatLinkLogic.INSTANCE; } return null; } @@ -1787,21 +1767,7 @@ * modification switchpoint which is touched when length is written. */ private static abstract class ArrayLinkLogic extends SpecializedFunction.LinkLogic { - private final NativeArray array; - - protected ArrayLinkLogic(final NativeArray array) { - this.array = array; - } - - private SwitchPoint getSwitchPoint() { - return array.lengthMadeNotWritableSwitchPoint; - } - - private SwitchPoint newSwitchPoint() { - assert array.lengthMadeNotWritableSwitchPoint == null; - final SwitchPoint sp = new SwitchPoint(); - array.lengthMadeNotWritableSwitchPoint = sp; - return sp; + protected ArrayLinkLogic() { } protected static ContinuousArrayData getContinuousArrayData(final Object self) { @@ -1822,68 +1788,13 @@ public Class getRelinkException() { return ClassCastException.class; } - - @Override - public boolean hasModificationSwitchPoints() { - return getSwitchPoint() != null; - } - - @Override - public boolean hasModificationSwitchPoint(final int index) { - assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; - return hasModificationSwitchPoints(); - } - - @Override - public SwitchPoint getOrCreateModificationSwitchPoint(final int index) { - assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; - SwitchPoint sp = getSwitchPoint(); - if (sp == null) { - sp = newSwitchPoint(); - } - return sp; - } - - @Override - public SwitchPoint[] getOrCreateModificationSwitchPoints() { - return new SwitchPoint[] { getOrCreateModificationSwitchPoint(LENGTH_NOT_WRITABLE_SWITCHPOINT) }; - } - - @Override - public void invalidateModificationSwitchPoint(final int index) { - assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; - invalidateModificationSwitchPoints(); - } - - @Override - public void invalidateModificationSwitchPoints() { - final SwitchPoint sp = getSwitchPoint(); - assert sp != null : "trying to invalidate non-existant modified SwitchPoint"; - if (!sp.hasBeenInvalidated()) { - SwitchPoint.invalidateAll(new SwitchPoint[] { sp }); - } - } - - @Override - public boolean hasInvalidatedModificationSwitchPoint(final int index) { - assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT; - return hasInvalidatedModificationSwitchPoints(); - } - - @Override - public boolean hasInvalidatedModificationSwitchPoints() { - final SwitchPoint sp = getSwitchPoint(); - return sp != null && !sp.hasBeenInvalidated(); - } } /** * This is linker logic for optimistic concatenations */ private static final class ConcatLinkLogic extends ArrayLinkLogic { - private ConcatLinkLogic(final NativeArray array) { - super(array); - } + private static final LinkLogic INSTANCE = new ConcatLinkLogic(); @Override public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { @@ -1915,9 +1826,7 @@ * This is linker logic for optimistic pushes */ private static final class PushLinkLogic extends ArrayLinkLogic { - private PushLinkLogic(final NativeArray array) { - super(array); - } + private static final LinkLogic INSTANCE = new PushLinkLogic(); @Override public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { @@ -1929,9 +1838,7 @@ * This is linker logic for optimistic pops */ private static final class PopLinkLogic extends ArrayLinkLogic { - private PopLinkLogic(final NativeArray array) { - super(array); - } + private static final LinkLogic INSTANCE = new PopLinkLogic(); /** * We need to check if we are dealing with a continuous non empty array data here, diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/objects/NativeArrayBuffer.java --- a/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java Fri Nov 14 10:03:48 2014 -0800 @@ -26,7 +26,6 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; - import java.nio.ByteBuffer; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; @@ -34,6 +33,7 @@ import jdk.nashorn.internal.objects.annotations.Getter; import jdk.nashorn.internal.objects.annotations.ScriptClass; import jdk.nashorn.internal.objects.annotations.SpecializedFunction; +import jdk.nashorn.internal.objects.annotations.Where; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; @@ -138,6 +138,19 @@ } /** + * Returns true if an object is an ArrayBufferView + * + * @param self self + * @param obj object to check + * + * @return true if obj is an ArrayBufferView + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) + public static boolean isView(final Object self, final Object obj) { + return obj instanceof ArrayBufferView; + } + + /** * Slice function * @param self native array buffer * @param begin0 start byte index diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/objects/NativeDebug.java --- a/src/jdk/nashorn/internal/objects/NativeDebug.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/objects/NativeDebug.java Fri Nov 14 10:03:48 2014 -0800 @@ -39,6 +39,7 @@ import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.events.RuntimeEvent; import jdk.nashorn.internal.runtime.linker.LinkerCallSite; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; @@ -66,6 +67,36 @@ } /** + * Return the ArrayData class for this ScriptObject + * @param self self + * @param obj script object to check + * @return ArrayData class, or undefined if no ArrayData is present + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) + public static Object getArrayDataClass(final Object self, final Object obj) { + try { + return ((ScriptObject)obj).getArray().getClass(); + } catch (final ClassCastException e) { + return ScriptRuntime.UNDEFINED; + } + } + + /** + * Return the ArrayData for this ScriptObject + * @param self self + * @param obj script object to check + * @return ArrayData, ArrayDatas have toString methods, return Undefined if data missing + */ + @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) + public static Object getArrayData(final Object self, final Object obj) { + try { + return ((ScriptObject)obj).getArray(); + } catch (final ClassCastException e) { + return ScriptRuntime.UNDEFINED; + } + } + + /** * Nashorn extension: get context, context utility * * @param self self reference diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/objects/NativeString.java --- a/src/jdk/nashorn/internal/objects/NativeString.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,6 +29,7 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -572,7 +573,7 @@ try { return ((CharSequence)self).charAt(pos); } catch (final IndexOutOfBoundsException e) { - throw new ClassCastException(); + throw new ClassCastException(); //invalid char, out of bounds, force relink } } @@ -1380,7 +1381,6 @@ * sequence and that we are in range */ private static final class CharCodeAtLinkLogic extends SpecializedFunction.LinkLogic { - private static final CharCodeAtLinkLogic INSTANCE = new CharCodeAtLinkLogic(); @Override @@ -1389,7 +1389,7 @@ //check that it's a char sequence or throw cce final CharSequence cs = (CharSequence)self; //check that the index, representable as an int, is inside the array - final int intIndex = JSType.toInteger(request.getArguments()[1]); + final int intIndex = JSType.toInteger(request.getArguments()[2]); return intIndex >= 0 && intIndex < cs.length(); //can link } catch (final ClassCastException | IndexOutOfBoundsException e) { //fallthru diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java --- a/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Fri Nov 14 10:03:48 2014 -0800 @@ -30,7 +30,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.invoke.MethodHandle; -import java.lang.invoke.SwitchPoint; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.LinkRequest; import jdk.nashorn.internal.runtime.ScriptFunction; @@ -62,10 +61,6 @@ */ public static final LinkLogic EMPTY_INSTANCE = new Empty(); - private static final SwitchPoint[] INVALIDATED_SWITCHPOINTS = new SwitchPoint[0]; - - private SwitchPoint[] modificationSwitchPoints; //cache - /** Empty link logic class - allow all linking, no guards */ private static final class Empty extends LinkLogic { @Override @@ -167,92 +162,6 @@ } /** - * Return the modification SwitchPoint of a particular index from this OptimisticBuiltins - * If none exists, one is created and that one is return. - * - * The implementor must map indexes to specific SwitchPoints for specific events and keep - * track of what they mean, for example NativeArray.LENGTH_NOT_WRITABLE_SWITCHPOINT - * might be a useful index mapping - * - * @param index index for SwitchPoint to get or create - * @return modification SwitchPoint of particular index for the receiver - */ - public SwitchPoint getOrCreateModificationSwitchPoint(final int index) { - return null; - } - - /** - * Return the modification SwitchPoint from this OptimisticBuiltins. If none - * exists, one is created and that one is return. - * - * @return modification SwitchPoint for the receiver - */ - public SwitchPoint[] getOrCreateModificationSwitchPoints() { - return null; - } - - /** - * Hook to invalidate a modification SwitchPoint by index. - * - * @param index index for SwitchPoint to invalidate - */ - public void invalidateModificationSwitchPoint(final int index) { - //empty - } - - /** - * Hook to invalidate all modification SwitchPoints for a receiver - */ - public void invalidateModificationSwitchPoints() { - //empty - } - - /** - * Check whether the receiver has an invalidated modification SwitchPoint. - * - * @param index index for the modification SwitchPoint - * @return true if the particular SwitchPoint at the index is invalidated - */ - public boolean hasInvalidatedModificationSwitchPoint(final int index) { - return false; - } - - /** - * Check whether at least one of the modification SwitchPoints has been - * invalidated - * @return true if one of the SwitchPoints has been invalidated - */ - public boolean hasInvalidatedModificationSwitchPoints() { - return false; - } - - /** - * Check whether this OptimisticBuiltins has a SwitchPoints of particular - * index. - * - * As creation overhead for a SwitchPoint is non-zero, we have to create them lazily instead of, - * e.g. in the constructor of every subclass. - * - * @param index index for the modification SwitchPoint - * @return true if a modification SwitchPoint exists, no matter if it has been invalidated or not - */ - public boolean hasModificationSwitchPoint(final int index) { - return false; - } - - /** - * Check whether this OptimisticBuiltins has SwitchPoints. - * - * As creation overhead for a SwitchPoint is non-zero, we have to create them lazily instead of, - * e.g. in the constructor of every subclass. - * - * @return true if a modification SwitchPoint exists, no matter if it has been invalidated or not - */ - public boolean hasModificationSwitchPoints() { - return false; - } - - /** * Check, given a link request and a receiver, if this specialization * fits This is used by the linker in {@link ScriptFunction} to figure * out if an optimistic builtin can be linked when first discovered @@ -265,47 +174,9 @@ * pick a non specialized target */ public boolean checkLinkable(final Object self, final CallSiteDescriptor desc, final LinkRequest request) { - // no matter what the modification switchpoints are, if any of them are invalidated, - // we can't link. Side effect is that if it's the first time we see this callsite, - // we have to create the SwitchPoint(s) so future modification switchpoint invalidations - // relink it - final SwitchPoint[] sps = getOrCreateModificationSwitchPoints(self); - if (sps == INVALIDATED_SWITCHPOINTS) { - // nope, can't do the fast link as this assumption - // has been invalidated already, e.g. length of an - // array set to not writable - return false; - } - modificationSwitchPoints = sps; //cache - // check the link guard, if it says we can link, go ahead return canLink(self, desc, request); } - - private SwitchPoint[] getOrCreateModificationSwitchPoints(final Object self) { - final SwitchPoint[] sps = getOrCreateModificationSwitchPoints(); //ask for all my switchpoints - if (sps != null) { //switchpoint exists, but some may be invalidated - for (final SwitchPoint sp : sps) { - if (sp.hasBeenInvalidated()) { - return INVALIDATED_SWITCHPOINTS; - } - } - } - return sps; - } - - /** - * Get the cached modification switchpoints. Only possible to do after a link - * check call has been performed, one that has answered "true", or you will get the - * wrong information. - * - * Should be used only from {@link ScriptFunction#findCallMethod} - * - * @return cached modification switchpoints for this callsite, null if none - */ - public SwitchPoint[] getModificationSwitchPoints() { - return modificationSwitchPoints == null ? null : modificationSwitchPoints.clone(); - } } /** diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/CodeStore.java --- a/src/jdk/nashorn/internal/runtime/CodeStore.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/CodeStore.java Fri Nov 14 10:03:48 2014 -0800 @@ -41,6 +41,7 @@ import java.util.Iterator; import java.util.Map; import java.util.ServiceLoader; +import jdk.nashorn.internal.codegen.OptimisticTypesPersistence; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.runtime.logging.DebugLogger; import jdk.nashorn.internal.runtime.logging.Loggable; @@ -102,7 +103,7 @@ } catch (final AccessControlException e) { context.getLogger(CodeStore.class).warning("failed to load code store provider ", e); } - final CodeStore store = new DirectoryCodeStore(); + final CodeStore store = new DirectoryCodeStore(context); store.initLogger(context); return store; } @@ -210,32 +211,34 @@ /** * Constructor * + * @param context the current context * @throws IOException if there are read/write problems with the cache and cache directory */ - public DirectoryCodeStore() throws IOException { - this(Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache"), false, DEFAULT_MIN_SIZE); + public DirectoryCodeStore(final Context context) throws IOException { + this(context, Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache"), false, DEFAULT_MIN_SIZE); } /** * Constructor * + * @param context the current context * @param path directory to store code in * @param readOnly is this a read only code store * @param minSize minimum file size for caching scripts * @throws IOException if there are read/write problems with the cache and cache directory */ - public DirectoryCodeStore(final String path, final boolean readOnly, final int minSize) throws IOException { - this.dir = checkDirectory(path, readOnly); + public DirectoryCodeStore(final Context context, final String path, final boolean readOnly, final int minSize) throws IOException { + this.dir = checkDirectory(path, context.getEnv(), readOnly); this.readOnly = readOnly; this.minSize = minSize; } - private static File checkDirectory(final String path, final boolean readOnly) throws IOException { + private static File checkDirectory(final String path, final ScriptEnvironment env, final boolean readOnly) throws IOException { try { return AccessController.doPrivileged(new PrivilegedExceptionAction() { @Override public File run() throws IOException { - final File dir = new File(path).getAbsoluteFile(); + final File dir = new File(path, getVersionDir(env)).getAbsoluteFile(); if (readOnly) { if (!dir.exists() || !dir.isDirectory()) { throw new IOException("Not a directory: " + dir.getPath()); @@ -257,6 +260,15 @@ } } + private static String getVersionDir(final ScriptEnvironment env) throws IOException { + try { + final String versionDir = OptimisticTypesPersistence.getVersionDirName(); + return env._optimistic_types ? versionDir + "_opt" : versionDir; + } catch (final Exception e) { + throw new IOException(e); + } + } + @Override public StoredScript load(final Source source, final String functionKey) { if (source.getLength() < minSize) { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/CompiledFunction.java --- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,16 +27,17 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; - import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.MutableCallSite; import java.lang.invoke.SwitchPoint; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.function.Supplier; @@ -727,34 +728,58 @@ * @param ipp * @return string describing the ipp map */ - private static String toStringInvalidations(final Map ipp) { + private static List toStringInvalidations(final Map ipp) { if (ipp == null) { - return ""; + return Collections.emptyList(); } - final StringBuilder sb = new StringBuilder(); + final List list = new ArrayList<>(); for (final Iterator> iter = ipp.entrySet().iterator(); iter.hasNext(); ) { final Map.Entry entry = iter.next(); final char bct = entry.getValue().getBytecodeStackType(); + final String type; + switch (entry.getValue().getBytecodeStackType()) { + case 'A': + type = "object"; + break; + case 'I': + type = "int"; + break; + case 'J': + type = "long"; + break; + case 'D': + type = "double"; + break; + default: + type = String.valueOf(bct); + break; + } + + final StringBuilder sb = new StringBuilder(); sb.append('['). + append("program point: "). append(entry.getKey()). - append("->"). - append(bct == 'A' ? 'O' : bct). + append(" -> "). + append(type). append(']'); - if (iter.hasNext()) { - sb.append(' '); - } + list.add(sb.toString()); } - return sb.toString(); + return list; } private void logRecompile(final String reason, final FunctionNode fn, final MethodType type, final Map ipp) { if (log.isEnabled()) { - log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", type, " ", toStringInvalidations(ipp)); + log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", type); + log.indent(); + for (final String str : toStringInvalidations(ipp)) { + log.fine(str); + } + log.unindent(); } } @@ -770,14 +795,21 @@ */ private synchronized MethodHandle handleRewriteException(final OptimismInfo oldOptInfo, final RewriteException re) { if (log.isEnabled()) { - log.info(new RecompilationEvent(Level.INFO, re, re.getReturnValueNonDestructive()), "RewriteException ", re.getMessageShort()); + log.info( + new RecompilationEvent( + Level.INFO, + re, + re.getReturnValueNonDestructive()), + "caught RewriteException ", + re.getMessageShort()); + log.indent(); } final MethodType type = type(); // Compiler needs a call site type as its input, which always has a callee parameter, so we must add it if // this function doesn't have a callee parameter. - final MethodType callSiteType = type.parameterType(0) == ScriptFunction.class ? + final MethodType ct = type.parameterType(0) == ScriptFunction.class ? type : type.insertParameterTypes(0, ScriptFunction.class); final OptimismInfo currentOptInfo = optimismInfo; @@ -788,44 +820,44 @@ final OptimismInfo effectiveOptInfo = currentOptInfo != null ? currentOptInfo : oldOptInfo; FunctionNode fn = effectiveOptInfo.reparse(); final boolean serialized = effectiveOptInfo.isSerialized(); - final Compiler compiler = effectiveOptInfo.getCompiler(fn, callSiteType, re); //set to non rest-of + final Compiler compiler = effectiveOptInfo.getCompiler(fn, ct, re); //set to non rest-of if (!shouldRecompile) { // It didn't necessarily recompile, e.g. for an outer invocation of a recursive function if we already // recompiled a deoptimized version for an inner invocation. // We still need to do the rest of from the beginning - logRecompile("Rest-of compilation [STANDALONE] ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints); + logRecompile("Rest-of compilation [STANDALONE] ", fn, ct, effectiveOptInfo.invalidatedProgramPoints); return restOfHandle(effectiveOptInfo, compiler.compile(fn, serialized ? CompilationPhases.COMPILE_SERIALIZED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null); } - logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints); + logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, ct, effectiveOptInfo.invalidatedProgramPoints); fn = compiler.compile(fn, serialized ? CompilationPhases.RECOMPILE_SERIALIZED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE); - log.info("Reusable IR generated"); + log.fine("Reusable IR generated"); // compile the rest of the function, and install it log.info("Generating and installing bytecode from reusable IR..."); - logRecompile("Rest-of compilation [CODE PIPELINE REUSE] ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints); + logRecompile("Rest-of compilation [CODE PIPELINE REUSE] ", fn, ct, effectiveOptInfo.invalidatedProgramPoints); final FunctionNode normalFn = compiler.compile(fn, CompilationPhases.GENERATE_BYTECODE_AND_INSTALL); if (effectiveOptInfo.data.usePersistentCodeCache()) { final RecompilableScriptFunctionData data = effectiveOptInfo.data; final int functionNodeId = data.getFunctionNodeId(); - final TypeMap typeMap = data.typeMap(callSiteType); + final TypeMap typeMap = data.typeMap(ct); final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId); final String cacheKey = CodeStore.getCacheKey(functionNodeId, paramTypes); compiler.persistClassInfo(cacheKey, normalFn); } - log.info("Done."); - final boolean canBeDeoptimized = normalFn.canBeDeoptimized(); if (log.isEnabled()) { - log.info("Recompiled '", fn.getName(), "' (", Debug.id(this), ") ", canBeDeoptimized ? " can still be deoptimized." : " is completely deoptimized."); + log.unindent(); + log.info("Done."); + + log.info("Recompiled '", fn.getName(), "' (", Debug.id(this), ") ", canBeDeoptimized ? "can still be deoptimized." : " is completely deoptimized."); + log.finest("Looking up invoker..."); } - log.info("Looking up invoker..."); - final MethodHandle newInvoker = effectiveOptInfo.data.lookup(fn); invoker = newInvoker.asType(type.changeReturnType(newInvoker.type().returnType())); constructor = null; // Will be regenerated when needed diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/Context.java --- a/src/jdk/nashorn/internal/runtime/Context.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/Context.java Fri Nov 14 10:03:48 2014 -0800 @@ -33,6 +33,7 @@ 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; @@ -60,6 +61,7 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.function.Supplier; import java.util.logging.Level; @@ -262,6 +264,10 @@ // persistent code store private CodeStore codeStore; + // A factory for linking global properties as constant method handles. It is created when the first Global + // is created, and invalidated forever once the second global is created. + private final AtomicReference globalConstantsRef = new AtomicReference<>(); + /** * Get the current global scope * @return the current global scope @@ -293,7 +299,10 @@ assert getGlobal() != global; //same code can be cached between globals, then we need to invalidate method handle constants if (global != null) { - Global.getConstants().invalidateAll(); + final GlobalConstants globalConstants = getContext(global).getGlobalConstants(); + if (globalConstants != null) { + globalConstants.invalidateAll(); + } } currentGlobal.set(global); } @@ -529,6 +538,15 @@ } /** + * Returns the factory for constant method handles for global properties. The returned factory can be + * invalidated if this Context has more than one Global. + * @return the factory for constant method handles for global properties. + */ + GlobalConstants getGlobalConstants() { + return globalConstantsRef.get(); + } + + /** * Get the error manager for this context * @return error manger */ @@ -1016,9 +1034,32 @@ * @return the global script object */ public Global newGlobal() { + createOrInvalidateGlobalConstants(); return new Global(this); } + private void createOrInvalidateGlobalConstants() { + for (;;) { + final GlobalConstants currentGlobalConstants = getGlobalConstants(); + if (currentGlobalConstants != null) { + // Subsequent invocation; we're creating our second or later Global. GlobalConstants is not safe to use + // with more than one Global, as the constant method handle linkages it creates create a coupling + // between the Global and the call sites in the compiled code. + currentGlobalConstants.invalidateForever(); + return; + } + final GlobalConstants newGlobalConstants = new GlobalConstants(getLogger(GlobalConstants.class)); + if (globalConstantsRef.compareAndSet(null, newGlobalConstants)) { + // First invocation; we're creating the first Global in this Context. Create the GlobalConstants object + // for this Context. + return; + } + + // If we reach here, then we started out as the first invocation, but another concurrent invocation won the + // CAS race. We'll just let the loop repeat and invalidate the CAS race winner. + } + } + /** * Initialize given global scope object. * @@ -1057,12 +1098,19 @@ * @return current global's context */ static Context getContextTrusted() { - return ((ScriptObject)Context.getGlobal()).getContext(); + return getContext(getGlobal()); } static Context getContextTrustedOrNull() { final Global global = Context.getGlobal(); - return global == null ? null : ((ScriptObject)global).getContext(); + return global == null ? null : getContext(global); + } + + private static Context getContext(final Global global) { + // We can't invoke Global.getContext() directly, as it's a protected override, and Global isn't in our package. + // In order to access the method, we must cast it to ScriptObject first (which is in our package) and then let + // virtual invocation do its thing. + return ((ScriptObject)global).getContext(); } /** @@ -1150,9 +1198,8 @@ 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. + // We only use the code store here if optimistic types are disabled. With optimistic types, initial compilation + // just creates a thin wrapper, and actual code is stored per function in RecompilableScriptFunctionData. final boolean useCodeStore = env._persistent_cache && !env._parse_only && !env._optimistic_types; final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/GlobalConstants.java --- a/src/jdk/nashorn/internal/runtime/GlobalConstants.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/GlobalConstants.java Fri Nov 14 10:03:48 2014 -0800 @@ -31,12 +31,14 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.getProgramPoint; import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.SwitchPoint; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.DynamicLinker; @@ -50,7 +52,7 @@ import jdk.nashorn.internal.runtime.logging.Logger; /** - * Each global owns one of these. This is basically table of accessors + * Each context owns one of these. This is basically table of accessors * for global properties. A global constant is evaluated to a MethodHandle.constant * for faster access and to avoid walking to proto chain looking for it. * @@ -67,12 +69,19 @@ * reregister the switchpoint. Set twice or more - don't try again forever, or we'd * just end up relinking our way into megamorphisism. * + * Also it has to be noted that this kind of linking creates a coupling between a Global + * and the call sites in compiled code belonging to the Context. For this reason, the + * linkage becomes incorrect as soon as the Context has more than one Global. The + * {@link #invalidateForever()} is invoked by the Context to invalidate all linkages and + * turn off the functionality of this object as soon as the Context's {@link Context#newGlobal()} is invoked + * for second time. + * * We can extend this to ScriptObjects in general (GLOBAL_ONLY=false), which requires * a receiver guard on the constant getter, but it currently leaks memory and its benefits * have not yet been investigated property. * - * As long as all Globals share the same constant instance, we need synchronization - * whenever we access the instance. + * As long as all Globals in a Context share the same GlobalConstants instance, we need synchronization + * whenever we access it. */ @Logger(name="const") public final class GlobalConstants implements Loggable { @@ -82,7 +91,7 @@ * Script objects require a receiver guard, which is memory intensive, so this is currently * disabled. We might implement a weak reference based approach to this later. */ - private static final boolean GLOBAL_ONLY = true; + public static final boolean GLOBAL_ONLY = true; private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); @@ -98,6 +107,8 @@ */ private final Map map = new HashMap<>(); + private final AtomicBoolean invalidatedForever = new AtomicBoolean(false); + /** * Constructor - used only by global * @param log logger, or null if none @@ -216,10 +227,34 @@ * the same class for a new global, but the builtins and global scoped variables * will have changed. */ - public synchronized void invalidateAll() { - log.info("New global created - invalidating all constant callsites without increasing invocation count."); - for (final Access acc : map.values()) { - acc.invalidateUncounted(); + public void invalidateAll() { + if (!invalidatedForever.get()) { + log.info("New global created - invalidating all constant callsites without increasing invocation count."); + synchronized (this) { + for (final Access acc : map.values()) { + acc.invalidateUncounted(); + } + } + } + } + + /** + * To avoid an expensive global guard "is this the same global", similar to the + * receiver guard on the ScriptObject level, we invalidate all getters when the + * second Global is created by the Context owning this instance. After this + * method is invoked, this GlobalConstants instance will both invalidate all the + * switch points it produced, and it will stop handing out new method handles + * altogether. + */ + public void invalidateForever() { + if (invalidatedForever.compareAndSet(false, true)) { + log.info("New global created - invalidating all constant callsites."); + synchronized (this) { + for (final Access acc : map.values()) { + acc.invalidateForever(); + } + map.clear(); + } } } @@ -251,7 +286,7 @@ return obj; } - private synchronized Access getOrCreateSwitchPoint(final String name) { + private Access getOrCreateSwitchPoint(final String name) { Access acc = map.get(name); if (acc != null) { return acc; @@ -267,9 +302,13 @@ * @param name name of property */ void delete(final String name) { - final Access acc = map.get(name); - if (acc != null) { - acc.invalidateForever(); + if (!invalidatedForever.get()) { + synchronized (this) { + final Access acc = map.get(name); + if (acc != null) { + acc.invalidateForever(); + } + } } } @@ -313,45 +352,45 @@ * * @return null if failed to set up constant linkage */ - synchronized GuardedInvocation findSetMethod(final FindProperty find, final ScriptObject receiver, final GuardedInvocation inv, final CallSiteDescriptor desc, final LinkRequest request) { - if (GLOBAL_ONLY && !isGlobalSetter(receiver, find)) { + GuardedInvocation findSetMethod(final FindProperty find, final ScriptObject receiver, final GuardedInvocation inv, final CallSiteDescriptor desc, final LinkRequest request) { + if (invalidatedForever.get() || (GLOBAL_ONLY && !isGlobalSetter(receiver, find))) { return null; } final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); - final Access acc = getOrCreateSwitchPoint(name); + synchronized (this) { + final Access acc = getOrCreateSwitchPoint(name); - if (log.isEnabled()) { - log.fine("Trying to link constant SETTER ", acc); - } + if (log.isEnabled()) { + log.fine("Trying to link constant SETTER ", acc); + } - if (!acc.mayRetry()) { - if (log.isEnabled()) { - log.fine("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation()); + if (!acc.mayRetry() || invalidatedForever.get()) { + if (log.isEnabled()) { + log.fine("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation()); + } + return null; } - return null; - } - - assert acc.mayRetry(); - if (acc.hasBeenInvalidated()) { - log.info("New chance for " + acc); - acc.newSwitchPoint(); - } + if (acc.hasBeenInvalidated()) { + log.info("New chance for " + acc); + acc.newSwitchPoint(); + } - assert !acc.hasBeenInvalidated(); + assert !acc.hasBeenInvalidated(); - // if we haven't given up on this symbol, add a switchpoint invalidation filter to the receiver parameter - final MethodHandle target = inv.getInvocation(); - final Class receiverType = target.type().parameterType(0); - final MethodHandle boundInvalidator = MH.bindTo(INVALIDATE_SP, this); - final MethodHandle invalidator = MH.asType(boundInvalidator, boundInvalidator.type().changeParameterType(0, receiverType).changeReturnType(receiverType)); - final MethodHandle mh = MH.filterArguments(inv.getInvocation(), 0, MH.insertArguments(invalidator, 1, acc)); + // if we haven't given up on this symbol, add a switchpoint invalidation filter to the receiver parameter + final MethodHandle target = inv.getInvocation(); + final Class receiverType = target.type().parameterType(0); + final MethodHandle boundInvalidator = MH.bindTo(INVALIDATE_SP, this); + final MethodHandle invalidator = MH.asType(boundInvalidator, boundInvalidator.type().changeParameterType(0, receiverType).changeReturnType(receiverType)); + final MethodHandle mh = MH.filterArguments(inv.getInvocation(), 0, MH.insertArguments(invalidator, 1, acc)); - assert inv.getSwitchPoints() == null : Arrays.asList(inv.getSwitchPoints()); - log.info("Linked setter " + quote(name) + " " + acc.getSwitchPoint()); - return new GuardedInvocation(mh, inv.getGuard(), acc.getSwitchPoint(), inv.getException()); + assert inv.getSwitchPoints() == null : Arrays.asList(inv.getSwitchPoints()); + log.info("Linked setter " + quote(name) + " " + acc.getSwitchPoint()); + return new GuardedInvocation(mh, inv.getGuard(), acc.getSwitchPoint(), inv.getException()); + } } /** @@ -380,11 +419,11 @@ * * @return resulting getter, or null if failed to create constant */ - synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc) { + GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc) { // Only use constant getter for fast scope access, because the receiver may change between invocations // for slow-scope and non-scope callsites. // Also return null for user accessor properties as they may have side effects. - if (!NashornCallSiteDescriptor.isFastScope(desc) + if (invalidatedForever.get() || !NashornCallSiteDescriptor.isFastScope(desc) || (GLOBAL_ONLY && !find.getOwner().isGlobal()) || find.getProperty() instanceof UserAccessorProperty) { return null; @@ -395,51 +434,53 @@ final Class retType = desc.getMethodType().returnType(); final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); - final Access acc = getOrCreateSwitchPoint(name); + synchronized (this) { + final Access acc = getOrCreateSwitchPoint(name); - log.fine("Starting to look up object value " + name); - final Object c = find.getObjectValue(); + log.fine("Starting to look up object value " + name); + final Object c = find.getObjectValue(); - if (log.isEnabled()) { - log.fine("Trying to link constant GETTER " + acc + " value = " + c); - } + if (log.isEnabled()) { + log.fine("Trying to link constant GETTER " + acc + " value = " + c); + } - if (acc.hasBeenInvalidated() || acc.guardFailed()) { - if (log.isEnabled()) { - log.info("*** GET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation()); + if (acc.hasBeenInvalidated() || acc.guardFailed() || invalidatedForever.get()) { + if (log.isEnabled()) { + log.info("*** GET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation()); + } + return null; } - return null; - } + + final MethodHandle cmh = constantGetter(c); - final MethodHandle cmh = constantGetter(c); - - MethodHandle mh; - MethodHandle guard; + MethodHandle mh; + MethodHandle guard; - if (isOptimistic) { - if (JSType.getAccessorTypeIndex(cmh.type().returnType()) <= JSType.getAccessorTypeIndex(retType)) { - //widen return type - this is pessimistic, so it will always work - mh = MH.asType(cmh, cmh.type().changeReturnType(retType)); + if (isOptimistic) { + if (JSType.getAccessorTypeIndex(cmh.type().returnType()) <= JSType.getAccessorTypeIndex(retType)) { + //widen return type - this is pessimistic, so it will always work + mh = MH.asType(cmh, cmh.type().changeReturnType(retType)); + } else { + //immediately invalidate - we asked for a too wide constant as a narrower one + mh = MH.dropArguments(MH.insertArguments(JSType.THROW_UNWARRANTED.methodHandle(), 0, c, programPoint), 0, Object.class); + } } else { - //immediately invalidate - we asked for a too wide constant as a narrower one - mh = MH.dropArguments(MH.insertArguments(JSType.THROW_UNWARRANTED.methodHandle(), 0, c, programPoint), 0, Object.class); + //pessimistic return type filter + mh = Lookup.filterReturnType(cmh, retType); } - } else { - //pessimistic return type filter - mh = Lookup.filterReturnType(cmh, retType); - } - if (find.getOwner().isGlobal()) { - guard = null; - } else { - guard = MH.insertArguments(RECEIVER_GUARD, 0, acc, receiver); - } + if (find.getOwner().isGlobal()) { + guard = null; + } else { + guard = MH.insertArguments(RECEIVER_GUARD, 0, acc, receiver); + } - if (log.isEnabled()) { - log.info("Linked getter " + quote(name) + " as MethodHandle.constant() -> " + c + " " + acc.getSwitchPoint()); - mh = MethodHandleFactory.addDebugPrintout(log, Level.FINE, mh, "get const " + acc); + if (log.isEnabled()) { + log.info("Linked getter " + quote(name) + " as MethodHandle.constant() -> " + c + " " + acc.getSwitchPoint()); + mh = MethodHandleFactory.addDebugPrintout(log, Level.FINE, mh, "get const " + acc); + } + + return new GuardedInvocation(mh, guard, acc.getSwitchPoint(), null); } - - return new GuardedInvocation(mh, guard, acc.getSwitchPoint(), null); } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/JSType.java --- a/src/jdk/nashorn/internal/runtime/JSType.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Fri Nov 14 10:03:48 2014 -0800 @@ -150,6 +150,12 @@ /** Div exact wrapper for potentially integer division that turns into float point */ public static final Call DIV_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", int.class, int.class, int.class, int.class); + /** Div zero wrapper for integer division that handles (0/0)|0 == 0 */ + public static final Call DIV_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", int.class, int.class, int.class); + + /** Mod zero wrapper for integer division that handles (0%0)|0 == 0 */ + public static final Call REM_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", int.class, int.class, int.class); + /** Mod exact wrapper for potentially integer remainders that turns into float point */ public static final Call REM_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", int.class, int.class, int.class, int.class); @@ -174,6 +180,12 @@ /** Div exact wrapper for potentially integer division that turns into float point */ public static final Call DIV_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", long.class, long.class, long.class, int.class); + /** Div zero wrapper for long division that handles (0/0) >>> 0 == 0 */ + public static final Call DIV_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", long.class, long.class, long.class); + + /** Mod zero wrapper for long division that handles (0%0) >>> 0 == 0 */ + public static final Call REM_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", long.class, long.class, long.class); + /** Mod exact wrapper for potentially integer remainders that turns into float point */ public static final Call REM_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", long.class, long.class, long.class, int.class); @@ -1486,6 +1498,28 @@ } /** + * Implements int division but allows {@code x / 0} to be represented as 0. Basically equivalent to + * {@code (x / y)|0} JavaScript expression (division of two ints coerced to int). + * @param x the dividend + * @param y the divisor + * @return the result + */ + public static int divZero(final int x, final int y) { + return y == 0 ? 0 : x / y; + } + + /** + * Implements int remainder but allows {@code x % 0} to be represented as 0. Basically equivalent to + * {@code (x % y)|0} JavaScript expression (remainder of two ints coerced to int). + * @param x the dividend + * @param y the divisor + * @return the remainder + */ + public static int remZero(final int x, final int y) { + return y == 0 ? 0 : x % y; + } + + /** * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int. * * @param x first term @@ -1529,6 +1563,28 @@ } /** + * Implements long division but allows {@code x / 0} to be represented as 0. Useful when division of two longs + * is coerced to long. + * @param x the dividend + * @param y the divisor + * @return the result + */ + public static long divZero(final long x, final long y) { + return y == 0L ? 0L : x / y; + } + + /** + * Implements long remainder but allows {@code x % 0} to be represented as 0. Useful when remainder of two longs + * is coerced to long. + * @param x the dividend + * @param y the divisor + * @return the remainder + */ + public static long remZero(final long x, final long y) { + return y == 0L ? 0L : x % y; + } + + /** * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int. * * @param x first term diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Fri Nov 14 10:03:48 2014 -0800 @@ -26,7 +26,6 @@ package jdk.nashorn.internal.runtime; import static jdk.nashorn.internal.lookup.Lookup.MH; - import java.io.IOException; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -475,6 +474,7 @@ * @return either the existing map, or a loaded map from the persistent type info cache, or a new empty map if * neither an existing map or a persistent cached type info is available. */ + @SuppressWarnings("unused") private static Map getEffectiveInvalidatedProgramPoints( final Map invalidatedProgramPoints, final Object typeInformationFile) { if(invalidatedProgramPoints != null) { @@ -619,20 +619,25 @@ return f; } - MethodHandle lookup(final FunctionInitializer fnInit) { + private void logLookup(final boolean shouldLog, final MethodType targetType) { + if (shouldLog && log.isEnabled()) { + log.info("Looking up ", DebugLogger.quote(functionName), " type=", targetType); + } + } + + private MethodHandle lookup(final FunctionInitializer fnInit, final boolean shouldLog) { final MethodType type = fnInit.getMethodType(); + logLookup(shouldLog, type); return lookupCodeMethod(fnInit.getCode(), type); } MethodHandle lookup(final FunctionNode fn) { final MethodType type = new FunctionSignature(fn).getMethodType(); + logLookup(true, type); return lookupCodeMethod(fn.getCompileUnit().getCode(), type); } MethodHandle lookupCodeMethod(final Class codeClass, final MethodType targetType) { - if (log.isEnabled()) { - log.info("Looking up ", DebugLogger.quote(functionName), " type=", targetType); - } return MH.findStatic(LOOKUP, codeClass, functionName, targetType); } @@ -648,7 +653,7 @@ if(!code.isEmpty()) { throw new IllegalStateException(name); } - addCode(lookup(initializer), null, null, initializer.getFlags()); + addCode(lookup(initializer, true), null, null, initializer.getFlags()); } private CompiledFunction addCode(final MethodHandle target, final Map invalidatedProgramPoints, @@ -670,10 +675,10 @@ */ private CompiledFunction addCode(final FunctionInitializer fnInit, final MethodType callSiteType) { if (isVariableArity()) { - return addCode(lookup(fnInit), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags()); + return addCode(lookup(fnInit, true), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags()); } - final MethodHandle handle = lookup(fnInit); + final MethodHandle handle = lookup(fnInit, true); final MethodType fromType = handle.type(); MethodType toType = needsCallee(fromType) ? callSiteType.changeParameterType(0, ScriptFunction.class) : callSiteType.dropParameterTypes(0, 1); toType = toType.changeReturnType(fromType.returnType()); @@ -698,7 +703,7 @@ toType = toType.dropParameterTypes(fromCount, toCount); } - return addCode(lookup(fnInit).asType(toType), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags()); + return addCode(lookup(fnInit, false).asType(toType), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags()); } /** @@ -727,7 +732,7 @@ assert existingBest != null; //we are calling a vararg method with real args - boolean applyToCall = existingBest.isVarArg() && !CompiledFunction.isVarArgsType(callSiteType); + boolean varArgWithRealArgs = existingBest.isVarArg() && !CompiledFunction.isVarArgsType(callSiteType); //if the best one is an apply to call, it has to match the callsite exactly //or we need to regenerate @@ -736,14 +741,16 @@ if (best != null) { return best; } - applyToCall = true; + varArgWithRealArgs = true; } - if (applyToCall) { + if (varArgWithRealArgs) { + // special case: we had an apply to call, but we failed to make it fit. + // Try to generate a specialized one for this callsite. It may + // be another apply to call specialization, or it may not, but whatever + // it is, it is a specialization that is guaranteed to fit final FunctionInitializer fnInit = compileTypeSpecialization(callSiteType, runtimeScope, false); - if ((fnInit.getFlags() & FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION) != 0) { //did the specialization work - existingBest = addCode(fnInit, callSiteType); - } + existingBest = addCode(fnInit, callSiteType); } return existingBest; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/ScriptEnvironment.java --- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java Fri Nov 14 10:03:48 2014 -0800 @@ -212,6 +212,7 @@ * @param out output print writer * @param err error print writer */ + @SuppressWarnings("unused") public ScriptEnvironment(final Options options, final PrintWriter out, final PrintWriter err) { this.out = out; this.err = err; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/ScriptFunction.java --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Fri Nov 14 10:03:48 2014 -0800 @@ -603,16 +603,6 @@ log.info("Linking optimistic builtin function: '", name, "' args=", Arrays.toString(request.getArguments()), " desc=", desc); } - final SwitchPoint[] msps = linkLogic.getModificationSwitchPoints(); - if (msps != null) { - for (final SwitchPoint sp : msps) { - if (sp != null) { - assert !sp.hasBeenInvalidated(); - sps.add(sp); - } - } - } - exceptionGuard = linkLogic.getRelinkException(); break; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/ScriptObject.java --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Fri Nov 14 10:03:48 2014 -0800 @@ -47,6 +47,7 @@ import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex; import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -509,6 +510,13 @@ } } + private void invalidateGlobalConstant(final String key) { + final GlobalConstants globalConstants = getGlobalConstants(); + if (globalConstants != null) { + globalConstants.delete(key); + } + } + /** * ECMA 8.12.9 [[DefineOwnProperty]] (P, Desc, Throw) * @@ -524,6 +532,8 @@ final Object current = getOwnPropertyDescriptor(key); final String name = JSType.toString(key); + invalidateGlobalConstant(key); + if (current == UNDEFINED) { if (isExtensible()) { // add a new own property @@ -922,7 +932,8 @@ if (property instanceof UserAccessorProperty) { ((UserAccessorProperty)property).setAccessors(this, getMap(), null); } - Global.getConstants().delete(property.getKey()); + + invalidateGlobalConstant(property.getKey()); return true; } } @@ -1348,12 +1359,9 @@ final PropertyMap selfMap = this.getMap(); final ArrayData array = getArray(); - final long length = array.length(); - - for (long i = 0; i < length; i = array.nextIndex(i)) { - if (array.has((int)i)) { - keys.add(JSType.toString(i)); - } + + for (final Iterator iter = array.indexIterator(); iter.hasNext(); ) { + keys.add(JSType.toString(iter.next().longValue())); } for (final Property property : selfMap.getProperties()) { @@ -1512,12 +1520,12 @@ * * @return {@code true} if 'length' property is non-writable */ - public final boolean isLengthNotWritable() { + public boolean isLengthNotWritable() { return (flags & IS_LENGTH_NOT_WRITABLE) != 0; } /** - * Flag this object as having non-writable length property + * Flag this object as having non-writable length property. */ public void setIsLengthNotWritable() { flags |= IS_LENGTH_NOT_WRITABLE; @@ -1983,9 +1991,12 @@ } } - final GuardedInvocation cinv = Global.getConstants().findGetMethod(find, this, desc); - if (cinv != null) { - return cinv; + final GlobalConstants globalConstants = getGlobalConstants(); + if (globalConstants != null) { + final GuardedInvocation cinv = globalConstants.findGetMethod(find, this, desc); + if (cinv != null) { + return cinv; + } } final Class returnType = desc.getMethodType().returnType(); @@ -2183,14 +2194,22 @@ final GuardedInvocation inv = new SetMethodCreator(this, find, desc, request).createGuardedInvocation(findBuiltinSwitchPoint(name)); - final GuardedInvocation cinv = Global.getConstants().findSetMethod(find, this, inv, desc, request); - if (cinv != null) { - return cinv; + final GlobalConstants globalConstants = getGlobalConstants(); + if (globalConstants != null) { + final GuardedInvocation cinv = globalConstants.findSetMethod(find, this, inv, desc, request); + if (cinv != null) { + return cinv; + } } return inv; } + private GlobalConstants getGlobalConstants() { + // Avoid hitting getContext() which might be costly for a non-Global unless needed. + return GlobalConstants.GLOBAL_ONLY && !isGlobal() ? null : getContext().getGlobalConstants(); + } + private GuardedInvocation createEmptySetMethod(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String strictErrorMessage, final boolean canBeFastScope) { final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); if (NashornCallSiteDescriptor.isStrict(desc)) { @@ -3137,6 +3156,8 @@ public final void setObject(final FindProperty find, final int callSiteFlags, final String key, final Object value) { FindProperty f = find; + invalidateGlobalConstant(key); + if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) { final boolean isScope = NashornCallSiteDescriptor.isScopeFlag(callSiteFlags); // If the start object of the find is not this object it means the property was found inside a @@ -3162,7 +3183,6 @@ if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) { throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this)); } - return; } @@ -3573,7 +3593,6 @@ } return false; } - return deleteObject(JSType.toObject(key), strict); } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/ArrayData.java --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Fri Nov 14 10:03:48 2014 -0800 @@ -30,6 +30,9 @@ import java.lang.invoke.MethodHandles; import java.lang.reflect.Array; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; @@ -56,6 +59,21 @@ public static final ArrayData EMPTY_ARRAY = new UntouchedArrayData(); /** + * Length of the array data. Not necessarily length of the wrapped array. + * This is private to ensure that no one in a subclass is able to touch the length + * without going through {@link setLength}. This is used to implement + * {@link LengthNotWritableFilter}s, ensuring that there are no ways past + * a {@link setLength} function replaced by a nop + */ + private long length; + + /** + * Method handle to throw an {@link UnwarrantedOptimismException} when getting an element + * of the wrong type + */ + protected static final CompilerConstants.Call THROW_UNWARRANTED = staticCall(MethodHandles.lookup(), ArrayData.class, "throwUnwarranted", void.class, ArrayData.class, int.class, int.class); + + /** * Immutable empty array to get ScriptObjects started. * Use the same array and convert it to mutable as soon as it is modified */ @@ -82,7 +100,7 @@ @Override public ContinuousArrayData copy() { - return new UntouchedArrayData((int)length); + return new UntouchedArrayData((int)length()); } @Override @@ -98,6 +116,10 @@ @Override public ArrayData ensure(final long safeIndex) { if (safeIndex > 0L) { + if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) { + return new SparseArrayData(this, safeIndex + 1); + } + //known to fit in int return toRealArrayData((int)safeIndex).ensure(safeIndex); } return this; @@ -109,6 +131,16 @@ } @Override + public ArrayData delete(final int index) { + return new DeletedRangeArrayFilter(this, index, index); + } + + @Override + public ArrayData delete(final long fromIndex, final long toIndex) { + return new DeletedRangeArrayFilter(this, fromIndex, toIndex); + } + + @Override public void shiftLeft(final int by) { //nop, always empty or we wouldn't be of this class } @@ -169,16 +201,6 @@ } @Override - public ArrayData delete(final int index) { - return new DeletedRangeArrayFilter(this, index, index); - } - - @Override - public ArrayData delete(final long fromIndex, final long toIndex) { - return new DeletedRangeArrayFilter(this, fromIndex, toIndex); - } - - @Override public Object pop() { return ScriptRuntime.UNDEFINED; } @@ -227,17 +249,6 @@ }; /** - * Length of the array data. Not necessarily length of the wrapped array. - */ - protected long length; - - /** - * Method handle to throw an {@link UnwarrantedOptimismException} when getting an element - * of the wrong type - */ - protected static final CompilerConstants.Call THROW_UNWARRANTED = staticCall(MethodHandles.lookup(), ArrayData.class, "throwUnwarranted", void.class, ArrayData.class, int.class, int.class); - - /** * Constructor * @param length Virtual length of the array. */ @@ -390,6 +401,16 @@ } /** + * Prevent this array from having its length reset + * + * @param underlying the underlying ArrayDAta to wrap in the non extensible filter + * @return new array data, filtered + */ + public static final ArrayData setIsLengthNotWritable(final ArrayData underlying) { + return new LengthNotWritableFilter(underlying); + } + + /** * Return the length of the array data. This may differ from the actual * length of the array this wraps as length may be set or gotten as any * other JavaScript Property @@ -442,6 +463,22 @@ } /** + * Increase length by 1 + * @return the new length, not the old one (i.e. pre-increment) + */ + protected final long increaseLength() { + return ++this.length; + } + + /** + * Decrease length by 1. + * @return the new length, not the old one (i.e. pre-decrement) + */ + protected final long decreaseLength() { + return --this.length; + } + + /** * Shift the array data left * * TODO: explore start at an index and not at zero, to make these operations @@ -450,7 +487,7 @@ * * @param by offset to shift */ - public abstract void shiftLeft(int by); + public abstract void shiftLeft(final int by); /** * Shift the array right @@ -459,7 +496,7 @@ * @return New arraydata (or same) */ - public abstract ArrayData shiftRight(int by); + public abstract ArrayData shiftRight(final int by); /** * Ensure that the given index exists and won't fail subsequent @@ -467,7 +504,7 @@ * @param safeIndex the index to ensure wont go out of bounds * @return new array data (or same) */ - public abstract ArrayData ensure(long safeIndex); + public abstract ArrayData ensure(final long safeIndex); /** * Shrink the array to a new length, may or may not retain the @@ -477,7 +514,7 @@ * * @return new array data (or same) */ - public abstract ArrayData shrink(long newLength); + public abstract ArrayData shrink(final long newLength); /** * Set an object value at a given index @@ -487,7 +524,7 @@ * @param strict are we in strict mode * @return new array data (or same) */ - public abstract ArrayData set(int index, Object value, boolean strict); + public abstract ArrayData set(final int index, final Object value, final boolean strict); /** * Set an int value at a given index @@ -497,7 +534,7 @@ * @param strict are we in strict mode * @return new array data (or same) */ - public abstract ArrayData set(int index, int value, boolean strict); + public abstract ArrayData set(final int index, final int value, final boolean strict); /** * Set a long value at a given index @@ -507,7 +544,7 @@ * @param strict are we in strict mode * @return new array data (or same) */ - public abstract ArrayData set(int index, long value, boolean strict); + public abstract ArrayData set(final int index, final long value, final boolean strict); /** * Set an double value at a given index @@ -517,7 +554,7 @@ * @param strict are we in strict mode * @return new array data (or same) */ - public abstract ArrayData set(int index, double value, boolean strict); + public abstract ArrayData set(final int index, final double value, final boolean strict); /** * Set an empty value at a given index. Should only affect Object array. @@ -548,7 +585,7 @@ * @param index the index * @return the value */ - public abstract int getInt(int index); + public abstract int getInt(final int index); /** * Returns the optimistic type of this array data. Basically, when an array data object needs to throw an @@ -577,7 +614,7 @@ * @param index the index * @return the value */ - public abstract long getLong(int index); + public abstract long getLong(final int index); /** * Get optimistic long - default is that it's impossible. Overridden @@ -597,7 +634,7 @@ * @param index the index * @return the value */ - public abstract double getDouble(int index); + public abstract double getDouble(final int index); /** * Get optimistic double - default is that it's impossible. Overridden @@ -617,14 +654,14 @@ * @param index the index * @return the value */ - public abstract Object getObject(int index); + public abstract Object getObject(final int index); /** * Tests to see if an entry exists (avoids boxing.) * @param index the index * @return true if entry exists */ - public abstract boolean has(int index); + public abstract boolean has(final int index); /** * Returns if element at specific index can be deleted or not. @@ -670,7 +707,7 @@ * @param index the index * @return new array data (or same) */ - public abstract ArrayData delete(int index); + public abstract ArrayData delete(final int index); /** * Delete a given range from this array; @@ -680,7 +717,7 @@ * * @return new ArrayData after deletion */ - public abstract ArrayData delete(long fromIndex, long toIndex); + public abstract ArrayData delete(final long fromIndex, final long toIndex); /** * Convert the ArrayData to one with a different element type @@ -690,7 +727,7 @@ * @param type new element type * @return new array data */ - public abstract ArrayData convert(Class type); + public abstract ArrayData convert(final Class type); /** * Push an array of items to the end of the array @@ -774,7 +811,7 @@ * @param to end index + 1 * @return new array data */ - public abstract ArrayData slice(long from, long to); + public abstract ArrayData slice(final long from, final long to); /** * Fast splice operation. This just modifies the array according to the number of @@ -819,6 +856,34 @@ } /** + * Return a list of keys in the array for the iterators + * @return iterator key list + */ + protected List computeIteratorKeys() { + final List keys = new ArrayList<>(); + + final long len = length(); + for (long i = 0L; i < len; i = nextIndex(i)) { + if (has((int)i)) { + keys.add(i); + } + } + + return keys; + } + + /** + * Return an iterator that goes through all indexes of elements + * in this array. This includes those after array.length if + * they exist + * + * @return iterator + */ + public Iterator indexIterator() { + return computeIteratorKeys().iterator(); + } + + /** * Exponential growth function for array size when in * need of resizing. * @@ -837,7 +902,7 @@ * * @return the next index */ - public long nextIndex(final long index) { + long nextIndex(final long index) { return index + 1; } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Fri Nov 14 10:03:48 2014 -0800 @@ -39,7 +39,7 @@ protected ArrayData underlying; ArrayFilter(final ArrayData underlying) { - super(underlying.length); + super(underlying.length()); this.underlying = underlying; } @@ -70,62 +70,55 @@ @Override public void shiftLeft(final int by) { underlying.shiftLeft(by); - setLength(underlying.length); + setLength(underlying.length()); } @Override public ArrayData shiftRight(final int by) { underlying = underlying.shiftRight(by); - setLength(underlying.length); - + setLength(underlying.length()); return this; } @Override public ArrayData ensure(final long safeIndex) { underlying = underlying.ensure(safeIndex); - setLength(underlying.length); - + setLength(underlying.length()); return this; } @Override public ArrayData shrink(final long newLength) { underlying = underlying.shrink(newLength); - setLength(underlying.length); - + setLength(underlying.length()); return this; } @Override public ArrayData set(final int index, final Object value, final boolean strict) { underlying = underlying.set(index, value, strict); - setLength(underlying.length); - + setLength(underlying.length()); return this; } @Override public ArrayData set(final int index, final int value, final boolean strict) { underlying = underlying.set(index, value, strict); - setLength(underlying.length); - + setLength(underlying.length()); return this; } @Override public ArrayData set(final int index, final long value, final boolean strict) { underlying = underlying.set(index, value, strict); - setLength(underlying.length); - + setLength(underlying.length()); return this; } @Override public ArrayData set(final int index, final double value, final boolean strict) { underlying = underlying.set(index, value, strict); - setLength(underlying.length); - + setLength(underlying.length()); return this; } @@ -189,29 +182,28 @@ @Override public ArrayData delete(final int index) { underlying = underlying.delete(index); - setLength(underlying.length); + setLength(underlying.length()); return this; } @Override public ArrayData delete(final long from, final long to) { underlying = underlying.delete(from, to); - setLength(underlying.length); + setLength(underlying.length()); return this; } @Override public ArrayData convert(final Class type) { underlying = underlying.convert(type); - setLength(underlying.length); + setLength(underlying.length()); return this; } @Override public Object pop() { final Object value = underlying.pop(); - setLength(underlying.length); - + setLength(underlying.length()); return value; } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java --- a/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Fri Nov 14 10:03:48 2014 -0800 @@ -65,7 +65,7 @@ * @return true if we don't need to do any array reallocation to fit an element at index */ public final boolean hasRoomFor(final int index) { - return has(index) || (index == length && ensure(index) == this); + return has(index) || (index == length() && ensure(index) == this); } /** @@ -73,7 +73,7 @@ * @return true if empty */ public boolean isEmpty() { - return length == 0L; + return length() == 0L; } /** diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java --- a/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java Fri Nov 14 10:03:48 2014 -0800 @@ -38,8 +38,7 @@ DeletedArrayFilter(final ArrayData underlying) { super(underlying); - - this.deleted = new BitVector(underlying.length); + this.deleted = new BitVector(underlying.length()); } @Override @@ -79,25 +78,24 @@ @Override public void shiftLeft(final int by) { super.shiftLeft(by); - deleted.shiftLeft(by, length); + deleted.shiftLeft(by, length()); } @Override public ArrayData shiftRight(final int by) { super.shiftRight(by); - deleted.shiftRight(by, length); - + deleted.shiftRight(by, length()); return this; } @Override public ArrayData ensure(final long safeIndex) { - if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) { + if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) { return new SparseArrayData(this, safeIndex + 1); } super.ensure(safeIndex); - deleted.resize(length); + deleted.resize(length()); return this; } @@ -105,36 +103,31 @@ @Override public ArrayData shrink(final long newLength) { super.shrink(newLength); - deleted.resize(length); - + deleted.resize(length()); return this; } @Override public ArrayData set(final int index, final Object value, final boolean strict) { deleted.clear(ArrayIndex.toLongIndex(index)); - return super.set(index, value, strict); } @Override public ArrayData set(final int index, final int value, final boolean strict) { deleted.clear(ArrayIndex.toLongIndex(index)); - return super.set(index, value, strict); } @Override public ArrayData set(final int index, final long value, final boolean strict) { deleted.clear(ArrayIndex.toLongIndex(index)); - return super.set(index, value, strict); } @Override public ArrayData set(final int index, final double value, final boolean strict) { deleted.clear(ArrayIndex.toLongIndex(index)); - return super.set(index, value, strict); } @@ -146,7 +139,7 @@ @Override public ArrayData delete(final int index) { final long longIndex = ArrayIndex.toLongIndex(index); - assert longIndex >= 0 && longIndex < length; + assert longIndex >= 0 && longIndex < length(); deleted.set(longIndex); underlying.setEmpty(index); return this; @@ -154,7 +147,7 @@ @Override public ArrayData delete(final long fromIndex, final long toIndex) { - assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length; + assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length(); deleted.setRange(fromIndex, toIndex + 1); underlying.setEmpty(fromIndex, toIndex); return this; @@ -162,7 +155,7 @@ @Override public Object pop() { - final long index = length - 1; + final long index = length() - 1; if (super.has((int)index)) { final boolean isDeleted = deleted.isSet(index); @@ -179,7 +172,7 @@ final ArrayData newArray = underlying.slice(from, to); final DeletedArrayFilter newFilter = new DeletedArrayFilter(newArray); newFilter.getDeleted().copy(deleted); - newFilter.getDeleted().shiftLeft(from, newFilter.length); + newFilter.getDeleted().shiftLeft(from, newFilter.length()); return newFilter; } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java --- a/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Fri Nov 14 10:03:48 2014 -0800 @@ -42,10 +42,10 @@ } private static ArrayData maybeSparse(final ArrayData underlying, final long hi) { - if(hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) { + if (hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) { return underlying; } - return new SparseArrayData(underlying, underlying.length); + return new SparseArrayData(underlying, underlying.length()); } private boolean isEmpty() { @@ -93,7 +93,7 @@ @Override public ArrayData ensure(final long safeIndex) { - if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) { + if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) { return new SparseArrayData(this, safeIndex + 1); } @@ -110,7 +110,7 @@ @Override public ArrayData shiftRight(final int by) { super.shiftRight(by); - final long len = length; + final long len = length(); lo = Math.min(len, lo + by); hi = Math.min(len - 1, hi + by); @@ -238,7 +238,7 @@ @Override public Object pop() { - final int index = (int)length - 1; + final int index = (int)length() - 1; if (super.has(index)) { final boolean isDeleted = isDeleted(index); final Object value = super.pop(); diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java --- a/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java Fri Nov 14 10:03:48 2014 -0800 @@ -26,9 +26,9 @@ package jdk.nashorn.internal.runtime.arrays; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; - import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.PropertyDescriptor; +import jdk.nashorn.internal.runtime.ScriptRuntime; /** * ArrayData after the array has been frozen by Object.freeze call. @@ -79,4 +79,15 @@ } return this; } + + @Override + public ArrayData push(final boolean strict, final Object... items) { + return this; //nop + } + + @Override + public Object pop() { + final int len = (int)underlying.length(); + return len == 0 ? ScriptRuntime.UNDEFINED : underlying.getObject(len - 1); + } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java --- a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Fri Nov 14 10:03:48 2014 -0800 @@ -119,22 +119,24 @@ @Override public IntArrayData copy() { - return new IntArrayData(array.clone(), (int)length); + return new IntArrayData(array.clone(), (int)length()); } @Override public Object asArrayOfType(final Class componentType) { if (componentType == int.class) { - return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length); + final int len = (int)length(); + return array.length == len ? array.clone() : Arrays.copyOf(array, len); } return super.asArrayOfType(componentType); } private Object[] toObjectArray(final boolean trim) { - assert length <= array.length : "length exceeds internal array size"; - final Object[] oarray = new Object[trim ? (int)length : array.length]; + assert length() <= array.length : "length exceeds internal array size"; + final int len = (int)length(); + final Object[] oarray = new Object[trim ? len : array.length]; - for (int index = 0; index < length; index++) { + for (int index = 0; index < len; index++) { oarray[index] = Integer.valueOf(array[index]); } @@ -142,10 +144,11 @@ } private double[] toDoubleArray() { - assert length <= array.length : "length exceeds internal array size"; + assert length() <= array.length : "length exceeds internal array size"; + final int len = (int)length(); final double[] darray = new double[array.length]; - for (int index = 0; index < length; index++) { + for (int index = 0; index < len; index++) { darray[index] = array[index]; } @@ -153,10 +156,11 @@ } private long[] toLongArray() { - assert length <= array.length : "length exceeds internal array size"; + assert length() <= array.length : "length exceeds internal array size"; + final int len = (int)length(); final long[] larray = new long[array.length]; - for (int index = 0; index < length; index++) { + for (int index = 0; index < len; index++) { larray[index] = array[index]; } @@ -164,15 +168,15 @@ } private LongArrayData convertToLong() { - return new LongArrayData(toLongArray(), (int)length); + return new LongArrayData(toLongArray(), (int)length()); } private NumberArrayData convertToDouble() { - return new NumberArrayData(toDoubleArray(), (int)length); + return new NumberArrayData(toDoubleArray(), (int)length()); } private ObjectArrayData convertToObject() { - return new ObjectArrayData(toObjectArray(false), (int)length); + return new ObjectArrayData(toObjectArray(false), (int)length()); } @Override @@ -196,7 +200,7 @@ @Override public ArrayData shiftRight(final int by) { - final ArrayData newData = ensure(by + length - 1); + final ArrayData newData = ensure(by + length() - 1); if (newData != this) { newData.shiftRight(by); return newData; @@ -241,7 +245,7 @@ @Override public ArrayData set(final int index, final int value, final boolean strict) { array[index] = value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @@ -250,7 +254,7 @@ public ArrayData set(final int index, final long value, final boolean strict) { if (JSType.isRepresentableAsInt(value)) { array[index] = JSType.toInt32(value); - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @@ -261,7 +265,7 @@ public ArrayData set(final int index, final double value, final boolean strict) { if (JSType.isRepresentableAsInt(value)) { array[index] = (int)(long)value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @@ -305,7 +309,7 @@ @Override public boolean has(final int index) { - return 0 <= index && index < length; + return 0 <= index && index < length(); } @Override @@ -320,11 +324,12 @@ @Override public Object pop() { - if (length == 0) { + final int len = (int)length(); + if (len == 0) { return ScriptRuntime.UNDEFINED; } - final int newLength = (int)length - 1; + final int newLength = len - 1; final int elem = array[newLength]; array[newLength] = 0; setLength(newLength); @@ -334,12 +339,12 @@ @Override public ArrayData slice(final long from, final long to) { - return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)(to - (from < 0 ? from + length : from))); + return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)(to - (from < 0 ? from + length() : from))); } @Override public final ArrayData push(final boolean strict, final int item) { - final long len = length; + final long len = length(); final ArrayData newData = ensure(len); if (newData == this) { array[(int)len] = item; @@ -350,7 +355,7 @@ @Override public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { - final long oldLength = length; + final long oldLength = length(); final long newLength = oldLength - removed + added; if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { throw new UnsupportedOperationException(); @@ -384,21 +389,21 @@ @Override public long fastPush(final int arg) { - final int len = (int)length; + final int len = (int)length(); if (len == array.length) { array = Arrays.copyOf(array, nextSize(len)); } array[len] = arg; - return ++length; + return increaseLength(); } //length must not be zero @Override public int fastPopInt() { - if (length == 0) { + if (length() == 0) { throw new ClassCastException(); //relink } - final int newLength = (int)--length; + final int newLength = (int)decreaseLength(); final int elem = array[newLength]; array[newLength] = 0; return elem; @@ -421,8 +426,8 @@ @Override public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) { - final int otherLength = (int)otherData.length; - final int thisLength = (int)length; + final int otherLength = (int)otherData.length(); + final int thisLength = (int)length(); assert otherLength > 0 && thisLength > 0; final int[] otherArray = ((IntArrayData)otherData).array; @@ -437,7 +442,7 @@ @Override public String toString() { - assert length <= array.length : length + " > " + array.length; - return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length)); + assert length() <= array.length : length() + " > " + array.length; + return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length())); } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java Fri Nov 14 10:03:48 2014 -0800 @@ -0,0 +1,198 @@ +package jdk.nashorn.internal.runtime.arrays; + +import java.util.Iterator; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; +import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.runtime.ScriptRuntime; + +/** + * Filter to use for ArrayData where the length is not writable. + * The default behavior is just to ignore {@link ArrayData#setLength} + */ +final class LengthNotWritableFilter extends ArrayFilter { + private final SortedMap extraElements; //elements with index >= length + + /** + * Constructor + * @param underlying array + */ + LengthNotWritableFilter(final ArrayData underlying) { + this(underlying, new TreeMap()); + } + + private LengthNotWritableFilter(final ArrayData underlying, final SortedMap extraElements) { + super(underlying); + this.extraElements = extraElements; + } + + @Override + public ArrayData copy() { + return new LengthNotWritableFilter(underlying.copy(), new TreeMap<>(extraElements)); + } + + @Override + public boolean has(final int index) { + return super.has(index) || extraElements.containsKey((long)index); + } + + /** + * Set the length of the data array + * + * @param length the new length for the data array + */ + @Override + public void setLength(final long length) { + //empty - setting length for a LengthNotWritableFilter is always a nop + } + + @Override + public ArrayData ensure(final long index) { + return this; + } + + @Override + public ArrayData slice(final long from, final long to) { + //return array[from...to), or array[from...length] if undefined, in this case not as we are an ArrayData + return new LengthNotWritableFilter(underlying.slice(from, to), extraElements.subMap(from, to)); + } + + private boolean checkAdd(final long index, final Object value) { + if (index >= length()) { + extraElements.put(index, value); + return true; + } + return false; + } + + private Object get(final long index) { + final Object obj = extraElements.get(index); + if (obj == null) { + return ScriptRuntime.UNDEFINED; + } + return obj; + } + + @Override + public int getInt(final int index) { + if (index >= length()) { + return JSType.toInt32(get(index)); + } + return underlying.getInt(index); + } + + @Override + public int getIntOptimistic(final int index, final int programPoint) { + if (index >= length()) { + return JSType.toInt32Optimistic(get(index), programPoint); + } + return underlying.getIntOptimistic(index, programPoint); + } + + @Override + public long getLong(final int index) { + if (index >= length()) { + return JSType.toLong(get(index)); + } + return underlying.getLong(index); + } + + @Override + public long getLongOptimistic(final int index, final int programPoint) { + if (index >= length()) { + return JSType.toLongOptimistic(get(index), programPoint); + } + return underlying.getLongOptimistic(index, programPoint); + } + + @Override + public double getDouble(final int index) { + if (index >= length()) { + return JSType.toNumber(get(index)); + } + return underlying.getDouble(index); + } + + @Override + public double getDoubleOptimistic(final int index, final int programPoint) { + if (index >= length()) { + return JSType.toNumberOptimistic(get(index), programPoint); + } + return underlying.getDoubleOptimistic(index, programPoint); + } + + @Override + public Object getObject(final int index) { + if (index >= length()) { + return get(index); + } + return underlying.getObject(index); + } + + @Override + public ArrayData set(final int index, final Object value, final boolean strict) { + if (checkAdd(index, value)) { + return this; + } + underlying = underlying.set(index, value, strict); + return this; + } + + @Override + public ArrayData set(final int index, final int value, final boolean strict) { + if (checkAdd(index, value)) { + return this; + } + underlying = underlying.set(index, value, strict); + return this; + } + + @Override + public ArrayData set(final int index, final long value, final boolean strict) { + if (checkAdd(index, value)) { + return this; + } + underlying = underlying.set(index, value, strict); + return this; + } + + @Override + public ArrayData set(final int index, final double value, final boolean strict) { + if (checkAdd(index, value)) { + return this; + } + underlying = underlying.set(index, value, strict); + return this; + } + + @Override + public ArrayData delete(final int index) { + extraElements.remove(index); + underlying = underlying.delete(index); + return this; + } + + @Override + public ArrayData delete(final long fromIndex, final long toIndex) { + for (final Iterator iter = extraElements.keySet().iterator(); iter.hasNext();) { + final long next = iter.next(); + if (next >= fromIndex && next <= toIndex) { + iter.remove(); + } + if (next > toIndex) { //ordering guaranteed because TreeSet + break; + } + } + underlying = underlying.delete(fromIndex, toIndex); + return this; + } + + @Override + public Iterator indexIterator() { + final List keys = computeIteratorKeys(); + keys.addAll(extraElements.keySet()); //even if they are outside length this is fine + return keys.iterator(); + } + +} diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java --- a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,7 +27,6 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; import static jdk.nashorn.internal.lookup.Lookup.MH; - import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.Arrays; @@ -77,7 +76,7 @@ @Override public LongArrayData copy() { - return new LongArrayData(array.clone(), (int)length); + return new LongArrayData(array.clone(), (int)length()); } @Override @@ -86,10 +85,11 @@ } private Object[] toObjectArray(final boolean trim) { - assert length <= array.length : "length exceeds internal array size"; - final Object[] oarray = new Object[trim ? (int)length : array.length]; + assert length() <= array.length : "length exceeds internal array size"; + final int len = (int)length(); + final Object[] oarray = new Object[trim ? len : array.length]; - for (int index = 0; index < length; index++) { + for (int index = 0; index < len; index++) { oarray[index] = Long.valueOf(array[index]); } @@ -99,16 +99,18 @@ @Override public Object asArrayOfType(final Class componentType) { if (componentType == long.class) { - return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length); + final int len = (int)length(); + return array.length == len ? array.clone() : Arrays.copyOf(array, len); } return super.asArrayOfType(componentType); } private double[] toDoubleArray() { - assert length <= array.length : "length exceeds internal array size"; + assert length() <= array.length : "length exceeds internal array size"; + final int len = (int)length(); final double[] darray = new double[array.length]; - for (int index = 0; index < length; index++) { + for (int index = 0; index < len; index++) { darray[index] = array[index]; } @@ -120,7 +122,7 @@ if (type == Integer.class || type == Long.class) { return this; } - final int len = (int)length; + final int len = (int)length(); if (type == Double.class) { return new NumberArrayData(toDoubleArray(), len); } @@ -134,7 +136,7 @@ @Override public ArrayData shiftRight(final int by) { - final ArrayData newData = ensure(by + length - 1); + final ArrayData newData = ensure(by + length() - 1); if (newData != this) { newData.shiftRight(by); return newData; @@ -179,14 +181,14 @@ @Override public ArrayData set(final int index, final int value, final boolean strict) { array[index] = value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @Override public ArrayData set(final int index, final long value, final boolean strict) { array[index] = value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @@ -194,7 +196,7 @@ public ArrayData set(final int index, final double value, final boolean strict) { if (JSType.isRepresentableAsLong(value)) { array[index] = (long)value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } return convert(Double.class).set(index, value, strict); @@ -265,7 +267,7 @@ @Override public boolean has(final int index) { - return 0 <= index && index < length; + return 0 <= index && index < length(); } @Override @@ -280,11 +282,12 @@ @Override public Object pop() { - if (length == 0) { + final int len = (int)length(); + if (len == 0) { return ScriptRuntime.UNDEFINED; } - final int newLength = (int)length - 1; + final int newLength = len - 1; final long elem = array[newLength]; array[newLength] = 0; setLength(newLength); @@ -294,14 +297,14 @@ @Override public ArrayData slice(final long from, final long to) { - final long start = from < 0 ? from + length : from; + final long start = from < 0 ? from + length() : from; final long newLength = to - start; return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); } @Override public final ArrayData push(final boolean strict, final long item) { - final long len = length; + final long len = length(); final ArrayData newData = ensure(len); if (newData == this) { array[(int)len] = item; @@ -312,7 +315,7 @@ @Override public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { - final long oldLength = length; + final long oldLength = length(); final long newLength = oldLength - removed + added; if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { throw new UnsupportedOperationException(); @@ -345,20 +348,20 @@ @Override public long fastPush(final long arg) { - final int len = (int)length; + final int len = (int)length(); if (len == array.length) { array = Arrays.copyOf(array, nextSize(len)); } array[len] = arg; - return ++length; + return increaseLength(); } @Override public long fastPopLong() { - if (length == 0) { - throw new ClassCastException(); + if (length() == 0) { + throw new ClassCastException(); //undefined result } - final int newLength = (int)--length; + final int newLength = (int)decreaseLength(); final long elem = array[newLength]; array[newLength] = 0; return elem; @@ -376,8 +379,8 @@ @Override public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) { - final int otherLength = (int)otherData.length; - final int thisLength = (int)length; + final int otherLength = (int)otherData.length(); + final int thisLength = (int)length(); assert otherLength > 0 && thisLength > 0; final long[] otherArray = ((LongArrayData)otherData).array; @@ -392,13 +395,14 @@ @Override public String toString() { - assert length <= array.length : length + " > " + array.length; + assert length() <= array.length : length() + " > " + array.length; final StringBuilder sb = new StringBuilder(getClass().getSimpleName()). append(": ["); - for (int i = 0; i < length; i++) { + final int len = (int)length(); + for (int i = 0; i < len; i++) { sb.append(array[i]).append('L'); //make sure L suffix is on elements, to discriminate this from IntArrayData.toString() - if (i + 1 < length) { + if (i + 1 < len) { sb.append(", "); } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java --- a/src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java Fri Nov 14 10:03:48 2014 -0800 @@ -7,13 +7,13 @@ /** * Filter class that wrap arrays that have been tagged non extensible */ -public class NonExtensibleArrayFilter extends ArrayFilter { +final class NonExtensibleArrayFilter extends ArrayFilter { /** * Constructor * @param underlying array */ - public NonExtensibleArrayFilter(final ArrayData underlying) { + NonExtensibleArrayFilter(final ArrayData underlying) { super(underlying); } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java --- a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Fri Nov 14 10:03:48 2014 -0800 @@ -28,7 +28,6 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; - import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.Arrays; @@ -76,7 +75,7 @@ @Override public NumberArrayData copy() { - return new NumberArrayData(array.clone(), (int)length); + return new NumberArrayData(array.clone(), (int)length()); } @Override @@ -85,10 +84,11 @@ } private Object[] toObjectArray(final boolean trim) { - assert length <= array.length : "length exceeds internal array size"; - final Object[] oarray = new Object[trim ? (int)length : array.length]; + assert length() <= array.length : "length exceeds internal array size"; + final int len = (int)length(); + final Object[] oarray = new Object[trim ? len : array.length]; - for (int index = 0; index < length; index++) { + for (int index = 0; index < len; index++) { oarray[index] = Double.valueOf(array[index]); } return oarray; @@ -96,8 +96,9 @@ @Override public Object asArrayOfType(final Class componentType) { - if(componentType == double.class) { - return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length); + if (componentType == double.class) { + final int len = (int)length(); + return array.length == len ? array.clone() : Arrays.copyOf(array, len); } return super.asArrayOfType(componentType); } @@ -105,7 +106,7 @@ @Override public ContinuousArrayData convert(final Class type) { if (type != Double.class && type != Integer.class && type != Long.class) { - final int len = (int)length; + final int len = (int)length(); return new ObjectArrayData(toObjectArray(false), len); } return this; @@ -118,7 +119,7 @@ @Override public ArrayData shiftRight(final int by) { - final ArrayData newData = ensure(by + length - 1); + final ArrayData newData = ensure(by + length() - 1); if (newData != this) { newData.shiftRight(by); return newData; @@ -163,21 +164,21 @@ @Override public ArrayData set(final int index, final int value, final boolean strict) { array[index] = value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @Override public ArrayData set(final int index, final long value, final boolean strict) { array[index] = value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @Override public ArrayData set(final int index, final double value, final boolean strict) { array[index] = value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @@ -241,7 +242,7 @@ @Override public boolean has(final int index) { - return 0 <= index && index < length; + return 0 <= index && index < length(); } @Override @@ -256,11 +257,12 @@ @Override public Object pop() { - if (length == 0) { + final int len = (int)length(); + if (len == 0) { return UNDEFINED; } - final int newLength = (int)length - 1; + final int newLength = len - 1; final double elem = array[newLength]; array[newLength] = 0; setLength(newLength); @@ -269,14 +271,14 @@ @Override public ArrayData slice(final long from, final long to) { - final long start = from < 0 ? from + length : from; + final long start = from < 0 ? from + length() : from; final long newLength = to - start; return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); } @Override public final ArrayData push(final boolean strict, final double item) { - final long len = length; + final long len = length(); final ArrayData newData = ensure(len); if (newData == this) { array[(int)len] = item; @@ -287,7 +289,7 @@ @Override public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { - final long oldLength = length; + final long oldLength = length(); final long newLength = oldLength - removed + added; if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { throw new UnsupportedOperationException(); @@ -325,21 +327,21 @@ @Override public long fastPush(final double arg) { - final int len = (int)length; + final int len = (int)length(); if (len == array.length) { //note that fastpush never creates spares arrays, there is nothing to gain by that - it will just use even more memory array = Arrays.copyOf(array, nextSize(len)); } array[len] = arg; - return ++length; + return increaseLength(); } @Override public double fastPopDouble() { - if (length == 0) { + if (length() == 0) { throw new ClassCastException(); } - final int newLength = (int)--length; + final int newLength = (int)decreaseLength(); final double elem = array[newLength]; array[newLength] = 0; return elem; @@ -352,8 +354,8 @@ @Override public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) { - final int otherLength = (int)otherData.length; - final int thisLength = (int)length; + final int otherLength = (int)otherData.length(); + final int thisLength = (int)length(); assert otherLength > 0 && thisLength > 0; final double[] otherArray = ((NumberArrayData)otherData).array; @@ -368,7 +370,7 @@ @Override public String toString() { - assert length <= array.length : length + " > " + array.length; - return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length)); + assert length() <= array.length : length() + " > " + array.length; + return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length())); } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java --- a/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Fri Nov 14 10:03:48 2014 -0800 @@ -26,7 +26,6 @@ package jdk.nashorn.internal.runtime.arrays; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; - import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.Arrays; @@ -77,16 +76,16 @@ @Override public ObjectArrayData copy() { - return new ObjectArrayData(array.clone(), (int)length); + return new ObjectArrayData(array.clone(), (int)length()); } @Override public Object[] asObjectArray() { - return array.length == length ? array.clone() : asObjectArrayCopy(); + return array.length == length() ? array.clone() : asObjectArrayCopy(); } private Object[] asObjectArrayCopy() { - final long len = length; + final long len = length(); assert len <= Integer.MAX_VALUE; final Object[] copy = new Object[(int)len]; System.arraycopy(array, 0, copy, 0, (int)len); @@ -105,7 +104,7 @@ @Override public ArrayData shiftRight(final int by) { - final ArrayData newData = ensure(by + length - 1); + final ArrayData newData = ensure(by + length() - 1); if (newData != this) { newData.shiftRight(by); return newData; @@ -137,28 +136,28 @@ @Override public ArrayData set(final int index, final Object value, final boolean strict) { array[index] = value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @Override public ArrayData set(final int index, final int value, final boolean strict) { array[index] = value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @Override public ArrayData set(final int index, final long value, final boolean strict) { array[index] = value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @Override public ArrayData set(final int index, final double value, final boolean strict) { array[index] = value; - setLength(Math.max(index + 1, length)); + setLength(Math.max(index + 1, length())); return this; } @@ -231,7 +230,7 @@ @Override public boolean has(final int index) { - return 0 <= index && index < length; + return 0 <= index && index < length(); } @Override @@ -263,20 +262,20 @@ @Override public long fastPush(final Object arg) { - final int len = (int)length; + final int len = (int)length(); if (len == array.length) { array = Arrays.copyOf(array, nextSize(len)); } array[len] = arg; - return ++length; + return increaseLength(); } @Override public Object fastPopObject() { - if (length == 0) { + if (length() == 0) { return ScriptRuntime.UNDEFINED; } - final int newLength = (int)--length; + final int newLength = (int)decreaseLength(); final Object elem = array[newLength]; array[newLength] = ScriptRuntime.EMPTY; return elem; @@ -284,11 +283,11 @@ @Override public Object pop() { - if (length == 0) { + if (length() == 0) { return ScriptRuntime.UNDEFINED; } - final int newLength = (int)length - 1; + final int newLength = (int)length() - 1; final Object elem = array[newLength]; setEmpty(newLength); setLength(newLength); @@ -297,14 +296,14 @@ @Override public ArrayData slice(final long from, final long to) { - final long start = from < 0 ? from + length : from; + final long start = from < 0 ? from + length() : from; final long newLength = to - start; return new ObjectArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); } @Override public ArrayData push(final boolean strict, final Object item) { - final long len = length; + final long len = length(); final ArrayData newData = ensure(len); if (newData == this) { array[(int)len] = item; @@ -315,7 +314,7 @@ @Override public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { - final long oldLength = length; + final long oldLength = length(); final long newLength = oldLength - removed + added; if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { throw new UnsupportedOperationException(); @@ -343,8 +342,8 @@ @Override public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) { - final int otherLength = (int)otherData.length; - final int thisLength = (int)length; + final int otherLength = (int)otherData.length(); + final int thisLength = (int)length(); assert otherLength > 0 && thisLength > 0; final Object[] otherArray = ((ObjectArrayData)otherData).array; @@ -359,7 +358,7 @@ @Override public String toString() { - assert length <= array.length : length + " > " + array.length; - return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length)); + assert length() <= array.length : length() + " > " + array.length; + return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length())); } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java --- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Fri Nov 14 10:03:48 2014 -0800 @@ -36,7 +36,7 @@ * Handle arrays where the index is very large. */ class SparseArrayData extends ArrayData { - static final long MAX_DENSE_LENGTH = 16 * 512 * 1024; + static final int MAX_DENSE_LENGTH = 8 * 1024 * 1024; /** Underlying array. */ private ArrayData underlying; @@ -53,21 +53,21 @@ SparseArrayData(final ArrayData underlying, final long length, final TreeMap sparseMap) { super(length); - assert underlying.length <= length; + assert underlying.length() <= length; this.underlying = underlying; - this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length); + this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length()); this.sparseMap = sparseMap; } @Override public ArrayData copy() { - return new SparseArrayData(underlying.copy(), length, new TreeMap<>(sparseMap)); + return new SparseArrayData(underlying.copy(), length(), new TreeMap<>(sparseMap)); } @Override public Object[] asObjectArray() { - final int len = (int)Math.min(length, Integer.MAX_VALUE); - final int underlyingLength = (int)Math.min(len, underlying.length); + final int len = (int)Math.min(length(), Integer.MAX_VALUE); + final int underlyingLength = (int)Math.min(len, underlying.length()); final Object[] objArray = new Object[len]; for (int i = 0; i < underlyingLength; i++) { @@ -104,14 +104,15 @@ } sparseMap = newSparseMap; - setLength(Math.max(length - by, 0)); + setLength(Math.max(length() - by, 0)); } @Override public ArrayData shiftRight(final int by) { final TreeMap newSparseMap = new TreeMap<>(); - if (underlying.length + by > maxDenseLength) { - for (long i = maxDenseLength - by; i < underlying.length; i++) { + final long len = underlying.length(); + if (len + by > maxDenseLength) { + for (long i = maxDenseLength - by; i < len; i++) { if (underlying.has((int) i)) { newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i)); } @@ -127,23 +128,23 @@ } sparseMap = newSparseMap; - setLength(length + by); + setLength(length() + by); return this; } @Override public ArrayData ensure(final long safeIndex) { - if (safeIndex < maxDenseLength && underlying.length <= safeIndex) { + if (safeIndex < maxDenseLength && underlying.length() <= safeIndex) { underlying = underlying.ensure(safeIndex); } - setLength(Math.max(safeIndex + 1, length)); + setLength(Math.max(safeIndex + 1, length())); return this; } @Override public ArrayData shrink(final long newLength) { - if (newLength < underlying.length) { + if (newLength < underlying.length()) { underlying = underlying.shrink(newLength); underlying.setLength(newLength); sparseMap.clear(); @@ -160,11 +161,11 @@ if (index >= 0 && index < maxDenseLength) { ensure(index); underlying = underlying.set(index, value, strict); - setLength(Math.max(underlying.length, length)); + setLength(Math.max(underlying.length(), length())); } else { final Long longIndex = indexToKey(index); sparseMap.put(longIndex, value); - setLength(Math.max(longIndex + 1, length)); + setLength(Math.max(longIndex + 1, length())); } return this; @@ -175,11 +176,11 @@ if (index >= 0 && index < maxDenseLength) { ensure(index); underlying = underlying.set(index, value, strict); - setLength(Math.max(underlying.length, length)); + setLength(Math.max(underlying.length(), length())); } else { final Long longIndex = indexToKey(index); sparseMap.put(longIndex, value); - setLength(Math.max(longIndex + 1, length)); + setLength(Math.max(longIndex + 1, length())); } return this; } @@ -189,11 +190,11 @@ if (index >= 0 && index < maxDenseLength) { ensure(index); underlying = underlying.set(index, value, strict); - setLength(Math.max(underlying.length, length)); + setLength(Math.max(underlying.length(), length())); } else { final Long longIndex = indexToKey(index); sparseMap.put(longIndex, value); - setLength(Math.max(longIndex + 1, length)); + setLength(Math.max(longIndex + 1, length())); } return this; } @@ -203,11 +204,11 @@ if (index >= 0 && index < maxDenseLength) { ensure(index); underlying = underlying.set(index, value, strict); - setLength(Math.max(underlying.length, length)); + setLength(Math.max(underlying.length(), length())); } else { final Long longIndex = indexToKey(index); sparseMap.put(longIndex, value); - setLength(Math.max(longIndex + 1, length)); + setLength(Math.max(longIndex + 1, length())); } return this; } @@ -294,7 +295,7 @@ @Override public boolean has(final int index) { if (index >= 0 && index < maxDenseLength) { - return index < underlying.length && underlying.has(index); + return index < underlying.length() && underlying.has(index); } return sparseMap.containsKey(indexToKey(index)); @@ -303,7 +304,7 @@ @Override public ArrayData delete(final int index) { if (index >= 0 && index < maxDenseLength) { - if (index < underlying.length) { + if (index < underlying.length()) { underlying = underlying.delete(index); } } else { @@ -315,8 +316,8 @@ @Override public ArrayData delete(final long fromIndex, final long toIndex) { - if (fromIndex < maxDenseLength && fromIndex < underlying.length) { - underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length - 1)); + if (fromIndex < maxDenseLength && fromIndex < underlying.length()) { + underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length() - 1)); } if (toIndex >= maxDenseLength) { sparseMap.subMap(fromIndex, true, toIndex, true).clear(); @@ -336,30 +337,34 @@ @Override public Object pop() { - if (length == 0) { + final long len = length(); + final long underlyingLen = underlying.length(); + if (len == 0) { return ScriptRuntime.UNDEFINED; } - if (length == underlying.length) { + if (len == underlyingLen) { final Object result = underlying.pop(); - setLength(underlying.length); + setLength(underlying.length()); return result; } - setLength(length - 1); - final Long key = Long.valueOf(length); + setLength(len - 1); + final Long key = Long.valueOf(len - 1); return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED; } @Override public ArrayData slice(final long from, final long to) { - assert to <= length; - final long start = from < 0 ? (from + length) : from; + assert to <= length(); + final long start = from < 0 ? (from + length()) : from; final long newLength = to - start; + final long underlyingLength = underlying.length(); + if (start >= 0 && to <= maxDenseLength) { - if (newLength <= underlying.length) { + if (newLength <= underlyingLength) { return underlying.slice(from, to); } - return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length, newLength); + return underlying.slice(from, to).ensure(newLength - 1).delete(underlyingLength, newLength); } ArrayData sliced = EMPTY_ARRAY; @@ -369,13 +374,13 @@ sliced = sliced.set((int)(i - start), getObject((int)i), false); } } - assert sliced.length == newLength; + assert sliced.length() == newLength; return sliced; } @Override public long nextIndex(final long index) { - if (index < underlying.length - 1) { + if (index < underlying.length() - 1) { return underlying.nextIndex(index); } @@ -383,6 +388,7 @@ if (nextKey != null) { return nextKey; } - return length; + + return length(); } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java --- a/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Fri Nov 14 10:03:48 2014 -0800 @@ -58,7 +58,7 @@ * @return element length */ public final int getElementLength() { - return (int)length; + return (int)length(); } /** @@ -119,7 +119,7 @@ @Override public final boolean has(final int index) { - return 0 <= index && index < length; + return 0 <= index && index < length(); } @Override diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java --- a/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Fri Nov 14 10:03:48 2014 -0800 @@ -39,8 +39,7 @@ UndefinedArrayFilter(final ArrayData underlying) { super(underlying); - - this.undefined = new BitVector(underlying.length); + this.undefined = new BitVector(underlying.length()); } @Override @@ -80,25 +79,24 @@ @Override public void shiftLeft(final int by) { super.shiftLeft(by); - undefined.shiftLeft(by, length); + undefined.shiftLeft(by, length()); } @Override public ArrayData shiftRight(final int by) { super.shiftRight(by); - undefined.shiftRight(by, length); - + undefined.shiftRight(by, length()); return this; } @Override public ArrayData ensure(final long safeIndex) { - if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) { + if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) { return new SparseArrayData(this, safeIndex + 1); } super.ensure(safeIndex); - undefined.resize(length); + undefined.resize(length()); return this; } @@ -106,8 +104,7 @@ @Override public ArrayData shrink(final long newLength) { super.shrink(newLength); - undefined.resize(length); - + undefined.resize(length()); return this; } @@ -216,7 +213,7 @@ @Override public Object pop() { - final long index = length - 1; + final long index = length() - 1; if (super.has((int)index)) { final boolean isUndefined = undefined.isSet(index); @@ -233,7 +230,7 @@ final ArrayData newArray = underlying.slice(from, to); final UndefinedArrayFilter newFilter = new UndefinedArrayFilter(newArray); newFilter.getUndefined().copy(undefined); - newFilter.getUndefined().shiftLeft(from, newFilter.length); + newFilter.getUndefined().shiftLeft(from, newFilter.length()); return newFilter; } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java --- a/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java Fri Nov 14 10:03:48 2014 -0800 @@ -47,10 +47,9 @@ * @param level logging level * @param rewriteException rewriteException wrapped by this RuntimEvent * @param returnValue rewriteException return value - as we don't want to make - * {@link RewriteException#getReturnValueNonDestructive()} public, we pass it as + * {@code RewriteException.getReturnValueNonDestructive()} public, we pass it as * an extra parameter, rather than querying the getter from another package. */ - @SuppressWarnings("javadoc") public RecompilationEvent(final Level level, final RewriteException rewriteException, final Object returnValue) { super(level, rewriteException); assert Context.getContext().getLogger(RecompilableScriptFunctionData.class).isEnabled() : diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/linker/Bootstrap.java --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Fri Nov 14 10:03:48 2014 -0800 @@ -42,6 +42,8 @@ import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.linker.LinkerServices; +import jdk.internal.dynalink.linker.MethodTypeConversionStrategy; +import jdk.internal.dynalink.support.TypeUtilities; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.codegen.ObjectClassGenerator; @@ -106,6 +108,12 @@ return OptimisticReturnFilters.filterOptimisticReturnValue(inv, desc).asType(linkerServices, desc.getMethodType()); } }); + factory.setAutoConversionStrategy(new MethodTypeConversionStrategy() { + @Override + public MethodHandle asType(final MethodHandle target, final MethodType newType) { + return unboxReturnType(target, newType); + } + }); final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD); if (relinkThreshold > -1) { factory.setUnstableRelinkThreshold(relinkThreshold); @@ -420,4 +428,29 @@ static GuardedInvocation asTypeSafeReturn(final GuardedInvocation inv, final LinkerServices linkerServices, final CallSiteDescriptor desc) { return inv == null ? null : inv.asTypeSafeReturn(linkerServices, desc.getMethodType()); } + + /** + * Adapts the return type of the method handle with {@code explicitCastArguments} when it is an unboxing + * conversion. This will ensure that nulls are unwrapped to false or 0. + * @param target the target method handle + * @param newType the desired new type. Note that this method does not adapt the method handle completely to the + * new type, it only adapts the return type; this is allowed as per + * {@link DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)}, which is what this method + * is used for. + * @return the method handle with adapted return type, if it required an unboxing conversion. + */ + private static MethodHandle unboxReturnType(final MethodHandle target, final MethodType newType) { + final MethodType targetType = target.type(); + final Class oldReturnType = targetType.returnType(); + if (TypeUtilities.isWrapperType(oldReturnType)) { + final Class newReturnType = newType.returnType(); + if (newReturnType.isPrimitive()) { + // The contract of setAutoConversionStrategy is such that the difference between newType and targetType + // can only be JLS method invocation conversions. + assert TypeUtilities.isMethodInvocationConvertible(oldReturnType, newReturnType); + return MethodHandles.explicitCastArguments(target, targetType.changeReturnType(newReturnType)); + } + } + return target; + } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,8 +25,10 @@ package jdk.nashorn.internal.runtime.linker; -import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.*; - +import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETMEMBER; +import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETSLOT; +import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETMEMBER; +import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETSLOT; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import jdk.internal.dynalink.CallSiteDescriptor; @@ -114,12 +116,10 @@ case "getMethod": if (c > 2) { return findGetMethod(desc); - } else { - // For indexed get, we want GuardedInvocation from beans linker and pass it. - // BrowserJSObjectLinker.get uses this fallback getter for explicit signature method access. - final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices); - return findGetIndexMethod(beanInv); } + // For indexed get, we want GuardedInvocation from beans linker and pass it. + // BrowserJSObjectLinker.get uses this fallback getter for explicit signature method access. + return findGetIndexMethod(nashornBeansLinker.getGuardedInvocation(request, linkerServices)); case "setProp": case "setElem": return c > 2 ? findSetMethod(desc) : findSetIndexMethod(); @@ -166,9 +166,8 @@ final String name = (String)key; if (name.indexOf('(') != -1) { return fallback.invokeExact(jsobj, key); - } else { - return JSOBJECT_GETMEMBER.invokeExact(jsobj, (String)key); } + return JSOBJECT_GETMEMBER.invokeExact(jsobj, (String)key); } return null; } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Fri Nov 14 10:03:48 2014 -0800 @@ -120,12 +120,10 @@ case "getMethod": if (c > 2) { return findGetMethod(desc); - } else { - // For indexed get, we want get GuardedInvocation beans linker and pass it. - // JSObjectLinker.get uses this fallback getter for explicit signature method access. - final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices); - return findGetIndexMethod(beanInv); } + // For indexed get, we want get GuardedInvocation beans linker and pass it. + // JSObjectLinker.get uses this fallback getter for explicit signature method access. + return findGetIndexMethod(nashornBeansLinker.getGuardedInvocation(request, linkerServices)); case "setProp": case "setElem": return c > 2 ? findSetMethod(desc) : findSetIndexMethod(); @@ -192,9 +190,8 @@ // get with method name and signature. delegate it to beans linker! if (name.indexOf('(') != -1) { return fallback.invokeExact(jsobj, key); - } else { - return ((JSObject)jsobj).getMember(name); } + return ((JSObject)jsobj).getMember(name); } return null; } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Fri Nov 14 10:03:48 2014 -0800 @@ -53,15 +53,34 @@ // Object type arguments of Java method calls, field set and array set. private static final boolean MIRROR_ALWAYS = Options.getBooleanProperty("nashorn.mirror.always", true); - private static final MethodHandle EXPORT_ARGUMENT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportArgument", Object.class, Object.class); - private static final MethodHandle EXPORT_NATIVE_ARRAY = new Lookup(MethodHandles.lookup()).findOwnStatic("exportNativeArray", Object.class, NativeArray.class); - private static final MethodHandle EXPORT_SCRIPT_OBJECT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportScriptObject", Object.class, ScriptObject.class); - private static final MethodHandle IMPORT_RESULT = new Lookup(MethodHandles.lookup()).findOwnStatic("importResult", Object.class, Object.class); + private static final MethodHandle EXPORT_ARGUMENT; + private static final MethodHandle EXPORT_NATIVE_ARRAY; + private static final MethodHandle EXPORT_SCRIPT_OBJECT; + private static final MethodHandle IMPORT_RESULT; + private static final MethodHandle FILTER_CONSSTRING; + + static { + final Lookup lookup = new Lookup(MethodHandles.lookup()); + EXPORT_ARGUMENT = lookup.findOwnStatic("exportArgument", Object.class, Object.class); + EXPORT_NATIVE_ARRAY = lookup.findOwnStatic("exportNativeArray", Object.class, NativeArray.class); + EXPORT_SCRIPT_OBJECT = lookup.findOwnStatic("exportScriptObject", Object.class, ScriptObject.class); + IMPORT_RESULT = lookup.findOwnStatic("importResult", Object.class, Object.class); + FILTER_CONSSTRING = lookup.findOwnStatic("consStringFilter", Object.class, Object.class); + } private final BeansLinker beansLinker = new BeansLinker(); @Override public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { + if (linkRequest.getReceiver() instanceof ConsString) { + // In order to treat ConsString like a java.lang.String we need a link request with a string receiver. + final Object[] arguments = linkRequest.getArguments(); + arguments[0] = ""; + final LinkRequest forgedLinkRequest = linkRequest.replaceArguments(linkRequest.getCallSiteDescriptor(), arguments); + final GuardedInvocation invocation = getGuardedInvocation(beansLinker, forgedLinkRequest, linkerServices); + // If an invocation is found we add a filter that makes it work for both Strings and ConsStrings. + return invocation == null ? null : invocation.filterArguments(0, FILTER_CONSSTRING); + } return getGuardedInvocation(beansLinker, linkRequest, linkerServices); } @@ -113,6 +132,11 @@ return ScriptUtils.unwrap(arg); } + @SuppressWarnings("unused") + private static Object consStringFilter(final Object arg) { + return arg instanceof ConsString ? arg.toString() : arg; + } + private static class NashornBeansLinkerServices implements LinkerServices { private final LinkerServices linkerServices; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,7 +27,6 @@ import static jdk.nashorn.internal.runtime.regexp.joni.Option.isMultiline; import static jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode.newAltNode; import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepeatInfinite; - import java.util.HashSet; import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode; @@ -53,6 +52,7 @@ super(env, chars, p, end); } + @SuppressWarnings("unused") protected final void compile() { if (Config.DEBUG) { Config.log.println(new String(chars, getBegin(), getEnd())); @@ -76,7 +76,9 @@ root = setupTree(root, 0); if (Config.DEBUG_PARSE_TREE) { - if (Config.DEBUG_PARSE_TREE_RAW) Config.log.println(""); + if (Config.DEBUG_PARSE_TREE_RAW) { + Config.log.println(""); + } root.verifyTree(new HashSet(), env.reg.warnings); Config.log.println(root + "\n"); } @@ -94,7 +96,9 @@ regex.clearOptimizeInfo(); - if (!Config.DONT_OPTIMIZE) setOptimizedInfoFromTree(root); + if (!Config.DONT_OPTIMIZE) { + setOptimizedInfoFromTree(root); + } env.memNodes = null; @@ -110,7 +114,9 @@ if (Config.DEBUG_COMPILE) { Config.log.println("stack used: " + regex.stackNeeded); - if (Config.USE_STRING_TEMPLATES) Config.log.print("templates: " + regex.templateNum + "\n"); + if (Config.USE_STRING_TEMPLATES) { + Config.log.print("templates: " + regex.templateNum + "\n"); + } Config.log.println(new ByteCodePrinter(regex).byteCodeListToString()); } // DEBUG_COMPILE @@ -136,7 +142,9 @@ ConsAltNode can = (ConsAltNode)node; do { final int v = quantifiersMemoryInfo(can.car); - if (v > info) info = v; + if (v > info) { + info = v; + } } while ((can = can.cdr) != null); break; @@ -182,7 +190,9 @@ switch (node.getType()) { case NodeType.BREF: final BackRefNode br = (BackRefNode)node; - if (br.isRecursion()) break; + if (br.isRecursion()) { + break; + } if (br.backRef > env.numMem) { throw new ValueException(ERR_INVALID_BACKREF); @@ -249,6 +259,9 @@ case EncloseType.STOP_BACKTRACK: min = getMinMatchLength(en.target); break; + + default: + break; } // inner switch break; @@ -276,7 +289,9 @@ ConsAltNode an = (ConsAltNode)node; do { final int tmax = getMaxMatchLength(an.car); - if (max < tmax) max = tmax; + if (max < tmax) { + max = tmax; + } } while ((an = an.cdr) != null); break; @@ -304,7 +319,9 @@ throw new ValueException(ERR_INVALID_BACKREF); } final int tmax = getMaxMatchLength(env.memNodes[br.backRef]); - if (max < tmax) max = tmax; + if (max < tmax) { + max = tmax; + } break; case NodeType.QTFR: @@ -338,6 +355,9 @@ case EncloseType.STOP_BACKTRACK: max = getMaxMatchLength(en.target); break; + + default: + break; } // inner switch break; @@ -355,8 +375,8 @@ return getCharLengthTree(node, 0); } - private int getCharLengthTree(final Node node, int level) { - level++; + private int getCharLengthTree(final Node node, final int levelp) { + final int level = levelp + 1; int len = 0; returnCode = 0; @@ -366,7 +386,9 @@ ConsAltNode ln = (ConsAltNode)node; do { final int tlen = getCharLengthTree(ln.car, level); - if (returnCode == 0) len = MinMaxLen.distanceAdd(len, tlen); + if (returnCode == 0) { + len = MinMaxLen.distanceAdd(len, tlen); + } } while (returnCode == 0 && (ln = ln.cdr) != null); break; @@ -378,7 +400,9 @@ while (returnCode == 0 && (an = an.cdr) != null) { final int tlen2 = getCharLengthTree(an.car, level); if (returnCode == 0) { - if (tlen != tlen2) varLen = true; + if (tlen != tlen2) { + varLen = true; + } } } @@ -404,7 +428,9 @@ final QuantifierNode qn = (QuantifierNode)node; if (qn.lower == qn.upper) { tlen = getCharLengthTree(qn.target, level); - if (returnCode == 0) len = MinMaxLen.distanceMultiply(tlen, qn.lower); + if (returnCode == 0) { + len = MinMaxLen.distanceMultiply(tlen, qn.lower); + } } else { returnCode = GET_CHAR_LEN_VARLEN; } @@ -435,6 +461,9 @@ case EncloseType.STOP_BACKTRACK: len = getCharLengthTree(en.target, level); break; + + default: + break; } // inner switch break; @@ -448,7 +477,9 @@ } /* x is not included y ==> 1 : 0 */ - private boolean isNotIncluded(Node x, Node y) { + private static boolean isNotIncluded(final Node xn, final Node yn) { + Node x = xn; + Node y = yn; Node tmp; // !retry:! @@ -492,10 +523,14 @@ boolean v = xc.bs.at(i); if ((v && !xc.isNot()) || (!v && xc.isNot())) { v = yc.bs.at(i); - if ((v && !yc.isNot()) || (!v && yc.isNot())) return false; + if ((v && !yc.isNot()) || (!v && yc.isNot())) { + return false; + } } } - if ((xc.mbuf == null && !xc.isNot()) || yc.mbuf == null && !yc.isNot()) return true; + if ((xc.mbuf == null && !xc.isNot()) || yc.mbuf == null && !yc.isNot()) { + return true; + } return false; // break; not reached @@ -514,7 +549,9 @@ case NodeType.STR: final StringNode xs = (StringNode)x; - if (xs.length() == 0) break; + if (xs.length() == 0) { + break; + } switch (yType) { @@ -526,13 +563,16 @@ case NodeType.STR: final StringNode ys = (StringNode)y; int len = xs.length(); - if (len > ys.length()) len = ys.length(); + if (len > ys.length()) { + len = ys.length(); + } if (xs.isAmbig() || ys.isAmbig()) { /* tiny version */ return false; - } else { - for (int i=0, p=ys.p, q=xs.p; i (?<=A)|(?<=B) (? (?= sbuf.length) { final char[]tmp = new char[sbuf.length << 1]; System.arraycopy(sbuf, 0, tmp, 0, sbuf.length); @@ -798,8 +862,8 @@ updateStringNodeCaseFoldMultiByte(sn); } - private Node expandCaseFoldMakeRemString(final char[] chars, final int p, final int end) { - final StringNode node = new StringNode(chars, p, end); + private Node expandCaseFoldMakeRemString(final char[] ch, final int pp, final int end) { + final StringNode node = new StringNode(ch, pp, end); updateStringNodeCaseFold(node); node.setAmbig(); @@ -807,7 +871,7 @@ return node; } - private boolean expandCaseFoldStringAlt(final int itemNum, final char[] items, + private static boolean expandCaseFoldStringAlt(final int itemNum, final char[] items, final char[] chars, final int p, final int slen, final int end, final ObjPtr node) { ConsAltNode altNode; @@ -833,59 +897,68 @@ private Node expandCaseFoldString(final Node node) { final StringNode sn = (StringNode)node; - if (sn.isAmbig() || sn.length() <= 0) return node; + if (sn.isAmbig() || sn.length() <= 0) { + return node; + } - final char[] chars = sn.chars; - int p = sn.p; + final char[] chars1 = sn.chars; + int pt = sn.p; final int end = sn.end; int altNum = 1; - ConsAltNode topRoot = null, root = null; + ConsAltNode topRoot = null, r = null; + @SuppressWarnings("unused") final ObjPtr prevNode = new ObjPtr(); StringNode stringNode = null; - while (p < end) { - final char[] items = EncodingHelper.caseFoldCodesByString(regex.caseFoldFlag, chars[p]); + while (pt < end) { + final char[] items = EncodingHelper.caseFoldCodesByString(regex.caseFoldFlag, chars1[pt]); if (items.length == 0) { if (stringNode == null) { - if (root == null && prevNode.p != null) { - topRoot = root = ConsAltNode.listAdd(null, prevNode.p); + if (r == null && prevNode.p != null) { + topRoot = r = ConsAltNode.listAdd(null, prevNode.p); } prevNode.p = stringNode = new StringNode(); // onig_node_new_str(NULL, NULL); - if (root != null) ConsAltNode.listAdd(root, stringNode); + if (r != null) { + ConsAltNode.listAdd(r, stringNode); + } } - stringNode.cat(chars, p, p + 1); + stringNode.cat(chars1, pt, pt + 1); } else { altNum *= (items.length + 1); - if (altNum > THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION) break; - - if (root == null && prevNode.p != null) { - topRoot = root = ConsAltNode.listAdd(null, prevNode.p); + if (altNum > THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION) { + break; } - expandCaseFoldStringAlt(items.length, items, chars, p, 1, end, prevNode); - if (root != null) ConsAltNode.listAdd(root, prevNode.p); + if (r == null && prevNode.p != null) { + topRoot = r = ConsAltNode.listAdd(null, prevNode.p); + } + + expandCaseFoldStringAlt(items.length, items, chars1, pt, 1, end, prevNode); + if (r != null) { + ConsAltNode.listAdd(r, prevNode.p); + } stringNode = null; } - p++; + pt++; } - if (p < end) { - final Node srem = expandCaseFoldMakeRemString(chars, p, end); + if (pt < end) { + final Node srem = expandCaseFoldMakeRemString(chars1, pt, end); - if (prevNode.p != null && root == null) { - topRoot = root = ConsAltNode.listAdd(null, prevNode.p); + if (prevNode.p != null && r == null) { + topRoot = r = ConsAltNode.listAdd(null, prevNode.p); } - if (root == null) { + if (r == null) { prevNode.p = srem; } else { - ConsAltNode.listAdd(root, srem); + ConsAltNode.listAdd(r, srem); } } /* ending */ @@ -909,7 +982,10 @@ 5. find invalid patterns in look-behind. 6. expand repeated string. */ - protected final Node setupTree(Node node, int state) { + protected final Node setupTree(final Node nodep, final int statep) { + Node node = nodep; + int state = statep; + restart: while (true) { switch (node.getType()) { case NodeType.LIST: @@ -958,7 +1034,9 @@ final QuantifierNode qn = (QuantifierNode)node; Node target = qn.target; - if ((state & IN_REPEAT) != 0) qn.setInRepeat(); + if ((state & IN_REPEAT) != 0) { + qn.setInRepeat(); + } if (isRepeatInfinite(qn.upper) || qn.lower >= 1) { final int d = getMinMatchLength(target); @@ -966,14 +1044,18 @@ qn.targetEmptyInfo = TargetInfo.IS_EMPTY; if (Config.USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT) { final int info = quantifiersMemoryInfo(target); - if (info > 0) qn.targetEmptyInfo = info; + if (info > 0) { + qn.targetEmptyInfo = info; + } } // USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK // strange stuff here (turned off) } } state |= IN_REPEAT; - if (qn.lower != qn.upper) state |= IN_VAR_REPEAT; + if (qn.lower != qn.upper) { + state |= IN_VAR_REPEAT; + } target = setupTree(target, state); @@ -1035,11 +1117,16 @@ final QuantifierNode tqn = (QuantifierNode)en.target; if (isRepeatInfinite(tqn.upper) && tqn.lower <= 1 && tqn.greedy) { /* (?>a*), a*+ etc... */ - if (tqn.target.isSimple()) en.setStopBtSimpleRepeat(); + if (tqn.target.isSimple()) { + en.setStopBtSimpleRepeat(); + } } } break; + default: + break; + } // inner switch break; @@ -1059,7 +1146,9 @@ throw new SyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN); } node = setupLookBehind(node); - if (node.getType() != NodeType.ANCHOR) continue restart; + if (node.getType() != NodeType.ANCHOR) { + continue restart; + } setupTree(((AnchorNode)node).target, state); break; @@ -1068,12 +1157,19 @@ throw new SyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN); } node = setupLookBehind(node); - if (node.getType() != NodeType.ANCHOR) continue restart; + if (node.getType() != NodeType.ANCHOR) { + continue restart; + } setupTree(((AnchorNode)node).target, (state | IN_NOT)); break; + default: + break; + } // inner switch break; + default: + break; } // switch return node; } // restart: while @@ -1191,7 +1287,9 @@ opt.expr.copy(nopt.exm); } opt.expr.reachEnd = false; - if (nopt.map.value > 0) opt.map.copy(nopt.map); + if (nopt.map.value > 0) { + opt.map.copy(nopt.map); + } break; case AnchorType.PREC_READ_NOT: @@ -1199,6 +1297,9 @@ case AnchorType.LOOK_BEHIND_NOT: break; + default: + break; + } // inner switch break; } @@ -1282,8 +1383,12 @@ if (++en.optCount > MAX_NODE_OPT_INFO_REF_COUNT) { int min = 0; int max = MinMaxLen.INFINITE_DISTANCE; - if (en.isMinFixed()) min = en.minLength; - if (en.isMaxFixed()) max = en.maxLength; + if (en.isMinFixed()) { + min = en.minLength; + } + if (en.isMaxFixed()) { + max = en.maxLength; + } opt.length.set(min, max); } else { // USE_SUBEXP_CALL optimizeNodeLeft(en.target, opt, oenv); @@ -1298,6 +1403,9 @@ case EncloseType.STOP_BACKTRACK: optimizeNodeLeft(en.target, opt, oenv); break; + + default: + break; } // inner switch break; } @@ -1307,6 +1415,7 @@ } // switch } + @SuppressWarnings("unused") protected final void setOptimizedInfoFromTree(final Node node) { final NodeOptInfo opt = new NodeOptInfo(); final OptEnvironment oenv = new OptEnvironment(); @@ -1347,7 +1456,9 @@ regex.setSubAnchor(opt.map.anchor); } else { regex.subAnchor |= opt.anchor.leftAnchor & AnchorType.BEGIN_LINE; - if (opt.length.max == 0) regex.subAnchor |= opt.anchor.rightAnchor & AnchorType.END_LINE; + if (opt.length.max == 0) { + regex.subAnchor |= opt.anchor.rightAnchor & AnchorType.END_LINE; + } } if (Config.DEBUG_COMPILE || Config.DEBUG_MATCH) { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java Fri Nov 14 10:03:48 2014 -0800 @@ -24,7 +24,7 @@ final class ApplyCaseFold { // i_apply_case_fold - public void apply(final int from, final int to, final Object o) { + public static void apply(final int from, final int to, final Object o) { final ApplyCaseFoldArg arg = (ApplyCaseFoldArg)o; final ScanEnvironment env = arg.env; @@ -45,7 +45,9 @@ } else { if (inCC) { if (to >= BitSet.SINGLE_BYTE_SIZE) { - if (cc.isNot()) cc.clearNotFlag(); + if (cc.isNot()) { + cc.clearNotFlag(); + } cc.addCodeRange(env, to, to); } else { if (cc.isNot()) { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java Fri Nov 14 10:03:48 2014 -0800 @@ -22,6 +22,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode; +@SuppressWarnings("javadoc") public final class ApplyCaseFoldArg { final ScanEnvironment env; final CClassNode cc; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java Fri Nov 14 10:03:48 2014 -0800 @@ -24,7 +24,6 @@ import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase; import static jdk.nashorn.internal.runtime.regexp.joni.Option.isMultiline; import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepeatInfinite; - import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode; @@ -98,15 +97,15 @@ } while ((aln = aln.cdr) != null); } - private boolean isNeedStrLenOpExact(final int op) { + private static boolean isNeedStrLenOpExact(final int op) { return op == OPCode.EXACTN || op == OPCode.EXACTN_IC; } - private boolean opTemplated(final int op) { + private static boolean opTemplated(final int op) { return isNeedStrLenOpExact(op); } - private int selectStrOpcode(final int strLength, final boolean ignoreCase) { + private static int selectStrOpcode(final int strLength, final boolean ignoreCase) { int op; if (ignoreCase) { @@ -139,7 +138,7 @@ compileTree(node); if (emptyInfo != 0) { - switch(emptyInfo) { + switch (emptyInfo) { case TargetInfo.IS_EMPTY: addOpcode(OPCode.NULL_CHECK_END); break; @@ -149,13 +148,15 @@ case TargetInfo.IS_EMPTY_REC: addOpcode(OPCode.NULL_CHECK_END_MEMST_PUSH); break; + default: + break; } // switch addMemNum(savedNumNullCheck); /* NULL CHECK ID */ } } - private int addCompileStringlength(final char[] chars, final int p, final int strLength, final boolean ignoreCase) { + private static int addCompileStringlength(final char[] chars, final int p, final int strLength, final boolean ignoreCase) { final int op = selectStrOpcode(strLength, ignoreCase); int len = OPSize.OPCODE; @@ -163,7 +164,9 @@ // string length, template index, template string pointer len += OPSize.LENGTH + OPSize.INDEX + OPSize.INDEX; } else { - if (isNeedStrLenOpExact(op)) len += OPSize.LENGTH; + if (isNeedStrLenOpExact(op)) { + len += OPSize.LENGTH; + } len += strLength; } return len; @@ -187,9 +190,11 @@ } } - private int compileLengthStringNode(final Node node) { + private static int compileLengthStringNode(final Node node) { final StringNode sn = (StringNode)node; - if (sn.length() <= 0) return 0; + if (sn.length() <= 0) { + return 0; + } final boolean ambig = sn.isAmbig(); int p, prev; @@ -210,8 +215,10 @@ return rlen; } - private int compileLengthStringRawNode(final StringNode sn) { - if (sn.length() <= 0) return 0; + private static int compileLengthStringRawNode(final StringNode sn) { + if (sn.length() <= 0) { + return 0; + } return addCompileStringlength(sn.chars, sn.p, sn.length(), false); } @@ -220,8 +227,10 @@ addInts(mbuf.p, mbuf.used); } - private int compileLengthCClassNode(final CClassNode cc) { - if (cc.isShare()) return OPSize.OPCODE + OPSize.POINTER; + private static int compileLengthCClassNode(final CClassNode cc) { + if (cc.isShare()) { + return OPSize.OPCODE + OPSize.POINTER; + } int len; if (cc.mbuf == null) { @@ -360,9 +369,8 @@ if (qn.greedy && infinite) { if (qn.nextHeadExact != null) { return OPSize.ANYCHAR_STAR_PEEK_NEXT + tlen * qn.lower; - } else { - return OPSize.ANYCHAR_STAR + tlen * qn.lower; } + return OPSize.ANYCHAR_STAR + tlen * qn.lower; } } @@ -425,14 +433,13 @@ final StringNode sn = (StringNode)qn.nextHeadExact; addChars(sn.chars, sn.p, 1); return; + } + if (isMultiline(regex.options)) { + addOpcode(OPCode.ANYCHAR_ML_STAR); } else { - if (isMultiline(regex.options)) { - addOpcode(OPCode.ANYCHAR_ML_STAR); - } else { - addOpcode(OPCode.ANYCHAR_STAR); - } - return; + addOpcode(OPCode.ANYCHAR_STAR); } + return; } int modTLen; @@ -510,9 +517,8 @@ if (isDynamic(prev ^ node.option)) { return OPSize.SET_OPTION_PUSH + OPSize.SET_OPTION + OPSize.FAIL + tlen + OPSize.SET_OPTION; - } else { - return tlen; } + return tlen; } @Override @@ -675,13 +681,15 @@ break; case AnchorType.WORD_BEGIN: - if (Config.USE_WORD_BEGIN_END) + if (Config.USE_WORD_BEGIN_END) { addOpcode(OPCode.WORD_BEGIN); + } break; case AnchorType.WORD_END: - if (Config.USE_WORD_BEGIN_END) + if (Config.USE_WORD_BEGIN_END) { addOpcode(OPCode.WORD_END); + } break; case AnchorType.PREC_READ: @@ -701,7 +709,9 @@ addOpcode(OPCode.LOOK_BEHIND); if (node.charLength < 0) { n = analyser.getCharLengthTree(node.target); - if (analyser.returnCode != 0) newSyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN); + if (analyser.returnCode != 0) { + newSyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN); + } } else { n = node.charLength; } @@ -714,7 +724,9 @@ addOpcodeRelAddr(OPCode.PUSH_LOOK_BEHIND_NOT, len + OPSize.FAIL_LOOK_BEHIND_NOT); if (node.charLength < 0) { n = analyser.getCharLengthTree(node.target); - if (analyser.returnCode != 0) newSyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN); + if (analyser.returnCode != 0) { + newSyntaxException(ERR_INVALID_LOOK_BEHIND_PATTERN); + } } else { n = node.charLength; } @@ -796,7 +808,9 @@ private void ensure(final int size) { if (size >= code.length) { int length = code.length << 1; - while (length <= size) length <<= 1; + while (length <= size) { + length <<= 1; + } final int[]tmp = new int[length]; System.arraycopy(code, 0, tmp, 0, code.length); code = tmp; @@ -829,11 +843,14 @@ regex.operands[regex.operandLength++] = o; } - private void addChars(final char[] chars, int p ,final int length) { + private void addChars(final char[] chars, final int pp ,final int length) { ensure(codeLength + length); + int p = pp; final int end = p + length; - while (p < end) code[codeLength++] = chars[p++]; + while (p < end) { + code[codeLength++] = chars[p++]; + } } private void addInts(final int[]ints, final int length) { @@ -876,6 +893,9 @@ case OPCode.CALL: case OPCode.RETURN: // it will appear only with CALL though regex.stackNeeded = true; + break; + default: + break; } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java Fri Nov 14 10:03:48 2014 -0800 @@ -19,6 +19,7 @@ */ package jdk.nashorn.internal.runtime.regexp.joni; +@SuppressWarnings("javadoc") public final class BitSet { static final int BITS_PER_BYTE = 8; public static final int SINGLE_BYTE_SIZE = (1 << BITS_PER_BYTE); @@ -34,7 +35,9 @@ final StringBuilder buffer = new StringBuilder(); buffer.append("BitSet"); for (int i=0; i>>= 1) != 0) log++; + int n = np; + while ((n >>>= 1) != 0) { + log++; + } return log; } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java Fri Nov 14 10:03:48 2014 -0800 @@ -34,7 +34,8 @@ return (n < BIT_STATUS_BITS_NUM ? stats & (1 << n) : (stats & 1)) != 0; } - public static int bsOnAt(int stats, final int n) { + public static int bsOnAt(final int statsp, final int n) { + int stats = statsp; if (n < BIT_STATUS_BITS_NUM) { stats |= (1 << n); } else { @@ -43,12 +44,7 @@ return stats; } - public static int bsOnOff(int v, final int f, final boolean negative) { - if (negative) { - v &= ~f; - } else { - v |= f; - } - return v; + public static int bsOnOff(final int v, final int f, final boolean negative) { + return negative ? (v & ~f) : (v | f); } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,10 +27,8 @@ import static jdk.nashorn.internal.runtime.regexp.joni.Option.isNotBol; import static jdk.nashorn.internal.runtime.regexp.joni.Option.isNotEol; import static jdk.nashorn.internal.runtime.regexp.joni.Option.isPosixRegion; - import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode; import jdk.nashorn.internal.runtime.regexp.joni.constants.OPCode; -import jdk.nashorn.internal.runtime.regexp.joni.constants.OPSize; import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder; import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages; import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException; @@ -52,8 +50,8 @@ this.code = regex.code; } - private boolean stringCmpIC(final int caseFlodFlag, int s1, final IntHolder ps2, final int mbLen, final int textEnd) { - + private boolean stringCmpIC(final int caseFlodFlag, final int s1p, final IntHolder ps2, final int mbLen, final int textEnd) { + int s1 = s1p; int s2 = ps2.value; final int end1 = s1 + mbLen; @@ -83,12 +81,16 @@ Config.log.printf("%4d", (s - str)).print("> \""); int q, i; for (i=0, q=s; i<7 && q=0; i++) { - if (q < end) Config.log.print(new String(new char[]{chars[q++]})); + if (q < end) { + Config.log.print(new String(new char[]{chars[q++]})); + } } - final String str = q < end ? "...\"" : "\""; - q += str.length(); - Config.log.print(str); - for (i=0; i<20-(q-s);i++) Config.log.print(" "); + final String string = q < end ? "...\"" : "\""; + q += string.length(); + Config.log.print(string); + for (i=0; i<20-(q-s);i++) { + Config.log.print(" "); + } final StringBuilder sb = new StringBuilder(); new ByteCodePrinter(regex).compiledByteCodeToString(sb, ip); Config.log.println(sb.toString()); @@ -96,28 +98,34 @@ } @Override - protected final int matchAt(final int range, final int sstart, final int sprev) { - this.range = range; - this.sstart = sstart; - this.sprev = sprev; + protected final int matchAt(final int r, final int ss, final int sp) { + this.range = r; + this.sstart = ss; + this.sprev = sp; stk = 0; ip = 0; - if (Config.DEBUG_MATCH) debugMatchBegin(); + if (Config.DEBUG_MATCH) { + debugMatchBegin(); + } init(); bestLen = -1; - s = sstart; + s = ss; - final int[]code = this.code; + final int[] c = this.code; while (true) { - if (Config.DEBUG_MATCH) debugMatchLoop(); + if (Config.DEBUG_MATCH) { + debugMatchLoop(); + } sbegin = s; - switch (code[ip++]) { - case OPCode.END: if (opEnd()) return finish(); break; + switch (c[ip++]) { + case OPCode.END: if (opEnd()) { + return finish(); + } break; case OPCode.EXACT1: opExact1(); break; case OPCode.EXACT2: opExact2(); continue; case OPCode.EXACT3: opExact3(); continue; @@ -358,10 +366,14 @@ final char[] bs = regex.templates[code[ip++]]; int ps = code[ip++]; - while (tlen-- > 0) if (bs[ps++] != chars[s++]) {opFail(); return;} + while (tlen-- > 0) { + if (bs[ps++] != chars[s++]) {opFail(); return;} + } } else { - while (tlen-- > 0) if (code[ip++] != chars[s++]) {opFail(); return;} + while (tlen-- > 0) { + if (code[ip++] != chars[s++]) {opFail(); return;} + } } sprev = s - 1; } @@ -380,10 +392,14 @@ final char[] bs = regex.templates[code[ip++]]; int ps = code[ip++]; - while (tlen-- > 0) if (bs[ps++] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;} + while (tlen-- > 0) { + if (bs[ps++] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;} + } } else { - while (tlen-- > 0) if (code[ip++] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;} + while (tlen-- > 0) { + if (code[ip++] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;} + } } sprev = s - 1; } @@ -402,11 +418,15 @@ private boolean isInClassMB() { final int tlen = code[ip++]; - if (s >= range) return false; + if (s >= range) { + return false; + } final int ss = s; s++; final int c = chars[ss]; - if (!EncodingHelper.isInCodeRange(code, ip, c)) return false; + if (!EncodingHelper.isInCodeRange(code, ip, c)) { + return false; + } ip += tlen; return true; } @@ -444,7 +464,9 @@ final int tlen = code[ip++]; if (!(s + 1 <= range)) { - if (s >= range) return false; + if (s >= range) { + return false; + } s = end; ip += tlen; return true; @@ -454,7 +476,9 @@ s++; final int c = chars[ss]; - if (EncodingHelper.isInCodeRange(code, ip, c)) return false; + if (EncodingHelper.isInCodeRange(code, ip, c)) { + return false; + } ip += tlen; return true; } @@ -511,10 +535,10 @@ } private void opAnyCharStar() { - final char[] chars = this.chars; + final char[] ch = this.chars; while (s < range) { pushAlt(ip, s, sprev); - if (isNewLine(chars, s, end)) {opFail(); return;} + if (isNewLine(ch, s, end)) {opFail(); return;} sprev = s; s++; } @@ -532,11 +556,13 @@ private void opAnyCharStarPeekNext() { final char c = (char)code[ip]; - final char[] chars = this.chars; + final char[] ch = this.chars; while (s < range) { - final char b = chars[s]; - if (c == b) pushAlt(ip + 1, s, sprev); + final char b = ch[s]; + if (c == b) { + pushAlt(ip + 1, s, sprev); + } if (isNewLine(b)) {opFail(); return;} sprev = s; s++; @@ -547,10 +573,12 @@ private void opAnyCharMLStarPeekNext() { final char c = (char)code[ip]; - final char[] chars = this.chars; + final char[] ch = this.chars; while (s < range) { - if (c == chars[s]) pushAlt(ip + 1, s, sprev); + if (c == ch[s]) { + pushAlt(ip + 1, s, sprev); + } sprev = s; s++; } @@ -592,29 +620,39 @@ private void opWordBegin() { if (s < range && EncodingHelper.isWord(chars[s])) { - if (s == str || !EncodingHelper.isWord(chars[sprev])) return; + if (s == str || !EncodingHelper.isWord(chars[sprev])) { + return; + } } opFail(); } private void opWordEnd() { if (s != str && EncodingHelper.isWord(chars[sprev])) { - if (s == end || !EncodingHelper.isWord(chars[s])) return; + if (s == end || !EncodingHelper.isWord(chars[s])) { + return; + } } opFail(); } private void opBeginBuf() { - if (s != str) opFail(); + if (s != str) { + opFail(); + } } private void opEndBuf() { - if (s != end) opFail(); + if (s != end) { + opFail(); + } } private void opBeginLine() { if (s == str) { - if (isNotBol(msaOptions)) opFail(); + if (isNotBol(msaOptions)) { + opFail(); + } return; } else if (isNewLine(chars, sprev, end) && s != end) { return; @@ -626,13 +664,16 @@ if (s == end) { if (Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) { if (str == end || !isNewLine(chars, sprev, end)) { - if (isNotEol(msaOptions)) opFail(); + if (isNotEol(msaOptions)) { + opFail(); + } } return; - } else { - if (isNotEol(msaOptions)) opFail(); - return; } + if (isNotEol(msaOptions)) { + opFail(); + } + return; } else if (isNewLine(chars, s, end)) { return; } @@ -643,13 +684,16 @@ if (s == end) { if (Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) { if (str == end || !isNewLine(chars, sprev, end)) { - if (isNotEol(msaOptions)) opFail(); + if (isNotEol(msaOptions)) { + opFail(); + } } return; - } else { - if (isNotEol(msaOptions)) opFail(); - return; } + if (isNotEol(msaOptions)) { + opFail(); + } + return; } else if (isNewLine(chars, s, end) && s + 1 == end) { return; } @@ -657,7 +701,9 @@ } private void opBeginPosition() { - if (s != msaStart) opFail(); + if (s != msaStart) { + opFail(); + } } private void opMemoryStartPush() { @@ -726,11 +772,15 @@ sprev = s; // STRING_CMP - while(n-- > 0) if (chars[pstart++] != chars[s++]) {opFail(); return;} + while(n-- > 0) { + if (chars[pstart++] != chars[s++]) {opFail(); return;} + } // beyond string check if (sprev < range) { - while (sprev + 1 < s) sprev++; + while (sprev + 1 < s) { + sprev++; + } } } @@ -764,7 +814,9 @@ s = value; // if (sprev < chars.length) - while (sprev + 1 < s) sprev++; + while (sprev + 1 < s) { + sprev++; + } } private void opBackRefMulti() { @@ -773,7 +825,9 @@ int i; loop:for (i=0; i 0) { - if (chars[pstart++] != chars[swork++]) continue loop; + if (chars[pstart++] != chars[swork++]) { + continue loop; + } } s = swork; // beyond string check if (sprev < range) { - while (sprev + 1 < s) sprev++; + while (sprev + 1 < s) { + sprev++; + } } ip += tlen - i - 1; // * SIZE_MEMNUM (1) @@ -807,7 +865,9 @@ int i; loop:for (i=0; i end - s) return false; /* or goto next_mem; */ + if (pend - pstart > end - s) { + return false; /* or goto next_mem; */ + } int p = pstart; value = s; @@ -867,7 +936,9 @@ } } else { while (p < pend) { - if (chars[p++] != chars[value++]) return false; /* or goto next_mem; */ + if (chars[p++] != chars[value++]) { + return false; /* or goto next_mem; */ + } } } s = value; @@ -893,24 +964,15 @@ sprev = s; if (backrefMatchAtNestedLevel(ic != 0, regex.caseFoldFlag, level, tlen, ip)) { // (s) and (end) implicit - while (sprev + 1 < s) sprev++; + while (sprev + 1 < s) { + sprev++; + } ip += tlen; // * SIZE_MEMNUM } else { {opFail(); return;} } } - /* no need: IS_DYNAMIC_OPTION() == 0 */ - private void opSetOptionPush() { - // option = code[ip++]; // final for now - pushAlt(ip, s, sprev); - ip += OPSize.SET_OPTION + OPSize.FAIL; - } - - private void opSetOption() { - // option = code[ip++]; // final for now - } - private void opNullCheckStart() { final int mem = code[ip++]; pushNullCheckStart(mem, s); @@ -1142,13 +1204,6 @@ sprev = EncodingHelper.prevCharHead(str, s); } - private void opLookBehindSb() { - final int tlen = code[ip++]; - s -= tlen; - if (s < str) {opFail(); return;} - sprev = s == str ? -1 : s - 1; - } - private void opPushLookBehindNot() { final int addr = code[ip++]; final int tlen = code[ip++]; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java Fri Nov 14 10:03:48 2014 -0800 @@ -236,16 +236,17 @@ sb.append(new String(code, s, len)); } - private void pLenStringFromTemplate(final StringBuilder sb, final int len, final char[] tm, final int idx) { + private static void pLenStringFromTemplate(final StringBuilder sb, final int len, final char[] tm, final int idx) { sb.append(":T:").append(len).append(":"); sb.append(tm, idx, len); } - public int compiledByteCodeToString(final StringBuilder sb, int bp) { + public int compiledByteCodeToString(final StringBuilder sb, final int bptr) { int len, n, mem, addr, scn, cod; BitSet bs; CClassNode cc; int tm, idx; + int bp = bptr; sb.append("[").append(OpCodeNames[code[bp]]); final int argType = OpCodeArgTypes[code[bp]]; @@ -253,6 +254,7 @@ if (argType != Arguments.SPECIAL) { bp++; switch (argType) { + default: case Arguments.NON: break; @@ -410,7 +412,9 @@ for (int i=0; i 0) sb.append(", "); + if (i > 0) { + sb.append(", "); + } sb.append(mem); } break; @@ -428,7 +432,9 @@ for (int i=0; i 0) sb.append(", "); + if (i > 0) { + sb.append(", "); + } sb.append(mem); } break; @@ -501,7 +507,9 @@ while (bp < end) { ncode++; - if (bp > 0) sb.append(ncode % 5 == 0 ? "\n" : " "); + if (bp > 0) { + sb.append(ncode % 5 == 0 ? "\n" : " "); + } bp = compiledByteCodeToString(sb, bp); } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java Fri Nov 14 10:03:48 2014 -0800 @@ -22,6 +22,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages; import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException; +@SuppressWarnings("javadoc") public final class CodeRangeBuffer implements Cloneable { private static final int INIT_MULTI_BYTE_RANGE_SIZE = 5; private static final int ALL_MULTI_BYTE_RANGE = 0x7fffffff; @@ -68,7 +69,9 @@ for (int i=0; i 0 && i % 6 == 0) buf.append("\n "); + if (i > 0 && i % 6 == 0) { + buf.append("\n "); + } } return buf.toString(); @@ -97,9 +100,13 @@ } private void moveRight(final int from, final int to, final int n) { - if (to + n > p.length) expand(to + n); + if (to + n > p.length) { + expand(to + n); + } System.arraycopy(p, from, p, to, n); - if (to + n > used) used = to + n; + if (to + n > used) { + used = to + n; + } } protected void moveLeft(final int from, final int to, final int n) { @@ -113,9 +120,13 @@ public void writeCodePoint(final int pos, final int b) { final int u = pos + 1; - if (p.length < u) expand(u); + if (p.length < u) { + expand(u); + } p[pos] = b; - if (used < u) used = u; + if (used < u) { + used = u; + } } @Override @@ -125,14 +136,19 @@ // ugly part: these methods should be made OO // add_code_range_to_buf - public static CodeRangeBuffer addCodeRangeToBuff(CodeRangeBuffer pbuf, int from, int to) { + public static CodeRangeBuffer addCodeRangeToBuff(final CodeRangeBuffer pbufp, final int fromp, final int top) { + int from = fromp, to = top; + CodeRangeBuffer pbuf = pbufp; + if (from > to) { final int n = from; from = to; to = n; } - if (pbuf == null) pbuf = new CodeRangeBuffer(); // move to CClassNode + if (pbuf == null) { + pbuf = new CodeRangeBuffer(); // move to CClassNode + } final int[]p = pbuf.p; int n = p[0]; @@ -163,11 +179,17 @@ final int incN = low + 1 - high; - if (n + incN > Config.MAX_MULTI_BYTE_RANGES_NUM) throw new ValueException(ErrorMessages.ERR_TOO_MANY_MULTI_BYTE_RANGES); + if (n + incN > Config.MAX_MULTI_BYTE_RANGES_NUM) { + throw new ValueException(ErrorMessages.ERR_TOO_MANY_MULTI_BYTE_RANGES); + } if (incN != 1) { - if (from > p[low * 2 + 1]) from = p[low * 2 + 1]; - if (to < p[(high - 1) * 2 + 2]) to = p[(high - 1) * 2 + 2]; + if (from > p[low * 2 + 1]) { + from = p[low * 2 + 1]; + } + if (to < p[(high - 1) * 2 + 2]) { + to = p[(high - 1) * 2 + 2]; + } } if (incN != 0 && high < n) { @@ -197,9 +219,8 @@ if (from > to) { if (env.syntax.allowEmptyRangeInCC()) { return pbuf; - } else { - throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS); } + throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS); } return addCodeRangeToBuff(pbuf, from, to); } @@ -218,12 +239,16 @@ public static CodeRangeBuffer notCodeRangeBuff(final CodeRangeBuffer bbuf) { CodeRangeBuffer pbuf = null; - if (bbuf == null) return setAllMultiByteRange(pbuf); + if (bbuf == null) { + return setAllMultiByteRange(pbuf); + } final int[]p = bbuf.p; final int n = p[0]; - if (n <= 0) return setAllMultiByteRange(pbuf); + if (n <= 0) { + return setAllMultiByteRange(pbuf); + } int pre = EncodingHelper.mbcodeStartPosition(); @@ -235,18 +260,26 @@ if (pre <= from - 1) { pbuf = addCodeRangeToBuff(pbuf, pre, from - 1); } - if (to == ALL_MULTI_BYTE_RANGE) break; + if (to == ALL_MULTI_BYTE_RANGE) { + break; + } pre = to + 1; } - if (to < ALL_MULTI_BYTE_RANGE) pbuf = addCodeRangeToBuff(pbuf, to + 1, ALL_MULTI_BYTE_RANGE); + if (to < ALL_MULTI_BYTE_RANGE) { + pbuf = addCodeRangeToBuff(pbuf, to + 1, ALL_MULTI_BYTE_RANGE); + } return pbuf; } // or_code_range_buf - public static CodeRangeBuffer orCodeRangeBuff(CodeRangeBuffer bbuf1, boolean not1, - CodeRangeBuffer bbuf2, boolean not2) { + public static CodeRangeBuffer orCodeRangeBuff(final CodeRangeBuffer bbuf1p, final boolean not1p, + final CodeRangeBuffer bbuf2p, final boolean not2p) { CodeRangeBuffer pbuf = null; + CodeRangeBuffer bbuf1 = bbuf1p; + CodeRangeBuffer bbuf2 = bbuf2p; + boolean not1 = not1p; + boolean not2 = not2p; if (bbuf1 == null && bbuf2 == null) { if (not1 || not2) { @@ -266,13 +299,11 @@ if (bbuf1 == null) { if (not1) { return setAllMultiByteRange(pbuf); - } else { - if (!not2) { - return bbuf2.clone(); - } else { - return notCodeRangeBuff(bbuf2); - } } + if (!not2) { + return bbuf2.clone(); + } + return notCodeRangeBuff(bbuf2); } if (not1) { @@ -302,16 +333,18 @@ } // and_code_range1 - public static CodeRangeBuffer andCodeRange1(CodeRangeBuffer pbuf, int from1, int to1, final int[]data, final int n) { + public static CodeRangeBuffer andCodeRange1(final CodeRangeBuffer pbufp, final int from1p, final int to1p, final int[]data, final int n) { + CodeRangeBuffer pbuf = pbufp; + int from1 = from1p, to1 = to1p; + for (int i=0; i to1) break; + if (from1 > to1) { + break; + } } if (from1 <= to1) { @@ -335,15 +370,22 @@ } // and_code_range_buf - public static CodeRangeBuffer andCodeRangeBuff(CodeRangeBuffer bbuf1, boolean not1, - CodeRangeBuffer bbuf2, boolean not2) { + public static CodeRangeBuffer andCodeRangeBuff(final CodeRangeBuffer bbuf1p, final boolean not1p, + final CodeRangeBuffer bbuf2p, final boolean not2p) { CodeRangeBuffer pbuf = null; + CodeRangeBuffer bbuf1 = bbuf1p; + CodeRangeBuffer bbuf2 = bbuf2p; + boolean not1 = not1p, not2 = not2p; if (bbuf1 == null) { - if (not1 && bbuf2 != null) return bbuf2.clone(); /* not1 != 0 -> not2 == 0 */ + if (not1 && bbuf2 != null) { + return bbuf2.clone(); /* not1 != 0 -> not2 == 0 */ + } return null; } else if (bbuf2 == null) { - if (not2) return bbuf1.clone(); + if (not2) { + return bbuf1.clone(); + } return null; } @@ -369,8 +411,12 @@ final int from2 = p2[j * 2 + 1]; final int to2 = p2[j * 2 + 2]; - if (from2 > to1) break; - if (to2 < from1) continue; + if (from2 > to1) { + break; + } + if (to2 < from1) { + continue; + } final int from = from1 > from2 ? from1 : from2; final int to = to1 < to2 ? to1 : to2; pbuf = addCodeRangeToBuff(pbuf, from, to); diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java Fri Nov 14 10:03:48 2014 -0800 @@ -53,13 +53,17 @@ protected abstract void compileAltNode(ConsAltNode node); private void compileStringRawNode(final StringNode sn) { - if (sn.length() <= 0) return; + if (sn.length() <= 0) { + return; + } addCompileString(sn.chars, sn.p, sn.length(), false); } private void compileStringNode(final StringNode node) { final StringNode sn = node; - if (sn.length() <= 0) return; + if (sn.length() <= 0) { + return; + } final boolean ambig = sn.isAmbig(); @@ -145,7 +149,9 @@ } protected final void compileTreeNTimes(final Node node, final int n) { - for (int i=0; i 0) { - if (s <= p) return -1; + public static int stepBack(final int p, final int sp, final int np) { + int s = sp, n = np; + while (s != -1 && n-- > 0) { + if (s <= p) { + return -1; + } s--; } return s; @@ -122,7 +128,7 @@ final int upper = toUpperCase(c); if (upper != c) { - fun.apply(c, upper, arg); + ApplyCaseFold.apply(c, upper, arg); } } } @@ -133,7 +139,7 @@ final int upper = toUpperCase(c); if (upper != c) { - fun.apply(upper, c, arg); + ApplyCaseFold.apply(upper, c, arg); } } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java Fri Nov 14 10:03:48 2014 -0800 @@ -21,7 +21,6 @@ import static jdk.nashorn.internal.runtime.regexp.joni.Option.isSingleline; import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepeatInfinite; - import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode; import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType; import jdk.nashorn.internal.runtime.regexp.joni.constants.MetaChar; @@ -53,9 +52,8 @@ if (!left()) { if (synAllow) { return 1; /* "....{" : OK! */ - } else { - throw new SyntaxException(ERR_END_PATTERN_AT_LEFT_BRACE); } + throw new SyntaxException(ERR_END_PATTERN_AT_LEFT_BRACE); } if (!synAllow) { @@ -83,7 +81,9 @@ } } - if (!left()) return invalidRangeQuantifier(synAllow); + if (!left()) { + return invalidRangeQuantifier(synAllow); + } fetch(); int up; @@ -99,25 +99,35 @@ } if (p == prev) { - if (nonLow) return invalidRangeQuantifier(synAllow); + if (nonLow) { + return invalidRangeQuantifier(synAllow); + } up = QuantifierNode.REPEAT_INFINITE; /* {n,} : {n,infinite} */ } } else { - if (nonLow) return invalidRangeQuantifier(synAllow); + if (nonLow) { + return invalidRangeQuantifier(synAllow); + } unfetch(); up = low; /* {n} : exact n times */ ret = 2; /* fixed */ } - if (!left()) return invalidRangeQuantifier(synAllow); + if (!left()) { + return invalidRangeQuantifier(synAllow); + } fetch(); if (syntax.opEscBraceInterval()) { - if (c != syntax.metaCharTable.esc) return invalidRangeQuantifier(synAllow); + if (c != syntax.metaCharTable.esc) { + return invalidRangeQuantifier(synAllow); + } fetch(); } - if (c != '}') return invalidRangeQuantifier(synAllow); + if (c != '}') { + return invalidRangeQuantifier(synAllow); + } if (!isRepeatInfinite(up) && low > up) { throw new ValueException(ERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE); @@ -134,9 +144,8 @@ if (synAllow) { restore(); return 1; - } else { - throw new SyntaxException(ERR_INVALID_REPEAT_RANGE_PATTERN); } + throw new SyntaxException(ERR_INVALID_REPEAT_RANGE_PATTERN); } @SuppressWarnings("fallthrough") @@ -218,17 +227,6 @@ } } - private int nameEndCodePoint(final int start) { - switch(start) { - case '<': - return '>'; - case '\'': - return '\''; - default: - return 0; - } - } - private void fetchTokenInCCFor_charType(final boolean flag, final int type) { token.type = TokenType.CHAR_TYPE; token.setPropCType(type); @@ -236,7 +234,9 @@ } private void fetchTokenInCCFor_x() { - if (!left()) return; + if (!left()) { + return; + } final int last = p; if (peekIs('{') && syntax.opEscXBraceHex8()) { @@ -274,7 +274,9 @@ } private void fetchTokenInCCFor_u() { - if (!left()) return; + if (!left()) { + return; + } final int last = p; if (syntax.op2EscUHex4()) { @@ -329,7 +331,9 @@ } else if (c == '-') { token.type = TokenType.CC_RANGE; } else if (c == syntax.metaCharTable.esc) { - if (!syntax.backSlashEscapeInCC()) return token.type; + if (!syntax.backSlashEscapeInCC()) { + return token.type; + } if (!left()) { throw new SyntaxException(ERR_END_PATTERN_AT_ESCAPE); } @@ -357,10 +361,14 @@ fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.S : CharacterType.SPACE); break; case 'h': - if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(false, CharacterType.XDIGIT); + if (syntax.op2EscHXDigit()) { + fetchTokenInCCFor_charType(false, CharacterType.XDIGIT); + } break; case 'H': - if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(true, CharacterType.XDIGIT); + if (syntax.op2EscHXDigit()) { + fetchTokenInCCFor_charType(true, CharacterType.XDIGIT); + } break; case 'x': fetchTokenInCCFor_x(); @@ -424,7 +432,9 @@ } private void fetchTokenFor_xBrace() { - if (!left()) return; + if (!left()) { + return; + } final int last = p; if (peekIs('{') && syntax.opEscXBraceHex8()) { @@ -461,7 +471,9 @@ } private void fetchTokenFor_uHex() { - if (!left()) return; + if (!left()) { + return; + } final int last = p; if (syntax.op2EscUHex4()) { @@ -562,79 +574,129 @@ switch(c) { case '*': - if (syntax.opEscAsteriskZeroInf()) fetchTokenFor_repeat(0, QuantifierNode.REPEAT_INFINITE); + if (syntax.opEscAsteriskZeroInf()) { + fetchTokenFor_repeat(0, QuantifierNode.REPEAT_INFINITE); + } break; case '+': - if (syntax.opEscPlusOneInf()) fetchTokenFor_repeat(1, QuantifierNode.REPEAT_INFINITE); + if (syntax.opEscPlusOneInf()) { + fetchTokenFor_repeat(1, QuantifierNode.REPEAT_INFINITE); + } break; case '?': - if (syntax.opEscQMarkZeroOne()) fetchTokenFor_repeat(0, 1); + if (syntax.opEscQMarkZeroOne()) { + fetchTokenFor_repeat(0, 1); + } break; case '{': - if (syntax.opEscBraceInterval()) fetchTokenFor_openBrace(); + if (syntax.opEscBraceInterval()) { + fetchTokenFor_openBrace(); + } break; case '|': - if (syntax.opEscVBarAlt()) token.type = TokenType.ALT; + if (syntax.opEscVBarAlt()) { + token.type = TokenType.ALT; + } break; case '(': - if (syntax.opEscLParenSubexp()) token.type = TokenType.SUBEXP_OPEN; + if (syntax.opEscLParenSubexp()) { + token.type = TokenType.SUBEXP_OPEN; + } break; case ')': - if (syntax.opEscLParenSubexp()) token.type = TokenType.SUBEXP_CLOSE; + if (syntax.opEscLParenSubexp()) { + token.type = TokenType.SUBEXP_CLOSE; + } break; case 'w': - if (syntax.opEscWWord()) fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.W : CharacterType.WORD); + if (syntax.opEscWWord()) { + fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.W : CharacterType.WORD); + } break; case 'W': - if (syntax.opEscWWord()) fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.W : CharacterType.WORD); + if (syntax.opEscWWord()) { + fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.W : CharacterType.WORD); + } break; case 'b': - if (syntax.opEscBWordBound()) fetchTokenFor_anchor(AnchorType.WORD_BOUND); + if (syntax.opEscBWordBound()) { + fetchTokenFor_anchor(AnchorType.WORD_BOUND); + } break; case 'B': - if (syntax.opEscBWordBound()) fetchTokenFor_anchor(AnchorType.NOT_WORD_BOUND); + if (syntax.opEscBWordBound()) { + fetchTokenFor_anchor(AnchorType.NOT_WORD_BOUND); + } break; case '<': - if (Config.USE_WORD_BEGIN_END && syntax.opEscLtGtWordBeginEnd()) fetchTokenFor_anchor(AnchorType.WORD_BEGIN); + if (Config.USE_WORD_BEGIN_END && syntax.opEscLtGtWordBeginEnd()) { + fetchTokenFor_anchor(AnchorType.WORD_BEGIN); + } break; case '>': - if (Config.USE_WORD_BEGIN_END && syntax.opEscLtGtWordBeginEnd()) fetchTokenFor_anchor(AnchorType.WORD_END); + if (Config.USE_WORD_BEGIN_END && syntax.opEscLtGtWordBeginEnd()) { + fetchTokenFor_anchor(AnchorType.WORD_END); + } break; case 's': - if (syntax.opEscSWhiteSpace()) fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.S : CharacterType.SPACE); + if (syntax.opEscSWhiteSpace()) { + fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.S : CharacterType.SPACE); + } break; case 'S': - if (syntax.opEscSWhiteSpace()) fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.S : CharacterType.SPACE); + if (syntax.opEscSWhiteSpace()) { + fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.S : CharacterType.SPACE); + } break; case 'd': - if (syntax.opEscDDigit()) fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.D : CharacterType.DIGIT); + if (syntax.opEscDDigit()) { + fetchTokenInCCFor_charType(false, Config.NON_UNICODE_SDW ? CharacterType.D : CharacterType.DIGIT); + } break; case 'D': - if (syntax.opEscDDigit()) fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.D : CharacterType.DIGIT); + if (syntax.opEscDDigit()) { + fetchTokenInCCFor_charType(true, Config.NON_UNICODE_SDW ? CharacterType.D : CharacterType.DIGIT); + } break; case 'h': - if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(false, CharacterType.XDIGIT); + if (syntax.op2EscHXDigit()) { + fetchTokenInCCFor_charType(false, CharacterType.XDIGIT); + } break; case 'H': - if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(true, CharacterType.XDIGIT); + if (syntax.op2EscHXDigit()) { + fetchTokenInCCFor_charType(true, CharacterType.XDIGIT); + } break; case 'A': - if (syntax.opEscAZBufAnchor()) fetchTokenFor_anchor(AnchorType.BEGIN_BUF); + if (syntax.opEscAZBufAnchor()) { + fetchTokenFor_anchor(AnchorType.BEGIN_BUF); + } break; case 'Z': - if (syntax.opEscAZBufAnchor()) fetchTokenFor_anchor(AnchorType.SEMI_END_BUF); + if (syntax.opEscAZBufAnchor()) { + fetchTokenFor_anchor(AnchorType.SEMI_END_BUF); + } break; case 'z': - if (syntax.opEscAZBufAnchor()) fetchTokenFor_anchor(AnchorType.END_BUF); + if (syntax.opEscAZBufAnchor()) { + fetchTokenFor_anchor(AnchorType.END_BUF); + } break; case 'G': - if (syntax.opEscCapitalGBeginAnchor()) fetchTokenFor_anchor(AnchorType.BEGIN_POSITION); + if (syntax.opEscCapitalGBeginAnchor()) { + fetchTokenFor_anchor(AnchorType.BEGIN_POSITION); + } break; case '`': - if (syntax.op2EscGnuBufAnchor()) fetchTokenFor_anchor(AnchorType.BEGIN_BUF); + if (syntax.op2EscGnuBufAnchor()) { + fetchTokenFor_anchor(AnchorType.BEGIN_BUF); + } break; case '\'': - if (syntax.op2EscGnuBufAnchor()) fetchTokenFor_anchor(AnchorType.END_BUF); + if (syntax.op2EscGnuBufAnchor()) { + fetchTokenFor_anchor(AnchorType.END_BUF); + } break; case 'x': fetchTokenFor_xBrace(); @@ -684,22 +746,34 @@ { switch(c) { case '.': - if (syntax.opDotAnyChar()) token.type = TokenType.ANYCHAR; + if (syntax.opDotAnyChar()) { + token.type = TokenType.ANYCHAR; + } break; case '*': - if (syntax.opAsteriskZeroInf()) fetchTokenFor_repeat(0, QuantifierNode.REPEAT_INFINITE); + if (syntax.opAsteriskZeroInf()) { + fetchTokenFor_repeat(0, QuantifierNode.REPEAT_INFINITE); + } break; case '+': - if (syntax.opPlusOneInf()) fetchTokenFor_repeat(1, QuantifierNode.REPEAT_INFINITE); + if (syntax.opPlusOneInf()) { + fetchTokenFor_repeat(1, QuantifierNode.REPEAT_INFINITE); + } break; case '?': - if (syntax.opQMarkZeroOne()) fetchTokenFor_repeat(0, 1); + if (syntax.opQMarkZeroOne()) { + fetchTokenFor_repeat(0, 1); + } break; case '{': - if (syntax.opBraceInterval()) fetchTokenFor_openBrace(); + if (syntax.opBraceInterval()) { + fetchTokenFor_openBrace(); + } break; case '|': - if (syntax.opVBarAlt()) token.type = TokenType.ALT; + if (syntax.opVBarAlt()) { + token.type = TokenType.ALT; + } break; case '(': @@ -713,9 +787,13 @@ } fetch(); if (c == syntax.metaCharTable.esc) { - if (left()) fetch(); + if (left()) { + fetch(); + } } else { - if (c == ')') break; + if (c == ')') { + break; + } } } continue start; // goto start @@ -723,19 +801,29 @@ unfetch(); } - if (syntax.opLParenSubexp()) token.type = TokenType.SUBEXP_OPEN; + if (syntax.opLParenSubexp()) { + token.type = TokenType.SUBEXP_OPEN; + } break; case ')': - if (syntax.opLParenSubexp()) token.type = TokenType.SUBEXP_CLOSE; + if (syntax.opLParenSubexp()) { + token.type = TokenType.SUBEXP_CLOSE; + } break; case '^': - if (syntax.opLineAnchor()) fetchTokenFor_anchor(isSingleline(env.option) ? AnchorType.BEGIN_BUF : AnchorType.BEGIN_LINE); + if (syntax.opLineAnchor()) { + fetchTokenFor_anchor(isSingleline(env.option) ? AnchorType.BEGIN_BUF : AnchorType.BEGIN_LINE); + } break; case '$': - if (syntax.opLineAnchor()) fetchTokenFor_anchor(isSingleline(env.option) ? AnchorType.END_BUF : AnchorType.END_LINE); + if (syntax.opLineAnchor()) { + fetchTokenFor_anchor(isSingleline(env.option) ? AnchorType.END_BUF : AnchorType.END_LINE); + } break; case '[': - if (syntax.opBracketCC()) token.type = TokenType.CC_CC_OPEN; + if (syntax.opBracketCC()) { + token.type = TokenType.CC_CC_OPEN; + } break; case ']': //if (*src > env->pattern) /* /].../ is allowed. */ @@ -745,7 +833,9 @@ if (Option.isExtend(env.option)) { while (left()) { fetch(); - if (EncodingHelper.isNewLine(c)) break; + if (EncodingHelper.isNewLine(c)) { + break; + } } continue start; // goto start } @@ -756,7 +846,10 @@ case '\n': case '\r': case '\f': - if (Option.isExtend(env.option)) continue start; // goto start + if (Option.isExtend(env.option)) + { + continue start; // goto start + } break; default: // string @@ -798,8 +891,8 @@ } } - protected final void syntaxWarn(final String message, final char c) { - syntaxWarn(message.replace("<%n>", Character.toString(c))); + protected final void syntaxWarn(final String message, final char ch) { + syntaxWarn(message.replace("<%n>", Character.toString(ch))); } protected final void syntaxWarn(final String message) { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java Fri Nov 14 10:03:48 2014 -0800 @@ -21,10 +21,10 @@ package jdk.nashorn.internal.runtime.regexp.joni; import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindLongest; - import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType; import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder; +@SuppressWarnings("javadoc") public abstract class Matcher extends IntHolder { protected final Regex regex; @@ -73,7 +73,9 @@ protected final void msaInit(final int option, final int start) { msaOptions = option; msaStart = start; - if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) msaBestLen = -1; + if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) { + msaBestLen = -1; + } } public final int match(final int at, final int range, final int option) { @@ -83,20 +85,19 @@ if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) { return matchAt(end /*range*/, at, prev); - } else { - return matchAt(range /*range*/, at, prev); } + return matchAt(range /*range*/, at, prev); } int low, high; // these are the return values - private boolean forwardSearchRange(final char[] chars, final int str, final int end, final int s, final int range, final IntHolder lowPrev) { + private boolean forwardSearchRange(final char[] ch, final int string, final int e, final int s, final int range, final IntHolder lowPrev) { int pprev = -1; int p = s; if (Config.DEBUG_SEARCH) { Config.log.println("forward_search_range: "+ - "str: " + str + - ", end: " + end + + "str: " + string + + ", end: " + e + ", s: " + s + ", range: " + range); } @@ -106,7 +107,7 @@ } retry:while (true) { - p = regex.searchAlgorithm.search(regex, chars, p, end, range); + p = regex.searchAlgorithm.search(regex, ch, p, e, range); if (p != -1 && p < range) { if (p - regex.dMin < s) { @@ -119,9 +120,9 @@ if (regex.subAnchor != 0) { switch (regex.subAnchor) { case AnchorType.BEGIN_LINE: - if (p != str) { - final int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, p); - if (!EncodingHelper.isNewLine(chars, prev, end)) { + if (p != string) { + final int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : string, p); + if (!EncodingHelper.isNewLine(ch, prev, e)) { // goto retry_gate; pprev = p; p++; @@ -131,17 +132,17 @@ break; case AnchorType.END_LINE: - if (p == end) { + if (p == e) { if (!Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) { - final int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, p); - if (prev != -1 && EncodingHelper.isNewLine(chars, prev, end)) { + final int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : string, p); + if (prev != -1 && EncodingHelper.isNewLine(ch, prev, e)) { // goto retry_gate; pprev = p; p++; continue retry; } } - } else if (!EncodingHelper.isNewLine(chars, p, end)) { + } else if (!EncodingHelper.isNewLine(ch, p, e)) { //if () break; // goto retry_gate; pprev = p; @@ -149,6 +150,9 @@ continue retry; } break; + + default: + break; } // switch } @@ -158,7 +162,7 @@ if (low > s) { lowPrev.value = EncodingHelper.prevCharHead(s, p); } else { - lowPrev.value = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, p); + lowPrev.value = EncodingHelper.prevCharHead((pprev != -1) ? pprev : string, p); } } } else { @@ -172,7 +176,7 @@ } } else { if (lowPrev != null) { - lowPrev.value = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, low); + lowPrev.value = EncodingHelper.prevCharHead((pprev != -1) ? pprev : string, low); } } } @@ -182,8 +186,8 @@ if (Config.DEBUG_SEARCH) { Config.log.println("forward_search_range success: "+ - "low: " + (low - str) + - ", high: " + (high - str) + + "low: " + (low - string) + + ", high: " + (high - string) + ", dmin: " + regex.dMin + ", dmax: " + regex.dMax); } @@ -196,20 +200,21 @@ } // low, high - private boolean backwardSearchRange(final char[] chars, final int str, final int end, final int s, int range, final int adjrange) { - range += regex.dMin; + private boolean backwardSearchRange(final char[] ch, final int string, final int e, final int s, final int range, final int adjrange) { + int r = range; + r += regex.dMin; int p = s; retry:while (true) { - p = regex.searchAlgorithm.searchBackward(regex, chars, range, adjrange, end, p, s, range); + p = regex.searchAlgorithm.searchBackward(regex, ch, r, adjrange, e, p, s, r); if (p != -1) { if (regex.subAnchor != 0) { switch (regex.subAnchor) { case AnchorType.BEGIN_LINE: - if (p != str) { - final int prev = EncodingHelper.prevCharHead(str, p); - if (!EncodingHelper.isNewLine(chars, prev, end)) { + if (p != string) { + final int prev = EncodingHelper.prevCharHead(string, p); + if (!EncodingHelper.isNewLine(ch, prev, e)) { p = prev; continue retry; } @@ -217,21 +222,28 @@ break; case AnchorType.END_LINE: - if (p == end) { + if (p == e) { if (!Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) { final int prev = EncodingHelper.prevCharHead(adjrange, p); - if (prev == -1) return false; - if (EncodingHelper.isNewLine(chars, prev, end)) { + if (prev == -1) { + return false; + } + if (EncodingHelper.isNewLine(ch, prev, e)) { p = prev; continue retry; } } - } else if (!EncodingHelper.isNewLine(chars, p, end)) { + } else if (!EncodingHelper.isNewLine(ch, p, e)) { p = EncodingHelper.prevCharHead(adjrange, p); - if (p == -1) return false; + if (p == -1) { + return false; + } continue retry; } break; + + default: + break; } // switch } @@ -243,14 +255,16 @@ if (Config.DEBUG_SEARCH) { Config.log.println("backward_search_range: "+ - "low: " + (low - str) + - ", high: " + (high - str)); + "low: " + (low - string) + + ", high: " + (high - string)); } return true; } - if (Config.DEBUG_SEARCH) Config.log.println("backward_search_range: fail."); + if (Config.DEBUG_SEARCH) { + Config.log.println("backward_search_range: fail."); + } return false; } // while } @@ -261,27 +275,36 @@ if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) { //range = upperRange; if (matchAt(upperRange, s, prev) != -1) { - if (!isFindLongest(regex.options)) return true; + if (!isFindLongest(regex.options)) { + return true; + } } } else { //range = upperRange; - if (matchAt(upperRange, s, prev) != -1) return true; + if (matchAt(upperRange, s, prev) != -1) { + return true; + } } } else { if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) { if (matchAt(end, s, prev) != -1) { //range = upperRange; - if (!isFindLongest(regex.options)) return true; + if (!isFindLongest(regex.options)) { + return true; + } } } else { //range = upperRange; - if (matchAt(end, s, prev) != -1) return true; + if (matchAt(end, s, prev) != -1) { + return true; + } } } return false; } - public final int search(int start, int range, final int option) { + public final int search(final int startp, final int rangep, final int option) { + int start = startp, range = rangep; int s, prev; int origStart = start; final int origRange = range; @@ -294,7 +317,9 @@ ", range " + (range - str)); } - if (start > end || start < str) return -1; + if (start > end || start < str) { + return -1; + } /* anchor optimize: resume search range */ if (regex.anchor != 0 && str < end) { @@ -311,7 +336,10 @@ } else if ((regex.anchor & AnchorType.BEGIN_BUF) != 0) { /* search str-position only */ if (range > start) { - if (start != str) return -1; // mismatch_no_msa; + if (start != str) + { + return -1; // mismatch_no_msa; + } range = str + 1; } else { if (range <= str) { @@ -324,7 +352,10 @@ } else if ((regex.anchor & AnchorType.END_BUF) != 0) { minSemiEnd = maxSemiEnd = end; // !end_buf:! - if (endBuf(start, range, minSemiEnd, maxSemiEnd)) return -1; // mismatch_no_msa; + if (endBuf(start, range, minSemiEnd, maxSemiEnd)) + { + return -1; // mismatch_no_msa; + } } else if ((regex.anchor & AnchorType.SEMI_END_BUF) != 0) { final int preEnd = EncodingHelper.stepBack(str, end, 1); maxSemiEnd = end; @@ -332,12 +363,18 @@ minSemiEnd = preEnd; if (minSemiEnd > str && start <= minSemiEnd) { // !goto end_buf;! - if (endBuf(start, range, minSemiEnd, maxSemiEnd)) return -1; // mismatch_no_msa; + if (endBuf(start, range, minSemiEnd, maxSemiEnd)) + { + return -1; // mismatch_no_msa; + } } } else { minSemiEnd = end; // !goto end_buf;! - if (endBuf(start, range, minSemiEnd, maxSemiEnd)) return -1; // mismatch_no_msa; + if (endBuf(start, range, minSemiEnd, maxSemiEnd)) + { + return -1; // mismatch_no_msa; + } } } else if ((regex.anchor & AnchorType.ANYCHAR_STAR_ML) != 0) { // goto !begin_position;! @@ -359,7 +396,9 @@ prev = -1; msaInit(option, start); - if (matchCheck(end, s, prev)) return match(s); + if (matchCheck(end, s, prev)) { + return match(s); + } return mismatch(); } return -1; // goto mismatch_no_msa; @@ -389,49 +428,62 @@ schRange = end; } else { schRange += regex.dMax; - if (schRange > end) schRange = end; + if (schRange > end) { + schRange = end; + } } } - if ((end - start) < regex.thresholdLength) return mismatch(); + if ((end - start) < regex.thresholdLength) { + return mismatch(); + } if (regex.dMax != MinMaxLen.INFINITE_DISTANCE) { do { - if (!forwardSearchRange(chars, str, end, s, schRange, this)) return mismatch(); // low, high, lowPrev + if (!forwardSearchRange(chars, str, end, s, schRange, this)) { + return mismatch(); // low, high, lowPrev + } if (s < low) { s = low; prev = value; } while (s <= high) { - if (matchCheck(origRange, s, prev)) return match(s); // ??? + if (matchCheck(origRange, s, prev)) { + return match(s); // ??? + } prev = s; s++; } } while (s < range); + } + /* check only. */ + if (!forwardSearchRange(chars, str, end, s, schRange, null)) { return mismatch(); - - } else { /* check only. */ - if (!forwardSearchRange(chars, str, end, s, schRange, null)) return mismatch(); + } - if ((regex.anchor & AnchorType.ANYCHAR_STAR) != 0) { - do { - if (matchCheck(origRange, s, prev)) return match(s); - prev = s; - s++; - } while (s < range); - return mismatch(); - } - + if ((regex.anchor & AnchorType.ANYCHAR_STAR) != 0) { + do { + if (matchCheck(origRange, s, prev)) { + return match(s); + } + prev = s; + s++; + } while (s < range); + return mismatch(); } } do { - if (matchCheck(origRange, s, prev)) return match(s); + if (matchCheck(origRange, s, prev)) { + return match(s); + } prev = s; s++; } while (s < range); if (s == range) { /* because empty match with /$/. */ - if (matchCheck(origRange, s, prev)) return match(s); + if (matchCheck(origRange, s, prev)) { + return match(s); + } } } else { /* backward search */ if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) { @@ -450,37 +502,51 @@ if (regex.dMax != MinMaxLen.INFINITE_DISTANCE && (end - range) >= regex.thresholdLength) { do { int schStart = s + regex.dMax; - if (schStart > end) schStart = end; - if (!backwardSearchRange(chars, str, end, schStart, range, adjrange)) return mismatch(); // low, high - if (s > high) s = high; + if (schStart > end) { + schStart = end; + } + if (!backwardSearchRange(chars, str, end, schStart, range, adjrange)) + { + return mismatch(); // low, high + } + if (s > high) { + s = high; + } while (s != -1 && s >= low) { prev = EncodingHelper.prevCharHead(str, s); - if (matchCheck(origStart, s, prev)) return match(s); + if (matchCheck(origStart, s, prev)) { + return match(s); + } s = prev; } } while (s >= range); return mismatch(); - } else { /* check only. */ - if ((end - range) < regex.thresholdLength) return mismatch(); + } + if ((end - range) < regex.thresholdLength) { + return mismatch(); + } - int schStart = s; - if (regex.dMax != 0) { - if (regex.dMax == MinMaxLen.INFINITE_DISTANCE) { + int schStart = s; + if (regex.dMax != 0) { + if (regex.dMax == MinMaxLen.INFINITE_DISTANCE) { + schStart = end; + } else { + schStart += regex.dMax; + if (schStart > end) { schStart = end; - } else { - schStart += regex.dMax; - if (schStart > end) { - schStart = end; - } } } - if (!backwardSearchRange(chars, str, end, schStart, range, adjrange)) return mismatch(); + } + if (!backwardSearchRange(chars, str, end, schStart, range, adjrange)) { + return mismatch(); } } do { prev = EncodingHelper.prevCharHead(str, s); - if (matchCheck(origStart, s, prev)) return match(s); + if (matchCheck(origStart, s, prev)) { + return match(s); + } s = prev; } while (s >= range); @@ -488,8 +554,13 @@ return mismatch(); } - private boolean endBuf(int start, int range, final int minSemiEnd, final int maxSemiEnd) { - if ((maxSemiEnd - str) < regex.anchorDmin) return true; // mismatch_no_msa; + private boolean endBuf(final int startp, final int rangep, final int minSemiEnd, final int maxSemiEnd) { + int start = startp; + int range = rangep; + + if ((maxSemiEnd - str) < regex.anchorDmin) { + return true; // mismatch_no_msa; + } if (range > start) { if ((minSemiEnd - start) > regex.anchorDmax) { @@ -502,7 +573,10 @@ if ((maxSemiEnd - (range - 1)) < regex.anchorDmin) { range = maxSemiEnd - regex.anchorDmin + 1; } - if (start >= range) return true; // mismatch_no_msa; + if (start >= range) + { + return true; // mismatch_no_msa; + } } else { if ((minSemiEnd - range) > regex.anchorDmax) { range = minSemiEnd - regex.anchorDmax; @@ -510,7 +584,10 @@ if ((maxSemiEnd - start) < regex.anchorDmin) { start = maxSemiEnd - regex.anchorDmin; } - if (range > start) return true; // mismatch_no_msa; + if (range > start) + { + return true; // mismatch_no_msa; + } } return false; } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java Fri Nov 14 10:03:48 2014 -0800 @@ -19,6 +19,7 @@ */ package jdk.nashorn.internal.runtime.regexp.joni; +@SuppressWarnings("javadoc") public abstract class MatcherFactory { public abstract Matcher create(Regex regex, char[] chars, int p, int end); diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java Fri Nov 14 10:03:48 2014 -0800 @@ -46,24 +46,40 @@ }; int distanceValue() { - if (max == INFINITE_DISTANCE) return 0; + if (max == INFINITE_DISTANCE) { + return 0; + } final int d = max - min; /* return dist_vals[d] * 16 / (mm->min + 12); */ return d < distValues.length ? distValues[d] : 1; } - int compareDistanceValue(final MinMaxLen other, int v1, int v2) { - if (v2 <= 0) return -1; - if (v1 <= 0) return 1; + int compareDistanceValue(final MinMaxLen other, final int v1p, final int v2p) { + int v1 = v1p, v2 = v2p; + + if (v2 <= 0) { + return -1; + } + if (v1 <= 0) { + return 1; + } v1 *= distanceValue(); v2 *= other.distanceValue(); - if (v2 > v1) return 1; - if (v2 < v1) return -1; + if (v2 > v1) { + return 1; + } + if (v2 < v1) { + return -1; + } - if (other.min < min) return 1; - if (other.min > min) return -1; + if (other.min < min) { + return 1; + } + if (other.min > min) { + return -1; + } return 0; } @@ -96,27 +112,33 @@ } void altMerge(final MinMaxLen other) { - if (min > other.min) min = other.min; - if (max < other.max) max = other.max; + if (min > other.min) { + min = other.min; + } + if (max < other.max) { + max = other.max; + } } static final int INFINITE_DISTANCE = 0x7FFFFFFF; static int distanceAdd(final int d1, final int d2) { if (d1 == INFINITE_DISTANCE || d2 == INFINITE_DISTANCE) { return INFINITE_DISTANCE; - } else { - if (d1 <= INFINITE_DISTANCE - d2) return d1 + d2; - else return INFINITE_DISTANCE; } + if (d1 <= INFINITE_DISTANCE - d2) { + return d1 + d2; + } + return INFINITE_DISTANCE; } static int distanceMultiply(final int d, final int m) { - if (m == 0) return 0; + if (m == 0) { + return 0; + } if (d < INFINITE_DISTANCE / m) { return d * m; - } else { - return INFINITE_DISTANCE; } + return INFINITE_DISTANCE; } static String distanceRangeToString(final int a, final int b) { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java Fri Nov 14 10:03:48 2014 -0800 @@ -19,6 +19,7 @@ */ package jdk.nashorn.internal.runtime.regexp.joni; +@SuppressWarnings("javadoc") public final class NodeOptInfo { final MinMaxLen length = new MinMaxLen(); final OptAnchorInfo anchor = new OptAnchorInfo(); @@ -91,8 +92,12 @@ if (other.length.max > 0) { // TODO: make sure it is not an Oniguruma bug (casting unsigned int to int for arithmetic comparison) int otherLengthMax = other.length.max; - if (otherLengthMax == MinMaxLen.INFINITE_DISTANCE) otherLengthMax = -1; - if (expr.length > otherLengthMax) expr.length = otherLengthMax; + if (otherLengthMax == MinMaxLen.INFINITE_DISTANCE) { + otherLengthMax = -1; + } + if (expr.length > otherLengthMax) { + expr.length = otherLengthMax; + } if (expr.mmd.max == 0) { exb.select(expr); } else { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java Fri Nov 14 10:03:48 2014 -0800 @@ -36,14 +36,20 @@ void concat(final OptAnchorInfo left, final OptAnchorInfo right, final int leftLength, final int rightLength) { leftAnchor = left.leftAnchor; - if (leftLength == 0) leftAnchor |= right.leftAnchor; + if (leftLength == 0) { + leftAnchor |= right.leftAnchor; + } rightAnchor = right.rightAnchor; - if (rightLength == 0) rightAnchor |= left.rightAnchor; + if (rightLength == 0) { + rightAnchor |= left.rightAnchor; + } } boolean isSet(final int anchor) { - if ((leftAnchor & anchor) != 0) return true; + if ((leftAnchor & anchor) != 0) { + return true; + } return (rightAnchor & anchor) != 0; } @@ -77,14 +83,30 @@ static String anchorToString(final int anchor) { final StringBuffer s = new StringBuffer("["); - if ((anchor & AnchorType.BEGIN_BUF) !=0 ) s.append("begin-buf "); - if ((anchor & AnchorType.BEGIN_LINE) !=0 ) s.append("begin-line "); - if ((anchor & AnchorType.BEGIN_POSITION) !=0 ) s.append("begin-pos "); - if ((anchor & AnchorType.END_BUF) !=0 ) s.append("end-buf "); - if ((anchor & AnchorType.SEMI_END_BUF) !=0 ) s.append("semi-end-buf "); - if ((anchor & AnchorType.END_LINE) !=0 ) s.append("end-line "); - if ((anchor & AnchorType.ANYCHAR_STAR) !=0 ) s.append("anychar-star "); - if ((anchor & AnchorType.ANYCHAR_STAR_ML) !=0 ) s.append("anychar-star-pl "); + if ((anchor & AnchorType.BEGIN_BUF) !=0 ) { + s.append("begin-buf "); + } + if ((anchor & AnchorType.BEGIN_LINE) !=0 ) { + s.append("begin-line "); + } + if ((anchor & AnchorType.BEGIN_POSITION) !=0 ) { + s.append("begin-pos "); + } + if ((anchor & AnchorType.END_BUF) !=0 ) { + s.append("end-buf "); + } + if ((anchor & AnchorType.SEMI_END_BUF) !=0 ) { + s.append("semi-end-buf "); + } + if ((anchor & AnchorType.END_LINE) !=0 ) { + s.append("end-line "); + } + if ((anchor & AnchorType.ANYCHAR_STAR) !=0 ) { + s.append("anychar-star "); + } + if ((anchor & AnchorType.ANYCHAR_STAR_ML) !=0 ) { + s.append("anychar-star-pl "); + } s.append("]"); return s.toString(); diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java Fri Nov 14 10:03:48 2014 -0800 @@ -56,7 +56,9 @@ void concat(final OptExactInfo other) { if (!ignoreCase && other.ignoreCase) { - if (length >= other.length) return; /* avoid */ + if (length >= other.length) { + return; /* avoid */ + } ignoreCase = true; } @@ -65,7 +67,9 @@ int i; for (i = length; p < end;) { - if (i + 1 > OPT_EXACT_MAXLEN) break; + if (i + 1 > OPT_EXACT_MAXLEN) { + break; + } chars[i++] = other.chars[p++]; } @@ -74,15 +78,20 @@ final OptAnchorInfo tmp = new OptAnchorInfo(); tmp.concat(anchor, other.anchor, 1, 1); - if (!other.reachEnd) tmp.rightAnchor = 0; + if (!other.reachEnd) { + tmp.rightAnchor = 0; + } anchor.copy(tmp); } // ?? raw is not used here - void concatStr(final char[] lchars, int p, final int end, final boolean raw) { + void concatStr(final char[] lchars, final int pp, final int end, final boolean raw) { int i; + int p = pp; for (i = length; p < end && i < OPT_EXACT_MAXLEN;) { - if (i + 1 > OPT_EXACT_MAXLEN) break; + if (i + 1 > OPT_EXACT_MAXLEN) { + break; + } chars[i++] = lchars[p++]; } @@ -102,17 +111,23 @@ int i; for (i = 0; i < length && i < other.length; i++) { - if (chars[i] != other.chars[i]) break; + if (chars[i] != other.chars[i]) { + break; + } } - if (!other.reachEnd || i 1) v1 += 5; - if (alt.length > 1) v2 += 5; + if (length > 1) { + v1 += 5; + } + if (alt.length > 1) { + v2 += 5; + } } - if (!ignoreCase) v1 *= 2; - if (!alt.ignoreCase) v2 *= 2; + if (!ignoreCase) { + v1 *= 2; + } + if (!alt.ignoreCase) { + v2 *= 2; + } - if (mmd.compareDistanceValue(alt.mmd, v1, v2) > 0) copy(alt); + if (mmd.compareDistanceValue(alt.mmd, v1, v2) > 0) { + copy(alt); + } } // comp_opt_exact_or_map_info private static final int COMP_EM_BASE = 20; int compare(final OptMapInfo m) { - if (m.value <= 0) return -1; + if (m.value <= 0) { + return -1; + } final int ve = COMP_EM_BASE * length * (ignoreCase ? 1 : 2); final int vm = COMP_EM_BASE * 5 * 2 / m.value; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java Fri Nov 14 10:03:48 2014 -0800 @@ -31,7 +31,9 @@ mmd.clear(); anchor.clear(); value = 0; - for (int i=0; i 0) copy(alt); + if (mmd.compareDistanceValue(alt.mmd, v1, v2) > 0) { + copy(alt); + } } // alt_merge_opt_map_info void altMerge(final OptMapInfo other) { /* if (! is_equal_mml(&to->mmd, &add->mmd)) return ; */ - if (value == 0) return; + if (value == 0) { + return; + } if (other.value == 0 || mmd.max < other.mmd.max) { clear(); return; @@ -89,8 +96,12 @@ int val = 0; for (int i=0; i 0) { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/Region.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java Fri Nov 14 10:03:48 2014 -0800 @@ -19,6 +19,7 @@ */ package jdk.nashorn.internal.runtime.regexp.joni; +@SuppressWarnings("javadoc") public final class Region { static final int REGION_NOTPOS = -1; @@ -36,7 +37,9 @@ public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("Region: \n"); - for (int i=0; i textRange) end = textRange; + if (end > textRange) { + end = textRange; + } int s = textP; @@ -71,11 +74,15 @@ int p = s + 1; int t = targetP + 1; while (t < targetEnd) { - if (target[t] != text[p++]) break; + if (target[t] != text[p++]) { + break; + } t++; } - if (t == targetEnd) return s; + if (t == targetEnd) { + return s; + } } s++; } @@ -101,10 +108,14 @@ int p = s + 1; int t = targetP + 1; while (t < targetEnd) { - if (target[t] != text[p++]) break; + if (target[t] != text[p++]) { + break; + } t++; } - if (t == targetEnd) return s; + if (t == targetEnd) { + return s; + } } // s = enc.prevCharHead or s = s <= adjustText ? -1 : s - 1; s--; @@ -114,10 +125,8 @@ }; public static final class SLOW_IC extends SearchAlgorithm { - private final int caseFoldFlag; - public SLOW_IC(final Regex regex) { - this.caseFoldFlag = regex.caseFoldFlag; + //empty } @Override @@ -134,11 +143,15 @@ int end = textEnd; end -= targetEnd - targetP - 1; - if (end > textRange) end = textRange; + if (end > textRange) { + end = textRange; + } int s = textP; while (s < end) { - if (lowerCaseMatch(target, targetP, targetEnd, text, s, textEnd)) return s; + if (lowerCaseMatch(target, targetP, targetEnd, text, s, textEnd)) { + return s; + } s++; } return -1; @@ -158,17 +171,21 @@ } while (s >= textP) { - if (lowerCaseMatch(target, targetP, targetEnd, text, s, textEnd)) return s; + if (lowerCaseMatch(target, targetP, targetEnd, text, s, textEnd)) { + return s; + } s = EncodingHelper.prevCharHead(adjustText, s); } return -1; } - private boolean lowerCaseMatch(final char[] t, int tP, final int tEnd, - final char[] chars, int p, final int end) { + private static boolean lowerCaseMatch(final char[] t, final int tPp, final int tEnd, + final char[] chars, final int pp, final int end) { - while (tP < tEnd) { - if (t[tP++] != EncodingHelper.toLowerCase(chars[p++])) return false; + for (int tP = tPp, p = pp; tP < tEnd; ) { + if (t[tP++] != EncodingHelper.toLowerCase(chars[p++])) { + return false; + } } return true; } @@ -188,7 +205,9 @@ final int targetEnd = regex.exactEnd; int end = textRange + (targetEnd - targetP) - 1; - if (end > textEnd) end = textEnd; + if (end > textEnd) { + end = textEnd; + } final int tail = targetEnd - 1; int s = textP + (targetEnd - targetP) - 1; @@ -199,7 +218,9 @@ int t = tail; while (text[p] == target[t]) { - if (t == targetP) return p; + if (t == targetP) { + return p; + } p--; t--; } @@ -211,7 +232,9 @@ int t = tail; while (text[p] == target[t]) { - if (t == targetP) return p; + if (t == targetP) { + return p; + } p--; t--; } @@ -249,7 +272,9 @@ while (t < targetEnd && text[p] == target[t]) { p++; t++; } - if (t == targetEnd) return s; + if (t == targetEnd) { + return s; + } s -= regex.intMapBackward[text[s] & 0xff]; } @@ -268,8 +293,12 @@ final int len = end - p; - for (int i=0; i0; i--) skip[chars[i] & 0xff] = i; + for (int i=0; i0; i--) { + skip[chars[i] & 0xff] = i; + } } }; @@ -286,7 +315,9 @@ int s = textP; while (s < textRange) { - if (text[s] > 0xff || map[text[s]] != 0) return s; + if (text[s] > 0xff || map[text[s]] != 0) { + return s; + } s++; } return -1; @@ -297,9 +328,13 @@ final byte[] map = regex.map; int s = textStart; - if (s >= textEnd) s = textEnd - 1; + if (s >= textEnd) { + s = textEnd - 1; + } while (s >= textP) { - if (text[s] > 0xff || map[text[s]] != 0) return s; + if (text[s] > 0xff || map[text[s]] != 0) { + return s; + } s--; } return -1; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java Fri Nov 14 10:03:48 2014 -0800 @@ -20,7 +20,6 @@ package jdk.nashorn.internal.runtime.regexp.joni; import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt; - import java.lang.ref.WeakReference; import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel; import jdk.nashorn.internal.runtime.regexp.joni.constants.StackType; @@ -61,12 +60,14 @@ static final ThreadLocal> stacks = new ThreadLocal>() { + @SuppressWarnings("unused") @Override protected WeakReference initialValue() { return new WeakReference(allocateStack()); } }; + @SuppressWarnings("unused") private static StackEntry[] fetchStack() { WeakReference ref = stacks.get(); StackEntry[] stack = ref.get(); @@ -78,7 +79,9 @@ } protected final void init() { - if (stack != null) pushEnsured(ALT, regex.codeLength - 1); /* bottom stack */ + if (stack != null) { + pushEnsured(ALT, regex.codeLength - 1); /* bottom stack */ + } if (repeatStk != null) { for (int i=1; i<=regex.numMem; i++) { repeatStk[i + memStartStk] = repeatStk[i + memEndStk] = INVALID_INDEX; @@ -87,9 +90,13 @@ } protected final StackEntry ensure1() { - if (stk >= stack.length) doubleStack(); + if (stk >= stack.length) { + doubleStack(); + } StackEntry e = stack[stk]; - if (e == null) stack[stk] = e = new StackEntry(); + if (e == null) { + stack[stk] = e = new StackEntry(); + } return e; } @@ -190,7 +197,9 @@ if ((e.type & MASK_MEM_END_OR_MARK) != 0 && e.getMemNum() == mnum) { level++; } else if (e.type == MEM_START && e.getMemNum() == mnum) { - if (level == 0) break; + if (level == 0) { + break; + } level--; } } @@ -371,9 +380,8 @@ if (e.getNullCheckNum() == id) { if (level == 0) { return e.getNullCheckPStr() == s ? 1 : 0; - } else { - level--; } + level--; } } else if (e.type == NULL_CHECK_END) { level++; @@ -393,7 +401,52 @@ if (e.getNullCheckPStr() != s) { isNull = 0; break; - } else { + } + int endp; + isNull = 1; + while (k < stk) { + if (e.type == MEM_START) { + if (e.getMemEnd() == INVALID_INDEX) { + isNull = 0; + break; + } + if (bsAt(regex.btMemEnd, e.getMemNum())) { + endp = stack[e.getMemEnd()].getMemPStr(); + } else { + endp = e.getMemEnd(); + } + if (stack[e.getMemStart()].getMemPStr() != endp) { + isNull = 0; + break; + } else if (endp != s) { + isNull = -1; /* empty, but position changed */ + } + } + k++; + e = stack[k]; // !! + } + break; + } + } + } + return isNull; + } + + protected final int nullCheckMemStRec(final int id, final int s) { + int level = 0; + int k = stk; + int isNull; + while (true) { + k--; + StackEntry e = stack[k]; + + if (e.type == NULL_CHECK_START) { + if (e.getNullCheckNum() == id) { + if (level == 0) { + if (e.getNullCheckPStr() != s) { + isNull = 0; + break; + } int endp; isNull = 1; while (k < stk) { @@ -415,62 +468,16 @@ } } k++; - e = stack[k]; // !! + e = stack[k]; } break; } - } - } - } - return isNull; - } - - protected final int nullCheckMemStRec(final int id, final int s) { - int level = 0; - int k = stk; - int isNull; - while (true) { - k--; - StackEntry e = stack[k]; - - if (e.type == NULL_CHECK_START) { - if (e.getNullCheckNum() == id) { - if (level == 0) { - if (e.getNullCheckPStr() != s) { - isNull = 0; - break; - } else { - int endp; - isNull = 1; - while (k < stk) { - if (e.type == MEM_START) { - if (e.getMemEnd() == INVALID_INDEX) { - isNull = 0; - break; - } - if (bsAt(regex.btMemEnd, e.getMemNum())) { - endp = stack[e.getMemEnd()].getMemPStr(); - } else { - endp = e.getMemEnd(); - } - if (stack[e.getMemStart()].getMemPStr() != endp) { - isNull = 0; - break; - } else if (endp != s) { - isNull = -1; /* empty, but position changed */ - } - } - k++; - e = stack[k]; - } - break; - } - } else { - level--; - } + level--; } } else if (e.type == NULL_CHECK_END) { - if (e.getNullCheckNum() == id) level++; + if (e.getNullCheckNum() == id) { + level++; + } } } return isNull; @@ -485,7 +492,9 @@ if (e.type == REPEAT) { if (level == 0) { - if (e.getRepeatNum() == id) return k; + if (e.getRepeatNum() == id) { + return k; + } } } else if (e.type == CALL_FRAME) { level--; @@ -505,9 +514,8 @@ if (e.type == CALL_FRAME) { if (level == 0) { return e.getCallFrameRetAddr(); - } else { - level--; } + level--; } else if (e.type == RETURN) { level++; } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java Fri Nov 14 10:03:48 2014 -0800 @@ -20,10 +20,10 @@ package jdk.nashorn.internal.runtime.regexp.joni; import static jdk.nashorn.internal.runtime.regexp.joni.constants.MetaChar.INEFFECTIVE_META_CHAR; - import jdk.nashorn.internal.runtime.regexp.joni.constants.SyntaxProperties; -public final class Syntax implements SyntaxProperties{ +@SuppressWarnings("javadoc") +public final class Syntax implements SyntaxProperties { private final int op; private final int op2; private final int behavior; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java Fri Nov 14 10:03:48 2014 -0800 @@ -22,6 +22,7 @@ /** * @author Ola Bini */ +@SuppressWarnings("javadoc") public interface WarnCallback { WarnCallback DEFAULT = new WarnCallback() { @Override diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/Warnings.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/Warnings.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Warnings.java Fri Nov 14 10:03:48 2014 -0800 @@ -19,6 +19,7 @@ */ package jdk.nashorn.internal.runtime.regexp.joni; +@SuppressWarnings("javadoc") public interface Warnings { final String INVALID_BACKREFERENCE = "invalid back reference"; final String INVALID_SUBEXP_CALL = "invalid subexp call"; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java Fri Nov 14 10:03:48 2014 -0800 @@ -21,6 +21,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType; +@SuppressWarnings("javadoc") public final class AnchorNode extends Node implements AnchorType { public int type; public Node target; @@ -65,28 +66,60 @@ } public String typeToString() { - final StringBuilder type = new StringBuilder(); - if (isType(BEGIN_BUF)) type.append("BEGIN_BUF "); - if (isType(BEGIN_LINE)) type.append("BEGIN_LINE "); - if (isType(BEGIN_POSITION)) type.append("BEGIN_POSITION "); - if (isType(END_BUF)) type.append("END_BUF "); - if (isType(SEMI_END_BUF)) type.append("SEMI_END_BUF "); - if (isType(END_LINE)) type.append("END_LINE "); - if (isType(WORD_BOUND)) type.append("WORD_BOUND "); - if (isType(NOT_WORD_BOUND)) type.append("NOT_WORD_BOUND "); - if (isType(WORD_BEGIN)) type.append("WORD_BEGIN "); - if (isType(WORD_END)) type.append("WORD_END "); - if (isType(PREC_READ)) type.append("PREC_READ "); - if (isType(PREC_READ_NOT)) type.append("PREC_READ_NOT "); - if (isType(LOOK_BEHIND)) type.append("LOOK_BEHIND "); - if (isType(LOOK_BEHIND_NOT)) type.append("LOOK_BEHIND_NOT "); - if (isType(ANYCHAR_STAR)) type.append("ANYCHAR_STAR "); - if (isType(ANYCHAR_STAR_ML)) type.append("ANYCHAR_STAR_ML "); - return type.toString(); + final StringBuilder sb = new StringBuilder(); + if (isType(BEGIN_BUF)) { + sb.append("BEGIN_BUF "); + } + if (isType(BEGIN_LINE)) { + sb.append("BEGIN_LINE "); + } + if (isType(BEGIN_POSITION)) { + sb.append("BEGIN_POSITION "); + } + if (isType(END_BUF)) { + sb.append("END_BUF "); + } + if (isType(SEMI_END_BUF)) { + sb.append("SEMI_END_BUF "); + } + if (isType(END_LINE)) { + sb.append("END_LINE "); + } + if (isType(WORD_BOUND)) { + sb.append("WORD_BOUND "); + } + if (isType(NOT_WORD_BOUND)) { + sb.append("NOT_WORD_BOUND "); + } + if (isType(WORD_BEGIN)) { + sb.append("WORD_BEGIN "); + } + if (isType(WORD_END)) { + sb.append("WORD_END "); + } + if (isType(PREC_READ)) { + sb.append("PREC_READ "); + } + if (isType(PREC_READ_NOT)) { + sb.append("PREC_READ_NOT "); + } + if (isType(LOOK_BEHIND)) { + sb.append("LOOK_BEHIND "); + } + if (isType(LOOK_BEHIND_NOT)) { + sb.append("LOOK_BEHIND_NOT "); + } + if (isType(ANYCHAR_STAR)) { + sb.append("ANYCHAR_STAR "); + } + if (isType(ANYCHAR_STAR_ML)) { + sb.append("ANYCHAR_STAR_ML "); + } + return sb.toString(); } - private boolean isType(final int type) { - return (this.type & type) != 0; + private boolean isType(final int t) { + return (this.type & t) != 0; } } diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java Fri Nov 14 10:03:48 2014 -0800 @@ -19,6 +19,7 @@ */ package jdk.nashorn.internal.runtime.regexp.joni.ast; +@SuppressWarnings("javadoc") public final class AnyCharNode extends Node { public AnyCharNode(){} diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java Fri Nov 14 10:03:48 2014 -0800 @@ -21,6 +21,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment; +@SuppressWarnings("javadoc") public final class BackRefNode extends StateNode { public final int backRef; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java Fri Nov 14 10:03:48 2014 -0800 @@ -34,6 +34,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.exception.SyntaxException; import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException; +@SuppressWarnings("javadoc") public final class CClassNode extends Node { private static final int FLAG_NCCLASS_NOT = 1<<0; private static final int FLAG_NCCLASS_SHARE = 1<<1; @@ -100,7 +101,9 @@ @Override public boolean equals(final Object other) { - if (!(other instanceof CClassNode)) return false; + if (!(other instanceof CClassNode)) { + return false; + } final CClassNode cc = (CClassNode)other; return ctype == cc.ctype && isNot() == cc.isNot(); } @@ -110,11 +113,12 @@ if (Config.USE_SHARED_CCLASS_TABLE) { int hash = 0; hash += ctype; - if (isNot()) hash++; + if (isNot()) { + hash++; + } return hash + (hash >> 5); - } else { - return super.hashCode(); } + return super.hashCode(); } @Override @@ -128,10 +132,14 @@ } public String flagsToString() { - final StringBuilder flags = new StringBuilder(); - if (isNot()) flags.append("NOT "); - if (isShare()) flags.append("SHARE "); - return flags.toString(); + final StringBuilder f = new StringBuilder(); + if (isNot()) { + f.append("NOT "); + } + if (isShare()) { + f.append("SHARE "); + } + return f.toString(); } public boolean isEmpty() { @@ -251,7 +259,7 @@ } // add_ctype_to_cc_by_range // Encoding out! - public void addCTypeByRange(final int ctype, final boolean not, final int sbOut, final int mbr[]) { + public void addCTypeByRange(final int ct, final boolean not, final int sbOut, final int mbr[]) { final int n = mbr[0]; if (!not) { @@ -294,10 +302,14 @@ // !goto sb_end2!, remove duplication prev = sbOut; for (i=0; i 0xff) throw new ValueException(ErrorMessages.ERR_INVALID_CODE_POINT_VALUE); + if (arg.vs > 0xff) { + throw new ValueException(ErrorMessages.ERR_INVALID_CODE_POINT_VALUE); + } bs.set(arg.vs); } else if (arg.type == CCVALTYPE.CODE_POINT) { addCodeRange(env, arg.vs, arg.vs); @@ -450,16 +489,17 @@ case RANGE: if (arg.inType == arg.type) { if (arg.inType == CCVALTYPE.SB) { - if (arg.vs > 0xff || arg.v > 0xff) throw new ValueException(ErrorMessages.ERR_INVALID_CODE_POINT_VALUE); + if (arg.vs > 0xff || arg.v > 0xff) { + throw new ValueException(ErrorMessages.ERR_INVALID_CODE_POINT_VALUE); + } if (arg.vs > arg.v) { if (env.syntax.allowEmptyRangeInCC()) { // goto ccs_range_end arg.state = CCSTATE.COMPLETE; break; - } else { - throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS); } + throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS); } bs.setRange(arg.vs, arg.v); } else { @@ -471,9 +511,8 @@ // goto ccs_range_end arg.state = CCSTATE.COMPLETE; break; - } else { - throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS); } + throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS); } bs.setRange(arg.vs, arg.v < 0xff ? arg.v : 0xff); addCodeRange(env, arg.vs, arg.v); @@ -509,9 +548,8 @@ if (isNot()) { return !found; - } else { - return found; } + return found; } // onig_is_code_in_cc diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java Fri Nov 14 10:03:48 2014 -0800 @@ -24,6 +24,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages; import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException; +@SuppressWarnings("javadoc") public final class ConsAltNode extends Node { public Node car; public ConsAltNode cdr; @@ -31,9 +32,13 @@ private ConsAltNode(final Node car, final ConsAltNode cdr, final int type) { this.car = car; - if (car != null) car.parent = this; + if (car != null) { + car.parent = this; + } this.cdr = cdr; - if (cdr != null) cdr.parent = this; + if (cdr != null) { + cdr.parent = this; + } this.type = type; } @@ -46,8 +51,9 @@ return new ConsAltNode(left, right, LIST); } - public static ConsAltNode listAdd(ConsAltNode list, final Node x) { + public static ConsAltNode listAdd(final ConsAltNode listp, final Node x) { final ConsAltNode n = newListNode(x, null); + ConsAltNode list = listp; if (list != null) { while (list.cdr != null) { diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java Fri Nov 14 10:03:48 2014 -0800 @@ -22,6 +22,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.Option; import jdk.nashorn.internal.runtime.regexp.joni.constants.EncloseType; +@SuppressWarnings("javadoc") public final class EncloseNode extends StateNode implements EncloseType { public final int type; // enclose type diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java Fri Nov 14 10:03:48 2014 -0800 @@ -24,6 +24,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.WarnCallback; import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType; +@SuppressWarnings("javadoc") public abstract class Node implements NodeType { public Node parent; @@ -33,8 +34,12 @@ return 1 << getType(); } - protected void setChild(final Node tgt){} // default definition - protected Node getChild(){return null;} // default definition + protected void setChild(final Node tgt) { + //empty, default definition + } + protected Node getChild() { + return null; // default definition + } public void swap(final Node with) { Node tmp; @@ -46,9 +51,13 @@ //setChild(with.getChild()); //with.setChild(tmp); - if (parent != null) parent.setChild(with); + if (parent != null) { + parent.setChild(with); + } - if (with.parent != null) with.parent.setChild(this); + if (with.parent != null) { + with.parent.setChild(this); + } tmp = parent; parent = with.parent; @@ -81,16 +90,22 @@ } protected static String pad(final Object value, final int level) { - if (value == null) return "NULL"; + if (value == null) { + return "NULL"; + } final StringBuilder pad = new StringBuilder(" "); - for (int i=0; i { public ObjPtr() { this(null); diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java Fri Nov 14 10:03:48 2014 -0800 @@ -19,6 +19,7 @@ */ package jdk.nashorn.internal.runtime.regexp.joni.exception; +@SuppressWarnings("javadoc") public interface ErrorMessages { /* from jcodings */ diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java Fri Nov 14 10:03:48 2014 -0800 @@ -19,6 +19,7 @@ */ package jdk.nashorn.internal.runtime.regexp.joni.exception; +@SuppressWarnings("javadoc") public class InternalException extends JOniException{ private static final long serialVersionUID = -3871816465397927992L; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java Fri Nov 14 10:03:48 2014 -0800 @@ -19,6 +19,7 @@ */ package jdk.nashorn.internal.runtime.regexp.joni.exception; +@SuppressWarnings("javadoc") public class JOniException extends RuntimeException{ private static final long serialVersionUID = -6027192180014164667L; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java Fri Nov 14 10:03:48 2014 -0800 @@ -19,6 +19,7 @@ */ package jdk.nashorn.internal.runtime.regexp.joni.exception; +@SuppressWarnings("javadoc") public class SyntaxException extends JOniException{ private static final long serialVersionUID = 7862720128961874288L; diff -r 99f9e7a9cf0e -r fc37699ddc0e src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java --- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java Wed Nov 12 13:47:23 2014 -0800 +++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java Fri Nov 14 10:03:48 2014 -0800 @@ -19,7 +19,8 @@ */ package jdk.nashorn.internal.runtime.regexp.joni.exception; -public class ValueException extends SyntaxException{ +@SuppressWarnings("javadoc") +public class ValueException extends SyntaxException { private static final long serialVersionUID = -196013852479929134L; public ValueException(final String message) { diff -r 99f9e7a9cf0e -r fc37699ddc0e test/script/basic/JDK-8035312.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8035312.js Fri Nov 14 10:03:48 2014 -0800 @@ -0,0 +1,225 @@ +/* + * 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-8035312 push to frozen array must not increase length property + * + * @test + * @run + * @fork + * @option -Dnashorn.debug=true + */ + +function printArrayDataClass(x) { + if (typeof Debug !== 'undefined') { + print(Debug.getArrayDataClass(x)); + } +} + +function gpush(x, elem) { + try { + print("Pushing " + elem + " to " + x); + x.push(elem); + } catch (e) { + print("caught error" + e); + } + print("\tarray is now [" + x + "] length is = " + x.length); + print(); + printArrayDataClass(x); +} + +function gpop(x) { + try { + print("Popping from " + x); + x.pop(); + } catch (e) { + if (!(e instanceof TypeError)) { + print("e of wrong type " + e); + } + } + print("\tarray is now [" + x + "] length is = " + x.length); + print(); + printArrayDataClass(x); +} + +function checkArray(x) { + print(); + print(">>> Push test"); + + var olen = x.length; + gpush(x, 0); + + print("x.length === " + x.length + " (should be " + olen + ")"); + print("x[3] === " + x[3] + " (should be 0)"); + print("x[4] === " + x[4] + " (should be undefined)"); + + print(); + print(">>> Pop test"); + gpop(x); + gpop(x); + print("x.length === " + x.length + " (should be " + olen + ")"); + print("x === " + x); + + for (var i = 0 ; i < 5; i++) { + gpop(x); + } + + print("x.length === " + x.length + " (should be " + olen + ")"); + print("x === " + x); +} + +print("*** Freezing"); +var frozen = [1,2,3]; +Object.freeze(frozen); +checkArray(frozen); +printArrayDataClass(frozen); + +//so far so good + +print(); +print("*** Other length not writable issues"); +var lengthNotWritable = [1,2,3]; +Object.defineProperty(lengthNotWritable, "length", { writable: false }); +checkArray(lengthNotWritable); +printArrayDataClass(lengthNotWritable); + +function set(array, from, to, stride) { + //add three elements + for (var i = from; i < to; i+=stride) { + try { + print("Writing " + i); + array[i] = i; + printArrayDataClass(array); + } catch (e) { + print(e instanceof TypeError); + } + } +} + +//define empty array with non writable length +var arr = [1]; +Object.defineProperty(arr, "length", { writable: false }); + +var olen2 = arr.length; + +set(arr, 0, 3, 1); + +if (arr.length != olen2) { + throw new ("error: " + arr.length + " != " + olen2); +} + +print(); +print("array writing 0-3, with 1 stride, array = " + arr); +print("length = " + arr.length + ", but elements are: " + arr[0] + " " + arr[1] + " " + arr[2]); +print(); + +//do the same but sparse/deleted range +var arr2 = [1]; +Object.defineProperty(arr2, "length", { writable: false }); + +print("initial length = " + arr2.length); +var olen3 = arr2.length; + +set(arr2, 0, 30, 3); + +if (arr2.length != olen3) { + throw new ("error: " + arr2.length + " != " + olen3); +} + +print(); +var larger = 20; +print("array writing 0-" + larger + ", with 3 stride, array = " + arr2); +print("length = " + arr2.length + ", but elements are: " + arr2[0] + " " + arr2[1] + " " + arr2[2]); + +for (var i = 0; i < larger; i++) { + if (arr2[i] === undefined) { + continue; + } + print(arr2[i] + " has length " + arr2.length); +} + +print(); +var elem = 0x7fffffff - 10; +printArrayDataClass(arr2); +print("adding a new element high up in the array"); +print("length before element was added " + arr2.length); +print("putting sparse at " + elem); +arr2[elem] = "sparse"; +print("length after element was added " + arr2.length + " should be the same"); +printArrayDataClass(arr2); + +print(); +print("Printing arr2 - this will fail if length is > 28 and it is " + arr2.length); +print("arr2 = [" + arr2 + "]"); +print("new length that should not be writable = " + arr2.length); +print(arr2[elem] === "sparse"); +print(arr2[elem]); +for (var i = 0; i < larger; i++) { + print(arr2[i]); +} +for (var key in arr2) { + print(key + ":" + arr2[key]); +} + +//issues reported by sundar - generic setter doesn't go through push/pop bulkable + +function sundarExample2(arr, _writable) { + print("Checking if push works for bulkable non bulkable arrays - Setting length property not allowed"); + arr[0] = "bar"; + print(arr.length + " should be 1"); // should be 1 + print(arr[0] + " should be bar"); + print("["+ arr + "] should be [bar]"); + + // Object.defineProperty(arr, "length", { configurable: _writable }); + Object.defineProperty(arr, "length", { writable: _writable }); + arr[1] = "baz"; + + if (_writable) { + print(arr.length + " should be 2"); + print(arr[0] + " should be bar"); + print(arr[1] + " should be baz"); + print("["+ arr + "] should be [bar,baz]"); + } else { + print(arr.length + " should STILL be 1"); + print(arr[0] + " should be bar"); + print(arr[1] + " should be baz"); + print("["+ arr + "] should be [bar]"); + } +} + +var newArr1 = []; +sundarExample2(newArr1, false); +print(); +try { + sundarExample2(newArr1, true); + print("should not get here"); +} catch (e) { + if (!(e instanceof TypeError)) { + print("Wrong exception"); + } + print("got TypeError when redefining length, as expected") +} +print(); + +sundarExample2([], true); +print("Done"); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/script/basic/JDK-8035312.js.EXPECTED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8035312.js.EXPECTED Fri Nov 14 10:03:48 2014 -0800 @@ -0,0 +1,186 @@ +*** Freezing + +>>> Push test +Pushing 0 to 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter +x.length === 3 (should be 3) +x[3] === undefined (should be 0) +x[4] === undefined (should be undefined) + +>>> Pop test +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter +x.length === 3 (should be 3) +x === 1,2,3 +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter +x.length === 3 (should be 3) +x === 1,2,3 +class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter + +*** Other length not writable issues + +>>> Push test +Pushing 0 to 1,2,3 +caught errorTypeError: "length" is not a writable property of [object Array] + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +x.length === 3 (should be 3) +x[3] === 0 (should be 0) +x[4] === undefined (should be undefined) + +>>> Pop test +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +x.length === 3 (should be 3) +x === 1,2,3 +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Popping from 1,2,3 + array is now [1,2,3] length is = 3 + +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +x.length === 3 (should be 3) +x === 1,2,3 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 0 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 1 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 2 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter + +array writing 0-3, with 1 stride, array = 0 +length = 1, but elements are: 0 undefined 2 + +initial length = 1 +Writing 0 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 3 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 6 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 9 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 12 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 15 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 18 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 21 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 24 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +Writing 27 +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter + +array writing 0-20, with 3 stride, array = 0 +length = 1, but elements are: 0 undefined undefined +0 has length 1 + +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter +adding a new element high up in the array +length before element was added 1 +putting sparse at 2147483637 +length after element was added 1 should be the same +class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter + +Printing arr2 - this will fail if length is > 28 and it is 1 +arr2 = [0] +new length that should not be writable = 1 +true +sparse +0 +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +undefined +0:0 +2147483637:sparse +Checking if push works for bulkable non bulkable arrays - Setting length property not allowed +1 should be 1 +bar should be bar +[bar] should be [bar] +1 should STILL be 1 +bar should be bar +baz should be baz +[bar] should be [bar] + +Checking if push works for bulkable non bulkable arrays - Setting length property not allowed +1 should be 1 +bar should be bar +[bar] should be [bar] +got TypeError when redefining length, as expected + +Checking if push works for bulkable non bulkable arrays - Setting length property not allowed +1 should be 1 +bar should be bar +[bar] should be [bar] +2 should be 2 +bar should be bar +baz should be baz +[bar,baz] should be [bar,baz] +Done diff -r 99f9e7a9cf0e -r fc37699ddc0e test/script/basic/JDK-8035312_2.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8035312_2.js Fri Nov 14 10:03:48 2014 -0800 @@ -0,0 +1,65 @@ +/* + * 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-8035312_2 - length setter and iterators + * + * @test + * @run + */ + +"use strict" + +function printArray(a,n) { + print("PRINT_ARRAY CALLED: length = " + a.length); + print(); + + print("INDEXED"); + for (var x = 0; x m = new HashMap<>(); + //final Map m = new HashMap<>(); e.eval("var x = 'f'; x += 'oo'; var obj = {x: x};"); assertEquals("foo", ((JSObject)b.get("obj")).getMember("x")); } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java --- a/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -28,7 +28,6 @@ import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals; - import java.util.Arrays; import java.util.Calendar; import java.util.Locale; @@ -45,6 +44,7 @@ * @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.MethodAccessTest * @run testng/othervm jdk.nashorn.api.javaaccess.MethodAccessTest */ +@SuppressWarnings("javadoc") public class MethodAccessTest { private static ScriptEngine e = null; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java --- a/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -28,7 +28,6 @@ import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals; - import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; @@ -42,6 +41,7 @@ * @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.NumberAccessTest * @run testng/othervm jdk.nashorn.api.javaaccess.NumberAccessTest */ +@SuppressWarnings("javadoc") public class NumberAccessTest { private static ScriptEngine e; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java --- a/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,7 +27,6 @@ import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; - import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; @@ -41,6 +40,7 @@ * @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.NumberBoxingTest * @run testng/othervm jdk.nashorn.api.javaaccess.NumberBoxingTest */ +@SuppressWarnings("javadoc") public class NumberBoxingTest { private static ScriptEngine e; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java --- a/test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,7 +27,6 @@ import static org.testng.AssertJUnit.assertEquals; import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals; - import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; @@ -41,6 +40,7 @@ * @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.ObjectAccessTest * @run testng/othervm jdk.nashorn.api.javaaccess.ObjectAccessTest */ +@SuppressWarnings("javadoc") public class ObjectAccessTest { private static ScriptEngine e = null; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/javaaccess/Person.java --- a/test/src/jdk/nashorn/api/javaaccess/Person.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/javaaccess/Person.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.api.javaaccess; +@SuppressWarnings("javadoc") public class Person { public int id = 0; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/javaaccess/SharedObject.java --- a/test/src/jdk/nashorn/api/javaaccess/SharedObject.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/javaaccess/SharedObject.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,6 +29,7 @@ import javax.script.ScriptEngine; import javax.script.ScriptException; +@SuppressWarnings("javadoc") public class SharedObject { // Public fields diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java --- a/test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,7 +27,6 @@ import static org.testng.AssertJUnit.assertEquals; import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals; - import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; @@ -41,6 +40,7 @@ * @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.StringAccessTest * @run testng/othervm jdk.nashorn.api.javaaccess.StringAccessTest */ +@SuppressWarnings("javadoc") public class StringAccessTest { private static ScriptEngine e = null; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/scripting/InvocableTest.java --- a/test/src/jdk/nashorn/api/scripting/InvocableTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/scripting/InvocableTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,7 +27,6 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; - import java.util.Objects; import java.util.function.Function; import javax.script.Invocable; @@ -42,9 +41,10 @@ /** * Tests for javax.script.Invocable implementation of nashorn. */ +@SuppressWarnings("javadoc") public class InvocableTest { - private void log(final String msg) { + private static void log(final String msg) { org.testng.Reporter.log(msg, true); } @@ -100,7 +100,7 @@ try { final Object obj = e.eval("({})"); - final Object res = ((Invocable) e).invokeMethod(obj, null); + ((Invocable) e).invokeMethod(obj, null); fail("should have thrown NPE"); } catch (final Exception exp) { if (!(exp instanceof NullPointerException)) { @@ -120,7 +120,7 @@ try { final Object obj = e.eval("({})"); - final Object res = ((Invocable) e).invokeMethod(obj, "nonExistentMethod"); + ((Invocable) e).invokeMethod(obj, "nonExistentMethod"); fail("should have thrown NoSuchMethodException"); } catch (final Exception exp) { if (!(exp instanceof NoSuchMethodException)) { @@ -398,7 +398,7 @@ final ScriptEngine e = m.getEngineByName("nashorn"); try { - final Object res = ((Invocable) e).invokeFunction(null); + ((Invocable)e).invokeFunction(null); fail("should have thrown NPE"); } catch (final Exception exp) { if (!(exp instanceof NullPointerException)) { @@ -418,7 +418,7 @@ final ScriptEngine e = m.getEngineByName("nashorn"); try { - final Object res = ((Invocable) e).invokeFunction("NonExistentFunc"); + ((Invocable)e).invokeFunction("NonExistentFunc"); fail("should have thrown NoSuchMethodException"); } catch (final Exception exp) { if (!(exp instanceof NoSuchMethodException)) { @@ -439,7 +439,7 @@ try { // define an object with method on it - final Object obj = e.eval("function hello() { return 'Hello World!'; }"); + e.eval("function hello() { return 'Hello World!'; }"); final ScriptContext ctxt = new SimpleScriptContext(); ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE); // change engine's current context @@ -526,13 +526,13 @@ } @Test - @SuppressWarnings("unchecked") public void defaultMethodTest() throws ScriptException { final ScriptEngineManager m = new ScriptEngineManager(); final ScriptEngine e = m.getEngineByName("nashorn"); final Invocable inv = (Invocable) e; final Object obj = e.eval("({ apply: function(arg) { return arg.toUpperCase(); }})"); + @SuppressWarnings("unchecked") final Function func = inv.getInterface(obj, Function.class); assertEquals(func.apply("hello"), "HELLO"); } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/scripting/MultipleEngineTest.java --- a/test/src/jdk/nashorn/api/scripting/MultipleEngineTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/scripting/MultipleEngineTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -37,7 +37,7 @@ * @test * @run testng jdk.nashorn.api.scripting.MultipleEngineTest */ - +@SuppressWarnings("javadoc") public class MultipleEngineTest { @Test public void createAndUseManyEngine() throws ScriptException { diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java --- a/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -44,6 +44,7 @@ * JDK-8024615: Refactor ScriptObjectMirror and JSObject to support external * JSObject implementations. */ +@SuppressWarnings("javadoc") public class PluggableJSObjectTest { public static class MapWrapperObject extends AbstractJSObject { private final HashMap map = new LinkedHashMap<>(); @@ -202,6 +203,7 @@ } public static class Factory extends AbstractJSObject { + @SuppressWarnings("unused") @Override public Object newObject(final Object... args) { return new HashMap(); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/scripting/ScopeTest.java --- a/test/src/jdk/nashorn/api/scripting/ScopeTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/scripting/ScopeTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -28,7 +28,6 @@ import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; - import javax.script.Bindings; import javax.script.ScriptContext; import javax.script.ScriptEngine; @@ -42,6 +41,7 @@ /** * Tests for jsr223 Bindings "scope" (engine, global scopes) */ +@SuppressWarnings("javadoc") public class ScopeTest { @Test @@ -655,6 +655,8 @@ /** * Test "slow" scopes involving {@code with} and {@code eval} statements for shared script classes with multiple globals. + * @throws ScriptException + * @throws InterruptedException */ @Test public static void testSlowScope() throws ScriptException, InterruptedException { diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java --- a/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -26,12 +26,9 @@ package jdk.nashorn.api.scripting; import static org.testng.Assert.fail; - import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; -import java.util.Objects; -import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; @@ -40,9 +37,10 @@ /** * jsr223 tests for security access checks. */ +@SuppressWarnings("javadoc") public class ScriptEngineSecurityTest { - private void log(final String msg) { + private static void log(final String msg) { org.testng.Reporter.log(msg, true); } @@ -169,6 +167,7 @@ } // @bug 8032948: Nashorn linkages awry + @SuppressWarnings("serial") public static class FakeProxy extends Proxy { public FakeProxy(final InvocationHandler ih) { super(ih); @@ -180,7 +179,7 @@ } @Test - public void fakeProxySubclassAccessCheckTest() throws ScriptException { + public void fakeProxySubclassAccessCheckTest() { if (System.getSecurityManager() == null) { // pass vacuously return; @@ -197,7 +196,7 @@ // Should not be able to call static methods of Proxy via fake subclass try { - final Class c = (Class)e.eval(getClass); + e.eval(getClass); fail("should have thrown SecurityException"); } catch (final Exception exp) { if (! (exp instanceof SecurityException)) { @@ -207,7 +206,7 @@ } @Test - public void fakeProxySubclassAccessCheckTest2() throws ScriptException { + public void fakeProxySubclassAccessCheckTest2() { if (System.getSecurityManager() == null) { // pass vacuously return; @@ -224,7 +223,7 @@ // Should not be able to call static methods of Proxy via fake subclass try { - final Class c = (Class)e.eval(getClass); + e.eval(getClass); fail("should have thrown SecurityException"); } catch (final Exception exp) { if (! (exp instanceof SecurityException)) { @@ -234,7 +233,7 @@ } @Test - public static void proxyStaticAccessCheckTest() throws ScriptException { + public static void proxyStaticAccessCheckTest() { if (System.getSecurityManager() == null) { // pass vacuously return; @@ -247,7 +246,7 @@ new Class[] { Runnable.class }, new InvocationHandler() { @Override - public Object invoke(final Object p, final Method m, final Object[] a) { + public Object invoke(final Object p, final Method mtd, final Object[] a) { return null; } }); @@ -284,7 +283,9 @@ } }); fail("SecurityException should have been thrown"); - } catch (final SecurityException exp) {} + } catch (final SecurityException e) { + //empty + } } @Test @@ -303,6 +304,8 @@ } }); fail("SecurityException should have been thrown"); - } catch (final SecurityException exp) {} + } catch (final SecurityException e) { + //empty + } } } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java --- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,7 +29,6 @@ import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; - import java.io.StringReader; import java.io.StringWriter; import java.lang.reflect.InvocationHandler; @@ -54,9 +53,10 @@ * @build jdk.nashorn.api.scripting.Window jdk.nashorn.api.scripting.WindowEventHandler jdk.nashorn.api.scripting.VariableArityTestInterface jdk.nashorn.api.scripting.ScriptEngineTest * @run testng/othervm jdk.nashorn.api.scripting.ScriptEngineTest */ +@SuppressWarnings("javadoc") public class ScriptEngineTest { - private void log(final String msg) { + private static void log(final String msg) { org.testng.Reporter.log(msg, true); } @@ -145,6 +145,8 @@ case "nashorn": seenNashorn = true; break; case "javascript": seenJavaScript = true; break; case "ECMAScript": seenECMAScript = true; break; + default: + break; } } @@ -159,6 +161,8 @@ case "application/ecmascript": seenAppECMA = true; break; case "text/javascript": seenTextJS = true; break; case "text/ecmascript": seenTextECMA = true; break; + default: + break; } } @@ -548,7 +552,7 @@ new Class[] { Runnable.class }, new InvocationHandler() { @Override - public Object invoke(final Object p, final Method m, final Object[] a) { + public Object invoke(final Object p, final Method mtd, final Object[] a) { reached[0] = true; return null; } @@ -633,7 +637,7 @@ public static class Context { private Object myobj; - public void set(Object o) { + public void set(final Object o) { myobj = o; } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java --- a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -46,6 +46,7 @@ /** * Tests to check jdk.nashorn.api.scripting.ScriptObjectMirror API. */ +@SuppressWarnings("javadoc") public class ScriptObjectMirrorTest { @SuppressWarnings("unchecked") @@ -343,14 +344,13 @@ assertEquals(ScriptObjectMirror.class, value3.getClass()); assertEquals(ScriptObjectMirror.class, value4.getClass()); assertTrue((boolean)invocable.invokeFunction("compare", value1, value1)); - assertTrue((boolean)example.compare(value1, value1)); + assertTrue(example.compare(value1, value1)); assertTrue((boolean)invocable.invokeFunction("compare", value3, value4)); - assertTrue((boolean)example.compare(value3, value4)); + assertTrue(example.compare(value3, value4)); } // @bug 8053910: ScriptObjectMirror causing havoc with Invocation interface @Test - @SuppressWarnings("unchecked") public void mirrorUnwrapInterfaceMethod() throws Exception { final ScriptEngineManager engineManager = new ScriptEngineManager(); final ScriptEngine engine = engineManager.getEngineByName("nashorn"); @@ -358,6 +358,7 @@ engine.eval("function apply(obj) { " + " return obj instanceof Packages.jdk.nashorn.api.scripting.ScriptObjectMirror; " + "}"); + @SuppressWarnings("unchecked") final Function func = invocable.getInterface(Function.class); assertFalse((boolean)func.apply(engine.eval("({ x: 2 })"))); } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java --- a/test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.api.scripting; +@SuppressWarnings("javadoc") public interface VariableArityTestInterface { public String test1(int i, String... strings); public String test2(int i, String... strings); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/scripting/Window.java --- a/test/src/jdk/nashorn/api/scripting/Window.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/scripting/Window.java Fri Nov 14 10:03:48 2014 -0800 @@ -28,6 +28,7 @@ import java.util.Map; import javax.script.Bindings; +@SuppressWarnings("javadoc") public class Window { private String location = "http://localhost:8080/window"; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/api/scripting/WindowEventHandler.java --- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,8 +25,7 @@ package jdk.nashorn.api.scripting; +@SuppressWarnings("javadoc") public interface WindowEventHandler { - public boolean loaded(); - } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/codegen/CompilerTest.java --- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,7 +27,6 @@ import static jdk.nashorn.internal.runtime.Source.readFully; import static jdk.nashorn.internal.runtime.Source.sourceFor; - import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; @@ -45,6 +44,7 @@ /** * Tests to check Nashorn JS compiler - just compiler and not execution of scripts. */ +@SuppressWarnings("javadoc") public class CompilerTest { private static final boolean VERBOSE = Boolean.valueOf(System.getProperty("compilertest.verbose")); private static final boolean TEST262 = Boolean.valueOf(System.getProperty("compilertest.test262")); @@ -56,7 +56,7 @@ public boolean exclude(File file, String content); } - private void log(final String msg) { + private static void log(final String msg) { org.testng.Reporter.log(msg, true); } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/parser/ParserTest.java --- a/test/src/jdk/nashorn/internal/parser/ParserTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/parser/ParserTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,7 +27,6 @@ import static jdk.nashorn.internal.runtime.Source.readFully; import static jdk.nashorn.internal.runtime.Source.sourceFor; - import java.io.File; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ErrorManager; @@ -41,6 +40,7 @@ /** * Run tests to check Nashorn's parser. */ +@SuppressWarnings("javadoc") public class ParserTest { private static final boolean VERBOSE = Boolean.valueOf(System.getProperty("parsertest.verbose")); private static final boolean TEST262 = Boolean.valueOf(System.getProperty("parsertest.test262")); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/performance/AuroraWrapper.java --- a/test/src/jdk/nashorn/internal/performance/AuroraWrapper.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/performance/AuroraWrapper.java Fri Nov 14 10:03:48 2014 -0800 @@ -43,6 +43,7 @@ import org.w3c.dom.NodeList; import org.xml.sax.SAXException; +@SuppressWarnings("javadoc") public class AuroraWrapper { public static String fileName = "report.xml"; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/performance/OctaneTest.java --- a/test/src/jdk/nashorn/internal/performance/OctaneTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/performance/OctaneTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -40,6 +40,7 @@ import java.util.List; import org.testng.annotations.Test; +@SuppressWarnings("javadoc") public class OctaneTest { @Test @@ -72,7 +73,7 @@ genericTest("GBEMU"); } - /* @Test +/* @Test public void mandreelTest() { genericTest("Mandreel"); }*/ @@ -107,10 +108,20 @@ genericTest("Splay"); } + @Test +/* public void typeScriptTest() { + genericTest("TypeScript"); + } + + @Test + public void zlibTest() { + genericTest("zlib"); + }/*/ + public void genericTest(final String benchmark) { try { final String mainScript = "test/script/basic/run-octane.js"; - final String benchmarkScript = "test/script/external/octane/benchmarks/"+benchmark.toLowerCase() + ".js"; + final String benchmarkScript = "test/script/external/octane/benchmarks/" + benchmark.toLowerCase() + ".js"; final String[] args = { "--", benchmarkScript, diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java --- a/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java Fri Nov 14 10:03:48 2014 -0800 @@ -36,10 +36,7 @@ import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptRuntime; -/** - * - * @author Pavel Stepanov - */ +@SuppressWarnings("javadoc") public class PerformanceWrapper extends jdk.nashorn.tools.Shell { int _numberOfIterations; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/performance/SplayTest.java --- a/test/src/jdk/nashorn/internal/performance/SplayTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/performance/SplayTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,10 +27,7 @@ import org.testng.annotations.Test; -/** - * - * @author Pavel Stepanov - */ +@SuppressWarnings("javadoc") public class SplayTest { @Test diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java --- a/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,18 +25,17 @@ package jdk.nashorn.internal.runtime; +import static org.testng.Assert.fail; +import java.io.File; +import javax.script.ScriptEngine; +import javax.script.ScriptException; 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; -import javax.script.ScriptException; -import java.io.File; - -import static org.testng.Assert.fail; - +@SuppressWarnings("javadoc") public class ClassFilterTest { private static final String NASHORN_CODE_CACHE = "nashorn.persistent.code.cache"; private static final String CLASSFILTER_CODE_CACHE = "build/classfilter_nashorn_code_cache"; @@ -48,7 +47,7 @@ // test contributes much. We need faster "ant clean test" cycle for // developers. public void runExternalJsTest() { - String[] paths = new String[]{ + final String[] paths = new String[]{ "test/script/basic/compile-octane.js", "test/script/basic/jquery.js", "test/script/basic/prototype.js", @@ -57,12 +56,12 @@ "test/script/basic/yui.js", "test/script/basic/run-octane.js" }; - NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); - for (String path : paths) { - ScriptEngine engine = factory.getScriptEngine(new String[]{"-scripting"}, getClass().getClassLoader(), getClassFilter()); + final NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); + for (final String path : paths) { + final ScriptEngine engine = factory.getScriptEngine(new String[]{"-scripting"}, getClass().getClassLoader(), getClassFilter()); try { engine.eval(new URLReader(new File(path).toURI().toURL())); - } catch (Exception e) { + } catch (final Exception e) { fail("Script " + path + " fails with exception :" + e.getMessage()); } } @@ -70,12 +69,13 @@ @Test public void noJavaOptionTest() { - NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); - ScriptEngine engine = factory.getScriptEngine(new String[]{"--no-java"}, getClass().getClassLoader(), getClassFilter()); + final NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); + final ScriptEngine engine = factory.getScriptEngine(new String[]{"--no-java"}, getClass().getClassLoader(), getClassFilter()); try { engine.eval("var str = Java.type('java.lang.String');"); fail("TypeError should have been thrown"); - } catch (ScriptException exc) { + } catch (final ScriptException e) { + //emtpy } } @@ -85,27 +85,31 @@ return; } - NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); - ScriptEngine engine = factory.getScriptEngine(getClassFilter()); + final NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); + final ScriptEngine engine = factory.getScriptEngine(getClassFilter()); try { engine.eval("var thread = Java.type('sun.misc.Unsafe')"); fail("SecurityException should have been thrown"); - } catch (final Exception exc) { + } catch (final Exception e) { + //empty } try { engine.eval("var thread = new sun.misc.Unsafe()"); fail("SecurityException should have been thrown"); - } catch (final Exception exc) { + } catch (final Exception e) { + //empty } try { engine.eval("var thread = Java.extend(sun.misc.Unsafe, {})"); fail("TypeError should have been thrown"); - } catch (final Exception exc) { + } catch (final Exception e) { + //empty } try { engine.eval("java.lang.System.exit(0)"); fail("SecurityException should have been thrown"); - } catch (final Exception exc) { + } catch (final Exception e) { + //empty } } @@ -124,24 +128,24 @@ } private void persistentCacheTestImpl() { - NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); - ScriptEngine engine = factory.getScriptEngine( + final NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); + final ScriptEngine engine = factory.getScriptEngine( TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}), getClass().getClassLoader(), getClassFilter() ); - String testScript = "var a = Java.type('java.lang.String');" + generateCodeForPersistentStore(); + final String testScript = "var a = Java.type('java.lang.String');" + generateCodeForPersistentStore(); try { engine.eval(testScript); } catch (final ScriptException exc) { fail(exc.getMessage()); } - ScriptEngine engineSafe = factory.getScriptEngine( + final ScriptEngine engineSafe = factory.getScriptEngine( TestFinder.addExplicitOptimisticTypes(new String[]{"--persistent-code-cache", "--optimistic-types=true"}), getClass().getClassLoader(), new ClassFilter() { @Override - public boolean exposeToScripts(String s) { + public boolean exposeToScripts(final String s) { return false; } } @@ -156,8 +160,8 @@ } } - private String generateCodeForPersistentStore() { - StringBuilder stringBuilder = new StringBuilder(); + private static String generateCodeForPersistentStore() { + final StringBuilder stringBuilder = new StringBuilder(); for (int i=0; i < 100; i++) { stringBuilder.append("function i") .append(i) @@ -170,10 +174,10 @@ return stringBuilder.toString(); } - private ClassFilter getClassFilter() { + private static ClassFilter getClassFilter() { return new ClassFilter() { @Override - public boolean exposeToScripts(String s) { + public boolean exposeToScripts(final String s) { return true; } }; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java --- a/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -26,7 +26,6 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; - import java.io.File; import java.io.IOException; import java.nio.file.DirectoryStream; @@ -44,7 +43,7 @@ * @summary Test for persistent code cache and path handling * @run testng jdk.nashorn.internal.runtime.CodeStoreAndPathTest */ - +@SuppressWarnings("javadoc") public class CodeStoreAndPathTest { final String code1 = "var code1; var x = 'Hello Script'; var x1 = 'Hello Script'; " @@ -96,21 +95,16 @@ final String codeCache = "build/nashorn_code_cache"; final String oldUserDir = System.getProperty("user.dir"); - private static final String[] ENGINE_OPTIONS = new String[]{"--persistent-code-cache", "--optimistic-types=false", "--lazy-compilation=false"}; - - public void checkCompiledScripts(final DirectoryStream stream, int numberOfScripts) throws IOException { - for (final Path file : stream) { - numberOfScripts--; - } - stream.close(); - assertEquals(numberOfScripts,0); - } + private static final String[] ENGINE_OPTIONS_OPT = new String[]{"--persistent-code-cache", "--optimistic-types=true"}; + private static final String[] ENGINE_OPTIONS_NOOPT = new String[]{"--persistent-code-cache", "--optimistic-types=false"}; @Test - public void pathHandlingTest() throws ScriptException, IOException { + public void pathHandlingTest() { System.setProperty("nashorn.persistent.code.cache", codeCache); final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); - final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS); + + fac.getScriptEngine(ENGINE_OPTIONS_NOOPT); + final Path expectedCodeCachePath = FileSystems.getDefault().getPath(oldUserDir + File.separator + codeCache); final Path actualCodeCachePath = FileSystems.getDefault().getPath(System.getProperty( "nashorn.persistent.code.cache")).toAbsolutePath(); @@ -126,9 +120,8 @@ public void changeUserDirTest() throws ScriptException, IOException { System.setProperty("nashorn.persistent.code.cache", codeCache); final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); - final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS); - final Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty( - "nashorn.persistent.code.cache")).toAbsolutePath(); + final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS_NOOPT); + final Path codeCachePath = getCodeCachePath(false); final String newUserDir = "build/newUserDir"; // Now changing current working directory System.setProperty("user.dir", System.getProperty("user.dir") + File.separator + newUserDir); @@ -147,9 +140,22 @@ public void codeCacheTest() throws ScriptException, IOException { System.setProperty("nashorn.persistent.code.cache", codeCache); final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); - final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS); - final Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty( - "nashorn.persistent.code.cache")).toAbsolutePath(); + final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS_NOOPT); + final Path codeCachePath = getCodeCachePath(false); + e.eval(code1); + e.eval(code2); + e.eval(code3);// less than minimum size for storing + // adding code1 and code2. + final DirectoryStream stream = Files.newDirectoryStream(codeCachePath); + checkCompiledScripts(stream, 2); + } + + @Test + public void codeCacheTestOpt() throws ScriptException, IOException { + System.setProperty("nashorn.persistent.code.cache", codeCache); + final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); + final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS_OPT); + final Path codeCachePath = getCodeCachePath(true); e.eval(code1); e.eval(code2); e.eval(code3);// less than minimum size for storing @@ -157,4 +163,26 @@ final DirectoryStream stream = Files.newDirectoryStream(codeCachePath); checkCompiledScripts(stream, 2); } + + private static Path getCodeCachePath(final boolean optimistic) { + final String codeCache = System.getProperty("nashorn.persistent.code.cache"); + final Path codeCachePath = FileSystems.getDefault().getPath(codeCache).toAbsolutePath(); + final String[] files = codeCachePath.toFile().list(); + for (final String file : files) { + if (file.endsWith("_opt") == optimistic) { + return codeCachePath.resolve(file); + } + } + throw new AssertionError("Code cache path not found"); + } + + private static void checkCompiledScripts(final DirectoryStream stream, final int numberOfScripts) throws IOException { + int n = numberOfScripts; + for (@SuppressWarnings("unused") final Path file : stream) { + n--; + } + stream.close(); + assertEquals(n, 0); + } + } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/runtime/ContextTest.java --- a/test/src/jdk/nashorn/internal/runtime/ContextTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/runtime/ContextTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,7 +29,6 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; - import java.util.Map; import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.options.Options; @@ -41,6 +40,7 @@ * @test * @run testng jdk.nashorn.internal.runtime.ContextTest */ +@SuppressWarnings("javadoc") public class ContextTest { // basic context eval test @Test @@ -96,7 +96,7 @@ final String code = "var obj = { x: 344, y: 42 }"; eval(cx, "", code); - final Object obj = cx.getGlobal().get("obj"); + final Object obj = Context.getGlobal().get("obj"); assertTrue(obj instanceof ScriptObject); @@ -129,7 +129,7 @@ } } - private Object eval(final Context cx, final String name, final String code) { + private static Object eval(final Context cx, final String name, final String code) { final Source source = sourceFor(name, code); final ScriptObject global = Context.getGlobal(); final ScriptFunction func = cx.compileScript(source, global); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java --- a/test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,7 +27,6 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.NotSerializableException; @@ -43,6 +42,7 @@ * @test * @run testng jdk.nashorn.internal.runtime.ExceptionsNotSerializable */ +@SuppressWarnings("javadoc") public class ExceptionsNotSerializable { @Test public void rewriteExceptionNotSerializable() throws ScriptException { @@ -59,7 +59,7 @@ } @Test - public void unwarrantedOptimismExceptionNotSerializable() throws IOException { + public void unwarrantedOptimismExceptionNotSerializable() { tryToSerialize(new UnwarrantedOptimismException(new Double(1.0), 128)); } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java --- a/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,7 +25,6 @@ package jdk.nashorn.internal.runtime; import static org.testng.Assert.fail; - import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.regex.Matcher; @@ -46,6 +45,7 @@ * @summary Sanity tests for no persistence caching * @run testng/othervm jdk.nashorn.internal.runtime.NoPersistenceCachingTest */ +@SuppressWarnings("javadoc") public class NoPersistenceCachingTest { private ScriptEngine engine; @@ -102,6 +102,8 @@ engine.eval(scriptThreeContexts, context2); engine.eval(scriptThreeContexts, context3); break; + default: + break; } } catch (final Exception se) { se.printStackTrace(); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/runtime/SourceTest.java --- a/test/src/jdk/nashorn/internal/runtime/SourceTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/runtime/SourceTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -29,7 +29,6 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; - import java.io.File; import java.io.IOException; import java.io.InputStreamReader; @@ -42,6 +41,7 @@ /** * Tests different Source representations. */ +@SuppressWarnings("javadoc") public class SourceTest { final private static String SOURCE_NAME = "source.js"; @@ -104,11 +104,11 @@ } } - private Reader getReader(final String path) { + private static Reader getReader(final String path) { return new InputStreamReader(SourceTest.class.getResourceAsStream(path)); } - private void testSources(final Source source1, final Source source2) { + private static void testSources(final Source source1, final Source source2) { final char[] chars1 = source1.getContent(); final char[] chars2 = source2.getContent(); final String str1 = source1.getString(); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java --- a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -28,7 +28,6 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; - import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; @@ -42,6 +41,7 @@ /** * Tests for trusted client usage of nashorn script engine factory extension API */ +@SuppressWarnings("javadoc") public class TrustedScriptEngineTest { @Test public void versionTest() { @@ -64,7 +64,7 @@ public boolean reached() { return reached[0]; } - }; + } // These are for "private" extension API of NashornScriptEngineFactory that // accepts a ClassLoader and/or command line options. @@ -140,7 +140,8 @@ // try nashorn specific extension e.eval("var f = funtion(x) 2*x;"); fail("should have thrown exception!"); - } catch (final ScriptException se) { + } catch (final Exception ex) { + //empty } return; } @@ -276,7 +277,9 @@ try { fac.getScriptEngine((ClassFilter)null); fail("should have thrown NPE"); - } catch (NullPointerException npe) {} + } catch (final NullPointerException e) { + //empty + } } @Test @@ -285,7 +288,9 @@ try { fac.getScriptEngine(new String[0], null, null); fail("should have thrown NPE"); - } catch (NullPointerException npe) {} + } catch (final NullPointerException e) { + //empty + } } @Test @@ -294,7 +299,9 @@ try { fac.getScriptEngine((String[])null); fail("should have thrown NPE"); - } catch (NullPointerException npe) {} + } catch (final NullPointerException e) { + //empty + } } @Test @@ -308,7 +315,9 @@ } }); fail("should have thrown NPE"); - } catch (NullPointerException npe) {} + } catch (final NullPointerException e) { + //empty + } } @Test diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java --- a/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -33,6 +33,7 @@ * @test * @run testng jdk.nashorn.internal.runtime.regexp.joni.JoniTest */ +@SuppressWarnings("javadoc") public class JoniTest { @Test diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java --- a/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java Fri Nov 14 10:03:48 2014 -0800 @@ -34,7 +34,6 @@ import static jdk.nashorn.internal.test.framework.TestConfig.OPTIONS_RUN; import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_FAIL_LIST; import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_SHARED_CONTEXT; - import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -50,6 +49,7 @@ /** * Abstract class to compile and run one .js script file. */ +@SuppressWarnings("javadoc") public abstract class AbstractScriptRunnable { // some test scripts need a "framework" script - whose features are used // in the test script. This optional framework script can be null. @@ -274,14 +274,14 @@ // compile and run this script protected abstract void execute(); - private boolean equalsCompilerMsgs(final String es, final String as) { + private static boolean equalsCompilerMsgs(final String es, final String as) { final int split = es.indexOf(':'); // Replace both types of separators ('/' and '\') with the one from // current environment return (split >= 0) && as.equals(es.substring(0, split).replaceAll("[/\\\\]", Matcher.quoteReplacement(File.separator)) + es.substring(split)); } - private void escape(final String value, final StringBuilder out) { + private static void escape(final String value, final StringBuilder out) { final int len = value.length(); for (int i = 0; i < len; i++) { final char ch = value.charAt(i); @@ -297,7 +297,7 @@ } } - private String escape(final String value) { + private static String escape(final String value) { final StringBuilder sb = new StringBuilder(); escape(value, sb); return sb.toString(); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/test/framework/OrphanTestFinder.java --- a/test/src/jdk/nashorn/internal/test/framework/OrphanTestFinder.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/test/framework/OrphanTestFinder.java Fri Nov 14 10:03:48 2014 -0800 @@ -34,6 +34,7 @@ * Test case used by JSCompilerTest to complain if test files are marked as * neither test nor subtest. */ +@SuppressWarnings("javadoc") public final class OrphanTestFinder implements ITest { private final Set orphanFiles; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java --- a/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java Fri Nov 14 10:03:48 2014 -0800 @@ -31,7 +31,6 @@ import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_EXCLUDE_LIST; import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_FRAMEWORK; import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_ROOTS; - import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; @@ -73,6 +72,7 @@ * Parallel test runner runs tests in multiple threads - but avoids any dependency * on third-party test framework library such as TestNG. */ +@SuppressWarnings("javadoc") public class ParallelTestRunner { // ParallelTestRunner-specific @@ -247,7 +247,7 @@ } } - private void compare(final String outputFileName, final String expected, final boolean compareCompilerMsg) throws IOException { + private void compare(final String fileName, final String expected, final boolean compareCompilerMsg) throws IOException { final File expectedFile = new File(expected); BufferedReader expectedReader; @@ -257,7 +257,7 @@ expectedReader = new BufferedReader(new StringReader("")); } - final BufferedReader actual = new BufferedReader(new InputStreamReader(new FileInputStream(outputFileName))); + final BufferedReader actual = new BufferedReader(new InputStreamReader(new FileInputStream(fileName))); compare(actual, expectedReader, compareCompilerMsg); } @@ -434,8 +434,8 @@ public static void main(final String[] args) throws Exception { parseArgs(args); - while(new ParallelTestRunner().run()) { - ; + while (new ParallelTestRunner().run()) { + //empty } } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java --- a/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java Fri Nov 14 10:03:48 2014 -0800 @@ -52,6 +52,7 @@ * class. Optionally, output from running the script is compared against the * corresponding .EXPECTED file. */ +@SuppressWarnings("javadoc") public final class ScriptRunnable extends AbstractScriptRunnable implements ITest { public ScriptRunnable(final String framework, final File testFile, final List engineOptions, final Map testOptions, final List scriptArguments) { super(framework, testFile, engineOptions, testOptions, scriptArguments); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/test/framework/ScriptTest.java --- a/test/src/jdk/nashorn/internal/test/framework/ScriptTest.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/test/framework/ScriptTest.java Fri Nov 14 10:03:48 2014 -0800 @@ -26,7 +26,6 @@ package jdk.nashorn.internal.test.framework; import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_INCLUDES; - import java.io.File; import java.util.ArrayList; import java.util.List; @@ -48,7 +47,9 @@ * Creates a test factory for the set of .js source tests. * * @return a Object[] of test objects. + * @throws Exception upon failure */ + @SuppressWarnings("static-method") @Factory public Object[] suite() throws Exception { Locale.setDefault(new Locale("")); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/test/framework/TestConfig.java --- a/test/src/jdk/nashorn/internal/test/framework/TestConfig.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/test/framework/TestConfig.java Fri Nov 14 10:03:48 2014 -0800 @@ -28,6 +28,7 @@ /** * Configuration info for script tests. */ +@SuppressWarnings("javadoc") public interface TestConfig { // Test options inferred from various test @foo tags and passed to test factory. public static final String OPTIONS_RUN = "run"; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/test/framework/TestFinder.java --- a/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Fri Nov 14 10:03:48 2014 -0800 @@ -42,7 +42,6 @@ import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_LIST; import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_ROOTS; import static jdk.nashorn.internal.test.framework.TestConfig.TEST_JS_UNCHECKED_DIR; - import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -76,6 +75,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. */ +@SuppressWarnings("javadoc") public final class TestFinder { private TestFinder() {} @@ -299,6 +299,8 @@ case "@fork": fork = true; break; + default: + break; } // negative tests are expected to fail at runtime only @@ -377,7 +379,7 @@ * * @args new argument list array */ - public static String[] addExplicitOptimisticTypes(String[] args) { + public static String[] addExplicitOptimisticTypes(final String[] args) { if (hasOptimisticOverride()) { final List newList = new ArrayList<>(Arrays.asList(args)); newList.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE)); @@ -392,7 +394,7 @@ * * @args argument list */ - public static void addExplicitOptimisticTypes(List args) { + public static void addExplicitOptimisticTypes(final List args) { if (hasOptimisticOverride()) { args.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE)); } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/test/framework/TestHelper.java --- a/test/src/jdk/nashorn/internal/test/framework/TestHelper.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/test/framework/TestHelper.java Fri Nov 14 10:03:48 2014 -0800 @@ -36,6 +36,7 @@ /** * Simple utilities to deal with build-dir, read/dump files etc. */ +@SuppressWarnings("javadoc") public abstract class TestHelper { public static final String TEST_ROOT = "test"; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java --- a/test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java Fri Nov 14 10:03:48 2014 -0800 @@ -47,10 +47,9 @@ final Object o2 = mi2.getInstance(); if (o1 instanceof ITest && o2 instanceof ITest) { return ((ITest)o1).getTestName().compareTo(((ITest)o2).getTestName()); - } else { - // something else, don't care about the order - return 0; } + // something else, don't care about the order + return 0; } }); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/test/models/InternalRunnable.java --- a/test/src/jdk/nashorn/internal/test/models/InternalRunnable.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/test/models/InternalRunnable.java Fri Nov 14 10:03:48 2014 -0800 @@ -28,6 +28,7 @@ import java.io.PrintWriter; import java.io.StringWriter; +@SuppressWarnings("javadoc") public class InternalRunnable implements Runnable, RestrictedRunnable { // This is a public field in a restricted class; scripts should not see it. diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/internal/test/models/RestrictedRunnable.java --- a/test/src/jdk/nashorn/internal/test/models/RestrictedRunnable.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/internal/test/models/RestrictedRunnable.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,8 +27,8 @@ /** * Acts as a restricted interface implemented by a restricted class. - * */ +@SuppressWarnings("javadoc") public interface RestrictedRunnable { public void restrictedRun(); } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/ClassLoaderAware.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/test/models/ClassLoaderAware.java Fri Nov 14 10:03:48 2014 -0800 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 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. 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. + */ + +package jdk.nashorn.test.models; + +@SuppressWarnings("javadoc") +public interface ClassLoaderAware { + public ClassLoader getContextClassLoader(); + public void checkMemberAccess(Class clazz, int which); +} diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/ClassWithFinalFinalizer.java --- a/test/src/jdk/nashorn/test/models/ClassWithFinalFinalizer.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/ClassWithFinalFinalizer.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,7 +25,10 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public class ClassWithFinalFinalizer { + @Override protected final void finalize() { + //empty } } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/ClassWithInheritedFinalFinalizer.java --- a/test/src/jdk/nashorn/test/models/ClassWithInheritedFinalFinalizer.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/ClassWithInheritedFinalFinalizer.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,5 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public class ClassWithInheritedFinalFinalizer extends ClassWithFinalFinalizer { + //empty } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/ConstructorWithArgument.java --- a/test/src/jdk/nashorn/test/models/ConstructorWithArgument.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/ConstructorWithArgument.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public abstract class ConstructorWithArgument { private final String token; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/DessertTopping.java --- a/test/src/jdk/nashorn/test/models/DessertTopping.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/DessertTopping.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public interface DessertTopping { public String pourOnDessert(); } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java --- a/test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public class DessertToppingFloorWaxDriver { public void decorateDessert(final DessertTopping dt) { dt.pourOnDessert(); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/FinalClass.java --- a/test/src/jdk/nashorn/test/models/FinalClass.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/FinalClass.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public final class FinalClass { //empty } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/FloorWax.java --- a/test/src/jdk/nashorn/test/models/FloorWax.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/FloorWax.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public interface FloorWax { public String shineUpTheFloor(); } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java --- a/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java Fri Nov 14 10:03:48 2014 -0800 @@ -24,6 +24,7 @@ */ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public class IntFloatOverloadSelection { public static String overloadedMethod(final int i) { diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/InternalRunnableSuperclass.java --- a/test/src/jdk/nashorn/test/models/InternalRunnableSuperclass.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/InternalRunnableSuperclass.java Fri Nov 14 10:03:48 2014 -0800 @@ -30,8 +30,9 @@ /** * Acts as a non-restricted superclass for a restricted class. - * */ + +@SuppressWarnings("javadoc") public class InternalRunnableSuperclass { public final int canSeeThisField = 19; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java --- a/test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java Fri Nov 14 10:03:48 2014 -0800 @@ -26,8 +26,9 @@ package jdk.nashorn.test.models; /** - * Test class used by JDK-8011362.js. + * Test class used by JDK-8011362.js */ +@SuppressWarnings("javadoc") public class Jdk8011362TestSubject { // This is selected for overloaded("", null) public String overloaded(final String a, final String b) { diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java --- a/test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public class Nashorn401TestSubject { public String method2(final int arg) { return "int method 2"; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/NoAccessibleConstructorClass.java --- a/test/src/jdk/nashorn/test/models/NoAccessibleConstructorClass.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/NoAccessibleConstructorClass.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public class NoAccessibleConstructorClass { NoAccessibleConstructorClass() { } } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/NullProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/test/models/NullProvider.java Fri Nov 14 10:03:48 2014 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 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. 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. + */ + +package jdk.nashorn.test.models; + + +public class NullProvider { + public static Integer getInteger() { return null; } + public static Long getLong() { return null; } + public static Double getDouble() { return null; } + public static Boolean getBoolean() { return null; } +} diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/OuterClass.java --- a/test/src/jdk/nashorn/test/models/OuterClass.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/OuterClass.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public class OuterClass { private final String value; @@ -35,6 +36,7 @@ public static class InnerStaticClass { public static class InnerInnerStaticClass { + //empty } private final String value; @@ -50,15 +52,15 @@ } public class InnerNonStaticClass { - private final String value; + private final String val; public InnerNonStaticClass(final String value) { - this.value = value; + this.val = value; } @Override public String toString() { - return "InnerNonStaticClass[value=" + value + ", outer=" + OuterClass.this + "]"; + return "InnerNonStaticClass[value=" + val + ", outer=" + OuterClass.this + "]"; } } diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/OverloadedSam.java --- a/test/src/jdk/nashorn/test/models/OverloadedSam.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/OverloadedSam.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public interface OverloadedSam { public void sam(String s); public void sam(String s1, String s2); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/OverrideObject.java --- a/test/src/jdk/nashorn/test/models/OverrideObject.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/OverrideObject.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public class OverrideObject { @Override public int hashCode() { diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/PropertyBind.java --- a/test/src/jdk/nashorn/test/models/PropertyBind.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/PropertyBind.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public class PropertyBind { public static int publicStaticInt; public static final int publicStaticFinalInt = 2112; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/SourceHelper.java --- a/test/src/jdk/nashorn/test/models/SourceHelper.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/SourceHelper.java Fri Nov 14 10:03:48 2014 -0800 @@ -34,6 +34,7 @@ /** * Helper class to facilitate script access of nashorn Source class. */ +@SuppressWarnings("javadoc") public final class SourceHelper { private SourceHelper() {} diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/StringArgs.java --- a/test/src/jdk/nashorn/test/models/StringArgs.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/StringArgs.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,6 +27,7 @@ import java.util.List; +@SuppressWarnings("javadoc") public class StringArgs { public static void checkString(final List list) { diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/Toothpaste.java --- a/test/src/jdk/nashorn/test/models/Toothpaste.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/Toothpaste.java Fri Nov 14 10:03:48 2014 -0800 @@ -25,6 +25,7 @@ package jdk.nashorn.test.models; +@SuppressWarnings("javadoc") public abstract class Toothpaste { public void applyToBrush() { applyToBrushImpl(); diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/models/VarArgConstructor.java --- a/test/src/jdk/nashorn/test/models/VarArgConstructor.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/models/VarArgConstructor.java Fri Nov 14 10:03:48 2014 -0800 @@ -27,6 +27,7 @@ import java.util.List; +@SuppressWarnings("javadoc") public class VarArgConstructor { private final String indicator; diff -r 99f9e7a9cf0e -r fc37699ddc0e test/src/jdk/nashorn/test/tools/StaticTypeInspector.java --- a/test/src/jdk/nashorn/test/tools/StaticTypeInspector.java Wed Nov 12 13:47:23 2014 -0800 +++ b/test/src/jdk/nashorn/test/tools/StaticTypeInspector.java Fri Nov 14 10:03:48 2014 -0800 @@ -26,6 +26,7 @@ import jdk.nashorn.internal.runtime.Undefined; +@SuppressWarnings("javadoc") public class StaticTypeInspector { public static String inspect(final boolean x, final String w) {