提交 42a28e9c 编写于 作者: H hannesw

8143896: java.lang.Long is implicitly converted to double

Reviewed-by: lagergren, sundar
上级 7aeb76cf
......@@ -293,8 +293,8 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
// Step 3c and 3d - get new length and convert to long
final long newLen = NativeArray.validLength(newLenDesc.getValue());
// Step 3e
newLenDesc.setValue(newLen);
// Step 3e - note that we need to convert to int or double as long is not considered a JS number type anymore
newLenDesc.setValue(JSType.isRepresentableAsInt(newLen) ? Integer.valueOf((int) newLen) : Double.valueOf((double) newLen));
// Step 3f
// increasing array length - just need to set new length value (and attributes if any) and return
......@@ -917,21 +917,6 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
return getContinuousNonEmptyArrayDataCCE(self, IntElements.class).fastPopInt();
}
/**
* Specialization of pop for ContinuousArrayData
*
* Primitive specialization, {@link LinkLogic}
*
* @param self self reference
* @return element popped
* @throws ClassCastException if array is empty, facilitating Undefined return value
*/
@SpecializedFunction(name="pop", linkLogic=PopLinkLogic.class)
public static long popLong(final Object self) {
//must be non empty Int or LongArrayData
return getContinuousNonEmptyArrayDataCCE(self, IntOrLongElements.class).fastPopLong();
}
/**
* Specialization of pop for ContinuousArrayData
*
......@@ -1006,7 +991,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return array length after push
*/
@SpecializedFunction(linkLogic=PushLinkLogic.class)
public static long push(final Object self, final int arg) {
public static double push(final Object self, final int arg) {
return getContinuousArrayDataCCE(self, Integer.class).fastPush(arg);
}
......@@ -1020,7 +1005,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return array length after push
*/
@SpecializedFunction(linkLogic=PushLinkLogic.class)
public static long push(final Object self, final long arg) {
public static double push(final Object self, final long arg) {
return getContinuousArrayDataCCE(self, Long.class).fastPush(arg);
}
......@@ -1034,7 +1019,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return array length after push
*/
@SpecializedFunction(linkLogic=PushLinkLogic.class)
public static long push(final Object self, final double arg) {
public static double push(final Object self, final double arg) {
return getContinuousArrayDataCCE(self, Double.class).fastPush(arg);
}
......@@ -1048,7 +1033,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return array length after push
*/
@SpecializedFunction(name="push", linkLogic=PushLinkLogic.class)
public static long pushObject(final Object self, final Object arg) {
public static double pushObject(final Object self, final Object arg) {
return getContinuousArrayDataCCE(self, Object.class).fastPush(arg);
}
......@@ -1090,7 +1075,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return array after pushes
*/
@SpecializedFunction
public static long push(final Object self, final Object arg) {
public static double push(final Object self, final Object arg) {
try {
final ScriptObject sobj = (ScriptObject)self;
final ArrayData arrayData = sobj.getArray();
......@@ -1507,7 +1492,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return index of element, or -1 if not found
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static long indexOf(final Object self, final Object searchElement, final Object fromIndex) {
public static double indexOf(final Object self, final Object searchElement, final Object fromIndex) {
try {
final ScriptObject sobj = (ScriptObject)Global.toObject(self);
final long len = JSType.toUint32(sobj.getLength());
......@@ -1543,7 +1528,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
* @return index of element, or -1 if not found
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static long lastIndexOf(final Object self, final Object... args) {
public static double lastIndexOf(final Object self, final Object... args) {
try {
final ScriptObject sobj = (ScriptObject)Global.toObject(self);
final long len = JSType.toUint32(sobj.getLength());
......
......@@ -256,8 +256,9 @@ public final class NativeDate extends ScriptObject {
* @return a Date that points to the current moment in time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static long now(final Object self) {
return System.currentTimeMillis();
public static double now(final Object self) {
// convert to double as long does not represent the primitive JS number type
return (double) System.currentTimeMillis();
}
/**
......
......@@ -49,6 +49,7 @@ import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.linker.NashornGuards;
import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
/**
......@@ -322,7 +323,7 @@ public final class NativeNumber extends ScriptObject {
* @return Link to be invoked at call site.
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) {
return PrimitiveLookup.lookupPrimitive(request, Number.class, new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER, PROTOFILTER);
return PrimitiveLookup.lookupPrimitive(request, NashornGuards.getNumberGuard(), new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER, PROTOFILTER);
}
@SuppressWarnings("unused")
......
......@@ -74,7 +74,7 @@ public final class NativeRegExpExecResult extends ScriptObject {
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
public static Object length(final Object self) {
if (self instanceof ScriptObject) {
return JSType.toUint32(((ScriptObject)self).getArray().length());
return (double) JSType.toUint32(((ScriptObject)self).getArray().length());
}
return 0;
......
......@@ -157,7 +157,7 @@ public final class NativeString extends ScriptObject implements OptimisticBuilti
if (returnType == Object.class && JSType.isString(self)) {
try {
return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getStringGuard());
} catch (final LookupException e) {
//empty. Shouldn't happen. Fall back to super
}
......@@ -1241,8 +1241,8 @@ public final class NativeString extends ScriptObject implements OptimisticBuilti
* @return Link to be invoked at call site.
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) {
final MethodHandle guard = NashornGuards.getInstanceOf2Guard(String.class, ConsString.class);
return PrimitiveLookup.lookupPrimitive(request, guard, new NativeString((CharSequence)receiver), WRAPFILTER, PROTOFILTER);
return PrimitiveLookup.lookupPrimitive(request, NashornGuards.getStringGuard(),
new NativeString((CharSequence)receiver), WRAPFILTER, PROTOFILTER);
}
@SuppressWarnings("unused")
......
......@@ -174,6 +174,12 @@ public enum JSType {
/** Method handle for void returns. */
public static final Call VOID_RETURN = staticCall(JSTYPE_LOOKUP, JSType.class, "voidReturn", void.class);
/** Method handle for isString method */
public static final Call IS_STRING = staticCall(JSTYPE_LOOKUP, JSType.class, "isString", boolean.class, Object.class);
/** Method handle for isNumber method */
public static final Call IS_NUMBER = staticCall(JSTYPE_LOOKUP, JSType.class, "isNumber", boolean.class, Object.class);
/**
* The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide
* in the dual--fields world
......@@ -276,7 +282,7 @@ public enum JSType {
return JSType.STRING;
}
if (obj instanceof Number) {
if (isNumber(obj)) {
return JSType.NUMBER;
}
......@@ -314,7 +320,7 @@ public enum JSType {
return JSType.STRING;
}
if (obj instanceof Number) {
if (isNumber(obj)) {
return JSType.NUMBER;
}
......@@ -421,9 +427,9 @@ public enum JSType {
public static boolean isPrimitive(final Object obj) {
return obj == null ||
obj == ScriptRuntime.UNDEFINED ||
obj instanceof Boolean ||
obj instanceof Number ||
isString(obj);
isString(obj) ||
isNumber(obj) ||
obj instanceof Boolean;
}
/**
......@@ -587,6 +593,24 @@ public enum JSType {
return obj instanceof String || obj instanceof ConsString;
}
/**
* Returns true if object represents a primitive JavaScript number value. Note that we only
* treat wrapper objects of Java primitive number types as objects that can be fully represented
* as JavaScript numbers (doubles). This means we exclude {@code long} and special purpose Number
* instances such as {@link java.util.concurrent.atomic.AtomicInteger}, as well as arbitrary precision
* numbers such as {@link java.math.BigInteger}.
*
* @param obj the object
* @return true if the object represents a primitive JavaScript number value.
*/
public static boolean isNumber(final Object obj) {
if (obj != null) {
final Class<?> c = obj.getClass();
return c == Integer.class || c == Double.class || c == Float.class || c == Short.class || c == Byte.class;
}
return false;
}
/**
* JavaScript compliant conversion of integer to String
*
......@@ -737,7 +761,7 @@ public enum JSType {
if (obj instanceof Double) {
return (Double)obj;
}
if (obj instanceof Number) {
if (isNumber(obj)) {
return ((Number)obj).doubleValue();
}
return Double.NaN;
......@@ -1313,7 +1337,7 @@ public enum JSType {
return obj.toString();
}
if (obj instanceof Number) {
if (isNumber(obj)) {
return toString(((Number)obj).doubleValue());
}
......
......@@ -290,7 +290,7 @@ public abstract class ContinuousArrayData extends ArrayData {
* @param arg argument
* @return new array length
*/
public long fastPush(final int arg) {
public double fastPush(final int arg) {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
......@@ -299,7 +299,7 @@ public abstract class ContinuousArrayData extends ArrayData {
* @param arg argument
* @return new array length
*/
public long fastPush(final long arg) {
public double fastPush(final long arg) {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
......@@ -308,7 +308,7 @@ public abstract class ContinuousArrayData extends ArrayData {
* @param arg argument
* @return new array length
*/
public long fastPush(final double arg) {
public double fastPush(final double arg) {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
......@@ -317,7 +317,7 @@ public abstract class ContinuousArrayData extends ArrayData {
* @param arg argument
* @return new array length
*/
public long fastPush(final Object arg) {
public double fastPush(final Object arg) {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
......@@ -329,14 +329,6 @@ public abstract class ContinuousArrayData extends ArrayData {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
/**
* Specialization - fast pop implementation
* @return element value
*/
public long fastPopLong() {
throw new ClassCastException(String.valueOf(getClass())); //type is wrong, relink
}
/**
* Specialization - fast pop implementation
* @return element value
......
......@@ -340,7 +340,7 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
}
@Override
public long fastPush(final int arg) {
public double fastPush(final int arg) {
final int len = (int)length();
if (len == array.length) {
array = Arrays.copyOf(array, nextSize(len));
......@@ -361,11 +361,6 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
return elem;
}
@Override
public long fastPopLong() {
return fastPopInt();
}
@Override
public double fastPopDouble() {
return fastPopInt();
......
......@@ -303,17 +303,17 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
}
@Override
public long fastPush(final int arg) {
public double fastPush(final int arg) {
return fastPush((double)arg);
}
@Override
public long fastPush(final long arg) {
public double fastPush(final long arg) {
return fastPush((double)arg);
}
@Override
public long fastPush(final double arg) {
public double fastPush(final double arg) {
final int len = (int)length();
if (len == array.length) {
//note that fastpush never creates spares arrays, there is nothing to gain by that - it will just use even more memory
......
......@@ -236,22 +236,22 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
}
@Override
public long fastPush(final int arg) {
public double fastPush(final int arg) {
return fastPush((Object)arg);
}
@Override
public long fastPush(final long arg) {
public double fastPush(final long arg) {
return fastPush((Object)arg);
}
@Override
public long fastPush(final double arg) {
public double fastPush(final double arg) {
return fastPush((Object)arg);
}
@Override
public long fastPush(final Object arg) {
public double fastPush(final Object arg) {
final int len = (int)length();
if (len == array.length) {
array = Arrays.copyOf(array, nextSize(len));
......
......@@ -34,6 +34,7 @@ import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
......@@ -46,10 +47,9 @@ import jdk.nashorn.internal.runtime.options.Options;
public final class NashornGuards {
private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, ScriptObject.class, PropertyMap.class);
private static final MethodHandle IS_MAP_SCRIPTOBJECT = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class);
private static final MethodHandle IS_NOT_JSOBJECT = findOwnMH("isNotJSObject", boolean.class, Object.class);
private static final MethodHandle SAME_OBJECT = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class);
private static final MethodHandle SAME_OBJECT = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class);
//TODO - maybe put this back in ScriptFunction instead of the ClassCastException.class relinkage
//private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class);
......@@ -165,14 +165,21 @@ public final class NashornGuards {
}
/**
* Get a guard that checks if in item is an instance of either of two classes.
* Get a guard that checks if in item is a JS string.
*
* @param class1 the first class
* @param class2 the second class
* @return method handle for guard
*/
public static MethodHandle getInstanceOf2Guard(final Class<?> class1, final Class<?> class2) {
return MH.insertArguments(IS_INSTANCEOF_2, 1, class1, class2);
public static MethodHandle getStringGuard() {
return JSType.IS_STRING.methodHandle();
}
/**
* Get a guard that checks if in item is a JS number.
*
* @return method handle for guard
*/
public static MethodHandle getNumberGuard() {
return JSType.IS_NUMBER.methodHandle();
}
/**
......@@ -223,11 +230,6 @@ public final class NashornGuards {
return self == ref.get();
}
@SuppressWarnings("unused")
private static boolean isInstanceOf2(final Object self, final Class<?> class1, final Class<?> class2) {
return class1.isInstance(self) || class2.isInstance(self);
}
@SuppressWarnings("unused")
private static boolean isScriptFunction(final Object self) {
return self instanceof ScriptFunction;
......
......@@ -57,7 +57,8 @@ final class NashornPrimitiveLinker implements TypeBasedGuardingDynamicLinker, Gu
}
private static boolean canLinkTypeStatic(final Class<?> type) {
return type == String.class || type == Boolean.class || type == ConsString.class || Number.class.isAssignableFrom(type);
return type == String.class || type == Boolean.class || type == ConsString.class || type == Integer.class
|| type == Double.class || type == Float.class || type == Short.class || type == Byte.class;
}
@Override
......@@ -171,7 +172,7 @@ final class NashornPrimitiveLinker implements TypeBasedGuardingDynamicLinker, Gu
@SuppressWarnings("unused")
private static boolean isJavaScriptPrimitive(final Object o) {
return JSType.isString(o) || o instanceof Boolean || o instanceof Number || o == null;
return JSType.isString(o) || o instanceof Boolean || JSType.isNumber(o) || o == null;
}
private static final MethodHandle GUARD_PRIMITIVE = findOwnMH("isJavaScriptPrimitive", boolean.class, Object.class);
......
......@@ -33,4 +33,4 @@ print(n);
var s = n.toString(5);
var m = parseInt(s, 5);
print(m === n);
print(n);
print(m);
......@@ -5,8 +5,8 @@ int array: check widen for false [class java.lang.Boolean]
int array: check widen for true [class java.lang.Boolean]
int array: check widen for 34 [class java.lang.Byte]
int array: check widen for 344454 [class java.lang.Integer]
int array: check widen for 454545 [class java.lang.Long]
int array: check widen for 2147483648 [class java.lang.Long]
int array: check widen for 454545
int array: check widen for 2147483648
int array: check widen for 34.29999923706055 [class java.lang.Float]
int array: check widen for 3.141592653589793 [class java.lang.Double]
int array: check widen for s
......@@ -17,8 +17,8 @@ long array: check widen for false [class java.lang.Boolean]
long array: check widen for true [class java.lang.Boolean]
long array: check widen for 34 [class java.lang.Byte]
long array: check widen for 344454 [class java.lang.Integer]
long array: check widen for 454545 [class java.lang.Long]
long array: check widen for 2147483648 [class java.lang.Long]
long array: check widen for 454545
long array: check widen for 2147483648
long array: check widen for 34.29999923706055 [class java.lang.Float]
long array: check widen for 3.141592653589793 [class java.lang.Double]
long array: check widen for s
......@@ -29,8 +29,8 @@ number array: check widen for false [class java.lang.Boolean]
number array: check widen for true [class java.lang.Boolean]
number array: check widen for 34 [class java.lang.Byte]
number array: check widen for 344454 [class java.lang.Integer]
number array: check widen for 454545 [class java.lang.Long]
number array: check widen for 2147483648 [class java.lang.Long]
number array: check widen for 454545
number array: check widen for 2147483648
number array: check widen for 34.29999923706055 [class java.lang.Float]
number array: check widen for 3.141592653589793 [class java.lang.Double]
number array: check widen for s
......@@ -41,8 +41,8 @@ object array: check widen for false [class java.lang.Boolean]
object array: check widen for true [class java.lang.Boolean]
object array: check widen for 34 [class java.lang.Byte]
object array: check widen for 344454 [class java.lang.Integer]
object array: check widen for 454545 [class java.lang.Long]
object array: check widen for 2147483648 [class java.lang.Long]
object array: check widen for 454545
object array: check widen for 2147483648
object array: check widen for 34.29999923706055 [class java.lang.Float]
object array: check widen for 3.141592653589793 [class java.lang.Double]
object array: check widen for s
/*
* 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-8143896: java.lang.Long is implicitly converted to double
*
* @test
* @run
*/
Assert.assertTrue(java.lang.Long.valueOf("301077366599181567").toString() === "301077366599181567");
Assert.assertTrue(java.lang.Long.valueOf("-301077366599181567").toString() === "-301077366599181567");
Assert.assertTrue(java.lang.Long.valueOf("301077366599181567") == 301077366599181567);
Assert.assertFalse(java.lang.Long.valueOf("301077366599181567") === 301077366599181567);
Assert.assertTrue(new java.math.BigInteger("301077366599181567").toString() === "301077366599181567");
Assert.assertTrue(new java.math.BigInteger("-301077366599181567").toString() === "-301077366599181567");
Assert.assertTrue(new java.math.BigInteger("301077366599181567") == 301077366599181567);
Assert.assertFalse(new java.math.BigInteger("301077366599181567") === 301077366599181567);
var n = new java.lang.Byte("123");
Assert.assertTrue(typeof n === "number");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertTrue(n === 123);
n = new java.lang.Short("123");
Assert.assertTrue(typeof n === "number");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertTrue(n === 123);
n = new java.lang.Integer("123");
Assert.assertTrue(typeof n === "number");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertTrue(n === 123);
n = new java.lang.Float("123");
Assert.assertTrue(typeof n === "number");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertTrue(n === 123);
n = new java.lang.Double("123");
Assert.assertTrue(typeof n === "number");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertTrue(n === 123);
n = new java.lang.Long("123");
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);
n = new java.util.concurrent.atomic.DoubleAdder();
n.add("123");
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);
n = new java.util.concurrent.atomic.AtomicInteger(123);
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);
n = new java.util.concurrent.atomic.AtomicLong(123);
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);
n = new java.math.BigInteger("123");
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);
n = new java.math.BigDecimal("123");
Assert.assertTrue(typeof n === "object");
Assert.assertTrue(n + 1 === 124);
Assert.assertTrue(n == 123);
Assert.assertFalse(n === 123);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册