Reviewers: danno, Vyacheslav Egorov, Jakob,

Description:
Canonicalize NaNs on store to Fast(Float|Double) arrays
Also treat holey NaN coming from external float/double arrays correctly


BUG=2596


Please review this at https://codereview.chromium.org/12918028/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/hydrogen-instructions.h
  M src/hydrogen-instructions.cc
  A + test/mjsunit/regress/regress-2596.js


Index: src/hydrogen-instructions.cc
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 9b96cfe7ca6a1dcd19ef7394a001c60e6863b84c..c3d5b9dc01c57316b5447d931550732cc75fd42e 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -2590,6 +2590,10 @@ bool HLoadKeyed::UsesMustHandleHole() const {
     return false;
   }

+  if (IsExternalArrayElementsKind(elements_kind())) {
+    return false;
+  }
+
   if (hole_mode() == ALLOW_RETURN_HOLE) return true;

   if (IsFastDoubleElementsKind(elements_kind())) {
@@ -3037,10 +3041,18 @@ bool HStoreKeyed::NeedsCanonicalization() {
// If value is an integer or smi or comes from the result of a keyed load or // constant then it is either be a non-hole value or in the case of a constant // the hole is only being stored explicitly: no need for canonicalization.
-  if (value()->IsLoadKeyed() || value()->IsConstant()) {
+  //
+ // The exception to that is keyed loads from external float or double arrays:
+  // these can load arbitrary representation of NaN
+
+  if (value()->IsConstant()) {
     return false;
   }

+  if (value()->IsLoadKeyed()) {
+    return HLoadKeyed::cast(value())->can_load_hole_nan();
+  }
+
   if (value()->IsChange()) {
     if (HChange::cast(value())->from().IsInteger32()) {
       return false;
Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index f741f292e8b1f0bf87591fc2c9dafb9e12c5bb78..0c564f091624e27226d708bb1392e9f4699d9aa6 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -5382,6 +5382,12 @@ class HLoadKeyed
   bool is_external() const {
     return IsExternalArrayElementsKind(elements_kind());
   }
+
+  bool can_load_hole_nan() const {
+    return elements_kind() == EXTERNAL_FLOAT_ELEMENTS
+      || elements_kind() == EXTERNAL_DOUBLE_ELEMENTS;
+  }
+
   HValue* elements() { return OperandAt(0); }
   HValue* key() { return OperandAt(1); }
   HValue* dependency() {
Index: test/mjsunit/regress/regress-2596.js
diff --git a/test/mjsunit/compiler/regress-const.js b/test/mjsunit/regress/regress-2596.js
similarity index 73%
copy from test/mjsunit/compiler/regress-const.js
copy to test/mjsunit/regress/regress-2596.js
index aa55d0fd3ae17051a084a6bf28c2257f2abc8495..201b88ac99b31330b19951c58357ef6fa5432214 100644
--- a/test/mjsunit/compiler/regress-const.js
+++ b/test/mjsunit/regress/regress-2596.js
@@ -27,42 +27,30 @@

 // Flags: --allow-natives-syntax

-// Test const initialization and assignments.
-function f() {
-  var x = 42;
-  while (true) {
-    const y = x;
-    if (--x == 0) return y;
-  }
+var bytes = new Uint8Array([
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]);  // kHoleNaN
+var doubles = new Float64Array(bytes.buffer);
+assertTrue(isNaN(doubles[0]));
+
+var prototype = [2.5, 2.5];
+var array = [3.5, 3.5];
+array.__proto__ = prototype;
+assertTrue(%HasFastDoubleElements(array));
+
+function boom(index) {
+  array[index] = doubles[0];
+  return array[index];
 }

-function g() {
-  const x = 42;
-  x += 1;
-  return x;
-}
-
-for (var i = 0; i < 5; i++) {
-  f();
-  g();
-}
-
-%OptimizeFunctionOnNextCall(f);
-%OptimizeFunctionOnNextCall(g);
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));

-assertEquals(42, f());
-assertEquals(42, g());
-
-
-function h(a, b) {
-  var r = a + b;
-  const X = 42;
-  return r + X;
-}
+// Test hydrogen
+%OptimizeFunctionOnNextCall(boom);
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));

-for (var i = 0; i < 5; i++) h(1,2);

-%OptimizeFunctionOnNextCall(h);

-assertEquals(45, h(1,2));
-assertEquals("foo742", h("foo", 7));


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to