--- 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");