• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_NUMBERS_CONVERSIONS_INL_H_
6 #define V8_NUMBERS_CONVERSIONS_INL_H_
7 
8 #include <float.h>   // Required for DBL_MAX and on Win32 for finite()
9 #include <limits.h>  // Required for INT_MAX etc.
10 #include <stdarg.h>
11 #include <cmath>
12 #include "src/common/globals.h"  // Required for V8_INFINITY
13 
14 // ----------------------------------------------------------------------------
15 // Extra POSIX/ANSI functions for Win32/MSVC.
16 
17 #include "src/base/bits.h"
18 #include "src/base/platform/platform.h"
19 #include "src/numbers/conversions.h"
20 #include "src/numbers/double.h"
21 #include "src/objects/heap-number-inl.h"
22 #include "src/objects/objects-inl.h"
23 
24 namespace v8 {
25 namespace internal {
26 
27 // The fast double-to-unsigned-int conversion routine does not guarantee
28 // rounding towards zero, or any reasonable value if the argument is larger
29 // than what fits in an unsigned 32-bit integer.
FastD2UI(double x)30 inline unsigned int FastD2UI(double x) {
31   // There is no unsigned version of lrint, so there is no fast path
32   // in this function as there is in FastD2I. Using lrint doesn't work
33   // for values of 2^31 and above.
34 
35   // Convert "small enough" doubles to uint32_t by fixing the 32
36   // least significant non-fractional bits in the low 32 bits of the
37   // double, and reading them from there.
38   const double k2Pow52 = 4503599627370496.0;
39   bool negative = x < 0;
40   if (negative) {
41     x = -x;
42   }
43   if (x < k2Pow52) {
44     x += k2Pow52;
45     uint32_t result;
46 #ifndef V8_TARGET_BIG_ENDIAN
47     void* mantissa_ptr = reinterpret_cast<void*>(&x);
48 #else
49     void* mantissa_ptr =
50         reinterpret_cast<void*>(reinterpret_cast<Address>(&x) + kInt32Size);
51 #endif
52     // Copy least significant 32 bits of mantissa.
53     memcpy(&result, mantissa_ptr, sizeof(result));
54     return negative ? ~result + 1 : result;
55   }
56   // Large number (outside uint32 range), Infinity or NaN.
57   return 0x80000000u;  // Return integer indefinite.
58 }
59 
DoubleToFloat32(double x)60 inline float DoubleToFloat32(double x) {
61   using limits = std::numeric_limits<float>;
62   if (x > limits::max()) {
63     // kRoundingThreshold is the maximum double that rounds down to
64     // the maximum representable float. Its mantissa bits are:
65     // 1111111111111111111111101111111111111111111111111111
66     // [<--- float range --->]
67     // Note the zero-bit right after the float mantissa range, which
68     // determines the rounding-down.
69     static const double kRoundingThreshold = 3.4028235677973362e+38;
70     if (x <= kRoundingThreshold) return limits::max();
71     return limits::infinity();
72   }
73   if (x < limits::lowest()) {
74     // Same as above, mirrored to negative numbers.
75     static const double kRoundingThreshold = -3.4028235677973362e+38;
76     if (x >= kRoundingThreshold) return limits::lowest();
77     return -limits::infinity();
78   }
79   return static_cast<float>(x);
80 }
81 
DoubleToInteger(double x)82 inline double DoubleToInteger(double x) {
83   if (std::isnan(x)) return 0;
84   if (!std::isfinite(x)) return x;
85   // ToInteger normalizes -0 to +0.
86   if (x == 0.0) return 0;
87   return (x >= 0) ? std::floor(x) : std::ceil(x);
88 }
89 
90 // Implements most of https://tc39.github.io/ecma262/#sec-toint32.
DoubleToInt32(double x)91 int32_t DoubleToInt32(double x) {
92   if ((std::isfinite(x)) && (x <= INT_MAX) && (x >= INT_MIN)) {
93     int32_t i = static_cast<int32_t>(x);
94     if (FastI2D(i) == x) return i;
95   }
96   Double d(x);
97   int exponent = d.Exponent();
98   uint64_t bits;
99   if (exponent < 0) {
100     if (exponent <= -Double::kSignificandSize) return 0;
101     bits = d.Significand() >> -exponent;
102   } else {
103     if (exponent > 31) return 0;
104     // Masking to a 32-bit value ensures that the result of the
105     // static_cast<int64_t> below is not the minimal int64_t value,
106     // which would overflow on multiplication with d.Sign().
107     bits = (d.Significand() << exponent) & 0xFFFFFFFFul;
108   }
109   return static_cast<int32_t>(d.Sign() * static_cast<int64_t>(bits));
110 }
111 
DoubleToSmiInteger(double value,int * smi_int_value)112 bool DoubleToSmiInteger(double value, int* smi_int_value) {
113   if (!IsSmiDouble(value)) return false;
114   *smi_int_value = FastD2I(value);
115   DCHECK(Smi::IsValid(*smi_int_value));
116   return true;
117 }
118 
IsSmiDouble(double value)119 bool IsSmiDouble(double value) {
120   return value >= Smi::kMinValue && value <= Smi::kMaxValue &&
121          !IsMinusZero(value) && value == FastI2D(FastD2I(value));
122 }
123 
IsInt32Double(double value)124 bool IsInt32Double(double value) {
125   return value >= kMinInt && value <= kMaxInt && !IsMinusZero(value) &&
126          value == FastI2D(FastD2I(value));
127 }
128 
IsUint32Double(double value)129 bool IsUint32Double(double value) {
130   return !IsMinusZero(value) && value >= 0 && value <= kMaxUInt32 &&
131          value == FastUI2D(FastD2UI(value));
132 }
133 
DoubleToUint32IfEqualToSelf(double value,uint32_t * uint32_value)134 bool DoubleToUint32IfEqualToSelf(double value, uint32_t* uint32_value) {
135   const double k2Pow52 = 4503599627370496.0;
136   const uint32_t kValidTopBits = 0x43300000;
137   const uint64_t kBottomBitMask = 0x0000'0000'FFFF'FFFF;
138 
139   // Add 2^52 to the double, to place valid uint32 values in the low-significant
140   // bits of the exponent, by effectively setting the (implicit) top bit of the
141   // significand. Note that this addition also normalises 0.0 and -0.0.
142   double shifted_value = value + k2Pow52;
143 
144   // At this point, a valid uint32 valued double will be represented as:
145   //
146   // sign = 0
147   // exponent = 52
148   // significand = 1. 00...00 <value>
149   //       implicit^          ^^^^^^^ 32 bits
150   //                  ^^^^^^^^^^^^^^^ 52 bits
151   //
152   // Therefore, we can first check the top 32 bits to make sure that the sign,
153   // exponent and remaining significand bits are valid, and only then check the
154   // value in the bottom 32 bits.
155 
156   uint64_t result = bit_cast<uint64_t>(shifted_value);
157   if ((result >> 32) == kValidTopBits) {
158     *uint32_value = result & kBottomBitMask;
159     return FastUI2D(result & kBottomBitMask) == value;
160   }
161   return false;
162 }
163 
164 int32_t NumberToInt32(Object number) {
165   if (number.IsSmi()) return Smi::ToInt(number);
166   return DoubleToInt32(number.Number());
167 }
168 
169 uint32_t NumberToUint32(Object number) {
170   if (number.IsSmi()) return Smi::ToInt(number);
171   return DoubleToUint32(number.Number());
172 }
173 
174 uint32_t PositiveNumberToUint32(Object number) {
175   if (number.IsSmi()) {
176     int value = Smi::ToInt(number);
177     if (value <= 0) return 0;
178     return value;
179   }
180   DCHECK(number.IsHeapNumber());
181   double value = number.Number();
182   // Catch all values smaller than 1 and use the double-negation trick for NANs.
183   if (!(value >= 1)) return 0;
184   uint32_t max = std::numeric_limits<uint32_t>::max();
185   if (value < max) return static_cast<uint32_t>(value);
186   return max;
187 }
188 
189 int64_t NumberToInt64(Object number) {
190   if (number.IsSmi()) return Smi::ToInt(number);
191   double d = number.Number();
192   if (std::isnan(d)) return 0;
193   if (d >= static_cast<double>(std::numeric_limits<int64_t>::max())) {
194     return std::numeric_limits<int64_t>::max();
195   }
196   if (d <= static_cast<double>(std::numeric_limits<int64_t>::min())) {
197     return std::numeric_limits<int64_t>::min();
198   }
199   return static_cast<int64_t>(d);
200 }
201 
202 uint64_t PositiveNumberToUint64(Object number) {
203   if (number.IsSmi()) {
204     int value = Smi::ToInt(number);
205     if (value <= 0) return 0;
206     return value;
207   }
208   DCHECK(number.IsHeapNumber());
209   double value = number.Number();
210   // Catch all values smaller than 1 and use the double-negation trick for NANs.
211   if (!(value >= 1)) return 0;
212   uint64_t max = std::numeric_limits<uint64_t>::max();
213   if (value < max) return static_cast<uint64_t>(value);
214   return max;
215 }
216 
217 bool TryNumberToSize(Object number, size_t* result) {
218   // Do not create handles in this function! Don't use SealHandleScope because
219   // the function can be used concurrently.
220   if (number.IsSmi()) {
221     int value = Smi::ToInt(number);
222     DCHECK(static_cast<unsigned>(Smi::kMaxValue) <=
223            std::numeric_limits<size_t>::max());
224     if (value >= 0) {
225       *result = static_cast<size_t>(value);
226       return true;
227     }
228     return false;
229   } else {
230     DCHECK(number.IsHeapNumber());
231     double value = HeapNumber::cast(number).value();
232     // If value is compared directly to the limit, the limit will be
233     // casted to a double and could end up as limit + 1,
234     // because a double might not have enough mantissa bits for it.
235     // So we might as well cast the limit first, and use < instead of <=.
236     double maxSize = static_cast<double>(std::numeric_limits<size_t>::max());
237     if (value >= 0 && value < maxSize) {
238       *result = static_cast<size_t>(value);
239       return true;
240     } else {
241       return false;
242     }
243   }
244 }
245 
NumberToSize(Object number)246 size_t NumberToSize(Object number) {
247   size_t result = 0;
248   bool is_valid = TryNumberToSize(number, &result);
249   CHECK(is_valid);
250   return result;
251 }
252 
DoubleToUint32(double x)253 uint32_t DoubleToUint32(double x) {
254   return static_cast<uint32_t>(DoubleToInt32(x));
255 }
256 
257 }  // namespace internal
258 }  // namespace v8
259 
260 #endif  // V8_NUMBERS_CONVERSIONS_INL_H_
261