# HG changeset patch # User lana # Date 1480628433 0 # Node ID 78b4e7cfccc0904bfe882cbd921ab795d07ed8f9 # Parent b83e676b8c947bf5a42af62e51d9d31227cc86e4# Parent 7c6ddb187262a9bd7f4fe8b173b05678d90405d5 Merge diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/.hgignore --- a/nashorn/.hgignore Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/.hgignore Thu Dec 01 21:40:33 2016 +0000 @@ -1,6 +1,5 @@ syntax: glob -^.hgtip build/* dist/* /nbproject/private/ diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Thu Dec 01 21:40:33 2016 +0000 @@ -29,7 +29,6 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJ_PKG; import static jdk.nashorn.internal.tools.nasgen.StringConstants.RUNTIME_PKG; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTS_PKG; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.STRING_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_SYMBOL; @@ -111,6 +110,8 @@ private boolean isOptimistic; + private boolean convertsNumericArgs; + /** * @return the kind */ @@ -172,6 +173,23 @@ } /** + * Check if this function converts arguments for numeric parameters to numbers + * so it's safe to pass booleans as 0 and 1 + * @return true if it is safe to convert arguments to numbers + */ + public boolean convertsNumericArgs() { + return convertsNumericArgs; + } + + /** + * Tag this as a function that converts arguments for numeric params to numbers + * @param convertsNumericArgs if true args can be safely converted to numbers + */ + public void setConvertsNumericArgs(final boolean convertsNumericArgs) { + this.convertsNumericArgs = convertsNumericArgs; + } + + /** * Get the SpecializedFunction guard for specializations, i.e. optimistic * builtins * @return specialization, null if none diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java Thu Dec 01 21:40:33 2016 +0000 @@ -412,6 +412,7 @@ visitLdcInsn(linkLogicClass); } visitInsn(mi.isOptimistic() ? ICONST_1 : ICONST_0); + visitInsn(mi.convertsNumericArgs() ? ICONST_1 : ICONST_0); visitMethodInsn(INVOKESPECIAL, SPECIALIZATION_TYPE, INIT, ctor, false); arrayStore(TYPE_SPECIALIZATION); } diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Thu Dec 01 21:40:33 2016 +0000 @@ -210,6 +210,7 @@ private Where where; private boolean isSpecializedConstructor; private boolean isOptimistic; + private boolean convertsNumericArgs; private Type linkLogicClass = MethodGenerator.EMPTY_LINK_LOGIC_TYPE; @Override @@ -238,6 +239,10 @@ case "linkLogic": this.linkLogicClass = (Type)annotationValue; break; + case "convertsNumericArgs": + assert annoKind == Kind.SPECIALIZED_FUNCTION; + this.convertsNumericArgs = (Boolean)annotationValue; + break; default: break; } @@ -298,6 +303,7 @@ memInfo.setLinkLogicClass(linkLogicClass); memInfo.setIsSpecializedConstructor(isSpecializedConstructor); memInfo.setIsOptimistic(isOptimistic); + memInfo.setConvertsNumericArgs(convertsNumericArgs); } }; } diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Thu Dec 01 21:40:33 2016 +0000 @@ -45,7 +45,6 @@ // standard jdk types, methods static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class); - static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class); static final Type TYPE_SPECIALIZATION = Type.getType("L" + RUNTIME_PKG + "Specialization;"); static final Type TYPE_SPECIALIZATION_ARRAY = Type.getType("[L" + RUNTIME_PKG + "Specialization;"); static final Type TYPE_OBJECT = Type.getType(Object.class); @@ -60,13 +59,11 @@ static final String INIT = ""; static final String DEFAULT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE); - static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName(); static final String SPECIALIZATION_TYPE = TYPE_SPECIALIZATION.getInternalName(); - static final String SPECIALIZATION_INIT2 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, Type.getType(boolean.class)); - static final String SPECIALIZATION_INIT3 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, TYPE_CLASS, Type.getType(boolean.class)); + static final String SPECIALIZATION_INIT2 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, Type.BOOLEAN_TYPE, Type.BOOLEAN_TYPE); + static final String SPECIALIZATION_INIT3 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, TYPE_CLASS, Type.BOOLEAN_TYPE, Type.BOOLEAN_TYPE); static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName(); static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor(); - static final String STRING_TYPE = TYPE_STRING.getInternalName(); static final String STRING_DESC = TYPE_STRING.getDescriptor(); static final String OBJECT_ARRAY_DESC = Type.getDescriptor(Object[].class); static final String ARRAYLIST_TYPE = TYPE_ARRAYLIST.getInternalName(); diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/make/project.properties --- a/nashorn/make/project.properties Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/make/project.properties Thu Dec 01 21:40:33 2016 +0000 @@ -154,7 +154,9 @@ --add-exports jdk.scripting.nashorn/jdk.nashorn.internal.runtime.regexp=ALL-UNNAMED \ --add-exports jdk.scripting.nashorn/jdk.nashorn.internal.runtime.regexp.joni=ALL-UNNAMED \ --add-exports jdk.scripting.nashorn/jdk.nashorn.tools=ALL-UNNAMED \ - --add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED + --add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED \ + --add-opens jdk.scripting.nashorn/jdk.nashorn.internal.runtime=ALL-UNNAMED \ + --add-opens jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv=ALL-UNNAMED meta.inf.dir=${nashorn.module.src.dir}/META-INF diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.dynalink/share/classes/module-info.java --- a/nashorn/src/jdk.dynalink/share/classes/module-info.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/module-info.java Thu Dec 01 21:40:33 2016 +0000 @@ -23,6 +23,9 @@ * questions. */ +/** + * Dynalink + */ module jdk.dynalink { requires java.logging; diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn.shell/share/classes/module-info.java --- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/module-info.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/module-info.java Thu Dec 01 21:40:33 2016 +0000 @@ -23,6 +23,9 @@ * questions. */ +/** + * Nashorn shell module + */ module jdk.scripting.nashorn.shell { requires java.desktop; requires java.compiler; diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java Thu Dec 01 21:40:33 2016 +0000 @@ -244,7 +244,7 @@ * @param global the global * @return initialized exception */ - protected NashornException initEcmaError(final ScriptObject global) { + NashornException initEcmaError(final ScriptObject global) { if (ecmaError != null) { return this; // initialized already! } diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Dec 01 21:40:33 2016 +0000 @@ -4066,7 +4066,7 @@ void loadStack() { assert assignNode.getWidestOperandType() == Type.INT; if (isRhsZero(binaryNode)) { - loadExpressionAsType(binaryNode.lhs(), Type.INT); + loadExpression(binaryNode.lhs(), TypeBounds.INT, true); } else { loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.INT, true, false); method.shr(); diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Thu Dec 01 21:40:33 2016 +0000 @@ -61,7 +61,6 @@ import jdk.nashorn.internal.runtime.OptimisticBuiltins; import jdk.nashorn.internal.runtime.PropertyDescriptor; 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.Undefined; @@ -748,7 +747,7 @@ * @param arg argument * @return resulting NativeArray */ - @SpecializedFunction(linkLogic=ConcatLinkLogic.class) + @SpecializedFunction(linkLogic=ConcatLinkLogic.class, convertsNumericArgs = false) public static NativeArray concat(final Object self, final int arg) { final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Integer.class).copy(); //get at least an integer data copy of this data newData.fastPush(arg); //add an integer to its end @@ -762,21 +761,7 @@ * @param arg argument * @return resulting NativeArray */ - @SpecializedFunction(linkLogic=ConcatLinkLogic.class) - public static NativeArray concat(final Object self, final long arg) { - final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Long.class).copy(); //get at least a long array data copy of this data - newData.fastPush(arg); //add a long at the end - return new NativeArray(newData); - } - - /** - * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] ) - * - * @param self self reference - * @param arg argument - * @return resulting NativeArray - */ - @SpecializedFunction(linkLogic=ConcatLinkLogic.class) + @SpecializedFunction(linkLogic=ConcatLinkLogic.class, convertsNumericArgs = false) public static NativeArray concat(final Object self, final double arg) { final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Double.class).copy(); //get at least a number array data copy of this data newData.fastPush(arg); //add a double at the end @@ -837,13 +822,12 @@ private static void concatToList(final ArrayList list, final Object obj) { final boolean isScriptArray = isArray(obj); final boolean isScriptObject = isScriptArray || obj instanceof ScriptObject; - if (isScriptArray || obj instanceof Iterable || (obj != null && obj.getClass().isArray())) { + if (isScriptArray || obj instanceof Iterable || obj instanceof JSObject || (obj != null && obj.getClass().isArray())) { final Iterator iter = arrayLikeIterator(obj, true); if (iter.hasNext()) { for (int i = 0; iter.hasNext(); ++i) { final Object value = iter.next(); - final boolean lacksIndex = obj != null && !((ScriptObject)obj).has(i); - if (value == ScriptRuntime.UNDEFINED && isScriptObject && lacksIndex) { + if (value == ScriptRuntime.UNDEFINED && isScriptObject && !((ScriptObject)obj).has(i)) { // TODO: eventually rewrite arrayLikeIterator to use a three-state enum for handling // UNDEFINED instead of an "includeUndefined" boolean with states SKIP, INCLUDE, // RETURN_EMPTY. Until then, this is how we'll make sure that empty elements don't make it @@ -980,7 +964,7 @@ * @param arg a primitive to push * @return array length after push */ - @SpecializedFunction(linkLogic=PushLinkLogic.class) + @SpecializedFunction(linkLogic=PushLinkLogic.class, convertsNumericArgs = false) public static double push(final Object self, final int arg) { return getContinuousArrayDataCCE(self, Integer.class).fastPush(arg); } @@ -994,21 +978,7 @@ * @param arg a primitive to push * @return array length after push */ - @SpecializedFunction(linkLogic=PushLinkLogic.class) - public static double push(final Object self, final long arg) { - return getContinuousArrayDataCCE(self, Long.class).fastPush(arg); - } - - /** - * ECMA 15.4.4.7 Array.prototype.push (args...) - * - * Primitive specialization, {@link LinkLogic} - * - * @param self self reference - * @param arg a primitive to push - * @return array length after push - */ - @SpecializedFunction(linkLogic=PushLinkLogic.class) + @SpecializedFunction(linkLogic=PushLinkLogic.class, convertsNumericArgs = false) public static double push(final Object self, final double arg) { return getContinuousArrayDataCCE(self, Double.class).fastPush(arg); } @@ -1857,15 +1827,14 @@ } final Object arg = args[2]; - //args[2] continuousarray or non arraydata, let past non array datas + // The generic version uses its own logic and ArrayLikeIterator to decide if an object should + // be iterated over or added as single element. To avoid duplication of code and err on the safe side + // we only use the specialized version if arg is either a continuous array or a JS primitive. if (arg instanceof NativeArray) { - final ContinuousArrayData argData = getContinuousArrayData(arg); - if (argData == null) { - return false; - } + return (getContinuousArrayData(arg) != null); } - return true; + return JSType.isPrimitive(arg); } } diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java Thu Dec 01 21:40:33 2016 +0000 @@ -539,17 +539,6 @@ } /** - * ECMA 15.5.4.5 String.prototype.charCodeAt (pos) - specialized version for long position - * @param self self reference - * @param pos position in string - * @return number representing charcode at position - */ - @SpecializedFunction(linkLogic=CharCodeAtLinkLogic.class) - public static int charCodeAt(final Object self, final long pos) { - return charCodeAt(self, (int)pos); - } - - /** * ECMA 15.5.4.5 String.prototype.charCodeAt (pos) - specialized version for int position * @param self self reference * @param pos position in string @@ -1176,24 +1165,7 @@ } /** - * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code int} arg - * - * Constructor - * - * @param newObj is this constructor invoked with the new operator - * @param self self reference - * @param arg the arg - * - * @return new NativeString containing the string representation of the arg - */ - @SpecializedFunction(isConstructor=true) - public static Object constructor(final boolean newObj, final Object self, final long arg) { - final String str = Long.toString(arg); - return newObj ? newObj(str) : str; - } - - /** - * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code int} arg + * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code double} arg * * Constructor * diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Thu Dec 01 21:40:33 2016 +0000 @@ -215,4 +215,14 @@ * @return whether this function can throw {@link UnwarrantedOptimismException}. */ boolean isOptimistic() default false; + + /** + * Is it safe to convert non-numeric arguments to numbers for this function's primitive numeric parameters? + * This is true for many built-in functions which expect numeric arguments, but not for those that + * expect generic arguments and just have specializations with numeric params to avoid boxing overhead. + * The default value is {@code true} because that is by far the most common case. + * + * @return true if it is safe to convert arguments to numbers + */ + boolean convertsNumericArgs() default true; } diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Thu Dec 01 21:40:33 2016 +0000 @@ -152,6 +152,10 @@ return null; } + boolean convertsNumericArgs() { + return isSpecialization() && specialization.convertsNumericArgs(); + } + int getFlags() { return flags; } @@ -388,10 +392,18 @@ int narrowWeightDelta = 0; int widenWeightDelta = 0; final int minParamsCount = Math.min(Math.min(thisParamCount, otherParamCount), callSiteParamCount); + final boolean convertsNumericArgs = cf.convertsNumericArgs(); for(int i = 0; i < minParamsCount; ++i) { - final int callSiteParamWeight = getParamType(i, callSiteType, csVarArg).getWeight(); + final Type callSiteParamType = getParamType(i, callSiteType, csVarArg); + final Type thisParamType = getParamType(i, thisType, thisVarArg); + if (!convertsNumericArgs && callSiteParamType.isBoolean() && thisParamType.isNumeric()) { + // When an argument is converted to number by a function it is safe to "widen" booleans to numeric types. + // However, we must avoid this conversion for generic functions such as Array.prototype.push. + return false; + } + final int callSiteParamWeight = callSiteParamType.getWeight(); // Delta is negative for narrowing, positive for widening - final int thisParamWeightDelta = getParamType(i, thisType, thisVarArg).getWeight() - callSiteParamWeight; + final int thisParamWeightDelta = thisParamType.getWeight() - callSiteParamWeight; final int otherParamWeightDelta = getParamType(i, otherType, otherVarArg).getWeight() - callSiteParamWeight; // Only count absolute values of narrowings narrowWeightDelta += Math.max(-thisParamWeightDelta, 0) - Math.max(-otherParamWeightDelta, 0); diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Thu Dec 01 21:40:33 2016 +0000 @@ -320,7 +320,7 @@ private final WeakValueCache> anonymousHostClasses = new WeakValueCache<>(); private static final class AnonymousContextCodeInstaller extends ContextCodeInstaller { - private static final Unsafe UNSAFE = getUnsafe(); + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private static final String ANONYMOUS_HOST_CLASS_NAME = Compiler.SCRIPTS_PACKAGE.replace('/', '.') + ".AnonymousHost"; private static final byte[] ANONYMOUS_HOST_CLASS_BYTES = getAnonymousHostClassBytes(); @@ -357,21 +357,6 @@ cw.visitEnd(); return cw.toByteArray(); } - - private static Unsafe getUnsafe() { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Unsafe run() { - try { - final Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeField.setAccessible(true); - return (Unsafe)theUnsafeField.get(null); - } catch (final ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - }); - } } /** Is Context global debug mode enabled ? */ diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java Thu Dec 01 21:40:33 2016 +0000 @@ -69,12 +69,12 @@ private Module createModule(final String moduleName) { final Module structMod = context.getStructLoader().getModule(); final ModuleDescriptor.Builder builder = - new ModuleDescriptor.Builder(moduleName) + ModuleDescriptor.module(moduleName) .requires("java.base") .requires("java.logging") .requires(NASHORN_MODULE.getName()) .requires(structMod.getName()) - .conceals(SCRIPTS_PKG); + .contains(SCRIPTS_PKG); if (Context.javaSqlFound) { builder.requires("java.sql"); diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Specialization.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Specialization.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Specialization.java Thu Dec 01 21:40:33 2016 +0000 @@ -36,6 +36,7 @@ private final MethodHandle mh; private final Class linkLogicClass; private final boolean isOptimistic; + private final boolean convertsNumericArgs; /** * Constructor @@ -43,7 +44,7 @@ * @param mh invoker method handler */ public Specialization(final MethodHandle mh) { - this(mh, false); + this(mh, false, true); } /** @@ -52,9 +53,10 @@ * @param mh invoker method handler * @param isOptimistic is this an optimistic native method, i.e. can it throw {@link UnwarrantedOptimismException} * which would have to lead to a relink and return value processing + * @param convertsNumericArgs true if it is safe to convert arguments to numbers */ - public Specialization(final MethodHandle mh, final boolean isOptimistic) { - this(mh, null, isOptimistic); + public Specialization(final MethodHandle mh, final boolean isOptimistic, final boolean convertsNumericArgs) { + this(mh, null, isOptimistic, convertsNumericArgs); } /** @@ -65,10 +67,13 @@ * if this can be linked on its first encounter, which is needed as per our standard linker semantics * @param isOptimistic is this an optimistic native method, i.e. can it throw {@link UnwarrantedOptimismException} * which would have to lead to a relink and return value processing + * @param convertsNumericArgs true if it is safe to convert arguments to numbers */ - public Specialization(final MethodHandle mh, final Class linkLogicClass, final boolean isOptimistic) { + public Specialization(final MethodHandle mh, final Class linkLogicClass, + final boolean isOptimistic, final boolean convertsNumericArgs) { this.mh = mh; this.isOptimistic = isOptimistic; + this.convertsNumericArgs = convertsNumericArgs; if (linkLogicClass != null) { //null out the "empty" link logic class for optimization purposes //we only use the empty instance because we can't default class annotations @@ -110,5 +115,15 @@ return isOptimistic; } + /** + * Check if this function converts arguments for numeric parameters to numbers + * so it's safe to pass booleans as 0 and 1 + * + * @return true if it is safe to convert arguments to numbers + */ + public boolean convertsNumericArgs() { + return convertsNumericArgs; + } + } diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StructureLoader.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StructureLoader.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StructureLoader.java Thu Dec 01 21:40:33 2016 +0000 @@ -63,10 +63,10 @@ private Module createModule(final String moduleName) { final ModuleDescriptor descriptor - = new ModuleDescriptor.Builder(moduleName) + = ModuleDescriptor.module(moduleName) .requires("java.base") .requires(NASHORN_MODULE.getName()) - .conceals(SCRIPTS_PKG) + .contains(SCRIPTS_PKG) .build(); final Module mod = Context.createModuleTrusted(descriptor, this); diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Dec 01 21:40:33 2016 +0000 @@ -40,9 +40,13 @@ import jdk.dynalink.linker.LinkerServices; import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; import jdk.nashorn.api.scripting.JSObject; +import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.lookup.MethodHandleFactory; import jdk.nashorn.internal.lookup.MethodHandleFunctionality; +import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.objects.Global; /** * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well @@ -142,9 +146,9 @@ } private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) { - MethodHandle mh = JSOBJECT_CALL; + MethodHandle mh = NashornCallSiteDescriptor.isScope(desc)? JSOBJECT_SCOPE_CALL : JSOBJECT_CALL; if (NashornCallSiteDescriptor.isApplyToCall(desc)) { - mh = MH.insertArguments(JSOBJECT_CALL_TO_APPLY, 0, JSOBJECT_CALL); + mh = MH.insertArguments(JSOBJECT_CALL_TO_APPLY, 0, mh); } final MethodType type = desc.getMethodType(); mh = type.parameterType(type.parameterCount() - 1) == Object[].class ? @@ -215,6 +219,19 @@ } } + // This is used when a JSObject is called as scope call to do undefined -> Global this translation. + @SuppressWarnings("unused") + private static Object jsObjectScopeCall(final JSObject jsObj, final Object thiz, final Object[] args) { + final Object modifiedThiz; + if (thiz == ScriptRuntime.UNDEFINED && !jsObj.isStrictFunction()) { + final Global global = Context.getGlobal(); + modifiedThiz = ScriptObjectMirror.wrap(global, global); + } else { + modifiedThiz = thiz; + } + return jsObj.call(modifiedThiz, args); + } + private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality(); // method handles of the current class @@ -226,6 +243,7 @@ private static final MethodHandle JSOBJECT_GETMEMBER = findJSObjectMH_V("getMember", Object.class, String.class); private static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class); private static final MethodHandle JSOBJECT_CALL = findJSObjectMH_V("call", Object.class, Object.class, Object[].class); + private static final MethodHandle JSOBJECT_SCOPE_CALL = findOwnMH_S("jsObjectScopeCall", Object.class, JSObject.class, Object.class, Object[].class); private static final MethodHandle JSOBJECT_CALL_TO_APPLY = findOwnMH_S("callToApply", Object.class, MethodHandle.class, JSObject.class, Object.class, Object[].class); private static final MethodHandle JSOBJECT_NEW = findJSObjectMH_V("newObject", Object.class, Object[].class); diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/ModuleGraphManipulator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/ModuleGraphManipulator.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/ModuleGraphManipulator.java Thu Dec 01 21:40:33 2016 +0000 @@ -61,8 +61,8 @@ throw new IllegalStateException(myClass + " loaded by wrong loader!"); } - // From this module add a qualified export to nashorn module - MY_MODULE.addExports(MY_PKG_NAME, nashornModule); + // open package to nashorn module + MY_MODULE.addOpens(MY_PKG_NAME, nashornModule); } // The following method is reflectively invoked from Nashorn diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/src/jdk.scripting.nashorn/share/classes/module-info.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/module-info.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/module-info.java Thu Dec 01 21:40:33 2016 +0000 @@ -23,9 +23,12 @@ * questions. */ +/** + * Nashorn + */ module jdk.scripting.nashorn { requires java.logging; - requires public java.scripting; + requires transitive java.scripting; requires jdk.dynalink; exports jdk.nashorn.api.scripting; diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/test/TEST.ROOT --- a/nashorn/test/TEST.ROOT Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/test/TEST.ROOT Thu Dec 01 21:40:33 2016 +0000 @@ -8,7 +8,7 @@ groups=TEST.groups # Minimum jtreg version -requiredVersion=4.2 b03 +requiredVersion=4.2 b04 # Use new module options useNewOptions=true diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/test/script/basic/JDK-8161579.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8161579.js Thu Dec 01 21:40:33 2016 +0000 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016, 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-8161579: Array-like AbstractJSObject-based instance not treated as array by native array functions + * + * @test + * @run + */ + + +var AbstractJSObject = Java.type("jdk.nashorn.api.scripting.AbstractJSObject"); +var JavaStringArray = Java.type("java.lang.String[]"); +var JavaArrayList = Java.type("java.util.ArrayList"); + +var arrayLikeJSObject = new AbstractJSObject() { + hasMember: function(name) { return name == "length"; }, + getMember: function(name) { return name == "length" ? 3 : null; }, + hasSlot: function(slot) { return slot >= 0 && slot <= 2; }, + getSlot: function(slot) { return "abc"[slot]; }, + isArray: function() { return true; } +} + +var javaStringArray = new JavaStringArray(3); +javaStringArray[0] = "x"; +javaStringArray[1] = "y"; +javaStringArray[2] = "z"; + +var javaArrayList = new JavaArrayList(); +javaArrayList.add("i"); +javaArrayList.add("j"); +javaArrayList.add("k"); + +Assert.assertEquals([1, 2, 3].concat(arrayLikeJSObject).join(), "1,2,3,a,b,c"); +Assert.assertEquals([1, 2, 3].concat(javaStringArray).join(), "1,2,3,x,y,z"); +Assert.assertEquals([1, 2, 3].concat(javaArrayList).join(), "1,2,3,i,j,k"); +Assert.assertEquals([1, 2, 3].concat("foo").join(), "1,2,3,foo"); +Assert.assertEquals([1, 2, 3].concat(4).join(), "1,2,3,4"); +Assert.assertEquals([1, 2, 3].concat(false).join(), "1,2,3,false"); + diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/test/script/basic/JDK-8170322.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8170322.js Thu Dec 01 21:40:33 2016 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, 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-8170322: Specialized functions convert booleans to numbers + * + * @test + * @run + */ + +var array = []; +array.push(true); +array.push(false); + +Assert.assertTrue([].concat(true)[0] === true); +Assert.assertTrue([].concat(false)[0] === false); + +Assert.assertTrue(array[0] === true); +Assert.assertTrue(array[1] === false); + +Assert.assertTrue("foo".charAt(false) === 'f'); +Assert.assertTrue("foo".charAt(true) === 'o'); diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/test/script/basic/JDK-8170594.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8170594.js Thu Dec 01 21:40:33 2016 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016 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-8170594: >>>=0 generates invalid bytecode for BaseNode LHS + * + * @test + * @run + */ + +var obj1 = {x: "100"}; +(function (o, p) { + if (p) { + o.x >>>= 0; + } +})(obj1, true) +Assert.assertTrue(obj1.x === 100) + +var obj2 = ["100"]; +(function (o, p) { + if (p) { + o[0] >>>= 0; + } +})(obj2, true) +Assert.assertTrue(obj2[0] === 100) diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/test/script/nosecurity/JDK-8044798.js --- a/nashorn/test/script/nosecurity/JDK-8044798.js Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/test/script/nosecurity/JDK-8044798.js Thu Dec 01 21:40:33 2016 +0000 @@ -33,13 +33,14 @@ var Arrays = Java.type("java.util.Arrays"); var CharArray = Java.type("char[]"); +var Reflector = Java.type("jdk.nashorn.test.models.Reflector"); var DebuggerSupport = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport"); var DebuggerValueDesc = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport.DebuggerValueDesc"); var valueDescFields = DebuggerValueDesc.class.declaredFields; Arrays.sort(valueDescFields, function(f1, f2) f1.name.compareTo(f2.name)); for each (var f in valueDescFields) { - f.accessible = true; + Reflector.setAccessible(f); } var debuggerSupportMethods = DebuggerSupport.class.declaredMethods; @@ -49,7 +50,7 @@ var getSourceInfoMethod, valueAsStringMethod; for each (var m in debuggerSupportMethods) { - m.accessible = true; + Reflector.setAccessible(m); switch (m.name) { case "eval": evalMethod = m; @@ -129,10 +130,10 @@ // private compile method of Context class var compileMethod = contextCls.getDeclaredMethod("compile", sourceCls, errorMgrCls, booleanCls, booleanCls); -compileMethod.accessible = true; +Reflector.setAccessible(compileMethod); var getContextMethod = contextCls.getMethod("getContext"); -getContextMethod.accessible = true; +Reflector.setAccessible(getContextMethod); var sourceForMethod = sourceCls.getMethod("sourceFor", stringCls, stringCls); var scriptCls = compileMethod.invoke(getContextMethod.invoke(null), @@ -149,7 +150,7 @@ print("Source info"); for each (var f in srcInfoFields) { - f.accessible = true; + Reflector.setAccessible(f); var fieldValue = f.get(srcInfo); if (fieldValue instanceof CharArray) { fieldValue = new java.lang.String(fieldValue); diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java --- a/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java Thu Dec 01 21:40:33 2016 +0000 @@ -41,6 +41,7 @@ import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; +import jdk.nashorn.api.scripting.AbstractJSObject; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.api.scripting.ScriptObjectMirror; import org.testng.annotations.Test; @@ -389,4 +390,41 @@ assertTrue(func.isFunction()); assertEquals(func.call(e.eval("this"), "hello"), "hello world"); } + + // @bug 8170565: JSObject call() is passed undefined for the argument 'thiz' + @Test + public void jsObjectThisTest() throws Exception { + final ScriptEngineManager engineManager = new ScriptEngineManager(); + final ScriptEngine e = engineManager.getEngineByName("nashorn"); + e.put("func", new AbstractJSObject() { + @Override + public boolean isFunction() { return true; } + + @Override + public Object call(Object thiz, Object...args) { + return thiz; + } + }); + + assertTrue((boolean)e.eval("func() === this")); + + // check that there is no blind undefined->Global translation! + assertTrue((boolean)e.eval("typeof(Function.prototype.call.call(func, undefined)) == 'undefined'")); + + // make sure that strict functions don't get translated this for scope calls! + e.put("sfunc", new AbstractJSObject() { + @Override + public boolean isFunction() { return true; } + + @Override + public boolean isStrictFunction() { return true; } + + @Override + public Object call(Object thiz, Object...args) { + return thiz; + } + }); + + assertTrue((boolean)e.eval("typeof sfunc() == 'undefined'")); + } } diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/BignumTest.java --- a/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/BignumTest.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/BignumTest.java Thu Dec 01 21:40:33 2016 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -69,7 +69,7 @@ * Bignum class tests * * @test - * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv + * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv:open * @run testng jdk.nashorn.internal.runtime.doubleconv.test.BignumTest */ @SuppressWarnings("javadoc") diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/DiyFpTest.java --- a/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/DiyFpTest.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/DiyFpTest.java Thu Dec 01 21:40:33 2016 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, 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 @@ -44,7 +44,7 @@ * DiyFp class tests * * @test - * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv + * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv:open * @run testng jdk.nashorn.internal.runtime.doubleconv.test.DiyFpTest */ @SuppressWarnings("javadoc") diff -r b83e676b8c94 -r 78b4e7cfccc0 nashorn/test/src/jdk/nashorn/test/models/Reflector.java --- a/nashorn/test/src/jdk/nashorn/test/models/Reflector.java Thu Dec 01 21:01:55 2016 +0000 +++ b/nashorn/test/src/jdk/nashorn/test/models/Reflector.java Thu Dec 01 21:40:33 2016 +0000 @@ -26,6 +26,7 @@ package jdk.nashorn.test.models; import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Module; @@ -42,6 +43,22 @@ private Reflector() {} private static final Module NASHORN_MOD = Context.class.getModule(); + public static void setAccessible(Executable e) { + if (e.getDeclaringClass().getModule() != NASHORN_MOD) { + throw new RuntimeException(e + " is not from Nashorn module"); + } + + e.setAccessible(true); + } + + public static void setAccessible(Field f) { + if (f.getDeclaringClass().getModule() != NASHORN_MOD) { + throw new RuntimeException(f + " is not from Nashorn module"); + } + + f.setAccessible(true); + } + public static Object invoke(final Method m, final Object self, final Object...args) { if (m.getDeclaringClass().getModule() != NASHORN_MOD) { throw new RuntimeException(m + " is not from Nashorn module");