Merge
authorlana
Thu, 01 Dec 2016 21:40:33 +0000
changeset 42384 78b4e7cfccc0
parent 42375 b83e676b8c94 (current diff)
parent 42383 7c6ddb187262 (diff)
child 42385 ce0f4196cdf6
Merge
--- 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/
--- 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
--- 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);
         }
--- 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);
                         }
                     };
                 }
--- 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 = "<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();
--- 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
 
--- 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;
 
--- 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;
--- 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!
         }
--- 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();
--- 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<Object> 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<Object> 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);
         }
     }
 
--- 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
      *
--- 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;
 }
--- 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);
--- 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<CodeSource, Class<?>> 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<Unsafe>() {
-                @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 ? */
--- 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");
--- 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<? extends LinkLogic> 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<? extends LinkLogic> linkLogicClass, final boolean isOptimistic) {
+    public Specialization(final MethodHandle mh, final Class<? extends LinkLogic> 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;
+    }
+
 }
 
--- 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);
--- 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);
 
--- 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
--- 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;
--- 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
--- /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");
+
--- /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');
--- /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)
--- 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);
--- 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'"));
+    }
 }
--- 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")
--- 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")
--- 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");