// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_UTILS_BOXED_FLOAT_H_ #define V8_UTILS_BOXED_FLOAT_H_ #include #include "src/base/macros.h" #include "src/common/globals.h" namespace v8 { namespace internal { // TODO(ahaas): Make these classes with the one in double.h // Safety wrapper for a 32-bit floating-point value to make sure we don't lose // the exact bit pattern during deoptimization when passing this value. class Float32 { public: Float32() = default; // This constructor does not guarantee that bit pattern of the input value // is preserved if the input is a NaN. explicit Float32(float value) : bit_pattern_(bit_cast(value)) { // Check that the provided value is not a NaN, because the bit pattern of a // NaN may be changed by a bit_cast, e.g. for signalling NaNs on ia32. DCHECK(!std::isnan(value)); } uint32_t get_bits() const { return bit_pattern_; } float get_scalar() const { return bit_cast(bit_pattern_); } bool is_nan() const { // Even though {get_scalar()} might flip the quiet NaN bit, it's ok here, // because this does not change the is_nan property. return std::isnan(get_scalar()); } // Return a pointer to the field storing the bit pattern. Used in code // generation tests to store generated values there directly. uint32_t* get_bits_address() { return &bit_pattern_; } static constexpr Float32 FromBits(uint32_t bits) { return Float32(bits); } private: uint32_t bit_pattern_ = 0; explicit constexpr Float32(uint32_t bit_pattern) : bit_pattern_(bit_pattern) {} }; ASSERT_TRIVIALLY_COPYABLE(Float32); // Safety wrapper for a 64-bit floating-point value to make sure we don't lose // the exact bit pattern during deoptimization when passing this value. // TODO(ahaas): Unify this class with Double in double.h class Float64 { public: Float64() = default; // This constructor does not guarantee that bit pattern of the input value // is preserved if the input is a NaN. explicit Float64(double value) : bit_pattern_(bit_cast(value)) { // Check that the provided value is not a NaN, because the bit pattern of a // NaN may be changed by a bit_cast, e.g. for signalling NaNs on ia32. DCHECK(!std::isnan(value)); } uint64_t get_bits() const { return bit_pattern_; } double get_scalar() const { return bit_cast(bit_pattern_); } bool is_hole_nan() const { return bit_pattern_ == kHoleNanInt64; } bool is_nan() const { // Even though {get_scalar()} might flip the quiet NaN bit, it's ok here, // because this does not change the is_nan property. return std::isnan(get_scalar()); } // Return a pointer to the field storing the bit pattern. Used in code // generation tests to store generated values there directly. uint64_t* get_bits_address() { return &bit_pattern_; } static constexpr Float64 FromBits(uint64_t bits) { return Float64(bits); } private: uint64_t bit_pattern_ = 0; explicit constexpr Float64(uint64_t bit_pattern) : bit_pattern_(bit_pattern) {} }; ASSERT_TRIVIALLY_COPYABLE(Float64); } // namespace internal } // namespace v8 #endif // V8_UTILS_BOXED_FLOAT_H_