aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorattila <none@none>2014-11-03 07:28:08 +0100
committerattila <none@none>2014-11-03 07:28:08 +0100
commit1e1da3ac540bca042275d25c6c90eda74aeae858 (patch)
tree895507dc01f57638e2c7db99e6b5d2feaa4c0baf
parent1c6a99aee9c9cac3a2bab08193cc9e63488670b4 (diff)
downloadnashorn-1e1da3ac540bca042275d25c6c90eda74aeae858.tar.gz
8061957: Some arithmetic operations have unnecessary widening
Reviewed-by: hannesw, lagergren
-rw-r--r--src/jdk/nashorn/internal/codegen/CodeGenerator.java9
-rw-r--r--src/jdk/nashorn/internal/codegen/types/IntType.java19
-rw-r--r--src/jdk/nashorn/internal/codegen/types/LongType.java18
-rw-r--r--src/jdk/nashorn/internal/runtime/JSType.java56
4 files changed, 80 insertions, 22 deletions
diff --git a/src/jdk/nashorn/internal/codegen/CodeGenerator.java b/src/jdk/nashorn/internal/codegen/CodeGenerator.java
index f6b9001e..28b08098 100644
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java
+++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java
@@ -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(),
diff --git a/src/jdk/nashorn/internal/codegen/types/IntType.java b/src/jdk/nashorn/internal/codegen/types/IntType.java
index dfa77467..43b06806 100644
--- a/src/jdk/nashorn/internal/codegen/types/IntType.java
+++ b/src/jdk/nashorn/internal/codegen/types/IntType.java
@@ -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;
}
diff --git a/src/jdk/nashorn/internal/codegen/types/LongType.java b/src/jdk/nashorn/internal/codegen/types/LongType.java
index 7c3b2675..aa2ceb23 100644
--- a/src/jdk/nashorn/internal/codegen/types/LongType.java
+++ b/src/jdk/nashorn/internal/codegen/types/LongType.java
@@ -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;
}
diff --git a/src/jdk/nashorn/internal/runtime/JSType.java b/src/jdk/nashorn/internal/runtime/JSType.java
index 2b64ff34..75395ea4 100644
--- a/src/jdk/nashorn/internal/runtime/JSType.java
+++ b/src/jdk/nashorn/internal/runtime/JSType.java
@@ -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);
@@ -1486,6 +1498,28 @@ public enum JSType {
}
/**
+ * 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.
*
* @param x first term
@@ -1529,6 +1563,28 @@ public enum JSType {
}
/**
+ * 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