tighten invariants of HValue::InferRange
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 3 Aug 2011 10:44:20 +0000 (10:44 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 3 Aug 2011 10:44:20 +0000 (10:44 +0000)
* src/hydrogen-instructions.cc (HValue::InferRange): Only mark values
  with int32 representation as never being -0.  Always return a non-NULL
  value; callers should check for representation().IsNone() if that's
  their concern.

  In practice these invariants were not violated by callers, but they
  were sometimes two calls away, which seems brittle.

BUG=
TEST=tests pass, modulo http://code.google.com/p/v8/issues/detail?id=1572

Review URL: http://codereview.chromium.org/7514040
Patch from Andy Wingo <wingo@igalia.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8804 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/hydrogen-instructions.cc
test/mjsunit/math-floor.js
test/mjsunit/math-round.js

index 2be2a03..5bea55a 100644 (file)
@@ -862,19 +862,10 @@ void HInstanceOf::PrintDataTo(StringStream* stream) {
 
 
 Range* HValue::InferRange() {
-  if (representation().IsTagged()) {
-    // Tagged values are always in int32 range when converted to integer,
-    // but they can contain -0.
-    Range* result = new Range();
-    result->set_can_be_minus_zero(true);
-    return result;
-  } else if (representation().IsNone()) {
-    return NULL;
-  } else {
-    // Untagged integer32 cannot be -0 and we don't compute ranges for
-    // untagged doubles.
-    return new Range();
-  }
+  // Untagged integer32 cannot be -0, all other representations can.
+  Range* result = new Range();
+  result->set_can_be_minus_zero(!representation().IsInteger32());
+  return result;
 }
 
 
index 11f4cd7..c299203 100644 (file)
@@ -51,6 +51,17 @@ function test() {
   testFloor(-Infinity, -Infinity);
   testFloor(NaN, NaN);
 
+  // Ensure that a negative zero coming from Math.floor is properly handled
+  // by other operations.
+  function ifloor(x) {
+    return 1 / Math.floor(x);
+  }
+  assertEquals(-Infinity, ifloor(-0));
+  assertEquals(-Infinity, ifloor(-0));
+  assertEquals(-Infinity, ifloor(-0));
+  %OptimizeFunctionOnNextCall(ifloor);
+  assertEquals(-Infinity, ifloor(-0));
+
   testFloor(0, 0.1);
   testFloor(0, 0.49999999999999994);
   testFloor(0, 0.5);
@@ -129,3 +140,19 @@ function test() {
 for (var i = 0; i < 500; i++) {
   test();
 }
+
+
+// Regression test for a bug where a negative zero coming from Math.floor
+// was not properly handled by other operations.
+function floorsum(i, n) {
+  var ret = Math.floor(n);
+  while (--i > 0) {
+    ret += Math.floor(n);
+  }
+  return ret;
+}
+assertEquals(-0, floorsum(1, -0));
+%OptimizeFunctionOnNextCall(floorsum);
+// The optimized function will deopt.  Run it with enough iterations to try
+// to optimize via OSR (triggering the bug).
+assertEquals(-0, floorsum(100000, -0));
index 1366557..973040d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -44,6 +44,21 @@ testRound(Infinity, Infinity);
 testRound(-Infinity, -Infinity);
 testRound(NaN, NaN);
 
+// Regression test for a bug where a negative zero coming from Math.round
+// was not properly handled by other operations.
+function roundsum(i, n) {
+  var ret = Math.round(n);
+  while (--i > 0) {
+    ret += Math.round(n);
+  }
+  return ret;
+}
+assertEquals(-0, roundsum(1, -0));
+%OptimizeFunctionOnNextCall(roundsum);
+// The optimized function will deopt.  Run it with enough iterations to try
+// to optimize via OSR (triggering the bug).
+assertEquals(-0, roundsum(100000, -0));
+
 testRound(1, 0.5);
 testRound(1, 0.7);
 testRound(1, 1);