Fix abs breakage, the compiler was rewriting 0.0-x with -x, which
breaks the subtle code required to correctly emulate IEEE754
functionality.
Patch by: jat, rice (pair programmed)
Review by: spoon
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8320 8db76d5a-ed1c-0410-87a9-c151d255dfc7
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 a90b297..bfc7f3f 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
@@ -1485,7 +1485,7 @@
ctx.replaceMe(simplifier.cast(type, lhs));
return true;
}
- if (isLiteralZero(lhs)) {
+ if (isLiteralZero(lhs) && !isTypeFloatOrDouble(type)) {
ctx.replaceMe(simplifyNegate(simplifier.cast(type, rhs)));
return true;
}
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 3a6d819..7f3909e 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
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JProgram;
@@ -28,6 +29,8 @@
addSnippetClassDecl("static volatile boolean b1;");
addSnippetClassDecl("static volatile int i;");
addSnippetClassDecl("static volatile long l;");
+ addSnippetClassDecl("static volatile float f;");
+ addSnippetClassDecl("static volatile double d;");
}
public void testConditionalOptimizations() throws Exception {
@@ -105,6 +108,17 @@
"} while (false);");
}
+ public void testSubtractFromZero() throws Exception {
+ optimize("int", "return 0 - i;").intoString("return -EntryPoint.i;");
+ optimize("long", "return 0 - l;").intoString("return -EntryPoint.l;");
+ // 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;");
+ optimize("double", "return 0.0 - d;").intoString("return 0.0 - EntryPoint.d;");
+ }
+
@Override
protected boolean optimizeMethod(JProgram program, JMethod method) {
return DeadCodeElimination.exec(program, method);
diff --git a/user/super/com/google/gwt/emul/java/lang/Math.java b/user/super/com/google/gwt/emul/java/lang/Math.java
index a9e8c11..308b978 100644
--- a/user/super/com/google/gwt/emul/java/lang/Math.java
+++ b/user/super/com/google/gwt/emul/java/lang/Math.java
@@ -19,6 +19,21 @@
* Math utility methods and constants.
*/
public final class Math {
+ // The following methods are not implemented because JS doesn't provide the
+ // necessary pieces:
+ // public static double ulp (double x)
+ // public static float ulp (float x)
+ // public static int getExponent (double d)
+ // public static int getExponent (float f)
+ // public static double IEEEremainder(double f1, double f2)
+ // public static double nextAfter(double start, double direction)
+ // public static float nextAfter(float start, float direction)
+ // public static double nextUp(double start) {
+ // return nextAfter(start, 1.0d);
+ // }
+ // public static float nextUp(float start) {
+ // return nextAfter(start,1.0f);
+ // }
public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;
@@ -27,11 +42,14 @@
private static final double PI_UNDER_180 = 180.0 / PI;
public static double abs(double x) {
- return (x <= 0.0) ? 0.0 - x : x;
+ // This is implemented this way so that either positive or negative zeroes
+ // get converted to positive zeros.
+ // See http://www.concentric.net/~Ttwang/tech/javafloat.htm for details.
+ return x <= 0 ? 0.0 - x : x;
}
public static float abs(float x) {
- return (x <= 0.0F) ? 0.0F - x : x;
+ return (float) abs((double) x);
}
public static int abs(int x) {
@@ -107,22 +125,10 @@
return Math.floor(x);
}-*/;
- /* NYI: Java 1.5 includes this, but JS doesn't give us the ingredients.
- public static int getExponent (double d) {
- }
-
- public static int getExponent (float f) {
- }
- */
-
public static double hypot(double x, double y) {
return sqrt(x * x + y * y);
}
- /* NYI: Java 1.5 includes this, but JS doesn't give us the ingredients.
- public static double IEEEremainder(double f1, double f2) {
- } */
-
public static native double log(double x) /*-{
return Math.log(x);
}-*/;
@@ -167,19 +173,6 @@
return x < y ? x : y;
}
- /* NYI: Java 1.5 includes this, but JS doesn't give us the ingredients.
- public static double nextAfter(double start, double direction) {
- }
- public static float nextAfter(float start, float direction) {
- }
- public static double nextUp(double start) {
- return nextAfter(start, 1.0d);
- }
- public static float nextUp(float start) {
- return nextAfter(start,1.0f);
- }
- */
-
public static native double pow(double x, double exp) /*-{
return Math.pow(x, exp);
}-*/;
@@ -283,11 +276,4 @@
private static native double round0(double x) /*-{
return Math.round(x);
}-*/;
-
- /* NYI: Java 1.5 includes this, but JS doesn't give us the ingredients.
- public static double ulp (double x) {
- };
- public static float ulp (float x) {
- };
- */
}
diff --git a/user/test/com/google/gwt/emultest/java/lang/MathTest.java b/user/test/com/google/gwt/emultest/java/lang/MathTest.java
index 4d5b99d..2683e5e 100644
--- a/user/test/com/google/gwt/emultest/java/lang/MathTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/MathTest.java
@@ -25,6 +25,15 @@
*/
public class MathTest extends GWTTestCase {
+ private static native boolean isNegativeZero(double x) /*-{
+ var v = 1 / x;
+ return v == Number.NEGATIVE_INFINITY;
+ }-*/;
+
+ private static native double makeNegativeZero() /*-{
+ return 1 / Number.NEGATIVE_INFINITY;
+ }-*/;
+
@Override
public String getModuleName() {
return "com.google.gwt.emultest.EmulSuite";
@@ -32,11 +41,14 @@
public void testAbs() {
double v = Math.abs(-1.0);
+ double negativeZero = makeNegativeZero();
+ assertTrue(isNegativeZero(negativeZero));
assertEquals(1.0, v);
v = Math.abs(1.0);
assertEquals(1.0, v);
- v = Math.abs(-0.0);
+ v = Math.abs(negativeZero);
assertEquals(0.0, v);
+ assertFalse(isNegativeZero(v));
v = Math.abs(0.0);
assertEquals(0.0, v);
v = Math.abs(Double.NEGATIVE_INFINITY);