1
0
mirror of https://github.com/roytam1/UXP.git synced 2026-05-26 13:58:49 +00:00

Issue #1240 - Part 3a - Adjust mozilla::FloatingPoint<T>'s definition. So only the barest details are specified for floating-point encodings, with every other number, bit mask, &c. mathematically derived. Also add a bunch of documentation comments. https://bugzilla.mozilla.org/show_bug.cgi?id=1508725 Prerequisite for our V8 fast forward.

This commit is contained in:
Brian Smith
2023-07-13 03:02:29 -05:00
committed by roytam1
parent 13ac0d6483
commit ddd49121a6
3 changed files with 77 additions and 37 deletions
+2 -2
View File
@@ -507,7 +507,7 @@ class MOZ_NON_PARAM alignas(8) Value
#if defined(JS_NUNBOX32)
return uint32_t(toTag()) <= uint32_t(JSVAL_TAG_CLEAR);
#elif defined(JS_PUNBOX64)
return (data.asBits | mozilla::DoubleTypeTraits::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
return (data.asBits | mozilla::FloatingPoint<double>::kSignBit) <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
#endif
}
@@ -1090,7 +1090,7 @@ IsCanonicalized(double d)
uint64_t bits;
mozilla::BitwiseCast<uint64_t>(d, &bits);
return (bits & ~mozilla::DoubleTypeTraits::kSignBit) == detail::CanonicalizedNaNBits;
return (bits & ~mozilla::FloatingPoint<double>::kSignBit) == detail::CanonicalizedNaNBits;
}
static inline Value
+1 -1
View File
@@ -54,7 +54,7 @@ template<class T>
bool
js::wasm::RenderNaN(StringBuffer& sb, Raw<T> num)
{
typedef typename mozilla::SelectTrait<T> Traits;
typedef typename mozilla::FloatingPoint<T> Traits;
MOZ_ASSERT(IsNaN(num.fp()));
+74 -34
View File
@@ -33,33 +33,38 @@ namespace mozilla {
* compiler bustage, particularly PGO-specific bustage.
*/
struct FloatTypeTraits
namespace detail {
/*
* These implementations assume float/double are 32/64-bit single/double
* format number types compatible with the IEEE-754 standard. C++ doesn't
* require this, but we required it in implementations of these algorithms that
* preceded this header, so we shouldn't break anything to continue doing so.
*/
template<typename T>
struct FloatingPointTrait;
template<>
struct FloatingPointTrait<float>
{
protected:
typedef uint32_t Bits;
static const unsigned kExponentBias = 127;
static const unsigned kExponentShift = 23;
static const Bits kSignBit = 0x80000000UL;
static const Bits kExponentBits = 0x7F800000UL;
static const Bits kSignificandBits = 0x007FFFFFUL;
static constexpr unsigned kExponentWidth = 8;
static constexpr unsigned kSignificandWidth = 23;
};
struct DoubleTypeTraits
template<>
struct FloatingPointTrait<double>
{
protected:
typedef uint64_t Bits;
static const unsigned kExponentBias = 1023;
static const unsigned kExponentShift = 52;
static const Bits kSignBit = 0x8000000000000000ULL;
static const Bits kExponentBits = 0x7ff0000000000000ULL;
static const Bits kSignificandBits = 0x000fffffffffffffULL;
static constexpr unsigned kExponentWidth = 11;
static constexpr unsigned kSignificandWidth = 52;
};
template<typename T> struct SelectTrait;
template<> struct SelectTrait<float> : public FloatTypeTraits {};
template<> struct SelectTrait<double> : public DoubleTypeTraits {};
} // namespace detail
/*
* This struct contains details regarding the encoding of floating-point
@@ -88,30 +93,65 @@ template<> struct SelectTrait<double> : public DoubleTypeTraits {};
* http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers
*/
template<typename T>
struct FloatingPoint : public SelectTrait<T>
struct FloatingPoint final : private detail::FloatingPointTrait<T>
{
typedef SelectTrait<T> Base;
typedef typename Base::Bits Bits;
private:
using Base = detail::FloatingPointTrait<T>;
static_assert((Base::kSignBit & Base::kExponentBits) == 0,
public:
/**
* An unsigned integral type suitable for accessing the bitwise representation
* of T.
*/
using Bits = typename Base::Bits;
static_assert(sizeof(T) == sizeof(Bits), "Bits must be same size as T");
/** The bit-width of the exponent component of T. */
using Base::kExponentWidth;
/** The bit-width of the significand component of T. */
using Base::kSignificandWidth;
static_assert(1 + kExponentWidth + kSignificandWidth ==
CHAR_BIT * sizeof(T),
"sign bit plus bit widths should sum to overall bit width");
/**
* The exponent field in an IEEE-754 floating point number consists of bits
* encoding an unsigned number. The *actual* represented exponent (for all
* values finite and not denormal) is that value, minus a bias |kExponentBias|
* so that a useful range of numbers is represented.
*/
static constexpr unsigned kExponentBias = (1U << (kExponentWidth - 1)) - 1;
/**
* The amount by which the bits of the exponent-field in an IEEE-754 floating
* point number are shifted from the LSB of the floating point type.
*/
static constexpr unsigned kExponentShift = kSignificandWidth;
/** The sign bit in the floating point representation. */
static constexpr Bits kSignBit =
static_cast<Bits>(1) << (CHAR_BIT * sizeof(Bits) - 1);
/** The exponent bits in the floating point representation. */
static constexpr Bits kExponentBits =
((static_cast<Bits>(1) << kExponentWidth) - 1) << kSignificandWidth;
/** The significand bits in the floating point representation. */
static constexpr Bits kSignificandBits =
(static_cast<Bits>(1) << kSignificandWidth) - 1;
static_assert((kSignBit & kExponentBits) == 0,
"sign bit shouldn't overlap exponent bits");
static_assert((Base::kSignBit & Base::kSignificandBits) == 0,
static_assert((kSignBit & kSignificandBits) == 0,
"sign bit shouldn't overlap significand bits");
static_assert((Base::kExponentBits & Base::kSignificandBits) == 0,
static_assert((kExponentBits & kSignificandBits) == 0,
"exponent bits shouldn't overlap significand bits");
static_assert((Base::kSignBit | Base::kExponentBits | Base::kSignificandBits) ==
~Bits(0),
static_assert((kSignBit | kExponentBits | kSignificandBits) == ~Bits(0),
"all bits accounted for");
/*
* These implementations assume float/double are 32/64-bit single/double
* format number types compatible with the IEEE-754 standard. C++ don't
* require this to be the case. But we required this in implementations of
* these algorithms that preceded this header, so we shouldn't break anything
* if we keep doing so.
*/
static_assert(sizeof(T) == sizeof(Bits), "Bits must be same size as T");
};
/** Determines whether a float/double is NaN. */