Bug 1311088 - Part 1: Add mozilla::SpecificNaNBits and JS::detail::CanonicalizedNaNBits. r=jwalden
authorTooru Fujisawa <arai_a@mac.com>
Sat, 29 Oct 2016 01:47:30 +0900
changeset 346657 c8357a5b2431329993612ecd1095bff70f1d1911
parent 346656 83ab2e59b7b537e420ba8aab75544a287686476a
child 346658 9581faa40dcaf5b090e12d581efc08deb839c8cd
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 1: Add mozilla::SpecificNaNBits and JS::detail::CanonicalizedNaNBits. r=jwalden
js/public/Value.h
mfbt/FloatingPoint.h
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -219,26 +219,39 @@ typedef enum JSWhyMagic
     JS_WHY_MAGIC_COUNT
 } JSWhyMagic;
 
 namespace JS {
 
 static inline constexpr JS::Value UndefinedValue();
 static inline JS::Value PoisonedObjectValue(JSObject* obj);
 
+namespace detail {
+
+constexpr int CanonicalizedNaNSignBit = 0;
+constexpr uint64_t CanonicalizedNaNSignificand = 0x8000000000000ULL;
+
+constexpr uint64_t CanonicalizedNaNBits =
+    mozilla::SpecificNaNBits<double,
+                             detail::CanonicalizedNaNSignBit,
+                             detail::CanonicalizedNaNSignificand>::value;
+
+} // namespace detail
+
 /**
  * Returns a generic quiet NaN value, with all payload bits set to zero.
  *
  * Among other properties, this NaN's bit pattern conforms to JS::Value's
  * bit pattern restrictions.
  */
 static MOZ_ALWAYS_INLINE double
 GenericNaN()
 {
-  return mozilla::SpecificNaN<double>(0, 0x8000000000000ULL);
+  return mozilla::SpecificNaN<double>(detail::CanonicalizedNaNSignBit,
+                                      detail::CanonicalizedNaNSignificand);
 }
 
 /* MSVC with PGO miscompiles this function. */
 #if defined(_MSC_VER)
 # pragma optimize("g", off)
 #endif
 static inline double
 CanonicalizeNaN(double d)
@@ -999,21 +1012,21 @@ Int32Value(int32_t i32)
 static inline Value
 DoubleValue(double dbl)
 {
     Value v;
     v.setDouble(dbl);
     return v;
 }
 
-static inline constexpr Value
+static inline Value
 CanonicalizedDoubleValue(double d)
 {
     return MOZ_UNLIKELY(mozilla::IsNaN(d))
-           ? Value::fromRawBits(0x7FF8000000000000ULL)
+           ? Value::fromRawBits(detail::CanonicalizedNaNBits)
            : Value::fromDouble(d);
 }
 
 static inline Value
 DoubleNaNValue()
 {
     Value v;
     v.setNaN();
--- a/mfbt/FloatingPoint.h
+++ b/mfbt/FloatingPoint.h
@@ -251,16 +251,36 @@ NegativeInfinity()
   /*
    * Negative infinity has all exponent bits set, sign bit set to 1, and no
    * significand.
    */
   typedef FloatingPoint<T> Traits;
   return BitwiseCast<T>(Traits::kSignBit | Traits::kExponentBits);
 }
 
+/**
+ * Computes the bit pattern for a NaN with the specified sign bit and
+ * significand bits.
+ */
+template<typename T,
+         int SignBit,
+         typename FloatingPoint<T>::Bits Significand>
+struct SpecificNaNBits
+{
+  using Traits = FloatingPoint<T>;
+
+  static_assert(SignBit == 0 || SignBit == 1, "bad sign bit");
+  static_assert((Significand & ~Traits::kSignificandBits) == 0,
+                "significand must only have significand bits set");
+  static_assert(Significand & Traits::kSignificandBits,
+                "significand must be nonzero");
+
+  static constexpr typename Traits::Bits value =
+    (SignBit * Traits::kSignBit) | Traits::kExponentBits | Significand;
+};
 
 /**
  * Constructs a NaN value with the specified sign bit and significand bits.
  *
  * There is also a variant that returns the value directly.  In most cases, the
  * two variants should be identical.  However, in the specific case of x86
  * chips, the behavior differs: returning floating-point values directly is done
  * through the x87 stack, and x87 loads and stores turn signaling NaNs into