Make static evaluation of java arithmethic JS compliant.
JavaScript always performs floating point operations in 64-bit
precision IEEE-754. Whereas Java has two floating point types.
The float type has a precision that nominally corresponds to
32-bit precision IEEE-754, and the double type to 64-bit
precision IEEE-754. On top Java can do most float operaions
in a precision that is at least the one required unless (strictfp
is specified).
This patch makes sure that static evaluation optimizations are
always performed in JavaScript semantics.
Bug: issue 8909.
Change-Id: I32f68009d689acf842674b932ed1f511763e337a
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JFloatLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JFloatLiteral.java
index 197ea05..05ef771 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JFloatLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JFloatLiteral.java
@@ -23,10 +23,10 @@
*/
public class JFloatLiteral extends JValueLiteral {
- public static final JFloatLiteral ZERO = new JFloatLiteral(SourceOrigin.UNKNOWN, Float
- .intBitsToFloat(0));
+ public static final JFloatLiteral ZERO = new JFloatLiteral(SourceOrigin.UNKNOWN, Double
+ .longBitsToDouble(0));
- public static JFloatLiteral get(float value) {
+ public static JFloatLiteral get(double value) {
return isZero(value) ? ZERO : new JFloatLiteral(SourceOrigin.UNKNOWN, value);
}
@@ -34,13 +34,13 @@
* Does this value match the exact 0 bit pattern? (This precludes
* canonicalizing -0.0 as 0.0).
*/
- private static boolean isZero(float value) {
- return Float.floatToRawIntBits(value) == 0;
+ private static boolean isZero(double value) {
+ return Double.doubleToRawLongBits(value) == 0L;
}
- private final float value;
+ private final double value;
- public JFloatLiteral(SourceInfo sourceInfo, float value) {
+ public JFloatLiteral(SourceInfo sourceInfo, double value) {
super(sourceInfo);
this.value = value;
}
@@ -50,13 +50,13 @@
return JPrimitiveType.FLOAT;
}
- public float getValue() {
+ public double getValue() {
return value;
}
@Override
public Object getValueObj() {
- return new Float(value);
+ return new Double(value);
}
@Override
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
index 1c81594..a013234 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -782,7 +782,7 @@
return JDoubleLiteral.get(d);
}
- public JFloatLiteral getLiteralFloat(float f) {
+ public JFloatLiteral getLiteralFloat(double f) {
return JFloatLiteral.get(f);
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
index 9180b42..2b5afe5 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
@@ -37,6 +37,7 @@
import com.google.gwt.dev.jjs.ast.JExpressionStatement;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JFieldRef;
+import com.google.gwt.dev.jjs.ast.JFloatLiteral;
import com.google.gwt.dev.jjs.ast.JForStatement;
import com.google.gwt.dev.jjs.ast.JIfStatement;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
@@ -66,6 +67,7 @@
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.JWhileStatement;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
+import com.google.gwt.dev.util.Ieee754_64_Arithmetic;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
@@ -793,11 +795,8 @@
if (isTypeBoolean(lhs)) {
return toBoolean(lhs) == toBoolean(rhs);
}
- if (isTypeDouble(lhs) || isTypeDouble(rhs)) {
- return toDouble(lhs) == toDouble(rhs);
- }
- if (isTypeFloat(lhs) || isTypeFloat(rhs)) {
- return toFloat(lhs) == toFloat(rhs);
+ if (isTypeFloatingPoint(lhs) || isTypeFloatingPoint(rhs)) {
+ return Ieee754_64_Arithmetic.eq(toDouble(lhs), toDouble(rhs));
}
if (isTypeLong(lhs) || isTypeLong(rhs)) {
return toLong(lhs) == toLong(rhs);
@@ -833,11 +832,11 @@
return true;
}
if (isTypeDouble(exp)) {
- ctx.replaceMe(program.getLiteralDouble(-toDouble(exp)));
+ ctx.replaceMe(program.getLiteralDouble(Ieee754_64_Arithmetic.neg(toDouble(exp))));
return true;
}
if (isTypeFloat(exp)) {
- ctx.replaceMe(program.getLiteralFloat(-toFloat(exp)));
+ ctx.replaceMe(program.getLiteralFloat(Ieee754_64_Arithmetic.neg(toDouble(exp))));
return true;
}
return false;
@@ -876,26 +875,26 @@
case MUL:
case DIV:
case MOD: {
- if (isTypeFloatOrDouble(lhs) || isTypeFloatOrDouble(rhs)) {
+ if (isTypeFloatingPoint(lhs) || isTypeFloatingPoint(rhs)) {
// do the op on doubles and cast back
double left = toDouble(lhs);
double right = toDouble(rhs);
double res;
switch (op) {
case ADD:
- res = left + right;
+ res = Ieee754_64_Arithmetic.add(left, right);
break;
case SUB:
- res = left - right;
+ res = Ieee754_64_Arithmetic.subtract(left, right);
break;
case MUL:
- res = left * right;
+ res = Ieee754_64_Arithmetic.multiply(left, right);
break;
case DIV:
- res = left / right;
+ res = Ieee754_64_Arithmetic.divide(left, right);
break;
case MOD:
- res = left % right;
+ res = Ieee754_64_Arithmetic.mod(left, right);
break;
default:
assert false;
@@ -904,7 +903,7 @@
if (isTypeDouble(lhs) || isTypeDouble(rhs)) {
ctx.replaceMe(program.getLiteralDouble(res));
} else {
- ctx.replaceMe(program.getLiteralFloat((float) res));
+ ctx.replaceMe(program.getLiteralFloat(res));
}
return true;
} else if (isTypeIntegral(lhs) && isTypeIntegral(rhs)) {
@@ -955,23 +954,23 @@
case LTE:
case GT:
case GTE: {
- if (isTypeFloatOrDouble(lhs) || isTypeFloatOrDouble(lhs)) {
+ if (isTypeFloatingPoint(lhs) || isTypeFloatingPoint(lhs)) {
// operate on doubles
double left = toDouble(lhs);
double right = toDouble(rhs);
boolean res;
switch (op) {
case LT:
- res = left < right;
+ res = Ieee754_64_Arithmetic.lt(left, right);
break;
case LTE:
- res = left <= right;
+ res = Ieee754_64_Arithmetic.le(left, right);
break;
case GT:
- res = left > right;
+ res = Ieee754_64_Arithmetic.gt(left, right);
break;
case GTE:
- res = left >= right;
+ res = Ieee754_64_Arithmetic.ge(left, right);
break;
default:
assert false;
@@ -1209,37 +1208,28 @@
}
private boolean isLiteralNegativeOne(JExpression exp) {
- if (exp instanceof JValueLiteral) {
- JValueLiteral lit = (JValueLiteral) exp;
- if (isTypeIntegral(lit)) {
- if (toLong(lit) == -1) {
- return true;
- }
- }
- if (isTypeFloatOrDouble(lit)) {
- if (toDouble(lit) == -1.0) {
- return true;
- }
- }
+ if (!(exp instanceof JValueLiteral)) {
+ return false;
+ }
+ JValueLiteral lit = (JValueLiteral) exp;
+ if (isTypeIntegral(lit) && toLong(lit) == -1) {
+ return true;
+ }
+ if (isTypeFloatingPoint(lit) && toDouble(lit) == -1.0) {
+ return true;
}
return false;
}
private boolean isLiteralOne(JExpression exp) {
- if (exp instanceof JValueLiteral) {
- JValueLiteral lit = (JValueLiteral) exp;
- if (isTypeIntegral(lit)) {
- if (toLong(lit) == 1) {
- return true;
- }
- }
- if (isTypeFloatOrDouble(lit)) {
- if (toDouble(lit) == 1.0) {
- return true;
- }
- }
+ if (!(exp instanceof JValueLiteral)) {
+ return false;
}
- return false;
+ JValueLiteral lit = (JValueLiteral) exp;
+ if (isTypeIntegral(lit) && toLong(lit) == 1) {
+ return true;
+ }
+ return isTypeFloatingPoint(lit) && toDouble(lit) == 1.0;
}
private boolean isLiteralZero(JExpression exp) {
@@ -1278,11 +1268,11 @@
/**
* Return whether the type of the expression is float or double.
*/
- private boolean isTypeFloatOrDouble(JExpression exp) {
- return isTypeFloatOrDouble(exp.getType());
+ private boolean isTypeFloatingPoint(JExpression exp) {
+ return isTypeFloatingPoint(exp.getType());
}
- private boolean isTypeFloatOrDouble(JType type) {
+ private boolean isTypeFloatingPoint(JType type) {
return ((type == program.getTypePrimitiveDouble()) || (type == program
.getTypePrimitiveFloat()));
}
@@ -1632,7 +1622,7 @@
ctx.replaceMe(Simplifier.cast(type, lhs));
return true;
}
- if (isLiteralZero(lhs) && !isTypeFloatOrDouble(type)) {
+ if (isLiteralZero(lhs) && !isTypeFloatingPoint(type)) {
ctx.replaceMe(simplifyNegate(Simplifier.cast(type, rhs)));
return true;
}
@@ -1683,10 +1673,6 @@
}
}
- private float toFloat(JValueLiteral x) {
- return (float) toDouble(x);
- }
-
/**
* Cast a Java wrapper class (Integer, Double, Float, etc.) to a long.
*/
@@ -1897,12 +1883,12 @@
if (type == char.class && maybeLit instanceof JCharLiteral) {
return Character.valueOf(((JCharLiteral) maybeLit).getValue());
}
+ if (type == double.class && maybeLit instanceof JFloatLiteral) {
+ return new Double(((JFloatLiteral) maybeLit).getValue());
+ }
if (type == double.class && maybeLit instanceof JDoubleLiteral) {
return new Double(((JDoubleLiteral) maybeLit).getValue());
}
- if (type == float.class && maybeLit instanceof JIntLiteral) {
- return new Float(((JIntLiteral) maybeLit).getValue());
- }
if (type == int.class && maybeLit instanceof JIntLiteral) {
return Integer.valueOf(((JIntLiteral) maybeLit).getValue());
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
index d761f21..65b0040 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
@@ -462,7 +462,7 @@
@Override
public boolean visit(JFloatLiteral x, Context ctx) {
- printFloatLiteral(x.getValue());
+ printDoubleLiteral(x.getValue());
return false;
}
@@ -1043,11 +1043,6 @@
}
}
- protected void printFloatLiteral(float value) {
- print(Float.toString(value));
- print('f');
- }
-
protected void printLongLiteral(long value) {
print(Long.toString(value));
print('L');
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/ConstantsAssumption.java b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/ConstantsAssumption.java
index a93e3c2..024dfc1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/ConstantsAssumption.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/constants/ConstantsAssumption.java
@@ -136,9 +136,9 @@
}
if (literal1 instanceof JFloatLiteral) {
- int bits1 = Float.floatToRawIntBits(
+ long bits1 = Double.doubleToRawLongBits(
((JFloatLiteral) literal1).getValue());
- int bits2 = Float.floatToRawIntBits(
+ long bits2 = Double.doubleToRawLongBits(
((JFloatLiteral) literal2).getValue());
return bits1 == bits2;
}
diff --git a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
index 87acfe0..1da3276 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsStaticEval.java
@@ -50,6 +50,7 @@
import com.google.gwt.dev.js.ast.JsVisitor;
import com.google.gwt.dev.js.ast.JsWhile;
import com.google.gwt.dev.js.rhino.ScriptRuntime;
+import com.google.gwt.dev.util.Ieee754_64_Arithmetic;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
@@ -182,19 +183,22 @@
trySimplifyEqAndRefEq(x, arg1, arg2, ctx);
} else if (op == JsBinaryOperator.NEQ || op == JsBinaryOperator.REF_NEQ) {
trySimplifyNeAndRefNe(x, arg1, arg2, ctx);
- } else if (op == JsBinaryOperator.ADD) {
- trySimplifyAdd(x, arg1, arg2, ctx);
- } else {
- switch (op) {
- case GT:
- case GTE:
- case LT:
- case LTE:
- trySimplifyCompare(x, arg1, arg2, op, ctx);
- break;
- default:
- break;
- }
+ } else if (arg1 instanceof JsValueLiteral && arg2 instanceof JsValueLiteral) {
+ switch (op) {
+ case ADD:
+ case SUB:
+ case MUL:
+ case DIV:
+ case MOD:
+ case GT:
+ case GTE:
+ case LT:
+ case LTE:
+ trySimplifyOp(x, arg1, arg2, op, ctx);
+ break;
+ default:
+ break;
+ }
}
}
@@ -565,37 +569,6 @@
}
}
- private JsExpression simplifyCompare(JsExpression original, JsExpression arg1,
- JsExpression arg2, JsBinaryOperator op) {
- assert (original != null);
-
- // TODO(cromwellian) handle all types
- if (arg1 instanceof JsNumberLiteral && arg2 instanceof JsNumberLiteral) {
- double num1 = ((JsNumberLiteral) arg1).getValue();
- double num2 = ((JsNumberLiteral) arg2).getValue();
- boolean result = false;
- switch(op) {
- case LT:
- result = num1 < num2;
- break;
- case LTE:
- result = num1 <= num2;
- break;
- case GT:
- result = num1 > num2;
- break;
- case GTE:
- result = num1 >= num2;
- break;
- default:
- throw new InternalCompilerException("Can't handle simplify of op " + op);
- }
- return JsBooleanLiteral.get(result);
- }
- // no simplification made
- return original;
- }
-
private JsExpression simplifyEqAndRefEq(JsExpression original, JsExpression arg1,
JsExpression arg2) {
assert (original != null);
@@ -653,25 +626,62 @@
}
/**
- * Simplify a + b.
+ * Simplify a op b.
*/
- private void trySimplifyAdd(JsExpression original, JsExpression arg1,
- JsExpression arg2, JsContext ctx) {
- if (arg1 instanceof JsValueLiteral && arg2 instanceof JsValueLiteral) {
- SourceInfo info = original.getSourceInfo();
- // case: number + number
- if (arg1 instanceof JsNumberLiteral && arg2 instanceof JsNumberLiteral) {
- double value = ((JsNumberLiteral) arg1).getValue()
- + ((JsNumberLiteral) arg2).getValue();
- ctx.replaceMe(new JsNumberLiteral(info, value));
- } else {
- // cases: number + string or string + number
- StringBuilder result = new StringBuilder();
- if (appendLiteral(result, (JsValueLiteral) arg1)
- && appendLiteral(result, (JsValueLiteral) arg2)) {
- ctx.replaceMe(new JsStringLiteral(info, result.toString()));
- }
+ private void trySimplifyOp(JsExpression original, JsExpression arg1, JsExpression arg2,
+ JsBinaryOperator op, JsContext ctx) {
+ SourceInfo info = original.getSourceInfo();
+
+ if (op == JsBinaryOperator.ADD &&
+ (arg1 instanceof JsStringLiteral || arg2 instanceof JsStringLiteral)) {
+ // cases: number + string or string + number
+ StringBuilder result = new StringBuilder();
+ if (appendLiteral(result, (JsValueLiteral) arg1)
+ && appendLiteral(result, (JsValueLiteral) arg2)) {
+ ctx.replaceMe(new JsStringLiteral(info, result.toString()));
}
+ return;
+ }
+
+ if (arg1 instanceof JsNumberLiteral && arg2 instanceof JsNumberLiteral) {
+ double num1 = ((JsNumberLiteral) arg1).getValue();
+ double num2 = ((JsNumberLiteral) arg2).getValue();
+ Object result;
+
+ switch (op) {
+ case ADD:
+ result = Ieee754_64_Arithmetic.add(num1, num2);
+ break;
+ case SUB:
+ result = Ieee754_64_Arithmetic.subtract(num1, num2);
+ break;
+ case MUL:
+ result = Ieee754_64_Arithmetic.multiply(num1, num2);
+ break;
+ case DIV:
+ result = Ieee754_64_Arithmetic.divide(num1, num2);
+ break;
+ case MOD:
+ result = Ieee754_64_Arithmetic.mod(num1, num2);
+ break;
+ case LT:
+ result = Ieee754_64_Arithmetic.lt(num1, num2);
+ break;
+ case LTE:
+ result = Ieee754_64_Arithmetic.le(num1, num2);
+ break;
+ case GT:
+ result = Ieee754_64_Arithmetic.gt(num1, num2);
+ break;
+ case GTE:
+ result = Ieee754_64_Arithmetic.ge(num1, num2);
+ break;
+ default:
+ throw new InternalCompilerException("Can't handle simplify of op " + op);
+ }
+ ctx.replaceMe(result instanceof Double ?
+ new JsNumberLiteral(info, ((Double) result).doubleValue()) :
+ JsBooleanLiteral.get(((Boolean) result).booleanValue()));
}
}
@@ -774,14 +784,6 @@
return toReturn;
}
- private void trySimplifyCompare(JsExpression original, JsExpression arg1,
- JsExpression arg2, JsBinaryOperator op, JsContext ctx) {
- JsExpression updated = simplifyCompare(original, arg1, arg2, op);
- if (updated != original) {
- ctx.replaceMe(updated);
- }
- }
-
private void trySimplifyEqAndRefEq(JsExpression original, JsExpression arg1,
JsExpression arg2, JsContext ctx) {
JsExpression updated = simplifyEqAndRefEq(original, arg1, arg2);
diff --git a/dev/core/src/com/google/gwt/dev/util/Ieee754_64_Arithmetic.java b/dev/core/src/com/google/gwt/dev/util/Ieee754_64_Arithmetic.java
new file mode 100644
index 0000000..05f79c5
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/util/Ieee754_64_Arithmetic.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.util;
+
+/**
+ * A class to perform arithmetic that is consistent with JavaScript.
+ */
+public strictfp class Ieee754_64_Arithmetic {
+
+ public static double add(double a, double b) {
+ return a + b;
+ }
+
+ public static double multiply(double a, double b) {
+ return a * b;
+ }
+
+ public static double divide(double a, double b) {
+ return a / b;
+ }
+
+ public static double subtract(double a, double b) {
+ return a - b;
+ }
+
+ public static double mod(double a, double b) {
+ return a % b;
+ }
+
+ public static boolean eq(double a, double b) {
+ return a == b;
+ }
+
+ public static boolean gt(double a, double b) {
+ return a > b;
+ }
+
+ public static boolean ge(double a, double b) {
+ return a >= b;
+ }
+
+ public static boolean le(double a, double b) {
+ return a <= b;
+ }
+
+ public static boolean lt(double a, double b) {
+ return a < b;
+ }
+
+ public static double neg(double a) {
+ return -a;
+ }
+ }
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/DeadCodeEliminationTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/DeadCodeEliminationTest.java
index 85bd45e..4502725 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/DeadCodeEliminationTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/DeadCodeEliminationTest.java
@@ -305,11 +305,18 @@
// Verify that float/double subtracts from zero aren't replaced, since they
// are needed for obscure IEEE754 functionality -- specifically, converting
// 0.0 - v into -v means the sign of the result is the opposite of the input
- // rathe than always being positive.
- optimize("float", "return 0.0F - f;").intoString("return 0.0f - EntryPoint.f;");
+ // rather than always being positive.
+ optimize("float", "return 0.0F - f;").intoString("return 0.0 - EntryPoint.f;");
optimize("double", "return 0.0 - d;").intoString("return 0.0 - EntryPoint.d;");
}
+ public void testFloatingPoint() throws Exception {
+ // Internally we represent float literals as double, so here we make sure that 1.1f is
+ // is printed as a double with the right precision.
+ optimize("float", "return 1.1f;").intoString("return " + String.format("%.16g", (double) 1.1f) +
+ ";");
+ }
+
public void testMultiExpression_RedundantClinitRemoval() throws Exception {
addSnippetClassDecl(
"static class A { "
diff --git a/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java b/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java
index ad8facc..bdad22d 100644
--- a/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java
+++ b/dev/core/test/com/google/gwt/dev/js/JsStaticEvalTest.java
@@ -45,7 +45,7 @@
assertEquals("a()&&b,c();", optimize("a() && b, c()"));
// Don't damage math expressions
- assertEquals("alert(seconds/(60*60));",
+ assertEquals("alert(seconds/3600);",
optimize("alert(seconds / (60 * 60))"));
assertEquals("alert(1-(1-foo));", optimize("alert(1 - (1 - foo))"));
diff --git a/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java b/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java
index 1fa7281..0932be7 100644
--- a/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java
@@ -25,6 +25,8 @@
import com.google.gwt.dev.jjs.test.overrides.package2.SomeSubSubClassInAnotherPackage;
import com.google.gwt.dev.jjs.test.overrides.package3.SomeInterface;
import com.google.gwt.dev.jjs.test.overrides.package3.SomePackageConfusedParent;
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
import com.google.gwt.junit.client.GWTTestCase;
import java.util.ArrayList;
@@ -258,6 +260,23 @@
regExp1.test(str), regExp2.test(str));
}-*/;
+ /**
+ * Test for issue 8909.
+ * <p>
+ * DevMode does not conform to JS arithmetic semantics and this method tests exactly that.
+ */
+ @DoNotRunWith(Platform.Devel)
+ public void testStaticEvaluationSematics() {
+ float num = getRoundedValue(1.005f);
+ assertEquals(1.00, num, 0.001);
+ }
+
+ private float getRoundedValue(float parameter) {
+ float local = parameter;
+ local = local * 100f;
+ return Math.round(local) / 100f;
+ }
+
private static void assertEqualContents(float[] expected, float[] actual) {
assertEquals("Array length mismatch", expected.length, actual.length);
diff --git a/user/test/com/google/gwt/validation/rebind/GwtSpecificValidatorCreatorTest.java b/user/test/com/google/gwt/validation/rebind/GwtSpecificValidatorCreatorTest.java
index aa9399b..ae62513 100644
--- a/user/test/com/google/gwt/validation/rebind/GwtSpecificValidatorCreatorTest.java
+++ b/user/test/com/google/gwt/validation/rebind/GwtSpecificValidatorCreatorTest.java
@@ -62,7 +62,9 @@
}
public void testAsLiteral_1_1f() {
- assertLiteral("1.1f", 1.1f);
+ // Internally we represent float literals as double, so here we make sure that 1.1f is
+ // is printed as a double with the right precision.
+ assertLiteral(String.format("%.16g", (double) 1.1f), 1.1f);
}
public void testAsLiteral_1L() {