--- old/src/jdk/nashorn/internal/codegen/CodeGenerator.java 2016-01-20 14:14:37.263064546 +0100 +++ new/src/jdk/nashorn/internal/codegen/CodeGenerator.java 2016-01-20 14:14:37.175064547 +0100 @@ -188,8 +188,6 @@ private static final Call ENSURE_INT = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, "ensureInt", int.class, Object.class, int.class); - private static final Call ENSURE_LONG = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, - "ensureLong", long.class, Object.class, int.class); private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, "ensureNumber", double.class, Object.class, int.class); @@ -1720,7 +1718,7 @@ enterStatement(expressionStatement); loadAndDiscard(expressionStatement.getExpression()); - assert method.getStackSize() == 0; + assert method.getStackSize() == 0 : "stack not empty in " + expressionStatement; return false; } @@ -2235,7 +2233,7 @@ * @param arrayType the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT */ private void loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) { - assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY; + assert arrayType == Type.INT_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY; final Expression[] nodes = arrayLiteralNode.getValue(); final Object presets = arrayLiteralNode.getPresets(); @@ -2383,20 +2381,9 @@ method.convert(Type.OBJECT); } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) { method.load(((Integer)value).doubleValue()); - } else if(!resultBounds.canBeNarrowerThan(Type.LONG)) { - method.load(((Integer)value).longValue()); } else { method.load((Integer)value); } - } else if (value instanceof Long) { - if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) { - method.load((Long)value); - method.convert(Type.OBJECT); - } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) { - method.load(((Long)value).doubleValue()); - } else { - method.load((Long)value); - } } else if (value instanceof Double) { if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) { method.load((Double)value); @@ -3647,8 +3634,6 @@ private void loadMinusOne() { if (type.isInteger()) { method.load(isIncrement ? 1 : -1); - } else if (type.isLong()) { - method.load(isIncrement ? 1L : -1L); } else { method.load(isIncrement ? 1.0 : -1.0); } @@ -4030,23 +4015,66 @@ } private void loadASSIGN_SHR(final BinaryNode binaryNode) { - new BinarySelfAssignment(binaryNode) { + new SelfModifyingStore(binaryNode, binaryNode.lhs()) { @Override - protected void op() { - doSHR(); - } + protected void evaluate() { + new OptimisticOperation(assignNode, new TypeBounds(Type.INT, Type.NUMBER)) { + @Override + void loadStack() { + assert assignNode.getWidestOperandType() == Type.INT; + if (isRhsZero(binaryNode)) { + loadExpressionAsType(binaryNode.lhs(), Type.INT); + } else { + loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.INT, true, false); + method.shr(); + } + } + @Override + void consumeStack() { + if (isOptimistic(binaryNode)) { + toUint32Optimistic(binaryNode.getProgramPoint()); + } else { + toUint32Double(); + } + } + }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(binaryNode.lhs())); + method.convert(assignNode.getType()); + } }.store(); } - private void doSHR() { - // TODO: make SHR optimistic - method.shr(); - toUint(); + private void doSHR(final BinaryNode binaryNode) { + new OptimisticOperation(binaryNode, new TypeBounds(Type.INT, Type.NUMBER)) { + @Override + void loadStack() { + if (isRhsZero(binaryNode)) { + loadExpressionAsType(binaryNode.lhs(), Type.INT); + } else { + loadBinaryOperands(binaryNode); + method.shr(); + } + } + + @Override + void consumeStack() { + if (isOptimistic(binaryNode)) { + toUint32Optimistic(binaryNode.getProgramPoint()); + } else { + toUint32Double(); + } + } + }.emit(); + + } + + private void toUint32Optimistic(final int programPoint) { + method.load(programPoint); + JSType.TO_UINT32_OPTIMISTIC.invoke(method); } - private void toUint() { - JSType.TO_UINT32_I.invoke(method); + private void toUint32Double() { + JSType.TO_UINT32_DOUBLE.invoke(method); } private void loadASSIGN_SUB(final BinaryNode binaryNode) { @@ -4084,7 +4112,7 @@ // Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow. operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(), numericBounds.widest), Type.NUMBER); - forceConversionSeparation = node.getWidestOperationType().narrowerThan(numericBounds.widest); + forceConversionSeparation = true; } } loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false, forceConversionSeparation); @@ -4186,14 +4214,7 @@ } private void loadSHR(final BinaryNode binaryNode) { - // Optimize x >>> 0 to (uint)x - if (isRhsZero(binaryNode)) { - loadExpressionAsType(binaryNode.lhs(), Type.INT); - toUint(); - } else { - loadBinaryOperands(binaryNode); - doSHR(); - } + doSHR(binaryNode); } private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) { @@ -4464,6 +4485,7 @@ } } else { final Type storeType = assignNode.getType(); + assert storeType != Type.LONG; if (symbol.hasSlotFor(storeType)) { // Only emit a convert for a store known to be live; converts for dead stores can // give us an unnecessary ClassCastException. @@ -4848,8 +4870,6 @@ method.load(optimistic.getProgramPoint()); if(optimisticType.isInteger()) { method.invoke(ENSURE_INT); - } else if(optimisticType.isLong()) { - method.invoke(ENSURE_LONG); } else if(optimisticType.isNumber()) { method.invoke(ENSURE_NUMBER); } else { --- old/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java 2016-01-20 14:14:37.675064539 +0100 +++ new/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java 2016-01-20 14:14:37.587064540 +0100 @@ -167,8 +167,7 @@ assert fieldName.equals(getFieldName(fieldIndex, PRIMITIVE_FIELD_TYPE)) || fieldType.isObject() : key + " object keys must store to L*-fields"; assert fieldName.equals(getFieldName(fieldIndex, Type.OBJECT)) || fieldType.isPrimitive() : key + " primitive keys must store to J*-fields"; - loadTuple(method, tuple); - + loadTuple(method, tuple, true); method.putField(fieldClass, fieldName, fieldDesc); } @@ -180,11 +179,7 @@ * @param tuple Tuple to store. */ private void putSlot(final MethodEmitter method, final long index, final MapTuple tuple) { - if (JSType.isRepresentableAsInt(index)) { - method.load((int)index); - } else { - method.load(index); - } + loadIndex(method, index); loadTuple(method, tuple, false); //we don't pack array like objects method.dynamicSetIndex(callSiteFlags); } --- old/src/jdk/nashorn/internal/codegen/FoldConstants.java 2016-01-20 14:14:37.987064533 +0100 +++ new/src/jdk/nashorn/internal/codegen/FoldConstants.java 2016-01-20 14:14:37.907064534 +0100 @@ -307,9 +307,7 @@ final Type widest = Type.widest(lhs.getType(), rhs.getType()); boolean isInteger = widest.isInteger(); - boolean isLong = widest.isLong(); - - double value; + final double value; switch (parent.tokenType()) { case DIV: @@ -336,7 +334,8 @@ value = lhs.getNumber() - rhs.getNumber(); break; case SHR: - return LiteralNode.newInstance(token, finish, JSType.toUint32(lhs.getInt32() >>> rhs.getInt32())); + final long result = JSType.toUint32(lhs.getInt32() >>> rhs.getInt32()); + return LiteralNode.newInstance(token, finish, JSType.isRepresentableAsInt(result) ? (int) result : (double) result); case SAR: return LiteralNode.newInstance(token, finish, lhs.getInt32() >> rhs.getInt32()); case SHL: @@ -368,12 +367,9 @@ } isInteger &= JSType.isStrictlyRepresentableAsInt(value); - isLong &= JSType.isStrictlyRepresentableAsLong(value); if (isInteger) { return LiteralNode.newInstance(token, finish, (int)value); - } else if (isLong) { - return LiteralNode.newInstance(token, finish, (long)value); } return LiteralNode.newInstance(token, finish, value); --- old/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java 2016-01-20 14:14:38.331064527 +0100 +++ new/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java 2016-01-20 14:14:38.251064528 +0100 @@ -131,7 +131,6 @@ UNDEFINED(Type.UNDEFINED), BOOLEAN(Type.BOOLEAN), INT(Type.INT), - LONG(Type.LONG), DOUBLE(Type.NUMBER), OBJECT(Type.OBJECT); @@ -272,12 +271,9 @@ } private static class SymbolConversions { - private static byte I2L = 1 << 0; - private static byte I2D = 1 << 1; - private static byte I2O = 1 << 2; - private static byte L2D = 1 << 3; - private static byte L2O = 1 << 4; - private static byte D2O = 1 << 5; + private static final byte I2D = 1 << 0; + private static final byte I2O = 1 << 1; + private static final byte D2O = 1 << 2; private byte conversions; @@ -288,9 +284,6 @@ case INT: case BOOLEAN: switch (to) { - case LONG: - recordConversion(I2L); - return; case DOUBLE: recordConversion(I2D); return; @@ -301,18 +294,6 @@ illegalConversion(from, to); return; } - case LONG: - switch (to) { - case DOUBLE: - recordConversion(L2D); - return; - case OBJECT: - recordConversion(L2O); - return; - default: - illegalConversion(from, to); - return; - } case DOUBLE: if(to == LvarType.OBJECT) { recordConversion(D2O); @@ -340,26 +321,15 @@ if(hasConversion(D2O)) { symbol.setHasSlotFor(Type.NUMBER); } - if(hasConversion(L2O)) { - symbol.setHasSlotFor(Type.LONG); - } if(hasConversion(I2O)) { symbol.setHasSlotFor(Type.INT); } } if(symbol.hasSlotFor(Type.NUMBER)) { - if(hasConversion(L2D)) { - symbol.setHasSlotFor(Type.LONG); - } if(hasConversion(I2D)) { symbol.setHasSlotFor(Type.INT); } } - if(symbol.hasSlotFor(Type.LONG)) { - if(hasConversion(I2L)) { - symbol.setHasSlotFor(Type.INT); - } - } } } @@ -378,7 +348,7 @@ if(lvarType != null) { return lvarType; } - assert type.isObject(); + assert type.isObject() : "Unsupported primitive type: " + type; return LvarType.OBJECT; } private static LvarType widestLvarType(final LvarType t1, final LvarType t2) { --- old/src/jdk/nashorn/internal/codegen/MethodEmitter.java 2016-01-20 14:14:38.691064521 +0100 +++ new/src/jdk/nashorn/internal/codegen/MethodEmitter.java 2016-01-20 14:14:38.603064522 +0100 @@ -543,7 +543,6 @@ } else { assert false : type + " cannot be packed!"; } - //all others are nops, objects aren't packed } /** --- old/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java 2016-01-20 14:14:39.043064514 +0100 +++ new/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java 2016-01-20 14:14:38.959064516 +0100 @@ -41,7 +41,6 @@ import static jdk.nashorn.internal.runtime.JSType.GET_UNDEFINED; import static jdk.nashorn.internal.runtime.JSType.TYPE_DOUBLE_INDEX; import static jdk.nashorn.internal.runtime.JSType.TYPE_INT_INDEX; -import static jdk.nashorn.internal.runtime.JSType.TYPE_LONG_INDEX; import static jdk.nashorn.internal.runtime.JSType.TYPE_OBJECT_INDEX; import static jdk.nashorn.internal.runtime.JSType.TYPE_UNDEFINED_INDEX; import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex; @@ -535,8 +534,6 @@ switch (getAccessorTypeIndex(forType)) { case TYPE_INT_INDEX: return MH.explicitCastArguments(primitiveGetter, primitiveGetter.type().changeReturnType(int.class)); - case TYPE_LONG_INDEX: - return primitiveGetter; case TYPE_DOUBLE_INDEX: return MH.filterReturnValue(primitiveGetter, UNPACK_DOUBLE); case TYPE_OBJECT_INDEX: @@ -623,7 +620,7 @@ } assert !isOptimistic; - //freely coerce the result to whatever you asked for, this is e.g. Object->int for a & b + // freely coerce the result to whatever you asked for, this is e.g. Object->int for a & b final MethodHandle tgetter = getterForType(forType, primitiveGetter, objectGetter); if (fti == TYPE_OBJECT_INDEX) { if (fti != ti) { @@ -638,22 +635,10 @@ case TYPE_INT_INDEX: { return MH.asType(tgetter, tgetterType.changeReturnType(type)); } - case TYPE_LONG_INDEX: - switch (ti) { - case TYPE_INT_INDEX: - //get int while an int, truncating cast of long value - return MH.filterReturnValue(tgetter, JSType.TO_INT32_L.methodHandle); - case TYPE_LONG_INDEX: - return primitiveGetter; - default: - return MH.asType(tgetter, tgetterType.changeReturnType(type)); - } case TYPE_DOUBLE_INDEX: switch (ti) { case TYPE_INT_INDEX: return MH.filterReturnValue(tgetter, JSType.TO_INT32_D.methodHandle); - case TYPE_LONG_INDEX: - return MH.explicitCastArguments(tgetter, tgetterType.changeReturnType(type)); case TYPE_DOUBLE_INDEX: assert tgetterType.returnType() == double.class; return tgetter; @@ -734,12 +719,9 @@ switch (fti) { case TYPE_INT_INDEX: - case TYPE_LONG_INDEX: switch (ti) { case TYPE_INT_INDEX: return MH.asType(primitiveSetter, pmt.changeParameterType(1, int.class)); - case TYPE_LONG_INDEX: - return primitiveSetter; case TYPE_DOUBLE_INDEX: return MH.filterArguments(primitiveSetter, 1, PACK_DOUBLE); default: --- old/src/jdk/nashorn/internal/codegen/ObjectCreator.java 2016-01-20 14:14:39.403064508 +0100 +++ new/src/jdk/nashorn/internal/codegen/ObjectCreator.java 2016-01-20 14:14:39.319064510 +0100 @@ -29,6 +29,7 @@ import java.util.List; import jdk.nashorn.internal.codegen.types.Type; +import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; @@ -156,15 +157,15 @@ MethodEmitter loadTuple(final MethodEmitter method, final MapTuple tuple, final boolean pack) { loadValue(tuple.value, tuple.type); - if (pack && codegen.useDualFields() && tuple.isPrimitive()) { - method.pack(); - } else { + if (!codegen.useDualFields() || !tuple.isPrimitive()) { method.convert(Type.OBJECT); + } else if (pack) { + method.pack(); } return method; } - MethodEmitter loadTuple(final MethodEmitter method, final MapTuple tuple) { - return loadTuple(method, tuple, true); + MethodEmitter loadIndex(final MethodEmitter method, final long index) { + return JSType.isRepresentableAsInt(index) ? method.load((int) index) : method.load((double) index); } } --- old/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java 2016-01-20 14:14:39.715064503 +0100 +++ new/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java 2016-01-20 14:14:39.635064504 +0100 @@ -109,8 +109,6 @@ //avoid blowing up the array if we can if (constantValue instanceof Integer) { arrayData = arrayData.set(index, ((Integer)constantValue).intValue(), false); - } else if (constantValue instanceof Long) { - arrayData = arrayData.set(index, ((Long)constantValue).longValue(), false); } else if (constantValue instanceof Double) { arrayData = arrayData.set(index, ((Double)constantValue).doubleValue(), false); } else { @@ -169,12 +167,12 @@ final int index = ArrayIndex.getArrayIndex(tuple.key); assert ArrayIndex.isValidArrayIndex(index); method.dup(); - method.load(ArrayIndex.toLongIndex(index)); - loadTuple(method, tuple); + loadIndex(method, ArrayIndex.toLongIndex(index)); + loadTuple(method, tuple, false); method.dynamicSetIndex(callSiteFlags); } else { method.dup(); - loadTuple(method, tuple); + loadTuple(method, tuple, false); method.dynamicSet(property.getKey(), codegen.getCallSiteFlags(), false); } } --- old/src/jdk/nashorn/internal/codegen/TypeEvaluator.java 2016-01-20 14:14:40.035064497 +0100 +++ new/src/jdk/nashorn/internal/codegen/TypeEvaluator.java 2016-01-20 14:14:39.951064498 +0100 @@ -239,7 +239,7 @@ // currently deoptimize all the way to Object. return Type.OBJECT; } - assert returnType == Type.INT || returnType == Type.LONG || returnType == Type.NUMBER || returnType == Type.OBJECT; + assert returnType == Type.INT || returnType == Type.NUMBER || returnType == Type.OBJECT; return returnType; } } --- old/src/jdk/nashorn/internal/codegen/types/IntType.java 2016-01-20 14:14:40.375064491 +0100 +++ new/src/jdk/nashorn/internal/codegen/types/IntType.java 2016-01-20 14:14:40.291064492 +0100 @@ -72,7 +72,7 @@ @Override public Type nextWider() { - return LONG; + return NUMBER; } @Override --- old/src/jdk/nashorn/internal/codegen/types/LongType.java 2016-01-20 14:14:40.739064485 +0100 +++ new/src/jdk/nashorn/internal/codegen/types/LongType.java 2016-01-20 14:14:40.615064487 +0100 @@ -28,20 +28,11 @@ import static jdk.internal.org.objectweb.asm.Opcodes.L2D; import static jdk.internal.org.objectweb.asm.Opcodes.L2I; import static jdk.internal.org.objectweb.asm.Opcodes.LADD; -import static jdk.internal.org.objectweb.asm.Opcodes.LAND; -import static jdk.internal.org.objectweb.asm.Opcodes.LCMP; import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_0; import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_1; import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD; -import static jdk.internal.org.objectweb.asm.Opcodes.LMUL; -import static jdk.internal.org.objectweb.asm.Opcodes.LOR; import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN; -import static jdk.internal.org.objectweb.asm.Opcodes.LSHL; -import static jdk.internal.org.objectweb.asm.Opcodes.LSHR; import static jdk.internal.org.objectweb.asm.Opcodes.LSTORE; -import static jdk.internal.org.objectweb.asm.Opcodes.LSUB; -import static jdk.internal.org.objectweb.asm.Opcodes.LUSHR; -import static jdk.internal.org.objectweb.asm.Opcodes.LXOR; import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; @@ -53,7 +44,7 @@ /** * Type class: LONG */ -class LongType extends BitwiseType { +class LongType extends Type { private static final long serialVersionUID = 1L; private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Long.class, "valueOf", Long.class, long.class); @@ -82,12 +73,6 @@ } @Override - public Type cmp(final MethodVisitor method) { - method.visitInsn(LCMP); - return INT; - } - - @Override public Type load(final MethodVisitor method, final int slot) { assert slot != -1; method.visitVarInsn(LLOAD, slot); @@ -149,88 +134,6 @@ } @Override - public Type sub(final MethodVisitor method, final int programPoint) { - if(programPoint == INVALID_PROGRAM_POINT) { - method.visitInsn(LSUB); - } else { - method.visitInvokeDynamicInsn("lsub", "(JJ)J", MATHBOOTSTRAP, programPoint); - } - return LONG; - } - - @Override - public Type mul(final MethodVisitor method, final int programPoint) { - if(programPoint == INVALID_PROGRAM_POINT) { - method.visitInsn(LMUL); - } else { - method.visitInvokeDynamicInsn("lmul", "(JJ)J", MATHBOOTSTRAP, programPoint); - } - return LONG; - } - - @Override - public Type div(final MethodVisitor method, final int programPoint) { - if (programPoint == INVALID_PROGRAM_POINT) { - JSType.DIV_ZERO_LONG.invoke(method); - } else { - method.visitInvokeDynamicInsn("ldiv", "(JJ)J", MATHBOOTSTRAP, programPoint); - } - return LONG; - } - - @Override - public Type rem(final MethodVisitor method, final int programPoint) { - if (programPoint == INVALID_PROGRAM_POINT) { - JSType.REM_ZERO_LONG.invoke(method); - } else { - method.visitInvokeDynamicInsn("lrem", "(JJ)J", MATHBOOTSTRAP, programPoint); - } - return LONG; - } - - @Override - public Type shr(final MethodVisitor method) { - method.visitInsn(LUSHR); - return LONG; - } - - @Override - public Type sar(final MethodVisitor method) { - method.visitInsn(LSHR); - return LONG; - } - - @Override - public Type shl(final MethodVisitor method) { - method.visitInsn(LSHL); - return LONG; - } - - @Override - public Type and(final MethodVisitor method) { - method.visitInsn(LAND); - return LONG; - } - - @Override - public Type or(final MethodVisitor method) { - method.visitInsn(LOR); - return LONG; - } - - @Override - public Type xor(final MethodVisitor method) { - method.visitInsn(LXOR); - return LONG; - } - - @Override - public Type neg(final MethodVisitor method, final int programPoint) { - method.visitInvokeDynamicInsn("lneg", "(J)J", MATHBOOTSTRAP, programPoint); - return LONG; - } - - @Override public void _return(final MethodVisitor method) { method.visitInsn(LRETURN); } @@ -246,9 +149,4 @@ method.visitInsn(LCONST_0); return LONG; } - - @Override - public Type cmp(final MethodVisitor method, final boolean isCmpG) { - return cmp(method); - } } --- old/src/jdk/nashorn/internal/codegen/types/Type.java 2016-01-20 14:14:41.187064477 +0100 +++ new/src/jdk/nashorn/internal/codegen/types/Type.java 2016-01-20 14:14:41.063064479 +0100 @@ -921,7 +921,7 @@ /** * This is the long singleton, used for all long types */ - public static final BitwiseType LONG = putInCache(new LongType()); + public static final Type LONG = putInCache(new LongType()); /** * A string singleton --- old/src/jdk/nashorn/internal/ir/BinaryNode.java 2016-01-20 14:14:41.663064468 +0100 +++ new/src/jdk/nashorn/internal/ir/BinaryNode.java 2016-01-20 14:14:41.583064470 +0100 @@ -70,7 +70,9 @@ TokenType.ASSIGN_DIV, TokenType.ASSIGN_MOD, TokenType.ASSIGN_MUL, - TokenType.ASSIGN_SUB + TokenType.ASSIGN_SUB, + TokenType.SHR, + TokenType.ASSIGN_SHR }))); /** @@ -196,9 +198,7 @@ return Type.CHARSEQUENCE; } final Type widestOperandType = Type.widest(undefinedToNumber(booleanToInt(lhsType)), undefinedToNumber(booleanToInt(rhsType))); - if(widestOperandType == Type.INT) { - return Type.LONG; - } else if (widestOperandType.isNumeric()) { + if (widestOperandType.isNumeric()) { return Type.NUMBER; } // We pretty much can't know what it will be statically. Must presume OBJECT conservatively, as we can end @@ -210,7 +210,7 @@ } case SHR: case ASSIGN_SHR: - return Type.LONG; + return Type.NUMBER; case ASSIGN_SAR: case ASSIGN_SHL: case BIT_AND: @@ -239,10 +239,6 @@ if(lhsType == Type.BOOLEAN && rhsType == Type.BOOLEAN) { return Type.INT; } - final Type widestOperandType = Type.widest(booleanToInt(lhsType), booleanToInt(rhsType)); - if(widestOperandType == Type.INT) { - return Type.LONG; - } return Type.NUMBER; } case VOID: { @@ -565,6 +561,9 @@ if(type == null) { return widest; } + if (tokenType() == TokenType.ASSIGN_SHR || tokenType() == TokenType.SHR) { + return type; + } return Type.narrowest(widest, Type.widest(type, Type.widest(lhs.getType(), rhs.getType()))); } --- old/src/jdk/nashorn/internal/ir/LiteralNode.java 2016-01-20 14:14:41.987064463 +0100 +++ new/src/jdk/nashorn/internal/ir/LiteralNode.java 2016-01-20 14:14:41.903064464 +0100 @@ -364,8 +364,6 @@ private static Type numberGetType(final Number number) { if (number instanceof Integer) { return Type.INT; - } else if (number instanceof Long) { - return Type.LONG; } else if (number instanceof Double) { return Type.NUMBER; } else { @@ -396,6 +394,7 @@ * @return the new literal node */ public static LiteralNode newInstance(final long token, final int finish, final Number value) { + assert !(value instanceof Long); return new NumberLiteralNode(token, finish, value); } @@ -748,8 +747,6 @@ assert !elementType.isUnknown(); if (elementType.isInteger()) { return presetIntArray(value, postsets); - } else if (elementType.isLong()) { - return presetLongArray(value, postsets); } else if (elementType.isNumeric()) { return presetDoubleArray(value, postsets); } else { @@ -818,8 +815,6 @@ private static ArrayType getArrayType(final Type elementType) { if (elementType.isInteger()) { return Type.INT_ARRAY; - } else if (elementType.isLong()) { - return Type.LONG_ARRAY; } else if (elementType.isNumeric()) { return Type.NUMBER_ARRAY; } else { @@ -854,8 +849,6 @@ private boolean presetsMatchElementType() { if (elementType == Type.INT) { return presets instanceof int[]; - } else if (elementType == Type.LONG) { - return presets instanceof long[]; } else if (elementType == Type.NUMBER) { return presets instanceof double[]; } else { --- old/src/jdk/nashorn/internal/ir/Symbol.java 2016-01-20 14:14:42.311064457 +0100 +++ new/src/jdk/nashorn/internal/ir/Symbol.java 2016-01-20 14:14:42.231064458 +0100 @@ -82,14 +82,12 @@ public static final int HAS_SLOT = 1 << 10; /** Is this symbol known to store an int value ? */ public static final int HAS_INT_VALUE = 1 << 11; - /** Is this symbol known to store a long value ? */ - public static final int HAS_LONG_VALUE = 1 << 12; /** Is this symbol known to store a double value ? */ - public static final int HAS_DOUBLE_VALUE = 1 << 13; + public static final int HAS_DOUBLE_VALUE = 1 << 12; /** Is this symbol known to store an object value ? */ - public static final int HAS_OBJECT_VALUE = 1 << 14; + public static final int HAS_OBJECT_VALUE = 1 << 13; /** Is this symbol seen a declaration? Used for block scoped LET and CONST symbols only. */ - public static final int HAS_BEEN_DECLARED = 1 << 15; + public static final int HAS_BEEN_DECLARED = 1 << 14; /** Null or name identifying symbol. */ private final String name; @@ -256,7 +254,6 @@ */ public int slotCount() { return ((flags & HAS_INT_VALUE) == 0 ? 0 : 1) + - ((flags & HAS_LONG_VALUE) == 0 ? 0 : 2) + ((flags & HAS_DOUBLE_VALUE) == 0 ? 0 : 2) + ((flags & HAS_OBJECT_VALUE) == 0 ? 0 : 1); } @@ -278,7 +275,6 @@ append("slot="). append(firstSlot).append(' '); if((flags & HAS_INT_VALUE) != 0) { sb.append('I'); } - if((flags & HAS_LONG_VALUE) != 0) { sb.append('J'); } if((flags & HAS_DOUBLE_VALUE) != 0) { sb.append('D'); } if((flags & HAS_OBJECT_VALUE) != 0) { sb.append('O'); } sb.append(')'); @@ -573,11 +569,6 @@ return typeSlot; } typeSlot += ((flags & HAS_INT_VALUE) == 0 ? 0 : 1); - if(type.isLong()) { - assert (flags & HAS_LONG_VALUE) != 0; - return typeSlot; - } - typeSlot += ((flags & HAS_LONG_VALUE) == 0 ? 0 : 2); if(type.isNumber()) { assert (flags & HAS_DOUBLE_VALUE) != 0; return typeSlot; @@ -595,8 +586,6 @@ public boolean hasSlotFor(final Type type) { if(type.isBoolean() || type.isInteger()) { return (flags & HAS_INT_VALUE) != 0; - } else if(type.isLong()) { - return (flags & HAS_LONG_VALUE) != 0; } else if(type.isNumber()) { return (flags & HAS_DOUBLE_VALUE) != 0; } @@ -611,8 +600,6 @@ public void setHasSlotFor(final Type type) { if(type.isBoolean() || type.isInteger()) { setFlag(HAS_INT_VALUE); - } else if(type.isLong()) { - setFlag(HAS_LONG_VALUE); } else if(type.isNumber()) { setFlag(HAS_DOUBLE_VALUE); } else { --- old/src/jdk/nashorn/internal/objects/Global.java 2016-01-20 14:14:42.647064451 +0100 +++ new/src/jdk/nashorn/internal/objects/Global.java 2016-01-20 14:14:42.563064452 +0100 @@ -1096,8 +1096,6 @@ return new NativeArray(ArrayData.allocate((Object[])obj), this); } else if (obj instanceof double[]) { // extension return new NativeArray(ArrayData.allocate((double[])obj), this); - } else if (obj instanceof long[]) { - return new NativeArray(ArrayData.allocate((long[])obj), this); } else if (obj instanceof int[]) { return new NativeArray(ArrayData.allocate((int[]) obj), this); } else if (obj instanceof ArrayData) { @@ -1965,16 +1963,6 @@ } /** - * Allocate a new long array. - * - * @param initial number values. - * @return the new array - */ - public static NativeArray allocate(final long[] initial) { - return new NativeArray(ArrayData.allocate(initial)); - } - - /** * Allocate a new integer array. * * @param initial number values. @@ -2263,7 +2251,6 @@ new Specialization[] { new Specialization(GlobalFunctions.PARSEINT_Z), new Specialization(GlobalFunctions.PARSEINT_I), - new Specialization(GlobalFunctions.PARSEINT_J), new Specialization(GlobalFunctions.PARSEINT_OI), new Specialization(GlobalFunctions.PARSEINT_O) }); this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT); --- old/src/jdk/nashorn/internal/objects/NativeArguments.java 2016-01-20 14:14:43.023064444 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeArguments.java 2016-01-20 14:14:42.919064446 +0100 @@ -128,12 +128,6 @@ } @Override - public boolean delete(final long key, final boolean strict) { - final int index = ArrayIndex.getArrayIndex(key); - return isMapped(index) ? deleteMapped(index, strict) : super.delete(key, strict); - } - - @Override public boolean delete(final double key, final boolean strict) { final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? deleteMapped(index, strict) : super.delete(key, strict); --- old/src/jdk/nashorn/internal/objects/NativeArray.java 2016-01-20 14:14:43.455064437 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeArray.java 2016-01-20 14:14:43.319064439 +0100 @@ -100,20 +100,38 @@ } NativeArray(final long length) { - // TODO assert valid index in long before casting - this(ArrayData.allocate((int)length)); + this(ArrayData.allocate(length)); } NativeArray(final int[] array) { this(ArrayData.allocate(array)); } - NativeArray(final long[] array) { + NativeArray(final double[] array) { this(ArrayData.allocate(array)); } - NativeArray(final double[] array) { - this(ArrayData.allocate(array)); + NativeArray(final long[] array) { + this(ArrayData.allocate(array.length)); + + ArrayData arrayData = this.getArray(); + Class widest = int.class; + + for (int index = 0; index < array.length; index++) { + final long value = array[index]; + + if (widest == int.class && JSType.isRepresentableAsInt(value)) { + arrayData = arrayData.set(index, (int) value, false); + } else if (widest != Object.class && JSType.isRepresentableAsDouble(value)) { + arrayData = arrayData.set(index, (double) value, false); + widest = double.class; + } else { + arrayData = arrayData.set(index, (Object) value, false); + widest = Object.class; + } + } + + this.setArray(arrayData); } NativeArray(final Object[] array) { @@ -188,7 +206,7 @@ @Override public MethodHandle call() { return Bootstrap.createDynamicInvoker("dyn:call", rtype, Object.class, Object.class, Object.class, - long.class, Object.class); + double.class, Object.class); } }); } @@ -219,7 +237,7 @@ @Override public MethodHandle call() { return Bootstrap.createDynamicInvoker("dyn:call", Object.class, Object.class, - Undefined.class, Object.class, Object.class, long.class, Object.class); + Undefined.class, Object.class, Object.class, double.class, Object.class); } }); } @@ -255,8 +273,9 @@ @Override public Object getLength() { - final long length = JSType.toUint32(getArray().length()); - if (length < Integer.MAX_VALUE) { + final long length = getArray().length(); + assert length >= 0L; + if (length <= Integer.MAX_VALUE) { return (int)length; } return length; @@ -454,7 +473,13 @@ @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) public static Object length(final Object self) { if (isArray(self)) { - return JSType.toUint32(((ScriptObject) self).getArray().length()); + final long length = ((ScriptObject) self).getArray().length(); + assert length >= 0L; + // Cast to the narrowest supported numeric type to help optimistic type calculator + if (length <= Integer.MAX_VALUE) { + return (int) length; + } + return (double) length; } return 0; @@ -1562,7 +1587,7 @@ private final MethodHandle everyInvoker = getEVERY_CALLBACK_INVOKER(); @Override - protected boolean forEach(final Object val, final long i) throws Throwable { + protected boolean forEach(final Object val, final double i) throws Throwable { return result = (boolean)everyInvoker.invokeExact(callbackfn, thisArg, val, i, self); } }.apply(); @@ -1582,7 +1607,7 @@ private final MethodHandle someInvoker = getSOME_CALLBACK_INVOKER(); @Override - protected boolean forEach(final Object val, final long i) throws Throwable { + protected boolean forEach(final Object val, final double i) throws Throwable { return !(result = (boolean)someInvoker.invokeExact(callbackfn, thisArg, val, i, self)); } }.apply(); @@ -1602,7 +1627,7 @@ private final MethodHandle forEachInvoker = getFOREACH_CALLBACK_INVOKER(); @Override - protected boolean forEach(final Object val, final long i) throws Throwable { + protected boolean forEach(final Object val, final double i) throws Throwable { forEachInvoker.invokeExact(callbackfn, thisArg, val, i, self); return true; } @@ -1623,7 +1648,7 @@ private final MethodHandle mapInvoker = getMAP_CALLBACK_INVOKER(); @Override - protected boolean forEach(final Object val, final long i) throws Throwable { + protected boolean forEach(final Object val, final double i) throws Throwable { final Object r = mapInvoker.invokeExact(callbackfn, thisArg, val, i, self); result.defineOwnProperty(ArrayIndex.getArrayIndex(index), r); return true; @@ -1653,7 +1678,7 @@ private final MethodHandle filterInvoker = getFILTER_CALLBACK_INVOKER(); @Override - protected boolean forEach(final Object val, final long i) throws Throwable { + protected boolean forEach(final Object val, final double i) throws Throwable { if ((boolean)filterInvoker.invokeExact(callbackfn, thisArg, val, i, self)) { result.defineOwnProperty(ArrayIndex.getArrayIndex(to++), val); } @@ -1685,7 +1710,7 @@ private final MethodHandle reduceInvoker = getREDUCE_CALLBACK_INVOKER(); @Override - protected boolean forEach(final Object val, final long i) throws Throwable { + protected boolean forEach(final Object val, final double i) throws Throwable { // TODO: why can't I declare the second arg as Undefined.class? result = reduceInvoker.invokeExact(callbackfn, ScriptRuntime.UNDEFINED, result, val, i, self); return true; --- old/src/jdk/nashorn/internal/objects/NativeFloat32Array.java 2016-01-20 14:14:43.895064429 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeFloat32Array.java 2016-01-20 14:14:43.775064431 +0100 @@ -124,7 +124,7 @@ @Override public MethodHandle getElementGetter(final Class returnType, final int programPoint) { - if (returnType == int.class || returnType == long.class) { + if (returnType == int.class) { return null; } return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint); @@ -136,11 +136,6 @@ } @Override - public long getLong(final int index) { - return (long)getDouble(index); - } - - @Override public double getDouble(final int index) { return getElem(index); } @@ -165,11 +160,6 @@ return set(index, (double)value, strict); } - @Override - public ArrayData set(final int index, final long value, final boolean strict) { - return set(index, (double)value, strict); - } - @Override public ArrayData set(final int index, final double value, final boolean strict) { setElem(index, value); --- old/src/jdk/nashorn/internal/objects/NativeFloat64Array.java 2016-01-20 14:14:44.263064422 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeFloat64Array.java 2016-01-20 14:14:44.179064424 +0100 @@ -124,7 +124,7 @@ @Override public MethodHandle getElementGetter(final Class returnType, final int programPoint) { - if (returnType == int.class || returnType == long.class) { + if (returnType == int.class) { return null; } return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint); @@ -136,11 +136,6 @@ } @Override - public long getLong(final int index) { - return (long)getDouble(index); - } - - @Override public double getDouble(final int index) { return getElem(index); } @@ -165,11 +160,6 @@ return set(index, (double)value, strict); } - @Override - public ArrayData set(final int index, final long value, final boolean strict) { - return set(index, (double)value, strict); - } - @Override public ArrayData set(final int index, final double value, final boolean strict) { setElem(index, value); --- old/src/jdk/nashorn/internal/objects/NativeInt16Array.java 2016-01-20 14:14:44.611064416 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeInt16Array.java 2016-01-20 14:14:44.511064418 +0100 @@ -134,16 +134,6 @@ } @Override - public long getLong(final int index) { - return getInt(index); - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - return getElem(index); - } - - @Override public double getDouble(final int index) { return getInt(index); } @@ -170,11 +160,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - return set(index, (int)value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { return set(index, (int)value, strict); } --- old/src/jdk/nashorn/internal/objects/NativeInt32Array.java 2016-01-20 14:14:44.967064410 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeInt32Array.java 2016-01-20 14:14:44.855064412 +0100 @@ -133,16 +133,6 @@ } @Override - public long getLong(final int index) { - return getInt(index); - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - return getElem(index); - } - - @Override public double getDouble(final int index) { return getInt(index); } @@ -169,11 +159,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - return set(index, (int)value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { return set(index, (int)value, strict); } --- old/src/jdk/nashorn/internal/objects/NativeInt8Array.java 2016-01-20 14:14:45.383064403 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeInt8Array.java 2016-01-20 14:14:45.295064404 +0100 @@ -132,16 +132,6 @@ } @Override - public long getLong(final int index) { - return getInt(index); - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - return getElem(index); - } - - @Override public double getDouble(final int index) { return getInt(index); } @@ -168,11 +158,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - return set(index, (int)value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { return set(index, (int)value, strict); } --- old/src/jdk/nashorn/internal/objects/NativeJSAdapter.java 2016-01-20 14:14:45.791064395 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeJSAdapter.java 2016-01-20 14:14:45.703064397 +0100 @@ -179,36 +179,11 @@ } @Override - public int getInt(final long key, final int programPoint) { - return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key); - } - - @Override public int getInt(final int key, final int programPoint) { return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key); } @Override - public long getLong(final Object key, final int programPoint) { - return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key); - } - - @Override - public long getLong(final double key, final int programPoint) { - return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key); - } - - @Override - public long getLong(final long key, final int programPoint) { - return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key); - } - - @Override - public long getLong(final int key, final int programPoint) { - return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key); - } - - @Override public double getDouble(final Object key, final int programPoint) { return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key); } @@ -219,11 +194,6 @@ } @Override - public double getDouble(final long key, final int programPoint) { - return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key); - } - - @Override public double getDouble(final int key, final int programPoint) { return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key); } @@ -239,11 +209,6 @@ } @Override - public Object get(final long key) { - return (overrides && super.hasOwnProperty(key)) ? super.get(key) : callAdaptee(__get__, key); - } - - @Override public Object get(final int key) { return (overrides && super.hasOwnProperty(key)) ? super.get(key) : callAdaptee(__get__, key); } @@ -258,15 +223,6 @@ } @Override - public void set(final Object key, final long value, final int flags) { - if (overrides && super.hasOwnProperty(key)) { - super.set(key, value, flags); - } else { - callAdaptee(__put__, key, value, flags); - } - } - - @Override public void set(final Object key, final double value, final int flags) { if (overrides && super.hasOwnProperty(key)) { super.set(key, value, flags); @@ -294,15 +250,6 @@ } @Override - public void set(final double key, final long value, final int flags) { - if (overrides && super.hasOwnProperty(key)) { - super.set(key, value, flags); - } else { - callAdaptee(__put__, key, value, flags); - } - } - - @Override public void set(final double key, final double value, final int flags) { if (overrides && super.hasOwnProperty(key)) { super.set(key, value, flags); @@ -321,42 +268,6 @@ } @Override - public void set(final long key, final int value, final int flags) { - if (overrides && super.hasOwnProperty(key)) { - super.set(key, value, flags); - } else { - callAdaptee(__put__, key, value, flags); - } - } - - @Override - public void set(final long key, final long value, final int flags) { - if (overrides && super.hasOwnProperty(key)) { - super.set(key, value, flags); - } else { - callAdaptee(__put__, key, value, flags); - } - } - - @Override - public void set(final long key, final double value, final int flags) { - if (overrides && super.hasOwnProperty(key)) { - super.set(key, value, flags); - } else { - callAdaptee(__put__, key, value, flags); - } - } - - @Override - public void set(final long key, final Object value, final int flags) { - if (overrides && super.hasOwnProperty(key)) { - super.set(key, value, flags); - } else { - callAdaptee(__put__, key, value, flags); - } - } - - @Override public void set(final int key, final int value, final int flags) { if (overrides && super.hasOwnProperty(key)) { super.set(key, value, flags); @@ -366,15 +277,6 @@ } @Override - public void set(final int key, final long value, final int flags) { - if (overrides && super.hasOwnProperty(key)) { - super.set(key, value, flags); - } else { - callAdaptee(__put__, key, value, flags); - } - } - - @Override public void set(final int key, final double value, final int flags) { if (overrides && super.hasOwnProperty(key)) { super.set(key, value, flags); @@ -411,15 +313,6 @@ } @Override - public boolean has(final long key) { - if (overrides && super.hasOwnProperty(key)) { - return true; - } - - return JSType.toBoolean(callAdaptee(Boolean.FALSE, __has__, key)); - } - - @Override public boolean has(final double key) { if (overrides && super.hasOwnProperty(key)) { return true; @@ -438,15 +331,6 @@ } @Override - public boolean delete(final long key, final boolean strict) { - if (overrides && super.hasOwnProperty(key)) { - return super.delete(key, strict); - } - - return JSType.toBoolean(callAdaptee(Boolean.TRUE, __delete__, key, strict)); - } - - @Override public boolean delete(final double key, final boolean strict) { if (overrides && super.hasOwnProperty(key)) { return super.delete(key, strict); @@ -663,10 +547,6 @@ return JSType.toNumberMaybeOptimistic(callAdaptee(name, args), programPoint); } - private long callAdapteeLong(final int programPoint, final String name, final Object... args) { - return JSType.toLongMaybeOptimistic(callAdaptee(name, args), programPoint); - } - private int callAdapteeInt(final int programPoint, final String name, final Object... args) { return JSType.toInt32MaybeOptimistic(callAdaptee(name, args), programPoint); } --- old/src/jdk/nashorn/internal/objects/NativeString.java 2016-01-20 14:14:46.183064389 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeString.java 2016-01-20 14:14:46.099064390 +0100 @@ -221,14 +221,6 @@ } @Override - public Object get(final long key) { - if (key >= 0 && key < value.length()) { - return String.valueOf(value.charAt((int)key)); - } - return super.get(key); - } - - @Override public Object get(final int key) { if (key >= 0 && key < value.length()) { return String.valueOf(value.charAt(key)); @@ -247,36 +239,11 @@ } @Override - public int getInt(final long key, final int programPoint) { - return JSType.toInt32MaybeOptimistic(get(key), programPoint); - } - - @Override public int getInt(final int key, final int programPoint) { return JSType.toInt32MaybeOptimistic(get(key), programPoint); } @Override - public long getLong(final Object key, final int programPoint) { - return JSType.toLongMaybeOptimistic(get(key), programPoint); - } - - @Override - public long getLong(final double key, final int programPoint) { - return JSType.toLongMaybeOptimistic(get(key), programPoint); - } - - @Override - public long getLong(final long key, final int programPoint) { - return JSType.toLongMaybeOptimistic(get(key), programPoint); - } - - @Override - public long getLong(final int key, final int programPoint) { - return JSType.toLongMaybeOptimistic(get(key), programPoint); - } - - @Override public double getDouble(final Object key, final int programPoint) { return JSType.toNumberMaybeOptimistic(get(key), programPoint); } @@ -287,11 +254,6 @@ } @Override - public double getDouble(final long key, final int programPoint) { - return JSType.toNumberMaybeOptimistic(get(key), programPoint); - } - - @Override public double getDouble(final int key, final int programPoint) { return JSType.toNumberMaybeOptimistic(get(key), programPoint); } @@ -309,12 +271,6 @@ } @Override - public boolean has(final long key) { - final int index = ArrayIndex.getArrayIndex(key); - return isValidStringIndex(index) || super.has(key); - } - - @Override public boolean has(final double key) { final int index = ArrayIndex.getArrayIndex(key); return isValidStringIndex(index) || super.has(key); @@ -333,12 +289,6 @@ } @Override - public boolean hasOwnProperty(final long key) { - final int index = ArrayIndex.getArrayIndex(key); - return isValidStringIndex(index) || super.hasOwnProperty(key); - } - - @Override public boolean hasOwnProperty(final double key) { final int index = ArrayIndex.getArrayIndex(key); return isValidStringIndex(index) || super.hasOwnProperty(key); @@ -350,12 +300,6 @@ } @Override - public boolean delete(final long key, final boolean strict) { - final int index = ArrayIndex.getArrayIndex(key); - return checkDeleteIndex(index, strict)? false : super.delete(key, strict); - } - - @Override public boolean delete(final double key, final boolean strict) { final int index = ArrayIndex.getArrayIndex(key); return checkDeleteIndex(index, strict)? false : super.delete(key, strict); --- old/src/jdk/nashorn/internal/objects/NativeUint16Array.java 2016-01-20 14:14:46.543064382 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeUint16Array.java 2016-01-20 14:14:46.459064384 +0100 @@ -138,16 +138,6 @@ } @Override - public long getLong(final int index) { - return getInt(index); - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - return getElem(index); - } - - @Override public double getDouble(final int index) { return getInt(index); } @@ -174,11 +164,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - return set(index, (int)value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { return set(index, (int)value, strict); } --- old/src/jdk/nashorn/internal/objects/NativeUint32Array.java 2016-01-20 14:14:47.055064373 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeUint32Array.java 2016-01-20 14:14:46.907064376 +0100 @@ -32,6 +32,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; +import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -41,6 +42,7 @@ import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; import jdk.nashorn.internal.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.arrays.TypedArrayData; @@ -78,7 +80,7 @@ private static final class Uint32ArrayData extends TypedArrayData { - private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "getElem", long.class, int.class).methodHandle(); + private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "getElem", double.class, int.class).methodHandle(); private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle(); private Uint32ArrayData(final IntBuffer nb, final int start, final int end) { @@ -103,14 +105,18 @@ return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint); } - private long getElem(final int index) { + private int getRawElem(final int index) { try { - return JSType.toUint32(nb.get(index)); + return nb.get(index); } catch (final IndexOutOfBoundsException e) { throw new ClassCastException(); //force relink - this works for unoptimistic too } } + private double getElem(final int index) { + return JSType.toUint32(getRawElem(index)); + } + private void setElem(final int index, final int elem) { try { if (index < nb.limit()) { @@ -128,42 +134,37 @@ @Override public Class getElementType() { - return long.class; + return double.class; } @Override public Class getBoxedElementType() { - return Integer.class; + return Double.class; } @Override public int getInt(final int index) { - return (int)getLong(index); + return getRawElem(index); } @Override - public long getLong(final int index) { - return getElem(index); - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - return getElem(index); + public int getIntOptimistic(final int index, final int programPoint) { + return JSType.toUint32Optimistic(getRawElem(index), programPoint); } @Override public double getDouble(final int index) { - return getLong(index); + return getElem(index); } @Override public double getDoubleOptimistic(final int index, final int programPoint) { - return getLong(index); + return getElem(index); } @Override public Object getObject(final int index) { - return getLong(index); + return getElem(index); } @Override @@ -178,11 +179,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - return set(index, (int)value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { return set(index, (int)value, strict); } --- old/src/jdk/nashorn/internal/objects/NativeUint8Array.java 2016-01-20 14:14:47.591064364 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeUint8Array.java 2016-01-20 14:14:47.443064366 +0100 @@ -138,16 +138,6 @@ } @Override - public long getLong(final int index) { - return getInt(index); - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - return getElem(index); - } - - @Override public double getDouble(final int index) { return getInt(index); } @@ -174,11 +164,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - return set(index, (int)value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { return set(index, (int)value, strict); } --- old/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java 2016-01-20 14:14:48.151064354 +0100 +++ new/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java 2016-01-20 14:14:48.015064356 +0100 @@ -168,16 +168,6 @@ } @Override - public long getLong(final int index) { - return getInt(index); - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - return getElem(index); - } - - @Override public double getDouble(final int index) { return getInt(index); } @@ -204,11 +194,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - return set(index, (int)value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { return set(index, rint(value), strict); } --- old/src/jdk/nashorn/internal/parser/JSONParser.java 2016-01-20 14:14:48.499064348 +0100 +++ new/src/jdk/nashorn/internal/parser/JSONParser.java 2016-01-20 14:14:48.411064349 +0100 @@ -293,8 +293,6 @@ private static Class getType(final Object value) { if (value instanceof Integer) { return int.class; - } else if (value instanceof Long) { - return long.class; } else if (value instanceof Double) { return double.class; } else { @@ -477,8 +475,6 @@ final double d = Double.parseDouble(source.substring(start, pos)); if (JSType.isRepresentableAsInt(d)) { return (int) d; - } else if (JSType.isRepresentableAsLong(d)) { - return (long) d; } return d; } --- old/src/jdk/nashorn/internal/parser/Lexer.java 2016-01-20 14:14:48.831064342 +0100 +++ new/src/jdk/nashorn/internal/parser/Lexer.java 2016-01-20 14:14:48.747064343 +0100 @@ -1042,11 +1042,7 @@ */ private static Number valueOf(final String valueString, final int radix) throws NumberFormatException { try { - final long value = Long.parseLong(valueString, radix); - if(value >= MIN_INT_L && value <= MAX_INT_L) { - return Integer.valueOf((int)value); - } - return Long.valueOf(value); + return Integer.parseInt(valueString, radix); } catch (final NumberFormatException e) { if (radix == 10) { return Double.valueOf(valueString); @@ -1655,8 +1651,6 @@ //yet we don't want e.g. 1e6 to be a double unnecessarily if (JSType.isStrictlyRepresentableAsInt(value)) { return (int)value; - } else if (JSType.isStrictlyRepresentableAsLong(value)) { - return (long)value; } return value; case STRING: --- old/src/jdk/nashorn/internal/runtime/AccessorProperty.java 2016-01-20 14:14:49.151064336 +0100 +++ new/src/jdk/nashorn/internal/runtime/AccessorProperty.java 2016-01-20 14:14:49.071064338 +0100 @@ -221,7 +221,7 @@ assert setterType == null || setterType == getterType; - if (getterType == int.class || getterType == long.class) { + if (getterType == int.class) { primitiveGetter = MH.asType(getter, Lookup.GET_PRIMITIVE_TYPE); primitiveSetter = setter == null ? null : MH.asType(setter, Lookup.SET_PRIMITIVE_TYPE); } else if (getterType == double.class) { @@ -400,17 +400,6 @@ } } - @Override - public long getLongValue(final ScriptObject self, final ScriptObject owner) { - try { - return (long)getGetter(long.class).invokeExact((Object)self); - } catch (final Error | RuntimeException e) { - throw e; - } catch (final Throwable e) { - throw new RuntimeException(e); - } - } - @Override public double getDoubleValue(final ScriptObject self, final ScriptObject owner) { try { @@ -453,21 +442,6 @@ * @param self owner * @param value value */ - protected final void invokeSetter(final ScriptObject self, final long value) { - try { - getSetter(long.class, self.getMap()).invokeExact((Object)self, value); - } catch (final Error | RuntimeException e) { - throw e; - } catch (final Throwable e) { - throw new RuntimeException(e); - } - } - - /** - * Invoke setter for this property with a value - * @param self owner - * @param value value - */ protected final void invokeSetter(final ScriptObject self, final double value) { try { getSetter(double.class, self.getMap()).invokeExact((Object)self, value); @@ -500,12 +474,6 @@ } @Override - public void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict) { - assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable"; - invokeSetter(self, value); - } - - @Override public void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict) { assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable"; invokeSetter(self, value); @@ -533,7 +501,6 @@ final int i = getAccessorTypeIndex(type); assert type == int.class || - type == long.class || type == double.class || type == Object.class : "invalid getter type " + type + " for " + getKey(); --- old/src/jdk/nashorn/internal/runtime/DebuggerSupport.java 2016-01-20 14:14:49.471064331 +0100 +++ new/src/jdk/nashorn/internal/runtime/DebuggerSupport.java 2016-01-20 14:14:49.391064332 +0100 @@ -239,7 +239,7 @@ if (ScriptObject.isArray(object)) { sb.append('['); - final long length = object.getLong("length", INVALID_PROGRAM_POINT); + final long length = (long) object.getDouble("length", INVALID_PROGRAM_POINT); for (long i = 0; i < length; i++) { if (object.has(i)) { --- old/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java 2016-01-20 14:14:49.847064324 +0100 +++ new/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java 2016-01-20 14:14:49.727064326 +0100 @@ -44,36 +44,11 @@ } @Override - public int getInt(final long key, final int programPoint) { - return getInt(JSType.toObject(key), programPoint); - } - - @Override public int getInt(final int key, final int programPoint) { return getInt(JSType.toObject(key), programPoint); } @Override - public long getLong(final Object key, final int programPoint) { - return JSType.toLong(get(key)); - } - - @Override - public long getLong(final double key, final int programPoint) { - return getLong(JSType.toObject(key), programPoint); - } - - @Override - public long getLong(final long key, final int programPoint) { - return getLong(JSType.toObject(key), programPoint); - } - - @Override - public long getLong(final int key, final int programPoint) { - return getLong(JSType.toObject(key), programPoint); - } - - @Override public double getDouble(final Object key, final int programPoint) { return JSType.toNumber(get(key)); } @@ -84,11 +59,6 @@ } @Override - public double getDouble(final long key, final int programPoint) { - return getDouble(JSType.toObject(key), programPoint); - } - - @Override public double getDouble(final int key, final int programPoint) { return getDouble(JSType.toObject(key), programPoint); } @@ -102,11 +72,6 @@ } @Override - public Object get(final long key) { - return get(JSType.toObject(key)); - } - - @Override public Object get(final int key) { return get(JSType.toObject(key)); } @@ -117,11 +82,6 @@ } @Override - public void set(final double key, final long value, final int flags) { - set(JSType.toObject(key), JSType.toObject(value), flags); - } - - @Override public void set(final double key, final double value, final int flags) { set(JSType.toObject(key), JSType.toObject(value), flags); } @@ -132,36 +92,11 @@ } @Override - public void set(final long key, final int value, final int flags) { - set(JSType.toObject(key), JSType.toObject(value), flags); - } - - @Override - public void set(final long key, final long value, final int flags) { - set(JSType.toObject(key), JSType.toObject(value), flags); - } - - @Override - public void set(final long key, final double value, final int flags) { - set(JSType.toObject(key), JSType.toObject(value), flags); - } - - @Override - public void set(final long key, final Object value, final int flags) { - set(JSType.toObject(key), value, flags); - } - - @Override public void set(final int key, final int value, final int flags) { set(JSType.toObject(key), JSType.toObject(value), flags); } @Override - public void set(final int key, final long value, final int flags) { - set(JSType.toObject(key), JSType.toObject(value), flags); - } - - @Override public void set(final int key, final double value, final int flags) { set(JSType.toObject(key), JSType.toObject(value), flags); } @@ -177,11 +112,6 @@ } @Override - public void set(final Object key, final long value, final int flags) { - set(key, JSType.toObject(value), flags); - } - - @Override public void set(final Object key, final double value, final int flags) { set(key, JSType.toObject(value), flags); } @@ -198,11 +128,6 @@ } @Override - public boolean has(final long key) { - return has(JSType.toObject(key)); - } - - @Override public boolean has(final double key) { return has(JSType.toObject(key)); } @@ -213,11 +138,6 @@ } @Override - public boolean hasOwnProperty(final long key) { - return hasOwnProperty(JSType.toObject(key)); - } - - @Override public boolean hasOwnProperty(final double key) { return hasOwnProperty(JSType.toObject(key)); } @@ -230,11 +150,6 @@ return delete(JSType.toObject(key), strict); } - @Override - public boolean delete(final long key, final boolean strict) { - return delete(JSType.toObject(key), strict); - } - @Override public boolean delete(final double key, final boolean strict) { return delete(JSType.toObject(key), strict); --- old/src/jdk/nashorn/internal/runtime/FindProperty.java 2016-01-20 14:14:50.211064318 +0100 +++ new/src/jdk/nashorn/internal/runtime/FindProperty.java 2016-01-20 14:14:50.111064319 +0100 @@ -218,13 +218,6 @@ * Get the property value from self as object. * @return the property value */ - public long getLongValue() { - return property.getLongValue(getGetterReceiver(), getOwner()); - } - /** - * Get the property value from self as object. - * @return the property value - */ public double getDoubleValue() { return property.getDoubleValue(getGetterReceiver(), getOwner()); } @@ -246,16 +239,6 @@ property.setValue(getSetterReceiver(), getOwner(), value, strict); } - /** - * Set the property value in self. - * - * @param value the new value - * @param strict strict flag - */ - public void setValue(final long value, final boolean strict) { - property.setValue(getSetterReceiver(), getOwner(), value, strict); - } - /** * Set the property value in self. * --- old/src/jdk/nashorn/internal/runtime/GlobalFunctions.java 2016-01-20 14:14:50.575064311 +0100 +++ new/src/jdk/nashorn/internal/runtime/GlobalFunctions.java 2016-01-20 14:14:50.471064313 +0100 @@ -48,9 +48,6 @@ /** ParseInt - identity for ints */ public static final MethodHandle PARSEINT_I = MH.dropArguments(MH.identity(int.class), 0, Object.class); - /** ParseInt - identity for longs */ - public static final MethodHandle PARSEINT_J = MH.dropArguments(MH.identity(long.class), 0, Object.class); - /** Methodhandle (specialized) to implementation of ECMA 15.1.2.2, parseInt */ public static final MethodHandle PARSEINT_O = findOwnMH("parseInt", double.class, Object.class, Object.class); --- old/src/jdk/nashorn/internal/runtime/JSType.java 2016-01-20 14:14:50.915064305 +0100 +++ new/src/jdk/nashorn/internal/runtime/JSType.java 2016-01-20 14:14:50.819064307 +0100 @@ -115,14 +115,14 @@ public static final Call TO_INT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, double.class); /** JavaScript compliant conversion function from int to uint32 */ - public static final Call TO_UINT32_I = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, int.class); + public static final Call TO_UINT32_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32Optimistic", int.class, int.class, int.class); + + /** JavaScript compliant conversion function from int to uint32 */ + public static final Call TO_UINT32_DOUBLE = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32Double", double.class, int.class); /** JavaScript compliant conversion function from Object to uint32 */ public static final Call TO_UINT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, Object.class); - /** JavaScript compliant conversion function from Object to long with type check */ - public static final Call TO_LONG_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toLongOptimistic", long.class, Object.class, int.class); - /** JavaScript compliant conversion function from number to uint32 */ public static final Call TO_UINT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, double.class); @@ -168,36 +168,6 @@ /** Negate exact exact wrapper for potentially overflowing integer operations */ public static final Call NEGATE_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", int.class, int.class, int.class); - /** Add exact wrapper for potentially overflowing long operations */ - public static final Call ADD_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "addExact", long.class, long.class, long.class, int.class); - - /** Sub exact wrapper for potentially overflowing long operations */ - public static final Call SUB_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "subExact", long.class, long.class, long.class, int.class); - - /** Multiply exact wrapper for potentially overflowing long operations */ - public static final Call MUL_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "mulExact", long.class, long.class, long.class, int.class); - - /** Div exact wrapper for potentially integer division that turns into float point */ - public static final Call DIV_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", long.class, long.class, long.class, int.class); - - /** Div zero wrapper for long division that handles (0/0) >>> 0 == 0 */ - public static final Call DIV_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", long.class, long.class, long.class); - - /** Mod zero wrapper for long division that handles (0%0) >>> 0 == 0 */ - public static final Call REM_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", long.class, long.class, long.class); - - /** Mod exact wrapper for potentially integer remainders that turns into float point */ - public static final Call REM_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", long.class, long.class, long.class, int.class); - - /** Decrement exact wrapper for potentially overflowing long operations */ - public static final Call DECREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "decrementExact", long.class, long.class, int.class); - - /** Increment exact wrapper for potentially overflowing long operations */ - public static final Call INCREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "incrementExact", long.class, long.class, int.class); - - /** Negate exact exact wrapper for potentially overflowing long operations */ - public static final Call NEGATE_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", long.class, long.class, int.class); - /** Method handle to convert a JS Object to a Java array. */ public static final Call TO_JAVA_ARRAY = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaArray", Object.class, Object.class, Class.class); @@ -211,7 +181,6 @@ private static final List ACCESSOR_TYPES = Collections.unmodifiableList( Arrays.asList( Type.INT, - Type.LONG, Type.NUMBER, Type.OBJECT)); @@ -219,17 +188,14 @@ public static final int TYPE_UNDEFINED_INDEX = -1; /** table index for integer type - hard coded so it can be used in switches at compile time */ public static final int TYPE_INT_INDEX = 0; //getAccessorTypeIndex(int.class); - /** table index for long type - hard coded so it can be used in switches at compile time */ - public static final int TYPE_LONG_INDEX = 1; //getAccessorTypeIndex(long.class); /** table index for double type - hard coded so it can be used in switches at compile time */ - public static final int TYPE_DOUBLE_INDEX = 2; //getAccessorTypeIndex(double.class); + public static final int TYPE_DOUBLE_INDEX = 1; //getAccessorTypeIndex(double.class); /** table index for object type - hard coded so it can be used in switches at compile time */ - public static final int TYPE_OBJECT_INDEX = 3; //getAccessorTypeIndex(Object.class); + public static final int TYPE_OBJECT_INDEX = 2; //getAccessorTypeIndex(Object.class); /** object conversion quickies with JS semantics - used for return value and parameter filter */ public static final List CONVERT_OBJECT = toUnmodifiableList( JSType.TO_INT32.methodHandle(), - JSType.TO_UINT32.methodHandle(), JSType.TO_NUMBER.methodHandle(), null ); @@ -240,7 +206,6 @@ */ public static final List CONVERT_OBJECT_OPTIMISTIC = toUnmodifiableList( JSType.TO_INT32_OPTIMISTIC.methodHandle(), - JSType.TO_LONG_OPTIMISTIC.methodHandle(), JSType.TO_NUMBER_OPTIMISTIC.methodHandle(), null ); @@ -252,13 +217,16 @@ /** The value of Undefined cast to a double */ public static final double UNDEFINED_DOUBLE = Double.NaN; + // Minimum and maximum range between which every long value can be precisely represented as a double. + private static final long MAX_PRECISE_DOUBLE = 1L << 53; + private static final long MIN_PRECISE_DOUBLE = -MAX_PRECISE_DOUBLE; + /** * Method handles for getters that return undefined coerced * to the appropriate type */ public static final List GET_UNDEFINED = toUnmodifiableList( MH.constant(int.class, UNDEFINED_INT), - MH.constant(long.class, UNDEFINED_LONG), MH.constant(double.class, UNDEFINED_DOUBLE), MH.constant(Object.class, Undefined.getUndefined()) ); @@ -416,7 +384,7 @@ /** * Returns true if double number can be represented as a long. Note that it returns true for negative - * zero. If you need to exclude negative zero, use {@link #isStrictlyRepresentableAsLong(double)}. + * zero. * * @param number a double to inspect * @return true for long representable doubles @@ -426,29 +394,12 @@ } /** - * Returns true if double number can be represented as a long. Note that it returns false for negative - * zero. If you don't need to distinguish negative zero, use {@link #isRepresentableAsLong(double)}. - * - * @param number a double to inspect - * - * @return true for long representable doubles - */ - public static boolean isStrictlyRepresentableAsLong(final double number) { - return isRepresentableAsLong(number) && isNotNegativeZero(number); - } - - /** - * Returns true if Object can be represented as a long - * - * @param obj an object to inspect - * - * @return true for long representable objects + * Returns true if long number can be represented as double without loss of precision. + * @param number a long number + * @return true if the double representation does not lose precision */ - public static boolean isRepresentableAsLong(final Object obj) { - if (obj instanceof Number) { - return isRepresentableAsLong(((Number)obj).doubleValue()); - } - return false; + public static boolean isRepresentableAsDouble(final long number) { + return MAX_PRECISE_DOUBLE >= number && number >= MIN_PRECISE_DOUBLE; } /** @@ -628,22 +579,6 @@ } /** - * Check whether a string is representable as a JavaScript number - * - * @param str a string - * - * @return true if string can be represented as a number - */ - public static boolean isNumber(final String str) { - try { - Double.parseDouble(str); - return true; - } catch (final NumberFormatException e) { - return false; - } - } - - /** * Returns true if object represents a primitive JavaScript string value. * @param obj the object * @return true if the object represents a primitive JavaScript string value. @@ -1009,35 +944,6 @@ } /** - * Optimistic long conversion - throws UnwarrantedOptimismException if double or Object - * - * @param obj object to convert - * @param programPoint program point - * @return long - */ - public static long toLongOptimistic(final Object obj, final int programPoint) { - if (obj != null) { - final Class clz = obj.getClass(); - if (clz == Long.class || clz == Integer.class) { - return ((Number)obj).longValue(); - } - } - throw new UnwarrantedOptimismException(obj, programPoint); - } - - /** - * Object to int conversion that delegates to either {@link #toLong(Object)} or to - * {@link #toLongOptimistic(Object, int)} depending on whether the program point is valid or not. - * @param obj the object to convert - * @param programPoint the program point; can be invalid. - * @return the value converted to long - * @throws UnwarrantedOptimismException if the value can't be represented as long and the program point is valid. - */ - public static long toLongMaybeOptimistic(final Object obj, final int programPoint) { - return UnwarrantedOptimismException.isValid(programPoint) ? toLongOptimistic(obj, programPoint) : toLong(obj); - } - - /** * JavaScript compliant Object to int32 conversion * See ECMA 9.5 ToInt32 * @@ -1074,10 +980,6 @@ return UnwarrantedOptimismException.isValid(programPoint) ? toInt32Optimistic(obj, programPoint) : toInt32(obj); } - // Minimum and maximum range between which every long value can be precisely represented as a double. - private static final long MAX_PRECISE_DOUBLE = 1L << 53; - private static final long MIN_PRECISE_DOUBLE = -MAX_PRECISE_DOUBLE; - /** * JavaScript compliant long to int32 conversion * @@ -1130,6 +1032,29 @@ } /** + * Optimistic JavaScript compliant int to uint32 conversion + * @param num an int + * @param pp the program point + * @return the uint32 value if it can be represented by an int + * @throws UnwarrantedOptimismException if uint32 value cannot be represented by an int + */ + public static int toUint32Optimistic(final int num, final int pp) { + if (num >= 0) { + return num; + } + throw new UnwarrantedOptimismException(toUint32Double(num), pp, Type.NUMBER); + } + + /** + * JavaScript compliant int to uint32 conversion with double return type + * @param num an int + * @return the uint32 value as double + */ + public static double toUint32Double(final int num) { + return (double) toUint32(num); + } + + /** * JavaScript compliant Object to uint16 conversion * ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer) * @@ -1453,26 +1378,6 @@ try { return Math.addExact(x, y); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((long)x + (long)y, programPoint); - } - } - - /** - * Wrapper for addExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x first term - * @param y second term - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long addExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { - try { - return Math.addExact(x, y); - } catch (final ArithmeticException e) { throw new UnwarrantedOptimismException((double)x + (double)y, programPoint); } } @@ -1493,26 +1398,6 @@ try { return Math.subtractExact(x, y); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((long)x - (long)y, programPoint); - } - } - - /** - * Wrapper for subExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x first term - * @param y second term - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long subExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { - try { - return Math.subtractExact(x, y); - } catch (final ArithmeticException e) { throw new UnwarrantedOptimismException((double)x - (double)y, programPoint); } } @@ -1533,26 +1418,6 @@ try { return Math.multiplyExact(x, y); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((long)x * (long)y, programPoint); - } - } - - /** - * Wrapper for mulExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x first term - * @param y second term - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long mulExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { - try { - return Math.multiplyExact(x, y); - } catch (final ArithmeticException e) { throw new UnwarrantedOptimismException((double)x * (double)y, programPoint); } } @@ -1624,71 +1489,6 @@ } /** - * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as - * long. - * - * @param x first term - * @param y second term - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if the result of the division can't be represented as long. - */ - public static long divExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { - final long res; - try { - res = x / y; - } catch (final ArithmeticException e) { - assert y == 0L; // Only div by zero anticipated - throw new UnwarrantedOptimismException(x > 0L ? Double.POSITIVE_INFINITY : x < 0L ? Double.NEGATIVE_INFINITY : Double.NaN, programPoint); - } - final long rem = x % y; - if (rem == 0L) { - return res; - } - throw new UnwarrantedOptimismException((double)x / (double)y, programPoint); - } - - /** - * Implements long division but allows {@code x / 0} to be represented as 0. Useful when division of two longs - * is coerced to long. - * @param x the dividend - * @param y the divisor - * @return the result - */ - public static long divZero(final long x, final long y) { - return y == 0L ? 0L : x / y; - } - - /** - * Implements long remainder but allows {@code x % 0} to be represented as 0. Useful when remainder of two longs - * is coerced to long. - * @param x the dividend - * @param y the divisor - * @return the remainder - */ - public static long remZero(final long x, final long y) { - return y == 0L ? 0L : x % y; - } - - /** - * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int. - * - * @param x first term - * @param y second term - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if the modulo can't be represented as int. - */ - public static long remExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { - try { - return x % y; - } catch (final ArithmeticException e) { - assert y == 0L; // Only mod by zero anticipated - throw new UnwarrantedOptimismException(Double.NaN, programPoint); - } - } - - /** * Wrapper for decrementExact * * Catches ArithmeticException and rethrows as UnwarrantedOptimismException @@ -1703,26 +1503,7 @@ try { return Math.decrementExact(x); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((long)x - 1, programPoint); - } - } - - /** - * Wrapper for decrementExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x number to negate - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long decrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException { - try { - return Math.decrementExact(x); - } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((double)x - 1L, programPoint); + throw new UnwarrantedOptimismException((double)x - 1, programPoint); } } @@ -1741,26 +1522,7 @@ try { return Math.incrementExact(x); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((long)x + 1, programPoint); - } - } - - /** - * Wrapper for incrementExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x the number to increment - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long incrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException { - try { - return Math.incrementExact(x); - } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((double)x + 1L, programPoint); + throw new UnwarrantedOptimismException((double)x + 1, programPoint); } } @@ -1782,28 +1544,6 @@ } return Math.negateExact(x); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException(-(long)x, programPoint); - } - } - - /** - * Wrapper for negateExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x the number to negate - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long negateExact(final long x, final int programPoint) throws UnwarrantedOptimismException { - try { - if (x == 0L) { - throw new UnwarrantedOptimismException(-0.0, programPoint); - } - return Math.negateExact(x); - } catch (final ArithmeticException e) { throw new UnwarrantedOptimismException(-(double)x, programPoint); } } @@ -1835,8 +1575,6 @@ return TYPE_UNDEFINED_INDEX; } else if (type == int.class) { return TYPE_INT_INDEX; - } else if (type == long.class) { - return TYPE_LONG_INDEX; } else if (type == double.class) { return TYPE_DOUBLE_INDEX; } else if (!type.isPrimitive()) { @@ -1937,8 +1675,6 @@ public static Class getBoxedClass(final Class clazz) { if (clazz == int.class) { return Integer.class; - } else if (clazz == long.class) { - return Long.class; } else if (clazz == double.class) { return Double.class; } @@ -1956,8 +1692,6 @@ if (o != null) { if (o.getClass() == Integer.class) { return MH.constant(int.class, ((Integer)o).intValue()); - } else if (o.getClass() == Long.class) { - return MH.constant(long.class, ((Long)o).longValue()); } else if (o.getClass() == Double.class) { return MH.constant(double.class, ((Double)o).doubleValue()); } @@ -1975,8 +1709,6 @@ return Object.class; } else if (o.getClass() == Integer.class) { return int.class; - } else if (o.getClass() == Long.class) { - return long.class; } else if (o.getClass() == Double.class) { return double.class; } else { --- old/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java 2016-01-20 14:14:51.391064297 +0100 +++ new/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java 2016-01-20 14:14:51.287064299 +0100 @@ -43,52 +43,42 @@ */ public final class OptimisticReturnFilters { private static final MethodHandle[] ENSURE_INT; - private static final MethodHandle[] ENSURE_LONG; private static final MethodHandle[] ENSURE_NUMBER; + // These extend the type index constants in JSType + private static final int VOID_TYPE_INDEX; private static final int BOOLEAN_TYPE_INDEX; private static final int CHAR_TYPE_INDEX; + private static final int LONG_TYPE_INDEX; private static final int FLOAT_TYPE_INDEX; - private static final int VOID_TYPE_INDEX; static { final MethodHandle INT_DOUBLE = findOwnMH("ensureInt", int.class, double.class, int.class); ENSURE_INT = new MethodHandle[] { null, - findOwnMH("ensureInt", int.class, long.class, int.class), INT_DOUBLE, findOwnMH("ensureInt", int.class, Object.class, int.class), findOwnMH("ensureInt", int.class, int.class), findOwnMH("ensureInt", int.class, boolean.class, int.class), findOwnMH("ensureInt", int.class, char.class, int.class), + findOwnMH("ensureInt", int.class, long.class, int.class), INT_DOUBLE.asType(INT_DOUBLE.type().changeParameterType(0, float.class)), }; - VOID_TYPE_INDEX = ENSURE_INT.length - 4; - BOOLEAN_TYPE_INDEX = ENSURE_INT.length - 3; - CHAR_TYPE_INDEX = ENSURE_INT.length - 2; + VOID_TYPE_INDEX = ENSURE_INT.length - 5; + BOOLEAN_TYPE_INDEX = ENSURE_INT.length - 4; + CHAR_TYPE_INDEX = ENSURE_INT.length - 3; + LONG_TYPE_INDEX = ENSURE_INT.length - 2; FLOAT_TYPE_INDEX = ENSURE_INT.length - 1; - final MethodHandle LONG_DOUBLE = findOwnMH("ensureLong", long.class, double.class, int.class); - ENSURE_LONG = new MethodHandle[] { - null, - null, - LONG_DOUBLE, - findOwnMH("ensureLong", long.class, Object.class, int.class), - ENSURE_INT[VOID_TYPE_INDEX].asType(ENSURE_INT[VOID_TYPE_INDEX].type().changeReturnType(long.class)), - ENSURE_INT[BOOLEAN_TYPE_INDEX].asType(ENSURE_INT[BOOLEAN_TYPE_INDEX].type().changeReturnType(long.class)), - ENSURE_INT[CHAR_TYPE_INDEX].asType(ENSURE_INT[CHAR_TYPE_INDEX].type().changeReturnType(long.class)), - LONG_DOUBLE.asType(LONG_DOUBLE.type().changeParameterType(0, float.class)), - }; - ENSURE_NUMBER = new MethodHandle[] { null, null, - null, findOwnMH("ensureNumber", double.class, Object.class, int.class), ENSURE_INT[VOID_TYPE_INDEX].asType(ENSURE_INT[VOID_TYPE_INDEX].type().changeReturnType(double.class)), ENSURE_INT[BOOLEAN_TYPE_INDEX].asType(ENSURE_INT[BOOLEAN_TYPE_INDEX].type().changeReturnType(double.class)), ENSURE_INT[CHAR_TYPE_INDEX].asType(ENSURE_INT[CHAR_TYPE_INDEX].type().changeReturnType(double.class)), + findOwnMH("ensureNumber", double.class, long.class, int.class), null }; } @@ -136,8 +126,6 @@ final int provableTypeIndex = getProvableTypeIndex(provable); if (actual == int.class) { guard = ENSURE_INT[provableTypeIndex]; - } else if (actual == long.class) { - guard = ENSURE_LONG[provableTypeIndex]; } else if (actual == double.class) { guard = ENSURE_NUMBER[provableTypeIndex]; } else { @@ -167,6 +155,8 @@ return 0; // never needs a guard, as it's assignable to int } else if(provable == char.class) { return CHAR_TYPE_INDEX; + } else if(provable == long.class) { + return LONG_TYPE_INDEX; } else if(provable == float.class) { return FLOAT_TYPE_INDEX; } @@ -179,7 +169,7 @@ if (JSType.isRepresentableAsInt(arg)) { return (int)arg; } - throw new UnwarrantedOptimismException(arg, programPoint); + throw UnwarrantedOptimismException.createNarrowest(arg, programPoint); } @SuppressWarnings("unused") @@ -187,7 +177,7 @@ if (JSType.isStrictlyRepresentableAsInt(arg)) { return (int)arg; } - throw new UnwarrantedOptimismException(arg, programPoint); + throw new UnwarrantedOptimismException(arg, programPoint, Type.NUMBER); } /** @@ -210,7 +200,7 @@ return (int)d; } } - throw new UnwarrantedOptimismException(arg, programPoint); + throw UnwarrantedOptimismException.createNarrowest(arg, programPoint); } private static boolean isPrimitiveNumberWrapper(final Object obj) { @@ -238,51 +228,29 @@ throw new UnwarrantedOptimismException(ScriptRuntime.UNDEFINED, programPoint, Type.OBJECT); } - private static long ensureLong(final double arg, final int programPoint) { - if (JSType.isStrictlyRepresentableAsLong(arg)) { - return (long)arg; - } - throw new UnwarrantedOptimismException(arg, programPoint); - } - - /** - * Returns the argument value as a long. If the argument is not a wrapper for a primitive numeric type - * with a value that can be exactly represented as a long, throw an {@link UnwarrantedOptimismException}. - * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_LONG}. - * @param arg the original argument. - * @param programPoint the program point used in the exception - * @return the value of the argument as a long. - * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type with - * a value that can be exactly represented as a long - */ - public static long ensureLong(final Object arg, final int programPoint) { - if (arg != null) { - final Class c = arg.getClass(); - if (c == Long.class) { - // Must check for Long separately, as Long.doubleValue() isn't precise. - return ((Long)arg).longValue(); - } else if (c == Integer.class || c == Double.class || c == Float.class || c == Short.class || - c == Byte.class) { - return ensureLong(((Number)arg).doubleValue(), programPoint); - } + @SuppressWarnings("unused") + private static double ensureNumber(final long arg, final int programPoint) { + if (JSType.isRepresentableAsDouble(arg)) { + return (double) arg; } - throw new UnwarrantedOptimismException(arg, programPoint); + throw new UnwarrantedOptimismException(arg, programPoint, Type.OBJECT); } /** - * Returns the argument value as a double. If the argument is not a a wrapper for a primitive numeric type - * throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code - * can use it. See {code CodeGenerator.ENSURE_NUMBER}. + * Returns the argument value as a double. If the argument is not a wrapper for a primitive numeric type + * that can be represented as double throw an {@link UnwarrantedOptimismException}. + * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_NUMBER}. * @param arg the original argument. * @param programPoint the program point used in the exception * @return the value of the argument as a double. * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type. */ public static double ensureNumber(final Object arg, final int programPoint) { - if (isPrimitiveNumberWrapper(arg)) { - return ((Number)arg).doubleValue(); + if (isPrimitiveNumberWrapper(arg) + && (arg.getClass() != Long.class || JSType.isRepresentableAsDouble((Long) arg))) { + return ((Number) arg).doubleValue(); } - throw new UnwarrantedOptimismException(arg, programPoint); + throw new UnwarrantedOptimismException(arg, programPoint, Type.OBJECT); } private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { --- old/src/jdk/nashorn/internal/runtime/Property.java 2016-01-20 14:14:51.839064289 +0100 +++ new/src/jdk/nashorn/internal/runtime/Property.java 2016-01-20 14:14:51.723064291 +0100 @@ -450,16 +450,6 @@ * @param owner the owner of the property * @return the property value */ - public abstract long getLongValue(final ScriptObject self, final ScriptObject owner); - - /** - * get the Object value of this property from {@code owner}. This allows to bypass creation of the - * getter MethodHandle for spill and user accessor properties. - * - * @param self the this object - * @param owner the owner of the property - * @return the property value - */ public abstract double getDoubleValue(final ScriptObject self, final ScriptObject owner); /** @@ -492,17 +482,6 @@ * @param value the new property value * @param strict is this a strict setter? */ - public abstract void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict); - - /** - * Set the value of this property in {@code owner}. This allows to bypass creation of the - * setter MethodHandle for spill and user accessor properties. - * - * @param self the this object - * @param owner the owner object - * @param value the new property value - * @param strict is this a strict setter? - */ public abstract void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict); /** @@ -593,8 +572,6 @@ return "undef"; } else if (type == int.class) { return "i"; - } else if (type == long.class) { - return "j"; } else if (type == double.class) { return "d"; } else { --- old/src/jdk/nashorn/internal/runtime/PropertyAccess.java 2016-01-20 14:14:52.323064280 +0100 +++ new/src/jdk/nashorn/internal/runtime/PropertyAccess.java 2016-01-20 14:14:52.207064282 +0100 @@ -57,49 +57,9 @@ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic * @return the value */ - public int getInt(long key, int programPoint); - - /** - * Get the value for a given key and return it as an int - * @param key the key - * @param programPoint or INVALID_PROGRAM_POINT if pessimistic - * @return the value - */ public int getInt(int key, int programPoint); /** - * Get the value for a given key and return it as a long - * @param key the key - * @param programPoint or INVALID_PROGRAM_POINT if pessimistic - * @return the value - */ - public long getLong(Object key, int programPoint); - - /** - * Get the value for a given key and return it as a long - * @param key the key - * @param programPoint or INVALID_PROGRAM_POINT if pessimistic - * @return the value - */ - public long getLong(double key, int programPoint); - - /** - * Get the value for a given key and return it as a long - * @param key the key - * @param programPoint or INVALID_PROGRAM_POINT if pessimistic - * @return the value - */ - public long getLong(long key, int programPoint); - - /** - * Get the value for a given key and return it as a long - * @param key the key - * @param programPoint or INVALID_PROGRAM_POINT if pessimistic - * @return the value - */ - public long getLong(int key, int programPoint); - - /** * Get the value for a given key and return it as a double * @param key the key * @param programPoint or INVALID_PROGRAM_POINT if pessimistic @@ -121,14 +81,6 @@ * @param programPoint or INVALID_PROGRAM_POINT if pessimistic * @return the value */ - public double getDouble(long key, int programPoint); - - /** - * Get the value for a given key and return it as a double - * @param key the key - * @param programPoint or INVALID_PROGRAM_POINT if pessimistic - * @return the value - */ public double getDouble(int key, int programPoint); /** @@ -150,13 +102,6 @@ * @param key the key * @return the value */ - public Object get(long key); - - /** - * Get the value for a given key and return it as an Object - * @param key the key - * @return the value - */ public Object get(int key); /** @@ -173,14 +118,6 @@ * @param value the value * @param flags call site flags */ - public void set(Object key, long value, int flags); - - /** - * Set the value of a given key - * @param key the key - * @param value the value - * @param flags call site flags - */ public void set(Object key, double value, int flags); /** @@ -205,14 +142,6 @@ * @param value the value * @param flags call site flags */ - public void set(double key, long value, int flags); - - /** - * Set the value of a given key - * @param key the key - * @param value the value - * @param flags call site flags - */ public void set(double key, double value, int flags); /** @@ -229,38 +158,6 @@ * @param value the value * @param flags call site flags */ - public void set(long key, int value, int flags); - - /** - * Set the value of a given key - * @param key the key - * @param value the value - * @param flags call site flags - */ - public void set(long key, long value, int flags); - - /** - * Set the value of a given key - * @param key the key - * @param value the value - * @param flags call site flags - */ - public void set(long key, double value, int flags); - - /** - * Set the value of a given key - * @param key the key - * @param value the value - * @param flags call site flags - */ - public void set(long key, Object value, int flags); - - /** - * Set the value of a given key - * @param key the key - * @param value the value - * @param flags call site flags - */ public void set(int key, int value, int flags); /** @@ -269,14 +166,6 @@ * @param value the value * @param flags call site flags */ - public void set(int key, long value, int flags); - - /** - * Set the value of a given key - * @param key the key - * @param value the value - * @param flags call site flags - */ public void set(int key, double value, int flags); /** @@ -306,13 +195,6 @@ * @param key the key * @return true if key exists */ - public boolean has(long key); - - /** - * Check if the given key exists anywhere in the proto chain - * @param key the key - * @return true if key exists - */ public boolean has(double key); /** @@ -334,13 +216,6 @@ * @param key the key * @return true if key exists */ - public boolean hasOwnProperty(long key); - - /** - * Check if the given key exists directly in the implementor - * @param key the key - * @return true if key exists - */ public boolean hasOwnProperty(double key); /** @@ -353,14 +228,6 @@ /** * Delete a property with the given key from the implementor - * @param key the key - * @param strict are we in strict mode - * @return true if deletion succeeded, false otherwise - */ - public boolean delete(long key, boolean strict); - - /** - * Delete a property with the given key from the implementor * @param key the key * @param strict are we in strict mode * @return true if deletion succeeded, false otherwise --- old/src/jdk/nashorn/internal/runtime/ScriptObject.java 2016-01-20 14:14:52.743064273 +0100 +++ new/src/jdk/nashorn/internal/runtime/ScriptObject.java 2016-01-20 14:14:52.611064275 +0100 @@ -33,7 +33,6 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_DOUBLE; import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT; -import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG; import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE; import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE; import static jdk.nashorn.internal.runtime.PropertyDescriptor.GET; @@ -186,7 +185,6 @@ static final MethodHandle[] SET_SLOW = new MethodHandle[] { findOwnMH_V("set", void.class, Object.class, int.class, int.class), - findOwnMH_V("set", void.class, Object.class, long.class, int.class), findOwnMH_V("set", void.class, Object.class, double.class, int.class), findOwnMH_V("set", void.class, Object.class, Object.class, int.class) }; @@ -1086,21 +1084,6 @@ return UNDEFINED_INT; } - private static long getLongValue(final FindProperty find, final int programPoint) { - final MethodHandle getter = find.getGetter(long.class, programPoint, null); - if (getter != null) { - try { - return (long)getter.invokeExact((Object)find.getGetterReceiver()); - } catch (final Error|RuntimeException e) { - throw e; - } catch (final Throwable e) { - throw new RuntimeException(e); - } - } - - return UNDEFINED_LONG; - } - private static double getDoubleValue(final FindProperty find, final int programPoint) { final MethodHandle getter = find.getGetter(double.class, programPoint, null); if (getter != null) { @@ -2768,18 +2751,6 @@ } @Override - public int getInt(final long key, final int programPoint) { - final int index = getArrayIndex(key); - final ArrayData array = getArray(); - - if (array.has(index)) { - return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index); - } - - return getInt(index, JSType.toString(key), programPoint); - } - - @Override public int getInt(final int key, final int programPoint) { final int index = getArrayIndex(key); final ArrayData array = getArray(); @@ -2791,88 +2762,6 @@ return getInt(index, JSType.toString(key), programPoint); } - private long getLong(final int index, final String key, final int programPoint) { - if (isValidArrayIndex(index)) { - for (ScriptObject object = this; ; ) { - if (object.getMap().containsArrayKeys()) { - final FindProperty find = object.findProperty(key, false, this); - if (find != null) { - return getLongValue(find, programPoint); - } - } - - if ((object = object.getProto()) == null) { - break; - } - - final ArrayData array = object.getArray(); - - if (array.has(index)) { - return isValid(programPoint) ? - array.getLongOptimistic(index, programPoint) : - array.getLong(index); - } - } - } else { - final FindProperty find = findProperty(key, true); - - if (find != null) { - return getLongValue(find, programPoint); - } - } - - return JSType.toLong(invokeNoSuchProperty(key, false, programPoint)); - } - - @Override - public long getLong(final Object key, final int programPoint) { - final Object primitiveKey = JSType.toPrimitive(key, String.class); - final int index = getArrayIndex(primitiveKey); - final ArrayData array = getArray(); - - if (array.has(index)) { - return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index); - } - - return getLong(index, JSType.toString(primitiveKey), programPoint); - } - - @Override - public long getLong(final double key, final int programPoint) { - final int index = getArrayIndex(key); - final ArrayData array = getArray(); - - if (array.has(index)) { - return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index); - } - - return getLong(index, JSType.toString(key), programPoint); - } - - @Override - public long getLong(final long key, final int programPoint) { - final int index = getArrayIndex(key); - final ArrayData array = getArray(); - - if (array.has(index)) { - return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index); - } - - return getLong(index, JSType.toString(key), programPoint); - } - - @Override - public long getLong(final int key, final int programPoint) { - final int index = getArrayIndex(key); - final ArrayData array = getArray(); - - if (array.has(index)) { - return isValid(programPoint) ? array.getLongOptimistic(key, programPoint) : array.getLong(key); - } - - return getLong(index, JSType.toString(key), programPoint); - } - private double getDouble(final int index, final String key, final int programPoint) { if (isValidArrayIndex(index)) { for (ScriptObject object = this; ; ) { @@ -2932,18 +2821,6 @@ } @Override - public double getDouble(final long key, final int programPoint) { - final int index = getArrayIndex(key); - final ArrayData array = getArray(); - - if (array.has(index)) { - return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index); - } - - return getDouble(index, JSType.toString(key), programPoint); - } - - @Override public double getDouble(final int key, final int programPoint) { final int index = getArrayIndex(key); final ArrayData array = getArray(); @@ -3013,18 +2890,6 @@ } @Override - public Object get(final long key) { - final int index = getArrayIndex(key); - final ArrayData array = getArray(); - - if (array.has(index)) { - return array.getObject(index); - } - - return get(index, JSType.toString(key)); - } - - @Override public Object get(final int key) { final int index = getArrayIndex(key); final ArrayData array = getArray(); @@ -3107,15 +2972,6 @@ } } - private void doesNotHave(final int index, final long value, final int callSiteFlags) { - final long oldLength = getArray().length(); - final long longIndex = ArrayIndex.toLongIndex(index); - if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) { - final boolean strict = isStrictFlag(callSiteFlags); - setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict)); - } - } - private void doesNotHave(final int index, final double value, final int callSiteFlags) { final long oldLength = getArray().length(); final long longIndex = ArrayIndex.toLongIndex(index); @@ -3222,26 +3078,6 @@ } @Override - public void set(final Object key, final long value, final int callSiteFlags) { - final Object primitiveKey = JSType.toPrimitive(key, String.class); - final int index = getArrayIndex(primitiveKey); - - if (isValidArrayIndex(index)) { - final ArrayData data = getArray(); - if (data.has(index)) { - setArray(data.set(index, value, isStrictFlag(callSiteFlags))); - } else { - doesNotHave(index, value, callSiteFlags); - } - - return; - } - - final String propName = JSType.toString(primitiveKey); - setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value)); - } - - @Override public void set(final Object key, final double value, final int callSiteFlags) { final Object primitiveKey = JSType.toPrimitive(key, String.class); final int index = getArrayIndex(primitiveKey); @@ -3301,25 +3137,6 @@ } @Override - public void set(final double key, final long value, final int callSiteFlags) { - final int index = getArrayIndex(key); - - if (isValidArrayIndex(index)) { - final ArrayData data = getArray(); - if (data.has(index)) { - setArray(data.set(index, value, isStrictFlag(callSiteFlags))); - } else { - doesNotHave(index, value, callSiteFlags); - } - - return; - } - - final String propName = JSType.toString(key); - setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value)); - } - - @Override public void set(final double key, final double value, final int callSiteFlags) { final int index = getArrayIndex(key); @@ -3358,82 +3175,6 @@ } @Override - public void set(final long key, final int value, final int callSiteFlags) { - final int index = getArrayIndex(key); - - if (isValidArrayIndex(index)) { - final ArrayData data = getArray(); - if (data.has(index)) { - setArray(data.set(index, value, isStrictFlag(callSiteFlags))); - } else { - doesNotHave(index, value, callSiteFlags); - } - - return; - } - - final String propName = JSType.toString(key); - setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value)); - } - - @Override - public void set(final long key, final long value, final int callSiteFlags) { - final int index = getArrayIndex(key); - - if (isValidArrayIndex(index)) { - final ArrayData data = getArray(); - if (data.has(index)) { - setArray(data.set(index, value, isStrictFlag(callSiteFlags))); - } else { - doesNotHave(index, value, callSiteFlags); - } - - return; - } - - final String propName = JSType.toString(key); - setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value)); - } - - @Override - public void set(final long key, final double value, final int callSiteFlags) { - final int index = getArrayIndex(key); - - if (isValidArrayIndex(index)) { - final ArrayData data = getArray(); - if (data.has(index)) { - setArray(data.set(index, value, isStrictFlag(callSiteFlags))); - } else { - doesNotHave(index, value, callSiteFlags); - } - - return; - } - - final String propName = JSType.toString(key); - setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value)); - } - - @Override - public void set(final long key, final Object value, final int callSiteFlags) { - final int index = getArrayIndex(key); - - if (isValidArrayIndex(index)) { - final ArrayData data = getArray(); - if (data.has(index)) { - setArray(data.set(index, value, isStrictFlag(callSiteFlags))); - } else { - doesNotHave(index, value, callSiteFlags); - } - - return; - } - - final String propName = JSType.toString(key); - setObject(findProperty(propName, true), callSiteFlags, propName, value); - } - - @Override public void set(final int key, final int value, final int callSiteFlags) { final int index = getArrayIndex(key); if (isValidArrayIndex(index)) { @@ -3451,25 +3192,6 @@ } @Override - public void set(final int key, final long value, final int callSiteFlags) { - final int index = getArrayIndex(key); - - if (isValidArrayIndex(index)) { - final ArrayData data = getArray(); - if (data.has(index)) { - setArray(data.set(index, value, isStrictFlag(callSiteFlags))); - } else { - doesNotHave(index, value, callSiteFlags); - } - - return; - } - - final String propName = JSType.toString(key); - setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value)); - } - - @Override public void set(final int key, final double value, final int callSiteFlags) { final int index = getArrayIndex(key); @@ -3521,12 +3243,6 @@ } @Override - public boolean has(final long key) { - final int index = getArrayIndex(key); - return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true); - } - - @Override public boolean has(final int key) { final int index = getArrayIndex(key); return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true); @@ -3559,12 +3275,6 @@ } @Override - public boolean hasOwnProperty(final long key) { - final int index = getArrayIndex(key); - return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false); - } - - @Override public boolean hasOwnProperty(final double key) { final int index = getArrayIndex(key); return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false); @@ -3589,22 +3299,6 @@ return deleteObject(JSType.toObject(key), strict); } - @Override - public boolean delete(final long key, final boolean strict) { - final int index = getArrayIndex(key); - final ArrayData array = getArray(); - - if (array.has(index)) { - if (array.canDelete(index, strict)) { - setArray(array.delete(index)); - return true; - } - return false; - } - - return deleteObject(JSType.toObject(key), strict); - } - @Override public boolean delete(final double key, final boolean strict) { final int index = getArrayIndex(key); --- old/src/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java 2016-01-20 14:14:53.283064263 +0100 +++ new/src/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java 2016-01-20 14:14:53.171064265 +0100 @@ -49,7 +49,10 @@ private final Type returnType; /** - * Constructor + * Constructor without explicit return type. The return type is determined statically from the class of + * the return value, and only canonical internal number representations are recognized. Use + * {@link #createNarrowest} if you want to handle float and long values as numbers instead of objects. + * * @param returnValue actual return value from the too narrow operation * @param programPoint program point where unwarranted optimism was detected */ @@ -58,7 +61,7 @@ } /** - * Check if a program point is valid + * Check if a program point is valid. * @param programPoint the program point * @return true if valid */ @@ -70,8 +73,6 @@ private static Type getReturnType(final Object v) { if (v instanceof Double) { return Type.NUMBER; - } else if (v instanceof Long) { - return Type.LONG; } assert !(v instanceof Integer) : v + " is an int"; // Can't have an unwarranted optimism exception with int return Type.OBJECT; @@ -97,6 +98,22 @@ } /** + * Create an {@code UnwarrantedOptimismException} with the given return value and program point, narrowing + * the type to {@code number} if the value is a float or a long that can be represented as double. + * + * @param returnValue the return value + * @param programPoint the program point + * @return the exception + */ + public static UnwarrantedOptimismException createNarrowest(final Object returnValue, final int programPoint) { + if (returnValue instanceof Float + || (returnValue instanceof Long && JSType.isRepresentableAsDouble((Long) returnValue))) { + return new UnwarrantedOptimismException(((Number) returnValue).doubleValue(), programPoint, Type.NUMBER); + } + return new UnwarrantedOptimismException(returnValue, programPoint); + } + + /** * Get the return value. This is a destructive readout, after the method is invoked the return value is null'd out. * @return return value */ --- old/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java 2016-01-20 14:14:53.703064256 +0100 +++ new/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java 2016-01-20 14:14:53.607064258 +0100 @@ -71,13 +71,11 @@ /** Getter method handle */ private final static MethodHandle INVOKE_OBJECT_GETTER = findOwnMH_S("invokeObjectGetter", Object.class, Accessors.class, MethodHandle.class, Object.class); private final static MethodHandle INVOKE_INT_GETTER = findOwnMH_S("invokeIntGetter", int.class, Accessors.class, MethodHandle.class, int.class, Object.class); - private final static MethodHandle INVOKE_LONG_GETTER = findOwnMH_S("invokeLongGetter", long.class, Accessors.class, MethodHandle.class, int.class, Object.class); private final static MethodHandle INVOKE_NUMBER_GETTER = findOwnMH_S("invokeNumberGetter", double.class, Accessors.class, MethodHandle.class, int.class, Object.class); /** Setter method handle */ private final static MethodHandle INVOKE_OBJECT_SETTER = findOwnMH_S("invokeObjectSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, Object.class); private final static MethodHandle INVOKE_INT_SETTER = findOwnMH_S("invokeIntSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, int.class); - private final static MethodHandle INVOKE_LONG_SETTER = findOwnMH_S("invokeLongSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, long.class); private final static MethodHandle INVOKE_NUMBER_SETTER = findOwnMH_S("invokeNumberSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, double.class); private static final Object OBJECT_GETTER_INVOKER_KEY = new Object(); @@ -188,11 +186,6 @@ } @Override - public long getLongValue(final ScriptObject self, final ScriptObject owner) { - return (long)getObjectValue(self, owner); - } - - @Override public double getDoubleValue(final ScriptObject self, final ScriptObject owner) { return (double)getObjectValue(self, owner); } @@ -214,11 +207,6 @@ } @Override - public void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict) { - setValue(self, owner, (Object) value, strict); - } - - @Override public void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict) { setValue(self, owner, (Object) value, strict); } @@ -244,8 +232,6 @@ public MethodHandle getOptimisticGetter(final Class type, final int programPoint) { if (type == int.class) { return INVOKE_INT_GETTER; - } else if (type == long.class) { - return INVOKE_LONG_GETTER; } else if (type == double.class) { return INVOKE_NUMBER_GETTER; } else { @@ -269,8 +255,6 @@ public MethodHandle getSetter(final Class type, final PropertyMap currentMap) { if (type == int.class) { return INVOKE_INT_SETTER; - } else if (type == long.class) { - return INVOKE_LONG_SETTER; } else if (type == double.class) { return INVOKE_NUMBER_SETTER; } else { @@ -320,16 +304,6 @@ } @SuppressWarnings("unused") - private static long invokeLongGetter(final Accessors gs, final MethodHandle invoker, final int programPoint, final Object self) throws Throwable { - final Object func = gs.getter; - if (func instanceof ScriptFunction) { - return (long) invoker.invokeExact(func, self); - } - - throw new UnwarrantedOptimismException(UNDEFINED, programPoint); - } - - @SuppressWarnings("unused") private static double invokeNumberGetter(final Accessors gs, final MethodHandle invoker, final int programPoint, final Object self) throws Throwable { final Object func = gs.getter; if (func instanceof ScriptFunction) { @@ -354,16 +328,6 @@ final Object func = gs.setter; if (func instanceof ScriptFunction) { invoker.invokeExact(func, self, value); - } else if (name != null) { - throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self)); - } - } - - @SuppressWarnings("unused") - private static void invokeLongSetter(final Accessors gs, final MethodHandle invoker, final String name, final Object self, final long value) throws Throwable { - final Object func = gs.setter; - if (func instanceof ScriptFunction) { - invoker.invokeExact(func, self, value); } else if (name != null) { throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self)); } --- old/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java 2016-01-20 14:14:54.219064247 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java 2016-01-20 14:14:54.087064249 +0100 @@ -52,9 +52,6 @@ /** Minimum chunk size for underlying arrays */ protected static final int CHUNK_SIZE = 32; - /** Mask for getting a chunk */ - protected static final int CHUNK_MASK = CHUNK_SIZE - 1; - /** Untouched data - still link callsites as IntArrayData, but expands to * a proper ArrayData when we try to write to it */ public static final ArrayData EMPTY_ARRAY = new UntouchedArrayData(); @@ -164,11 +161,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - return toRealArrayData(index).set(index, value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { return toRealArrayData(index).set(index, value, strict); } @@ -179,11 +171,6 @@ } @Override - public long getLong(final int index) { - throw new ArrayIndexOutOfBoundsException(index); //empty - } - - @Override public double getDouble(final int index) { throw new ArrayIndexOutOfBoundsException(index); //empty } @@ -288,13 +275,13 @@ * @param length the initial length * @return ArrayData */ - public static ArrayData allocate(final int length) { - if (length == 0) { + public static ArrayData allocate(final long length) { + if (length == 0L) { return new IntArrayData(); } else if (length >= SparseArrayData.MAX_DENSE_LENGTH) { return new SparseArrayData(EMPTY_ARRAY, length); } else { - return new DeletedRangeArrayFilter(new IntArrayData(length), 0, length - 1); + return new DeletedRangeArrayFilter(new IntArrayData((int) length), 0, length - 1); } } @@ -309,8 +296,6 @@ if (clazz == int[].class) { return new IntArrayData((int[])array, ((int[])array).length); - } else if (clazz == long[].class) { - return new LongArrayData((long[])array, ((long[])array).length); } else if (clazz == double[].class) { return new NumberArrayData((double[])array, ((double[])array).length); } else { @@ -334,16 +319,6 @@ * @param array the array to use for initial elements * @return the ArrayData */ - public static ArrayData allocate(final long[] array) { - return new LongArrayData(array, array.length); - } - - /** - * Allocate an ArrayData wrapping a given array - * - * @param array the array to use for initial elements - * @return the ArrayData - */ public static ArrayData allocate(final double[] array) { return new NumberArrayData(array, array.length); } @@ -537,16 +512,6 @@ public abstract ArrayData set(final int index, final int value, final boolean strict); /** - * Set a long value at a given index - * - * @param index the index - * @param value the value - * @param strict are we in strict mode - * @return new array data (or same) - */ - public abstract ArrayData set(final int index, final long value, final boolean strict); - - /** * Set an double value at a given index * * @param index the index @@ -609,26 +574,6 @@ } /** - * Get a long value from a given index - * - * @param index the index - * @return the value - */ - public abstract long getLong(final int index); - - /** - * Get optimistic long - default is that it's impossible. Overridden - * by arrays that actually represents longs or narrower - * - * @param index the index - * @param programPoint program point - * @return the value - */ - public long getLongOptimistic(final int index, final int programPoint) { - throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType()); - } - - /** * Get a double value from a given index * * @param index the index @@ -821,12 +766,8 @@ return Object.class; } final Class itemClass = item.getClass(); - if (itemClass == Long.class) { + if (itemClass == Double.class || itemClass == Float.class || itemClass == Long.class) { if (widest == Integer.class) { - widest = Long.class; - } - } else if (itemClass == Double.class || itemClass == Float.class) { - if (widest == Integer.class || widest == Long.class) { widest = Double.class; } } else if (itemClass != Integer.class && itemClass != Short.class && itemClass != Byte.class) { --- old/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java 2016-01-20 14:14:54.707064238 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java 2016-01-20 14:14:54.575064241 +0100 @@ -109,13 +109,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - underlying = underlying.set(index, value, strict); - setLength(underlying.length()); - return this; - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { underlying = underlying.set(index, value, strict); setLength(underlying.length()); @@ -150,16 +143,6 @@ } @Override - public long getLong(final int index) { - return underlying.getLong(index); - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - return underlying.getLongOptimistic(index, programPoint); - } - - @Override public double getDouble(final int index) { return underlying.getDouble(index); } --- old/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java 2016-01-20 14:14:55.199064230 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java 2016-01-20 14:14:55.063064232 +0100 @@ -122,12 +122,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - buf.put(index, (byte)value); - return this; - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { buf.put(index, (byte)value); return this; @@ -138,11 +132,6 @@ return 0x0ff & buf.get(index); } - @Override - public long getLong(final int index) { - return 0x0ff & buf.get(index); - } - @Override public double getDouble(final int index) { return 0x0ff & buf.get(index); --- old/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java 2016-01-20 14:14:55.695064221 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java 2016-01-20 14:14:55.591064223 +0100 @@ -120,12 +120,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - deleted.clear(ArrayIndex.toLongIndex(index)); - return super.set(index, value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { deleted.clear(ArrayIndex.toLongIndex(index)); return super.set(index, value, strict); --- old/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java 2016-01-20 14:14:56.127064213 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java 2016-01-20 14:14:56.003064216 +0100 @@ -163,24 +163,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - final long longIndex = ArrayIndex.toLongIndex(index); - if (longIndex < lo || longIndex > hi) { - return super.set(index, value, strict); - } else if (longIndex > lo && longIndex < hi) { - return getDeletedArrayFilter().set(index, value, strict); - } - if (longIndex == lo) { - lo++; - } else { - assert longIndex == hi; - hi--; - } - - return isEmpty() ? getUnderlying().set(index, value, strict) : super.set(index, value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { final long longIndex = ArrayIndex.toLongIndex(index); if (longIndex < lo || longIndex > hi) { --- old/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java 2016-01-20 14:14:56.635064204 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java 2016-01-20 14:14:56.507064207 +0100 @@ -57,14 +57,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - if (strict) { - throw typeError("cant.set.property", Integer.toString(index), "frozen array"); - } - return this; - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { if (strict) { throw typeError("cant.set.property", Integer.toString(index), "frozen array"); --- old/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java 2016-01-20 14:14:57.011064198 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java 2016-01-20 14:14:56.931064199 +0100 @@ -156,22 +156,6 @@ return darray; } - private long[] toLongArray() { - assert length() <= array.length : "length exceeds internal array size"; - final int len = (int)length(); - final long[] larray = new long[array.length]; - - for (int index = 0; index < len; index++) { - larray[index] = array[index]; - } - - return larray; - } - - private LongArrayData convertToLong() { - return new LongArrayData(toLongArray(), (int)length()); - } - private NumberArrayData convertToDouble() { return new NumberArrayData(toDoubleArray(), (int)length()); } @@ -184,8 +168,6 @@ public ArrayData convert(final Class type) { if (type == Integer.class || type == Byte.class || type == Short.class) { return this; - } else if (type == Long.class) { - return convertToLong(); } else if (type == Double.class || type == Float.class) { return convertToDouble(); } else { @@ -253,17 +235,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - if (JSType.isRepresentableAsInt(value)) { - array[index] = JSType.toInt32(value); - setLength(Math.max(index + 1, length())); - return this; - } - - return convert(Long.class).set(index, value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { if (JSType.isRepresentableAsInt(value)) { array[index] = (int)(long)value; @@ -284,16 +255,6 @@ return array[index]; } - @Override - public long getLong(final int index) { - return array[index]; - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - return array[index]; - } - @Override public double getDouble(final int index) { return array[index]; --- old/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java 2016-01-20 14:14:57.419064191 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java 2016-01-20 14:14:57.335064192 +0100 @@ -130,6 +130,6 @@ * * @throws Throwable if invocation throws an exception/error */ - protected abstract boolean forEach(final Object val, final long i) throws Throwable; + protected abstract boolean forEach(final Object val, final double i) throws Throwable; } --- old/src/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java 2016-01-20 14:14:57.731064185 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java 2016-01-20 14:14:57.651064186 +0100 @@ -91,22 +91,6 @@ } @Override - public long getLong(final int index) { - if (index >= length()) { - return JSType.toLong(get(index)); - } - return underlying.getLong(index); - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - if (index >= length()) { - return JSType.toLongOptimistic(get(index), programPoint); - } - return underlying.getLongOptimistic(index, programPoint); - } - - @Override public double getDouble(final int index) { if (index >= length()) { return JSType.toNumber(get(index)); @@ -144,15 +128,6 @@ if (checkAdd(index, value)) { return this; } - underlying = underlying.set(index, value, strict); - return this; - } - - @Override - public ArrayData set(final int index, final long value, final boolean strict) { - if (checkAdd(index, value)) { - return this; - } underlying = underlying.set(index, value, strict); return this; } --- old/src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java 2016-01-20 14:14:58.223064176 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java 2016-01-20 14:14:58.095064179 +0100 @@ -51,14 +51,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - if (has(index)) { - return underlying.set(index, value, strict); - } - return extensionCheck(strict, index); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { if (has(index)) { return underlying.set(index, value, strict); --- old/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java 2016-01-20 14:14:58.703064168 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java 2016-01-20 14:14:58.575064170 +0100 @@ -179,13 +179,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - array[index] = value; - setLength(Math.max(index + 1, length())); - return this; - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { array[index] = value; setLength(Math.max(index + 1, length())); @@ -214,7 +207,7 @@ @Override public MethodHandle getElementGetter(final Class returnType, final int programPoint) { - if (returnType == int.class || returnType == long.class) { + if (returnType == int.class) { return null; } return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint); @@ -231,11 +224,6 @@ } @Override - public long getLong(final int index) { - return (long)array[index]; - } - - @Override public double getDouble(final int index) { return array[index]; } --- old/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java 2016-01-20 14:14:59.119064161 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java 2016-01-20 14:14:58.999064163 +0100 @@ -150,13 +150,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - array[index] = value; - setLength(Math.max(index + 1, length())); - return this; - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { array[index] = value; setLength(Math.max(index + 1, length())); @@ -216,11 +209,6 @@ } @Override - public long getLong(final int index) { - return JSType.toLong(array[index]); - } - - @Override public double getDouble(final int index) { return JSType.toNumber(array[index]); } --- old/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java 2016-01-20 14:14:59.539064153 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java 2016-01-20 14:14:59.431064155 +0100 @@ -195,21 +195,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - if (index >= 0 && index < maxDenseLength) { - final long oldLength = underlying.length(); - ensure(index); - underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict); - setLength(Math.max(underlying.length(), length())); - } else { - final Long longIndex = indexToKey(index); - sparseMap.put(longIndex, value); - setLength(Math.max(longIndex + 1, length())); - } - return this; - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { if (index >= 0 && index < maxDenseLength) { final long oldLength = underlying.length(); @@ -258,22 +243,6 @@ } @Override - public long getLong(final int index) { - if (index >= 0 && index < maxDenseLength) { - return underlying.getLong(index); - } - return JSType.toLong(sparseMap.get(indexToKey(index))); - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - if (index >= 0 && index < maxDenseLength) { - return underlying.getLongOptimistic(index, programPoint); - } - return JSType.toLongOptimistic(sparseMap.get(indexToKey(index)), programPoint); - } - - @Override public double getDouble(final int index) { if (index >= 0 && index < maxDenseLength) { return underlying.getDouble(index); --- old/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java 2016-01-20 14:14:59.951064146 +0100 +++ new/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java 2016-01-20 14:14:59.819064148 +0100 @@ -128,13 +128,6 @@ } @Override - public ArrayData set(final int index, final long value, final boolean strict) { - undefined.clear(index); - - return super.set(index, value, strict); - } - - @Override public ArrayData set(final int index, final double value, final boolean strict) { undefined.clear(index); @@ -160,24 +153,6 @@ } @Override - public long getLong(final int index) { - if (undefined.isSet(index)) { - return 0L; - } - - return super.getLong(index); - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - if (undefined.isSet(index)) { - throw new UnwarrantedOptimismException(UNDEFINED, programPoint); - } - - return super.getLongOptimistic(index, programPoint); - } - - @Override public double getDouble(final int index) { if (undefined.isSet(index)) { return Double.NaN; --- old/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java 2016-01-20 14:15:00.471064137 +0100 +++ new/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java 2016-01-20 14:15:00.339064139 +0100 @@ -215,7 +215,7 @@ * * @return callsite for a math intrinsic node */ - public static CallSite mathBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int programPoint) { + public static CallSite mathBootstrap(final Lookup lookup, final String name, final MethodType type, final int programPoint) { final MethodHandle mh; switch (name) { case "iadd": @@ -236,24 +236,6 @@ case "ineg": mh = JSType.NEGATE_EXACT.methodHandle(); break; - case "ladd": - mh = JSType.ADD_EXACT_LONG.methodHandle(); - break; - case "lsub": - mh = JSType.SUB_EXACT_LONG.methodHandle(); - break; - case "lmul": - mh = JSType.MUL_EXACT_LONG.methodHandle(); - break; - case "ldiv": - mh = JSType.DIV_EXACT_LONG.methodHandle(); - break; - case "lrem": - mh = JSType.REM_EXACT_LONG.methodHandle(); - break; - case "lneg": - mh = JSType.NEGATE_EXACT_LONG.methodHandle(); - break; default: throw new AssertionError("unsupported math intrinsic"); } --- old/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java 2016-01-20 14:15:01.023064127 +0100 +++ new/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java 2016-01-20 14:15:00.895064129 +0100 @@ -141,8 +141,9 @@ } /** - * Main part of the implementation of {@link GuardingTypeConverterFactory#convertToType(Class, Class)} that doesn't - * care about adapting the method signature; that's done by the invoking method. Returns conversion from Object to String/number/boolean (JS primitive types). + * Main part of the implementation of {@link GuardingTypeConverterFactory#convertToType} that doesn't + * care about adapting the method signature; that's done by the invoking method. Returns conversion + * from Object to String/number/boolean (JS primitive types). * @param sourceType the source type * @param targetType the target type * @return a guarded invocation that converts from the source type to the target type. --- old/test/script/basic/JDK-8062799.js 2016-01-20 14:15:01.483064119 +0100 +++ new/test/script/basic/JDK-8062799.js 2016-01-20 14:15:01.371064121 +0100 @@ -33,67 +33,46 @@ var b = true; var i = 1; - var l = 4294967296; var d = 2.1; var o = "foo"; print(inspect(b || b, "b || b")); print(inspect(b || i, "b || i")); - print(inspect(b || l, "b || l")); print(inspect(b || d, "b || d")); print(inspect(b || o, "b || o")); print(inspect(i || b, "i || b")); print(inspect(i || i, "i || i")); - print(inspect(i || l, "i || l")); print(inspect(i || d, "i || d")); print(inspect(i || o, "i || o")); - print(inspect(l || b, "l || b")); - print(inspect(l || i, "l || i")); - print(inspect(l || l, "l || l")); - print(inspect(l || d, "l || d")); - print(inspect(l || o, "l || o")); - print(inspect(d || b, "d || b")); print(inspect(d || i, "d || i")); - print(inspect(d || l, "d || l")); print(inspect(d || d, "d || d")); print(inspect(d || o, "d || o")); print(inspect(o || b, "o || b")); print(inspect(o || i, "o || i")); - print(inspect(o || l, "o || l")); print(inspect(o || d, "o || d")); print(inspect(o || o, "o || o")); print(inspect(b && b, "b && b")); print(inspect(b && i, "b && i")); - print(inspect(b && l, "b && l")); print(inspect(b && d, "b && d")); print(inspect(b && o, "b && o")); print(inspect(i && b, "i && b")); print(inspect(i && i, "i && i")); - print(inspect(i && l, "i && l")); print(inspect(i && d, "i && d")); print(inspect(i && o, "i && o")); - print(inspect(l && b, "l && b")); - print(inspect(l && i, "l && i")); - print(inspect(l && l, "l && l")); - print(inspect(l && d, "l && d")); - print(inspect(l && o, "l && o")); - print(inspect(d && b, "d && b")); print(inspect(d && i, "d && i")); - print(inspect(d && l, "d && l")); print(inspect(d && d, "d && d")); print(inspect(d && o, "d && o")); print(inspect(o && b, "o && b")); print(inspect(o && i, "o && i")); - print(inspect(o && l, "o && l")); print(inspect(o && d, "o && d")); print(inspect(o && o, "o && o")); })(); --- old/test/script/basic/JDK-8062799.js.EXPECTED 2016-01-20 14:15:01.927064111 +0100 +++ new/test/script/basic/JDK-8062799.js.EXPECTED 2016-01-20 14:15:01.791064114 +0100 @@ -1,50 +1,32 @@ b || b: boolean b || i: boolean -b || l: boolean b || d: boolean b || o: boolean i || b: int i || i: int -i || l: long i || d: double i || o: int -l || b: long -l || i: long -l || l: long -l || d: double -l || o: long d || b: double d || i: double -d || l: double d || d: double d || o: double o || b: object o || i: object -o || l: object o || d: object o || o: object b && b: boolean b && i: int -b && l: long b && d: double b && o: object i && b: boolean i && i: int -i && l: long i && d: double i && o: object -l && b: boolean -l && i: long -l && l: long -l && d: double -l && o: object d && b: boolean d && i: double -d && l: double d && d: double d && o: object o && b: boolean o && i: int -o && l: long o && d: double o && o: object --- old/test/script/basic/JDK-8144131.js 2016-01-20 14:15:02.443064102 +0100 +++ new/test/script/basic/JDK-8144131.js 2016-01-20 14:15:02.307064104 +0100 @@ -30,12 +30,9 @@ var doubleArray = [97912312397.234, -182374983434.56]; var doubleArrayResults = [-871935411, -1986357002]; -var longArray = [0x7fffffff8c102ebc, -0x7fffffffe9dfec18]; -var longArrayResults = [-1945096192, 371201024]; -// Make sure arrays use double and long array data +// Make sure array uses double array data Assert.assertEquals(doubleArray[0].getClass(), java.lang.Double.class); -Assert.assertEquals(longArray[0].getClass(), java.lang.Long.class); function testBinaryOp(array, index, expected) { Assert.assertEquals(array[index] & 0xffffffff, expected); @@ -44,7 +41,4 @@ for (var i = 0; i < doubleArray.length; i++) { testBinaryOp(doubleArray, i, doubleArrayResults[i]); } -for (var i = 0; i < longArray.length; i++) { - testBinaryOp(longArray, i, longArrayResults[i]); -} --- old/test/script/nosecurity/JDK-8067215.js 2016-01-20 14:15:02.907064094 +0100 +++ new/test/script/nosecurity/JDK-8067215.js 2016-01-20 14:15:02.811064096 +0100 @@ -32,7 +32,6 @@ var intType = Java.type("int"); var doubleType = Java.type("double"); -var longType = Java.type("long"); var objectType = Java.type("java.lang.Object"); var Context = Java.type("jdk.nashorn.internal.runtime.Context"); @@ -58,7 +57,6 @@ } if (prop.getType() != getExpectedType(obj[key])) { throw new Error("Wrong property type: " + prop.getType() + " // " + getExpectedType(obj[key])); - } } } @@ -67,14 +65,8 @@ if (!dualFields) { return objectType.class; } - if (JSType.isRepresentableAsInt(value)) { - return intType.class; - } - if (JSType.isRepresentableAsLong(value)) { - return longType.class; - } - if (JSType.isNumber(value)) { - return doubleType.class; + if (typeof value === "number") { + return JSType.isRepresentableAsInt(value) ? intType.class : doubleType.class; } return objectType.class; } --- old/test/src/jdk/nashorn/api/javaaccess/test/NumberAccessTest.java 2016-01-20 14:15:03.323064087 +0100 +++ new/test/src/jdk/nashorn/api/javaaccess/test/NumberAccessTest.java 2016-01-20 14:15:03.239064088 +0100 @@ -143,7 +143,7 @@ @Test public void accessStaticFinalFieldLong() throws ScriptException { e.eval("var psf_long = SharedObject.publicStaticFinalLong;"); - assertEquals(SharedObject.publicStaticFinalLong, e.get("psf_long")); + assertEquals(SharedObject.publicStaticFinalLong, ((Number) e.get("psf_long")).longValue()); e.eval("SharedObject.publicStaticFinalLong = 120;"); assertEquals(8333333333333L, SharedObject.publicStaticFinalLong); } --- old/test/src/jdk/nashorn/api/javaaccess/test/NumberBoxingTest.java 2016-01-20 14:15:03.655064081 +0100 +++ new/test/src/jdk/nashorn/api/javaaccess/test/NumberBoxingTest.java 2016-01-20 14:15:03.563064082 +0100 @@ -70,7 +70,7 @@ @Test public void accessFieldLongBoxing() throws ScriptException { e.eval("var p_long = o.publicLongBox;"); - assertEquals(o.publicLongBox, e.get("p_long")); + assertEquals(o.publicLongBox.longValue(), ((Number) e.get("p_long")).longValue()); e.eval("o.publicLongBox = 12;"); assertEquals(Long.valueOf(12), o.publicLongBox); } @@ -78,7 +78,7 @@ @Test public void accessStaticFieldLongBoxing() throws ScriptException { e.eval("var ps_long = SharedObject.publicStaticLongBox;"); - assertEquals(SharedObject.publicStaticLongBox, e.get("ps_long")); + assertEquals(SharedObject.publicStaticLongBox.longValue(), ((Number) e.get("ps_long")).longValue()); e.eval("SharedObject.publicStaticLongBox = 120;"); assertEquals(120L, SharedObject.publicStaticLongBox.longValue()); } @@ -86,7 +86,7 @@ @Test public void accessFinalFieldLongBoxing() throws ScriptException { e.eval("var pf_long = o.publicFinalLongBox;"); - assertEquals(o.publicFinalLongBox, e.get("pf_long")); + assertEquals(o.publicFinalLongBox.longValue(), ((Number) e.get("pf_long")).longValue()); e.eval("o.publicFinalLongBox = 120;"); assertEquals(Long.valueOf(9377333334L), o.publicFinalLongBox); } @@ -94,7 +94,7 @@ @Test public void accessStaticFinalFieldLongBoxing() throws ScriptException { e.eval("var psf_long = SharedObject.publicStaticFinalLong;"); - assertEquals(SharedObject.publicStaticFinalLong, e.get("psf_long")); + assertEquals(SharedObject.publicStaticFinalLong, ((Number) e.get("psf_long")).longValue()); e.eval("SharedObject.publicStaticFinalLong = 120;"); assertEquals(8333333333333L, SharedObject.publicStaticFinalLong); } --- /dev/null 2016-01-20 09:42:27.247595856 +0100 +++ new/test/script/basic/JDK-8144020.js 2016-01-20 14:15:03.991064075 +0100 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015, 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-8144020: Remove long as an internal numeric type + * + * @test + * @run + */ + +var LongProvider = Java.type("jdk.nashorn.test.models.LongProvider"); +var Long = Java.type("java.lang.Long"); +var LongClass = Long.class; +var Integer = Java.type("java.lang.Integer"); +var Double = Java.type("java.lang.Double"); + +var INT = "3"; +var DOUBLE = "5.5"; +var MAX_LONG = "9223372036854775807"; +var MIN_LONG = "-9223372036854775808"; +var BIG_LONG = "281474976710655"; // can be represented as double +var NEG_LONG = "-281474976710656"; // can be represented as double +var SMALL_LONG = "13"; + +// Make sure we can pass longs from and to Java without losing precision +LongProvider.checkLong(LongProvider.getLong(MAX_LONG), MAX_LONG); +LongProvider.checkLong(LongProvider.getLong(MIN_LONG), MIN_LONG); +LongProvider.checkLong(LongProvider.getLong(BIG_LONG), BIG_LONG); +LongProvider.checkLong(LongProvider.getLong(NEG_LONG), NEG_LONG); +LongProvider.checkLong(LongProvider.getLong(SMALL_LONG), SMALL_LONG); + +// a polymorphic function that can return various number types +function getNumber(str) { + switch (str) { + case INT: return +INT; + case DOUBLE: return +DOUBLE; + default: return Long.parseLong(str); + } +} + +function compareValue(n, str) { + switch (str) { + case INT: return Integer.compare(n, Integer.parseInt(str) == 0); + case DOUBLE: return Double.compare(n, Double.parseDouble(str) == 0); + default: return Long.compare(n, Long.parseLong(str) == 0); + } +} + +// Call a a function with a sequence of values. The purpose of this is that we can handle +// longs without losing precision in the presence of optimistic deoptimization, cached callsites, etc. +function testSequence(fn, values) { + for (var i in values) { + fn(values[i]); + } +} + +// We need to use "fresh" (unlinked and un-deoptimized) functions for each of the test runs. +testSequence(function(str) { + var n = getNumber(str); + Assert.assertTrue(compareValue(n, str)); +}, [INT, BIG_LONG, MIN_LONG]); + +testSequence(function(str) { + var n = getNumber(str); + Assert.assertTrue(compareValue(n, str)); +}, [INT, MAX_LONG]); + +testSequence(function(str) { + var n = getNumber(str); + Assert.assertTrue(compareValue(n, str)); +}, [INT, DOUBLE, NEG_LONG]); + +testSequence(function(str) { + var n = getNumber(str); + Assert.assertTrue(compareValue(n, str)); +}, [DOUBLE, MAX_LONG]); + +testSequence(function(str) { + var n = getNumber(str); + Assert.assertTrue(compareValue(n, str)); +}, [DOUBLE, SMALL_LONG, MAX_LONG]); + +testSequence(function(str) { + var n = getNumber(str); + Assert.assertTrue(compareValue(n, str)); +}, [INT, DOUBLE, NEG_LONG, MAX_LONG]); + +testSequence(function(str) { + var n = getNumber(str); + Assert.assertTrue(compareValue(n, str)); +}, [DOUBLE, MAX_LONG, DOUBLE, INT]); + +// Make sure long arrays make it through Java.from and Java.to without losing precision +var longArrayType = Java.type("long[]"); +for (var i = 0; i < 3; i++) { + LongProvider.checkLongArray(Java.to(Java.from(LongProvider.getLongArray(i)), longArrayType), i); +} + +l = Long.parseLong(BIG_LONG); +Assert.assertTrue(l >>> 8 === 0xffffff); +Assert.assertTrue(l << 8 === -0x100); +Assert.assertTrue(l + 1 === 0x1000000000000); +Assert.assertTrue(l - 1 === 0xfffffffffffe); + +Assert.assertEquals(LongProvider.getLong(MAX_LONG).getClass(), LongClass); +Assert.assertEquals(LongProvider.getLong(MIN_LONG).getClass(), LongClass); --- /dev/null 2016-01-20 09:42:27.247595856 +0100 +++ new/test/src/jdk/nashorn/test/models/LongProvider.java 2016-01-20 14:15:04.307064069 +0100 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.test.models; + +import java.util.Arrays; + +/** + * A class that returns and receives longs. + */ +@SuppressWarnings("javadoc") +public class LongProvider { + + final static long[][] arrays = { + {1L, 2L, 3L}, + {1L, 1L << 30, 1L << 50, 4L}, + {1L, Long.MAX_VALUE, Long.MIN_VALUE, 4L} + }; + + public static long getLong(final String str) { + final long l = Long.parseLong(str); + checkLong(l, str); + return l; + } + + public static long[] getLongArray(final int n) { + return arrays[n]; + } + + public static void checkLong(final long value, final String str) { + if (!Long.toString(value).equals(str)) { + throw new RuntimeException("Wrong value. Expected " + str + ", got " + value); + } + } + + public static void checkLongArray(final long[] array, final int n) { + if (!Arrays.equals(array, arrays[n])) { + throw new RuntimeException("Arrays don't match: " + Arrays.toString(array) + ", " + Arrays.toString(arrays[n])); + } + } +} --- old/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java 2016-01-20 14:15:04.907064059 +0100 +++ /dev/null 2016-01-20 09:42:27.247595856 +0100 @@ -1,406 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.nashorn.internal.runtime.arrays; - -import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; -import static jdk.nashorn.internal.lookup.Lookup.MH; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.util.Arrays; -import jdk.nashorn.internal.runtime.JSType; -import jdk.nashorn.internal.runtime.ScriptRuntime; - -/** - * Implementation of {@link ArrayData} as soon as a long has been - * written to the array - */ -final class LongArrayData extends ContinuousArrayData implements IntOrLongElements { - /** - * The wrapped array - */ - private long[] array; - - /** - * Constructor - * @param array an int array - * @param length a length, not necessarily array.length - */ - LongArrayData(final long array[], final int length) { - super(length); - assert array.length >= length; - this.array = array; - } - - @Override - public final Class getElementType() { - return long.class; - } - - @Override - public final Class getBoxedElementType() { - return Long.class; - } - - @Override - public final ContinuousArrayData widest(final ContinuousArrayData otherData) { - return otherData instanceof IntElements ? this : otherData; - } - - @Override - public final int getElementWeight() { - return 2; - } - - @Override - public LongArrayData copy() { - return new LongArrayData(array.clone(), (int)length()); - } - - @Override - public Object[] asObjectArray() { - return toObjectArray(true); - } - - private Object[] toObjectArray(final boolean trim) { - assert length() <= array.length : "length exceeds internal array size"; - final int len = (int)length(); - final Object[] oarray = new Object[trim ? len : array.length]; - - for (int index = 0; index < len; index++) { - oarray[index] = Long.valueOf(array[index]); - } - - return oarray; - } - - @Override - public Object asArrayOfType(final Class componentType) { - if (componentType == long.class) { - final int len = (int)length(); - return array.length == len ? array.clone() : Arrays.copyOf(array, len); - } - return super.asArrayOfType(componentType); - } - - private double[] toDoubleArray() { - assert length() <= array.length : "length exceeds internal array size"; - final int len = (int)length(); - final double[] darray = new double[array.length]; - - for (int index = 0; index < len; index++) { - darray[index] = array[index]; - } - - return darray; - } - - @Override - public ContinuousArrayData convert(final Class type) { - if (type == Integer.class || type == Long.class || type == Byte.class || type == Short.class) { - return this; - } - final int len = (int)length(); - if (type == Double.class || type == Float.class) { - return new NumberArrayData(toDoubleArray(), len); - } - return new ObjectArrayData(toObjectArray(false), len); - } - - @Override - public void shiftLeft(final int by) { - System.arraycopy(array, by, array, 0, array.length - by); - } - - @Override - public ArrayData shiftRight(final int by) { - final ArrayData newData = ensure(by + length() - 1); - if (newData != this) { - newData.shiftRight(by); - return newData; - } - System.arraycopy(array, 0, array, by, array.length - by); - - return this; - } - - @Override - public ArrayData ensure(final long safeIndex) { - if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) { - return new SparseArrayData(this, safeIndex + 1); - } - final int alen = array.length; - if (safeIndex >= alen) { - final int newLength = ArrayData.nextSize((int)safeIndex); - array = Arrays.copyOf(array, newLength); - } - if (safeIndex >= length()) { - setLength(safeIndex + 1); - } - return this; - } - - @Override - public ArrayData shrink(final long newLength) { - Arrays.fill(array, (int)newLength, array.length, 0L); - return this; - } - - @Override - public ArrayData set(final int index, final Object value, final boolean strict) { - if (value instanceof Long || value instanceof Integer || - value instanceof Byte || value instanceof Short) { - return set(index, ((Number)value).longValue(), strict); - } else if (value == ScriptRuntime.UNDEFINED) { - return new UndefinedArrayFilter(this).set(index, value, strict); - } - - final ArrayData newData = convert(value == null ? Object.class : value.getClass()); - return newData.set(index, value, strict); - } - - @Override - public ArrayData set(final int index, final int value, final boolean strict) { - array[index] = value; - setLength(Math.max(index + 1, length())); - return this; - } - - @Override - public ArrayData set(final int index, final long value, final boolean strict) { - array[index] = value; - setLength(Math.max(index + 1, length())); - return this; - } - - @Override - public ArrayData set(final int index, final double value, final boolean strict) { - if (JSType.isRepresentableAsLong(value)) { - array[index] = (long)value; - setLength(Math.max(index + 1, length())); - return this; - } - return convert(Double.class).set(index, value, strict); - } - - private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "getElem", long.class, int.class).methodHandle(); - private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "setElem", void.class, int.class, long.class).methodHandle(); - - @SuppressWarnings("unused") - private long getElem(final int index) { - if (has(index)) { - return array[index]; - } - throw new ClassCastException(); - } - - @SuppressWarnings("unused") - private void setElem(final int index, final long elem) { - if (hasRoomFor(index)) { - array[index] = elem; - return; - } - throw new ClassCastException(); - } - - @Override - public MethodHandle getElementGetter(final Class returnType, final int programPoint) { - if (returnType == int.class) { - return null; - } - return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint); - } - - @Override - public MethodHandle getElementSetter(final Class elementType) { - return elementType == int.class || elementType == long.class ? getContinuousElementSetter(MH.asType(SET_ELEM, SET_ELEM.type().changeParameterType(2, elementType)), elementType) : null; - } - - @Override - public int getInt(final int index) { - return JSType.toInt32(array[index]); - } - - @Override - public long getLong(final int index) { - return array[index]; - } - - @Override - public long getLongOptimistic(final int index, final int programPoint) { - return array[index]; - } - - @Override - public double getDouble(final int index) { - return array[index]; - } - - @Override - public double getDoubleOptimistic(final int index, final int programPoint) { - return array[index]; - } - - @Override - public Object getObject(final int index) { - return array[index]; - } - - @Override - public boolean has(final int index) { - return 0 <= index && index < length(); - } - - @Override - public ArrayData delete(final int index) { - return new DeletedRangeArrayFilter(this, index, index); - } - - @Override - public ArrayData delete(final long fromIndex, final long toIndex) { - return new DeletedRangeArrayFilter(this, fromIndex, toIndex); - } - - @Override - public Object pop() { - final int len = (int)length(); - if (len == 0) { - return ScriptRuntime.UNDEFINED; - } - - final int newLength = len - 1; - final long elem = array[newLength]; - array[newLength] = 0; - setLength(newLength); - - return elem; - } - - @Override - public ArrayData slice(final long from, final long to) { - final long start = from < 0 ? from + length() : from; - final long newLength = to - start; - return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength); - } - - @Override - public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException { - final long oldLength = length(); - final long newLength = oldLength - removed + added; - if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) { - throw new UnsupportedOperationException(); - } - final ArrayData returnValue = removed == 0 ? - EMPTY_ARRAY : new LongArrayData(Arrays.copyOfRange(array, start, start + removed), removed); - - if (newLength != oldLength) { - final long[] newArray; - - if (newLength > array.length) { - newArray = new long[ArrayData.nextSize((int)newLength)]; - System.arraycopy(array, 0, newArray, 0, start); - } else { - newArray = array; - } - - System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed)); - array = newArray; - setLength(newLength); - } - - return returnValue; - } - - @Override - public long fastPush(final int arg) { - return fastPush((long)arg); - } - - @Override - public long fastPush(final long arg) { - final int len = (int)length(); - if (len == array.length) { - array = Arrays.copyOf(array, nextSize(len)); - } - array[len] = arg; - return increaseLength(); - } - - @Override - public long fastPopLong() { - if (length() == 0) { - throw new ClassCastException(); //undefined result - } - final int newLength = (int)decreaseLength(); - final long elem = array[newLength]; - array[newLength] = 0; - return elem; - } - - @Override - public double fastPopDouble() { - return fastPopLong(); - } - - @Override - public Object fastPopObject() { - return fastPopLong(); - } - - @Override - public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) { - final int otherLength = (int)otherData.length(); - final int thisLength = (int)length(); - assert otherLength > 0 && thisLength > 0; - - final long[] otherArray = ((LongArrayData)otherData).array; - final int newLength = otherLength + thisLength; - final long[] newArray = new long[ArrayData.alignUp(newLength)]; - - System.arraycopy(array, 0, newArray, 0, thisLength); - System.arraycopy(otherArray, 0, newArray, thisLength, otherLength); - - return new LongArrayData(newArray, newLength); - } - - @Override - public String toString() { - assert length() <= array.length : length() + " > " + array.length; - - final StringBuilder sb = new StringBuilder(getClass().getSimpleName()). - append(": ["); - final int len = (int)length(); - for (int i = 0; i < len; i++) { - sb.append(array[i]).append('L'); //make sure L suffix is on elements, to discriminate this from IntArrayData.toString() - if (i + 1 < len) { - sb.append(", "); - } - } - sb.append(']'); - - return sb.toString(); - } -}