Bug 1311088 - Part 2: Add JS::IsCanonicalized and remove JS::Value::setDoubleNoCheck. r=jwalden
authorTooru Fujisawa <arai_a@mac.com>
Sat, 29 Oct 2016 01:47:31 +0900
changeset 346658 9581faa40dcaf5b090e12d581efc08deb839c8cd
parent 346657 c8357a5b2431329993612ecd1095bff70f1d1911
child 346659 c2b8b8480075a26f7caeb6d2f4d49779a9632aa7
push id10298
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:33:03 +0000
treeherdermozilla-aurora@7e29173b1641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1311088
milestone52.0a1
Bug 1311088 - Part 2: Add JS::IsCanonicalized and remove JS::Value::setDoubleNoCheck. r=jwalden
js/public/Value.h
js/src/vm/StructuredClone.cpp
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* JS::Value implementation. */
 
 #ifndef js_Value_h
 #define js_Value_h
 
 #include "mozilla/Attributes.h"
+#include "mozilla/Casting.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/Likely.h"
 
 #include <limits> /* for std::numeric_limits */
 
 #include "js-config.h"
 #include "jstypes.h"
 
@@ -335,24 +336,20 @@ class MOZ_NON_PARAM alignas(8) Value
     }
 
     int32_t& getInt32Ref() {
         MOZ_ASSERT(isInt32());
         return data.s.payload.i32;
     }
 
     void setDouble(double d) {
-        setDoubleNoCheck(d);
-        MOZ_ASSERT(isDouble());
-    }
-
-    void setDoubleNoCheck(double d) {
         // Don't assign to data.asDouble to fix a miscompilation with
         // GCC 5.2.1 and 5.3.1. See bug 1312488.
         data = layout(d);
+        MOZ_ASSERT(isDouble());
     }
 
     void setNaN() {
         setDouble(GenericNaN());
     }
 
     double& getDoubleRef() {
         MOZ_ASSERT(isDouble());
@@ -1020,16 +1017,27 @@ DoubleValue(double dbl)
 static inline Value
 CanonicalizedDoubleValue(double d)
 {
     return MOZ_UNLIKELY(mozilla::IsNaN(d))
            ? Value::fromRawBits(detail::CanonicalizedNaNBits)
            : Value::fromDouble(d);
 }
 
+static inline bool
+IsCanonicalized(double d)
+{
+  if (mozilla::IsInfinite(d) || mozilla::IsFinite(d))
+      return true;
+
+  uint64_t bits;
+  mozilla::BitwiseCast<uint64_t>(d, &bits);
+  return (bits & ~mozilla::DoubleTypeTraits::kSignBit) == detail::CanonicalizedNaNBits;
+}
+
 static inline Value
 DoubleNaNValue()
 {
     Value v;
     v.setNaN();
     return v;
 }
 
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -1612,19 +1612,17 @@ JSStructuredCloneWriter::write(HandleVal
 
     memory.clear();
     return transferOwnership();
 }
 
 bool
 JSStructuredCloneReader::checkDouble(double d)
 {
-    JS::Value v;
-    v.setDoubleNoCheck(d);
-    if (!v.isDouble()) {
+    if (!JS::IsCanonicalized(d)) {
         JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA,
                                   "unrecognized NaN");
         return false;
     }
     return true;
 }
 
 namespace {