mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-25 23:29:55 +00:00
8061957: Some arithmetic operations have unnecessary widening
Reviewed-by: hannesw, lagergren
This commit is contained in:
parent
44b0af6eb9
commit
c0a2e40859
@ -3569,7 +3569,8 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
||||
operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT);
|
||||
} else {
|
||||
// Non-optimistic, non-FP +. Allow it to overflow.
|
||||
operandBounds = new TypeBounds(binaryNode.getWidestOperandType(), Type.OBJECT);
|
||||
operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest),
|
||||
Type.OBJECT);
|
||||
forceConversionSeparation = binaryNode.getWidestOperationType().narrowerThan(resultBounds.widest);
|
||||
}
|
||||
loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false, forceConversionSeparation);
|
||||
@ -3856,12 +3857,8 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
||||
operandBounds = numericBounds;
|
||||
} else {
|
||||
final boolean isOptimistic = isValid(getProgramPoint());
|
||||
if(isOptimistic) {
|
||||
if(isOptimistic || node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) {
|
||||
operandBounds = new TypeBounds(node.getType(), Type.NUMBER);
|
||||
} else if(node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) {
|
||||
// Non-optimistic division must always take double arguments as its result must also be
|
||||
// double.
|
||||
operandBounds = TypeBounds.NUMBER;
|
||||
} else {
|
||||
// Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow.
|
||||
operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(),
|
||||
|
||||
@ -55,6 +55,7 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_
|
||||
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.nashorn.internal.codegen.CompilerConstants;
|
||||
import jdk.nashorn.internal.runtime.JSType;
|
||||
|
||||
/**
|
||||
* Type class: INT
|
||||
@ -230,19 +231,21 @@ class IntType extends BitwiseType {
|
||||
|
||||
@Override
|
||||
public Type div(final MethodVisitor method, final int programPoint) {
|
||||
// Never perform non-optimistic integer division in JavaScript.
|
||||
assert programPoint != INVALID_PROGRAM_POINT;
|
||||
|
||||
method.visitInvokeDynamicInsn("idiv", "(II)I", MATHBOOTSTRAP, programPoint);
|
||||
if (programPoint == INVALID_PROGRAM_POINT) {
|
||||
JSType.DIV_ZERO.invoke(method);
|
||||
} else {
|
||||
method.visitInvokeDynamicInsn("idiv", "(II)I", MATHBOOTSTRAP, programPoint);
|
||||
}
|
||||
return INT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type rem(final MethodVisitor method, final int programPoint) {
|
||||
// Never perform non-optimistic integer remainder in JavaScript.
|
||||
assert programPoint != INVALID_PROGRAM_POINT;
|
||||
|
||||
method.visitInvokeDynamicInsn("irem", "(II)I", MATHBOOTSTRAP, programPoint);
|
||||
if (programPoint == INVALID_PROGRAM_POINT) {
|
||||
JSType.REM_ZERO.invoke(method);
|
||||
} else {
|
||||
method.visitInvokeDynamicInsn("irem", "(II)I", MATHBOOTSTRAP, programPoint);
|
||||
}
|
||||
return INT;
|
||||
}
|
||||
|
||||
|
||||
@ -170,19 +170,21 @@ class LongType extends BitwiseType {
|
||||
|
||||
@Override
|
||||
public Type div(final MethodVisitor method, final int programPoint) {
|
||||
// Never perform non-optimistic integer division in JavaScript.
|
||||
assert programPoint != INVALID_PROGRAM_POINT;
|
||||
|
||||
method.visitInvokeDynamicInsn("ldiv", "(JJ)J", MATHBOOTSTRAP, 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) {
|
||||
// Never perform non-optimistic integer remainder in JavaScript.
|
||||
assert programPoint != INVALID_PROGRAM_POINT;
|
||||
|
||||
method.visitInvokeDynamicInsn("lrem", "(JJ)J", MATHBOOTSTRAP, programPoint);
|
||||
if (programPoint == INVALID_PROGRAM_POINT) {
|
||||
JSType.REM_ZERO_LONG.invoke(method);
|
||||
} else {
|
||||
method.visitInvokeDynamicInsn("lrem", "(JJ)J", MATHBOOTSTRAP, programPoint);
|
||||
}
|
||||
return LONG;
|
||||
}
|
||||
|
||||
|
||||
@ -150,6 +150,12 @@ public enum JSType {
|
||||
/** Div exact wrapper for potentially integer division that turns into float point */
|
||||
public static final Call DIV_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", int.class, int.class, int.class, int.class);
|
||||
|
||||
/** Div zero wrapper for integer division that handles (0/0)|0 == 0 */
|
||||
public static final Call DIV_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", int.class, int.class, int.class);
|
||||
|
||||
/** Mod zero wrapper for integer division that handles (0%0)|0 == 0 */
|
||||
public static final Call REM_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", int.class, int.class, int.class);
|
||||
|
||||
/** Mod exact wrapper for potentially integer remainders that turns into float point */
|
||||
public static final Call REM_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", int.class, int.class, int.class, int.class);
|
||||
|
||||
@ -174,6 +180,12 @@ public enum JSType {
|
||||
/** 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);
|
||||
|
||||
@ -1485,6 +1497,28 @@ public enum JSType {
|
||||
throw new UnwarrantedOptimismException((double)x / (double)y, programPoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements int division but allows {@code x / 0} to be represented as 0. Basically equivalent to
|
||||
* {@code (x / y)|0} JavaScript expression (division of two ints coerced to int).
|
||||
* @param x the dividend
|
||||
* @param y the divisor
|
||||
* @return the result
|
||||
*/
|
||||
public static int divZero(final int x, final int y) {
|
||||
return y == 0 ? 0 : x / y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements int remainder but allows {@code x % 0} to be represented as 0. Basically equivalent to
|
||||
* {@code (x % y)|0} JavaScript expression (remainder of two ints coerced to int).
|
||||
* @param x the dividend
|
||||
* @param y the divisor
|
||||
* @return the remainder
|
||||
*/
|
||||
public static int remZero(final int x, final int y) {
|
||||
return y == 0 ? 0 : x % y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int.
|
||||
*
|
||||
@ -1528,6 +1562,28 @@ public enum JSType {
|
||||
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.
|
||||
*
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user