Canonicalize NaNs on store to Fast(Float|Double) arrays
authordslomov@chromium.org <dslomov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 28 Mar 2013 13:30:16 +0000 (13:30 +0000)
committerdslomov@chromium.org <dslomov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 28 Mar 2013 13:30:16 +0000 (13:30 +0000)
Also treat holey NaN coming from external float/double arrays correctly

BUG=2596

Review URL: https://codereview.chromium.org/12918028

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

src/elements-kind.h
src/hydrogen-instructions.cc
test/mjsunit/regress/regress-2596.js [new file with mode: 0644]

index cb3bb9c..da15192 100644 (file)
@@ -110,10 +110,15 @@ inline bool IsFastDoubleElementsKind(ElementsKind kind) {
 }
 
 
+inline bool IsExternalFloatOrDoubleElementsKind(ElementsKind kind) {
+  return kind == EXTERNAL_DOUBLE_ELEMENTS ||
+      kind == EXTERNAL_FLOAT_ELEMENTS;
+}
+
+
 inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
   return IsFastDoubleElementsKind(kind) ||
-      kind == EXTERNAL_DOUBLE_ELEMENTS ||
-      kind == EXTERNAL_FLOAT_ELEMENTS;
+      IsExternalFloatOrDoubleElementsKind(kind);
 }
 
 
index 9b96cfe..8e0d89e 100644 (file)
@@ -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())) {
@@ -2612,6 +2616,10 @@ bool HLoadKeyed::RequiresHoleCheck() const {
     return false;
   }
 
+  if (IsExternalArrayElementsKind(elements_kind())) {
+    return false;
+  }
+
   return !UsesMustHandleHole();
 }
 
@@ -3037,10 +3045,19 @@ 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 IsExternalFloatOrDoubleElementsKind(
+        HLoadKeyed::cast(value())->elements_kind());
+  }
+
   if (value()->IsChange()) {
     if (HChange::cast(value())->from().IsInteger32()) {
       return false;
diff --git a/test/mjsunit/regress/regress-2596.js b/test/mjsunit/regress/regress-2596.js
new file mode 100644 (file)
index 0000000..1d327fe
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2013 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:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+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];
+}
+
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));
+
+// Test hydrogen
+%OptimizeFunctionOnNextCall(boom);
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));
+assertTrue(isNaN(boom(0)));
+
+
+