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);