Line data Source code
1 : // Copyright 2012 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_UTILS_H_
6 : #define V8_UTILS_H_
7 :
8 : #include <limits.h>
9 : #include <stdlib.h>
10 : #include <string.h>
11 : #include <cmath>
12 : #include <string>
13 : #include <type_traits>
14 :
15 : #include "include/v8.h"
16 : #include "src/allocation.h"
17 : #include "src/base/bits.h"
18 : #include "src/base/compiler-specific.h"
19 : #include "src/base/logging.h"
20 : #include "src/base/macros.h"
21 : #include "src/base/platform/platform.h"
22 : #include "src/base/v8-fallthrough.h"
23 : #include "src/globals.h"
24 : #include "src/third_party/siphash/halfsiphash.h"
25 : #include "src/vector.h"
26 :
27 : #if defined(V8_OS_AIX)
28 : #include <fenv.h> // NOLINT(build/c++11)
29 : #endif
30 :
31 : namespace v8 {
32 : namespace internal {
33 :
34 : // ----------------------------------------------------------------------------
35 : // General helper functions
36 :
37 : // Returns the value (0 .. 15) of a hexadecimal character c.
38 : // If c is not a legal hexadecimal character, returns a value < 0.
39 : inline int HexValue(uc32 c) {
40 72467110 : c -= '0';
41 72467110 : if (static_cast<unsigned>(c) <= 9) return c;
42 8769035 : c = (c | 0x20) - ('a' - '0'); // detect 0x11..0x16 and 0x31..0x36.
43 8769035 : if (static_cast<unsigned>(c) <= 5) return c + 10;
44 : return -1;
45 : }
46 :
47 : inline char HexCharOfValue(int value) {
48 : DCHECK(0 <= value && value <= 16);
49 8202248 : if (value < 10) return value + '0';
50 533771 : return value - 10 + 'A';
51 : }
52 :
53 37025 : inline int BoolToInt(bool b) { return b ? 1 : 0; }
54 :
55 : // Same as strcmp, but can handle NULL arguments.
56 : inline bool CStringEquals(const char* s1, const char* s2) {
57 : return (s1 == s2) || (s1 != nullptr && s2 != nullptr && strcmp(s1, s2) == 0);
58 : }
59 :
60 : // Checks if value is in range [lower_limit, higher_limit] using a single
61 : // branch.
62 : template <typename T, typename U>
63 2322421606 : inline constexpr bool IsInRange(T value, U lower_limit, U higher_limit) {
64 : #if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
65 : DCHECK(lower_limit <= higher_limit);
66 : #endif
67 : STATIC_ASSERT(sizeof(U) <= sizeof(T));
68 : typedef typename std::make_unsigned<T>::type unsigned_T;
69 : // Use static_cast to support enum classes.
70 : return static_cast<unsigned_T>(static_cast<unsigned_T>(value) -
71 : static_cast<unsigned_T>(lower_limit)) <=
72 : static_cast<unsigned_T>(static_cast<unsigned_T>(higher_limit) -
73 8128169660 : static_cast<unsigned_T>(lower_limit));
74 : }
75 :
76 : // Checks if [index, index+length) is in range [0, max). Note that this check
77 : // works even if {index+length} would wrap around.
78 : inline constexpr bool IsInBounds(size_t index, size_t length, size_t max) {
79 7942805 : return length <= max && index <= (max - length);
80 : }
81 :
82 : // X must be a power of 2. Returns the number of trailing zeros.
83 : template <typename T,
84 : typename = typename std::enable_if<std::is_integral<T>::value>::type>
85 21437 : inline int WhichPowerOf2(T x) {
86 : DCHECK(base::bits::IsPowerOfTwo(x));
87 : int bits = 0;
88 : #ifdef DEBUG
89 : const T original_x = x;
90 : #endif
91 : constexpr int max_bits = sizeof(T) * 8;
92 : static_assert(max_bits <= 64, "integral types are not bigger than 64 bits");
93 : // Avoid shifting by more than the bit width of x to avoid compiler warnings.
94 : #define CHECK_BIGGER(s) \
95 : if (max_bits > s && x >= T{1} << (max_bits > s ? s : 0)) { \
96 : bits += s; \
97 : x >>= max_bits > s ? s : 0; \
98 : }
99 18618 : CHECK_BIGGER(32)
100 21437 : CHECK_BIGGER(16)
101 21437 : CHECK_BIGGER(8)
102 21437 : CHECK_BIGGER(4)
103 : #undef CHECK_BIGGER
104 21437 : switch (x) {
105 0 : default: UNREACHABLE();
106 : case 8:
107 8979 : bits++;
108 : V8_FALLTHROUGH;
109 : case 4:
110 9446 : bits++;
111 : V8_FALLTHROUGH;
112 : case 2:
113 13211 : bits++;
114 : V8_FALLTHROUGH;
115 : case 1: break;
116 : }
117 : DCHECK_EQ(T{1} << bits, original_x);
118 21437 : return bits;
119 : }
120 :
121 : inline int MostSignificantBit(uint32_t x) {
122 : static const int msb4[] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};
123 : int nibble = 0;
124 : if (x & 0xffff0000) {
125 : nibble += 16;
126 : x >>= 16;
127 : }
128 : if (x & 0xff00) {
129 : nibble += 8;
130 : x >>= 8;
131 : }
132 : if (x & 0xf0) {
133 : nibble += 4;
134 : x >>= 4;
135 : }
136 : return nibble + msb4[x];
137 : }
138 :
139 : template <typename T>
140 29940 : static T ArithmeticShiftRight(T x, int shift) {
141 : DCHECK_LE(0, shift);
142 30314 : if (x < 0) {
143 : // Right shift of signed values is implementation defined. Simulate a
144 : // true arithmetic right shift by adding leading sign bits.
145 : using UnsignedT = typename std::make_unsigned<T>::type;
146 6990 : UnsignedT mask = ~(static_cast<UnsignedT>(~0) >> shift);
147 6990 : return (static_cast<UnsignedT>(x) >> shift) | mask;
148 : } else {
149 23324 : return x >> shift;
150 : }
151 : }
152 :
153 : template <typename T>
154 : int Compare(const T& a, const T& b) {
155 3935 : if (a == b)
156 : return 0;
157 3935 : else if (a < b)
158 : return -1;
159 : else
160 : return 1;
161 : }
162 :
163 : // Compare function to compare the object pointer value of two
164 : // handlified objects. The handles are passed as pointers to the
165 : // handles.
166 : template<typename T> class Handle; // Forward declaration.
167 : template <typename T>
168 : int HandleObjectPointerCompare(const Handle<T>* a, const Handle<T>* b) {
169 : return Compare<T*>(*(*a), *(*b));
170 : }
171 :
172 : // Returns the maximum of the two parameters.
173 : template <typename T>
174 59685 : constexpr T Max(T a, T b) {
175 156335351 : return a < b ? b : a;
176 : }
177 :
178 :
179 : // Returns the minimum of the two parameters.
180 : template <typename T>
181 8435439 : constexpr T Min(T a, T b) {
182 306053792 : return a < b ? a : b;
183 : }
184 :
185 : // Returns the maximum of the two parameters according to JavaScript semantics.
186 : template <typename T>
187 543810 : T JSMax(T x, T y) {
188 543810 : if (std::isnan(x)) return x;
189 532205 : if (std::isnan(y)) return y;
190 1041770 : if (std::signbit(x) < std::signbit(y)) return x;
191 393265 : return x > y ? x : y;
192 : }
193 :
194 : // Returns the maximum of the two parameters according to JavaScript semantics.
195 : template <typename T>
196 543810 : T JSMin(T x, T y) {
197 543810 : if (std::isnan(x)) return x;
198 532205 : if (std::isnan(y)) return y;
199 1041770 : if (std::signbit(x) < std::signbit(y)) return y;
200 393265 : return x > y ? y : x;
201 : }
202 :
203 : // Returns the absolute value of its argument.
204 : template <typename T,
205 : typename = typename std::enable_if<std::is_signed<T>::value>::type>
206 : typename std::make_unsigned<T>::type Abs(T a) {
207 : // This is a branch-free implementation of the absolute value function and is
208 : // described in Warren's "Hacker's Delight", chapter 2. It avoids undefined
209 : // behavior with the arithmetic negation operation on signed values as well.
210 : typedef typename std::make_unsigned<T>::type unsignedT;
211 7490 : unsignedT x = static_cast<unsignedT>(a);
212 7490 : unsignedT y = static_cast<unsignedT>(a >> (sizeof(T) * 8 - 1));
213 7490 : return (x ^ y) - y;
214 : }
215 :
216 : // Returns the negative absolute value of its argument.
217 : template <typename T,
218 : typename = typename std::enable_if<std::is_signed<T>::value>::type>
219 : T Nabs(T a) {
220 : return a < 0 ? a : -a;
221 : }
222 :
223 : // Floor(-0.0) == 0.0
224 : inline double Floor(double x) {
225 : #if V8_CC_MSVC
226 : if (x == 0) return x; // Fix for issue 3477.
227 : #endif
228 144842 : return std::floor(x);
229 : }
230 :
231 : inline double Modulo(double x, double y) {
232 : #if defined(V8_OS_WIN)
233 : // Workaround MS fmod bugs. ECMA-262 says:
234 : // dividend is finite and divisor is an infinity => result equals dividend
235 : // dividend is a zero and divisor is nonzero finite => result equals dividend
236 : if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) &&
237 : !(x == 0 && (y != 0 && std::isfinite(y)))) {
238 : double result = fmod(x, y);
239 : // Workaround MS bug in VS CRT in some OS versions, https://crbug.com/915045
240 : // fmod(-17, +/-1) should equal -0.0 but now returns 0.0.
241 : if (x < 0 && result == 0) result = -0.0;
242 : x = result;
243 : }
244 : return x;
245 : #elif defined(V8_OS_AIX)
246 : // AIX raises an underflow exception for (Number.MIN_VALUE % Number.MAX_VALUE)
247 : feclearexcept(FE_ALL_EXCEPT);
248 : double result = std::fmod(x, y);
249 : int exception = fetestexcept(FE_UNDERFLOW);
250 : return (exception ? x : result);
251 : #else
252 729146 : return std::fmod(x, y);
253 : #endif
254 : }
255 :
256 65700 : inline double Pow(double x, double y) {
257 65700 : if (y == 0.0) return 1.0;
258 67318 : if (std::isnan(y) || ((x == 1 || x == -1) && std::isinf(y))) {
259 : return std::numeric_limits<double>::quiet_NaN();
260 : }
261 : #if (defined(__MINGW64_VERSION_MAJOR) && \
262 : (!defined(__MINGW64_VERSION_RC) || __MINGW64_VERSION_RC < 1)) || \
263 : defined(V8_OS_AIX)
264 : // MinGW64 and AIX have a custom implementation for pow. This handles certain
265 : // special cases that are different.
266 : if ((x == 0.0 || std::isinf(x)) && y != 0.0 && std::isfinite(y)) {
267 : double f;
268 : double result = ((x == 0.0) ^ (y > 0)) ? V8_INFINITY : 0;
269 : /* retain sign if odd integer exponent */
270 : return ((std::modf(y, &f) == 0.0) && (static_cast<int64_t>(y) & 1))
271 : ? copysign(result, x)
272 : : result;
273 : }
274 :
275 : if (x == 2.0) {
276 : int y_int = static_cast<int>(y);
277 : if (y == y_int) {
278 : return std::ldexp(1.0, y_int);
279 : }
280 : }
281 : #endif
282 63183 : return std::pow(x, y);
283 : }
284 :
285 : template <typename T>
286 11322 : T SaturateAdd(T a, T b) {
287 : if (std::is_signed<T>::value) {
288 11322 : if (a > 0 && b > 0) {
289 2694 : if (a > std::numeric_limits<T>::max() - b) {
290 : return std::numeric_limits<T>::max();
291 : }
292 8628 : } else if (a < 0 && b < 0) {
293 2037 : if (a < std::numeric_limits<T>::min() - b) {
294 : return std::numeric_limits<T>::min();
295 : }
296 : }
297 : } else {
298 : CHECK(std::is_unsigned<T>::value);
299 11313 : if (a > std::numeric_limits<T>::max() - b) {
300 : return std::numeric_limits<T>::max();
301 : }
302 : }
303 15424 : return a + b;
304 : }
305 :
306 : template <typename T>
307 11384 : T SaturateSub(T a, T b) {
308 : if (std::is_signed<T>::value) {
309 11384 : if (a >= 0 && b < 0) {
310 2724 : if (a > std::numeric_limits<T>::max() + b) {
311 : return std::numeric_limits<T>::max();
312 : }
313 8660 : } else if (a < 0 && b > 0) {
314 2225 : if (a < std::numeric_limits<T>::min() + b) {
315 : return std::numeric_limits<T>::min();
316 : }
317 : }
318 : } else {
319 : CHECK(std::is_unsigned<T>::value);
320 11313 : if (a < b) {
321 : return static_cast<T>(0);
322 : }
323 : }
324 15161 : return a - b;
325 : }
326 :
327 : // ----------------------------------------------------------------------------
328 : // BitField is a help template for encoding and decode bitfield with
329 : // unsigned content.
330 :
331 : template<class T, int shift, int size, class U>
332 : class BitFieldBase {
333 : public:
334 : typedef T FieldType;
335 :
336 : // A type U mask of bit field. To use all bits of a type U of x bits
337 : // in a bitfield without compiler warnings we have to compute 2^x
338 : // without using a shift count of x in the computation.
339 : static const U kOne = static_cast<U>(1U);
340 : static const U kMask = ((kOne << shift) << size) - (kOne << shift);
341 : static const U kShift = shift;
342 : static const U kSize = size;
343 : static const U kNext = kShift + kSize;
344 : static const U kNumValues = kOne << size;
345 :
346 : // Value for the field with all bits set.
347 : static const T kMax = static_cast<T>(kNumValues - 1);
348 :
349 : // Tells whether the provided value fits into the bit field.
350 : static constexpr bool is_valid(T value) {
351 79349809 : return (static_cast<U>(value) & ~static_cast<U>(kMax)) == 0;
352 : }
353 :
354 : // Returns a type U with the bit field value encoded.
355 : static constexpr U encode(T value) {
356 : #if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
357 : DCHECK(is_valid(value));
358 : #endif
359 5764608690 : return static_cast<U>(value) << shift;
360 : }
361 :
362 : // Returns a type U with the bit field value updated.
363 : static constexpr U update(U previous, T value) {
364 6739070263 : return (previous & ~kMask) | encode(value);
365 : }
366 :
367 : // Extracts the bit field from the value.
368 27026799 : static constexpr T decode(U value) {
369 45142244661 : return static_cast<T>((value & kMask) >> shift);
370 : }
371 :
372 : STATIC_ASSERT((kNext - 1) / 8 < sizeof(U));
373 : };
374 :
375 : template <class T, int shift, int size>
376 : class BitField8 : public BitFieldBase<T, shift, size, uint8_t> {};
377 :
378 :
379 : template <class T, int shift, int size>
380 : class BitField16 : public BitFieldBase<T, shift, size, uint16_t> {};
381 :
382 :
383 : template<class T, int shift, int size>
384 : class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
385 :
386 :
387 : template<class T, int shift, int size>
388 : class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
389 :
390 : // Helper macros for defining a contiguous sequence of bit fields. Example:
391 : // (backslashes at the ends of respective lines of this multi-line macro
392 : // definition are omitted here to please the compiler)
393 : //
394 : // #define MAP_BIT_FIELD1(V, _)
395 : // V(IsAbcBit, bool, 1, _)
396 : // V(IsBcdBit, bool, 1, _)
397 : // V(CdeBits, int, 5, _)
398 : // V(DefBits, MutableMode, 1, _)
399 : //
400 : // DEFINE_BIT_FIELDS(MAP_BIT_FIELD1)
401 : // or
402 : // DEFINE_BIT_FIELDS_64(MAP_BIT_FIELD1)
403 : //
404 : #define DEFINE_BIT_FIELD_RANGE_TYPE(Name, Type, Size, _) \
405 : k##Name##Start, k##Name##End = k##Name##Start + Size - 1,
406 :
407 : #define DEFINE_BIT_RANGES(LIST_MACRO) \
408 : struct LIST_MACRO##_Ranges { \
409 : enum { LIST_MACRO(DEFINE_BIT_FIELD_RANGE_TYPE, _) kBitsCount }; \
410 : };
411 :
412 : #define DEFINE_BIT_FIELD_TYPE(Name, Type, Size, RangesName) \
413 : typedef BitField<Type, RangesName::k##Name##Start, Size> Name;
414 :
415 : #define DEFINE_BIT_FIELD_64_TYPE(Name, Type, Size, RangesName) \
416 : typedef BitField64<Type, RangesName::k##Name##Start, Size> Name;
417 :
418 : #define DEFINE_BIT_FIELDS(LIST_MACRO) \
419 : DEFINE_BIT_RANGES(LIST_MACRO) \
420 : LIST_MACRO(DEFINE_BIT_FIELD_TYPE, LIST_MACRO##_Ranges)
421 :
422 : #define DEFINE_BIT_FIELDS_64(LIST_MACRO) \
423 : DEFINE_BIT_RANGES(LIST_MACRO) \
424 : LIST_MACRO(DEFINE_BIT_FIELD_64_TYPE, LIST_MACRO##_Ranges)
425 :
426 : // ----------------------------------------------------------------------------
427 : // BitSetComputer is a help template for encoding and decoding information for
428 : // a variable number of items in an array.
429 : //
430 : // To encode boolean data in a smi array you would use:
431 : // typedef BitSetComputer<bool, 1, kSmiValueSize, uint32_t> BoolComputer;
432 : //
433 : template <class T, int kBitsPerItem, int kBitsPerWord, class U>
434 : class BitSetComputer {
435 : public:
436 : static const int kItemsPerWord = kBitsPerWord / kBitsPerItem;
437 : static const int kMask = (1 << kBitsPerItem) - 1;
438 :
439 : // The number of array elements required to embed T information for each item.
440 : static int word_count(int items) {
441 17275526 : if (items == 0) return 0;
442 17263602 : return (items - 1) / kItemsPerWord + 1;
443 : }
444 :
445 : // The array index to look at for item.
446 : static int index(int base_index, int item) {
447 66593621 : return base_index + item / kItemsPerWord;
448 : }
449 :
450 : // Extract T data for a given item from data.
451 : static T decode(U data, int item) {
452 42503681 : return static_cast<T>((data >> shift(item)) & kMask);
453 : }
454 :
455 : // Return the encoding for a store of value for item in previous.
456 : static U encode(U previous, int item, T value) {
457 : int shift_value = shift(item);
458 24094215 : int set_bits = (static_cast<int>(value) << shift_value);
459 24094215 : return (previous & ~(kMask << shift_value)) | set_bits;
460 : }
461 :
462 66593621 : static int shift(int item) { return (item % kItemsPerWord) * kBitsPerItem; }
463 : };
464 :
465 : // Helper macros for defining a contiguous sequence of field offset constants.
466 : // Example: (backslashes at the ends of respective lines of this multi-line
467 : // macro definition are omitted here to please the compiler)
468 : //
469 : // #define MAP_FIELDS(V)
470 : // V(kField1Offset, kTaggedSize)
471 : // V(kField2Offset, kIntSize)
472 : // V(kField3Offset, kIntSize)
473 : // V(kField4Offset, kSystemPointerSize)
474 : // V(kSize, 0)
475 : //
476 : // DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, MAP_FIELDS)
477 : //
478 : #define DEFINE_ONE_FIELD_OFFSET(Name, Size) Name, Name##End = Name + (Size)-1,
479 :
480 : #define DEFINE_FIELD_OFFSET_CONSTANTS(StartOffset, LIST_MACRO) \
481 : enum { \
482 : LIST_MACRO##_StartOffset = StartOffset - 1, \
483 : LIST_MACRO(DEFINE_ONE_FIELD_OFFSET) \
484 : };
485 :
486 : // Size of the field defined by DEFINE_FIELD_OFFSET_CONSTANTS
487 : #define FIELD_SIZE(Name) (Name##End + 1 - Name)
488 :
489 : // ----------------------------------------------------------------------------
490 : // Hash function.
491 :
492 : static const uint64_t kZeroHashSeed = 0;
493 :
494 : // Thomas Wang, Integer Hash Functions.
495 : // http://www.concentric.net/~Ttwang/tech/inthash.htm`
496 : inline uint32_t ComputeUnseededHash(uint32_t key) {
497 : uint32_t hash = key;
498 91039154 : hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
499 91039154 : hash = hash ^ (hash >> 12);
500 91039154 : hash = hash + (hash << 2);
501 91039154 : hash = hash ^ (hash >> 4);
502 91039154 : hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11);
503 91039154 : hash = hash ^ (hash >> 16);
504 91039154 : return hash & 0x3fffffff;
505 : }
506 :
507 : inline uint32_t ComputeLongHash(uint64_t key) {
508 : uint64_t hash = key;
509 151208302 : hash = ~hash + (hash << 18); // hash = (hash << 18) - hash - 1;
510 151208302 : hash = hash ^ (hash >> 31);
511 151208302 : hash = hash * 21; // hash = (hash + (hash << 2)) + (hash << 4);
512 151208302 : hash = hash ^ (hash >> 11);
513 151208302 : hash = hash + (hash << 6);
514 151208302 : hash = hash ^ (hash >> 22);
515 151208302 : return static_cast<uint32_t>(hash & 0x3fffffff);
516 : }
517 :
518 : inline uint32_t ComputeSeededHash(uint32_t key, uint64_t seed) {
519 : #ifdef V8_USE_SIPHASH
520 : return halfsiphash(key, seed);
521 : #else
522 147175710 : return ComputeLongHash(static_cast<uint64_t>(key) ^ seed);
523 : #endif // V8_USE_SIPHASH
524 : }
525 :
526 : inline uint32_t ComputePointerHash(void* ptr) {
527 : return ComputeUnseededHash(
528 21520 : static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)));
529 : }
530 :
531 : inline uint32_t ComputeAddressHash(Address address) {
532 10505998 : return ComputeUnseededHash(static_cast<uint32_t>(address & 0xFFFFFFFFul));
533 : }
534 :
535 : // ----------------------------------------------------------------------------
536 : // Miscellaneous
537 :
538 : // Memory offset for lower and higher bits in a 64 bit integer.
539 : #if defined(V8_TARGET_LITTLE_ENDIAN)
540 : static const int kInt64LowerHalfMemoryOffset = 0;
541 : static const int kInt64UpperHalfMemoryOffset = 4;
542 : #elif defined(V8_TARGET_BIG_ENDIAN)
543 : static const int kInt64LowerHalfMemoryOffset = 4;
544 : static const int kInt64UpperHalfMemoryOffset = 0;
545 : #endif // V8_TARGET_LITTLE_ENDIAN
546 :
547 : // A static resource holds a static instance that can be reserved in
548 : // a local scope using an instance of Access. Attempts to re-reserve
549 : // the instance will cause an error.
550 : template <typename T>
551 : class StaticResource {
552 : public:
553 62883 : StaticResource() : is_reserved_(false) {}
554 :
555 : private:
556 : template <typename S> friend class Access;
557 : T instance_;
558 : bool is_reserved_;
559 : };
560 :
561 :
562 : // Locally scoped access to a static resource.
563 : template <typename T>
564 : class Access {
565 : public:
566 : explicit Access(StaticResource<T>* resource)
567 : : resource_(resource)
568 5821 : , instance_(&resource->instance_) {
569 : DCHECK(!resource->is_reserved_);
570 5821 : resource->is_reserved_ = true;
571 : }
572 :
573 : ~Access() {
574 5821 : resource_->is_reserved_ = false;
575 : resource_ = nullptr;
576 : instance_ = nullptr;
577 : }
578 :
579 : T* value() { return instance_; }
580 : T* operator -> () { return instance_; }
581 :
582 : private:
583 : StaticResource<T>* resource_;
584 : T* instance_;
585 : };
586 :
587 : // A pointer that can only be set once and doesn't allow NULL values.
588 : template<typename T>
589 : class SetOncePointer {
590 : public:
591 : SetOncePointer() = default;
592 :
593 7462381 : bool is_set() const { return pointer_ != nullptr; }
594 :
595 : T* get() const {
596 : DCHECK_NOT_NULL(pointer_);
597 10639906 : return pointer_;
598 : }
599 :
600 : void set(T* value) {
601 : DCHECK(pointer_ == nullptr && value != nullptr);
602 1925975 : pointer_ = value;
603 : }
604 :
605 : T* operator=(T* value) {
606 : set(value);
607 : return value;
608 : }
609 :
610 108272 : bool operator==(std::nullptr_t) const { return pointer_ == nullptr; }
611 : bool operator!=(std::nullptr_t) const { return pointer_ != nullptr; }
612 :
613 : private:
614 : T* pointer_ = nullptr;
615 : };
616 :
617 :
618 : template <typename T, int kSize>
619 : class EmbeddedVector : public Vector<T> {
620 : public:
621 1467778764 : EmbeddedVector() : Vector<T>(buffer_, kSize) { }
622 :
623 : explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) {
624 1024 : for (int i = 0; i < kSize; ++i) {
625 1024 : buffer_[i] = initial_value;
626 : }
627 : }
628 :
629 : // When copying, make underlying Vector to reference our buffer.
630 : EmbeddedVector(const EmbeddedVector& rhs) V8_NOEXCEPT : Vector<T>(rhs) {
631 : MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
632 : this->set_start(buffer_);
633 : }
634 :
635 : EmbeddedVector& operator=(const EmbeddedVector& rhs) V8_NOEXCEPT {
636 : if (this == &rhs) return *this;
637 : Vector<T>::operator=(rhs);
638 : MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
639 : this->set_start(buffer_);
640 : return *this;
641 : }
642 :
643 : private:
644 : T buffer_[kSize];
645 : };
646 :
647 : // Compare 8bit/16bit chars to 8bit/16bit chars.
648 : template <typename lchar, typename rchar>
649 : inline int CompareCharsUnsigned(const lchar* lhs, const rchar* rhs,
650 : size_t chars) {
651 815834 : const lchar* limit = lhs + chars;
652 : if (sizeof(*lhs) == sizeof(char) && sizeof(*rhs) == sizeof(char)) {
653 : // memcmp compares byte-by-byte, yielding wrong results for two-byte
654 : // strings on little-endian systems.
655 147710336 : return memcmp(lhs, rhs, chars);
656 : }
657 3914910 : while (lhs < limit) {
658 3116968 : int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
659 3116968 : if (r != 0) return r;
660 3099076 : ++lhs;
661 3099076 : ++rhs;
662 : }
663 : return 0;
664 : }
665 :
666 : template <typename lchar, typename rchar>
667 : inline int CompareChars(const lchar* lhs, const rchar* rhs, size_t chars) {
668 : DCHECK_LE(sizeof(lchar), 2);
669 : DCHECK_LE(sizeof(rchar), 2);
670 : if (sizeof(lchar) == 1) {
671 : if (sizeof(rchar) == 1) {
672 : return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
673 : reinterpret_cast<const uint8_t*>(rhs),
674 : chars);
675 : } else {
676 : return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
677 : reinterpret_cast<const uint16_t*>(rhs),
678 : chars);
679 : }
680 : } else {
681 : if (sizeof(rchar) == 1) {
682 : return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
683 : reinterpret_cast<const uint8_t*>(rhs),
684 : chars);
685 : } else {
686 : return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
687 : reinterpret_cast<const uint16_t*>(rhs),
688 : chars);
689 : }
690 : }
691 : }
692 :
693 :
694 : // Calculate 10^exponent.
695 : inline int TenToThe(int exponent) {
696 : DCHECK_LE(exponent, 9);
697 : DCHECK_GE(exponent, 1);
698 : int answer = 10;
699 : for (int i = 1; i < exponent; i++) answer *= 10;
700 : return answer;
701 : }
702 :
703 :
704 : template<typename ElementType, int NumElements>
705 : class EmbeddedContainer {
706 : public:
707 : EmbeddedContainer() : elems_() { }
708 :
709 : int length() const { return NumElements; }
710 : const ElementType& operator[](int i) const {
711 : DCHECK(i < length());
712 : return elems_[i];
713 : }
714 : ElementType& operator[](int i) {
715 : DCHECK(i < length());
716 : return elems_[i];
717 : }
718 :
719 : private:
720 : ElementType elems_[NumElements];
721 : };
722 :
723 :
724 : template<typename ElementType>
725 : class EmbeddedContainer<ElementType, 0> {
726 : public:
727 : int length() const { return 0; }
728 : const ElementType& operator[](int i) const {
729 : UNREACHABLE();
730 : static ElementType t = 0;
731 : return t;
732 : }
733 : ElementType& operator[](int i) {
734 : UNREACHABLE();
735 : static ElementType t = 0;
736 : return t;
737 : }
738 : };
739 :
740 :
741 : // Helper class for building result strings in a character buffer. The
742 : // purpose of the class is to use safe operations that checks the
743 : // buffer bounds on all operations in debug mode.
744 : // This simple base class does not allow formatted output.
745 : class SimpleStringBuilder {
746 : public:
747 : // Create a string builder with a buffer of the given size. The
748 : // buffer is allocated through NewArray<char> and must be
749 : // deallocated by the caller of Finalize().
750 : explicit SimpleStringBuilder(int size);
751 :
752 : SimpleStringBuilder(char* buffer, int size)
753 2253656 : : buffer_(buffer, size), position_(0) { }
754 :
755 1136772 : ~SimpleStringBuilder() { if (!is_finalized()) Finalize(); }
756 :
757 : int size() const { return buffer_.length(); }
758 :
759 : // Get the current position in the builder.
760 : int position() const {
761 : DCHECK(!is_finalized());
762 : return position_;
763 : }
764 :
765 : // Reset the position.
766 0 : void Reset() { position_ = 0; }
767 :
768 : // Add a single character to the builder. It is not allowed to add
769 : // 0-characters; use the Finalize() method to terminate the string
770 : // instead.
771 : void AddCharacter(char c) {
772 : DCHECK_NE(c, '\0');
773 : DCHECK(!is_finalized() && position_ < buffer_.length());
774 4220922 : buffer_[position_++] = c;
775 : }
776 :
777 : // Add an entire string to the builder. Uses strlen() internally to
778 : // compute the length of the input string.
779 : void AddString(const char* s);
780 :
781 : // Add the first 'n' characters of the given 0-terminated string 's' to the
782 : // builder. The input string must have enough characters.
783 : void AddSubstring(const char* s, int n);
784 :
785 : // Add character padding to the builder. If count is non-positive,
786 : // nothing is added to the builder.
787 : void AddPadding(char c, int count);
788 :
789 : // Add the decimal representation of the value.
790 : void AddDecimalInteger(int value);
791 :
792 : // Finalize the string by 0-terminating it and returning the buffer.
793 : char* Finalize();
794 :
795 : protected:
796 : Vector<char> buffer_;
797 : int position_;
798 :
799 : bool is_finalized() const { return position_ < 0; }
800 :
801 : private:
802 : DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder);
803 : };
804 :
805 : // Bit field extraction.
806 : inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) {
807 : return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
808 : }
809 :
810 : inline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) {
811 : return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
812 : }
813 :
814 : inline int32_t signed_bitextract_32(int msb, int lsb, int32_t x) {
815 : return (x << (31 - msb)) >> (lsb + 31 - msb);
816 : }
817 :
818 : inline int signed_bitextract_64(int msb, int lsb, int x) {
819 : // TODO(jbramley): This is broken for big bitfields.
820 : return (x << (63 - msb)) >> (lsb + 63 - msb);
821 : }
822 :
823 : // Check number width.
824 : inline bool is_intn(int64_t x, unsigned n) {
825 : DCHECK((0 < n) && (n < 64));
826 : int64_t limit = static_cast<int64_t>(1) << (n - 1);
827 67997268 : return (-limit <= x) && (x < limit);
828 : }
829 :
830 : inline bool is_uintn(int64_t x, unsigned n) {
831 : DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
832 19929285 : return !(x >> n);
833 : }
834 :
835 : template <class T>
836 : inline T truncate_to_intn(T x, unsigned n) {
837 : DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
838 : return (x & ((static_cast<T>(1) << n) - 1));
839 : }
840 :
841 : #define INT_1_TO_63_LIST(V) \
842 : V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \
843 : V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \
844 : V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \
845 : V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32) \
846 : V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \
847 : V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \
848 : V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \
849 : V(57) V(58) V(59) V(60) V(61) V(62) V(63)
850 :
851 : #define DECLARE_IS_INT_N(N) \
852 : inline bool is_int##N(int64_t x) { return is_intn(x, N); }
853 : #define DECLARE_IS_UINT_N(N) \
854 : template <class T> \
855 : inline bool is_uint##N(T x) { return is_uintn(x, N); }
856 : #define DECLARE_TRUNCATE_TO_INT_N(N) \
857 : template <class T> \
858 : inline T truncate_to_int##N(T x) { return truncate_to_intn(x, N); }
859 : INT_1_TO_63_LIST(DECLARE_IS_INT_N)
860 6068894 : INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
861 : INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
862 : #undef DECLARE_IS_INT_N
863 : #undef DECLARE_IS_UINT_N
864 : #undef DECLARE_TRUNCATE_TO_INT_N
865 :
866 : // clang-format off
867 : #define INT_0_TO_127_LIST(V) \
868 : V(0) V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) V(9) \
869 : V(10) V(11) V(12) V(13) V(14) V(15) V(16) V(17) V(18) V(19) \
870 : V(20) V(21) V(22) V(23) V(24) V(25) V(26) V(27) V(28) V(29) \
871 : V(30) V(31) V(32) V(33) V(34) V(35) V(36) V(37) V(38) V(39) \
872 : V(40) V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) V(49) \
873 : V(50) V(51) V(52) V(53) V(54) V(55) V(56) V(57) V(58) V(59) \
874 : V(60) V(61) V(62) V(63) V(64) V(65) V(66) V(67) V(68) V(69) \
875 : V(70) V(71) V(72) V(73) V(74) V(75) V(76) V(77) V(78) V(79) \
876 : V(80) V(81) V(82) V(83) V(84) V(85) V(86) V(87) V(88) V(89) \
877 : V(90) V(91) V(92) V(93) V(94) V(95) V(96) V(97) V(98) V(99) \
878 : V(100) V(101) V(102) V(103) V(104) V(105) V(106) V(107) V(108) V(109) \
879 : V(110) V(111) V(112) V(113) V(114) V(115) V(116) V(117) V(118) V(119) \
880 : V(120) V(121) V(122) V(123) V(124) V(125) V(126) V(127)
881 : // clang-format on
882 :
883 : class FeedbackSlot {
884 : public:
885 259545335 : FeedbackSlot() : id_(kInvalidSlot) {}
886 2111217 : explicit FeedbackSlot(int id) : id_(id) {}
887 :
888 1494749 : int ToInt() const { return id_; }
889 :
890 : static FeedbackSlot Invalid() { return FeedbackSlot(); }
891 2857146 : bool IsInvalid() const { return id_ == kInvalidSlot; }
892 :
893 15 : bool operator==(FeedbackSlot that) const { return this->id_ == that.id_; }
894 : bool operator!=(FeedbackSlot that) const { return !(*this == that); }
895 :
896 0 : friend size_t hash_value(FeedbackSlot slot) { return slot.ToInt(); }
897 : friend std::ostream& operator<<(std::ostream& os, FeedbackSlot);
898 :
899 : private:
900 : static const int kInvalidSlot = -1;
901 :
902 : int id_;
903 : };
904 :
905 :
906 : class BailoutId {
907 : public:
908 7128432 : explicit BailoutId(int id) : id_(id) { }
909 3308157 : int ToInt() const { return id_; }
910 :
911 : static BailoutId None() { return BailoutId(kNoneId); }
912 : static BailoutId ScriptContext() { return BailoutId(kScriptContextId); }
913 : static BailoutId FunctionContext() { return BailoutId(kFunctionContextId); }
914 : static BailoutId FunctionEntry() { return BailoutId(kFunctionEntryId); }
915 : static BailoutId Declarations() { return BailoutId(kDeclarationsId); }
916 : static BailoutId FirstUsable() { return BailoutId(kFirstUsableId); }
917 : static BailoutId StubEntry() { return BailoutId(kStubEntryId); }
918 :
919 : // Special bailout id support for deopting into the {JSConstructStub} stub.
920 : // The following hard-coded deoptimization points are supported by the stub:
921 : // - {ConstructStubCreate} maps to {construct_stub_create_deopt_pc_offset}.
922 : // - {ConstructStubInvoke} maps to {construct_stub_invoke_deopt_pc_offset}.
923 : static BailoutId ConstructStubCreate() { return BailoutId(1); }
924 : static BailoutId ConstructStubInvoke() { return BailoutId(2); }
925 : bool IsValidForConstructStub() const {
926 : return id_ == ConstructStubCreate().ToInt() ||
927 : id_ == ConstructStubInvoke().ToInt();
928 : }
929 :
930 12120362 : bool IsNone() const { return id_ == kNoneId; }
931 2 : bool operator==(const BailoutId& other) const { return id_ == other.id_; }
932 : bool operator!=(const BailoutId& other) const { return id_ != other.id_; }
933 : friend size_t hash_value(BailoutId);
934 : V8_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream&, BailoutId);
935 :
936 : private:
937 : friend class Builtins;
938 :
939 : static const int kNoneId = -1;
940 :
941 : // Using 0 could disguise errors.
942 : static const int kScriptContextId = 1;
943 : static const int kFunctionContextId = 2;
944 : static const int kFunctionEntryId = 3;
945 :
946 : // This AST id identifies the point after the declarations have been visited.
947 : // We need it to capture the environment effects of declarations that emit
948 : // code (function declarations).
949 : static const int kDeclarationsId = 4;
950 :
951 : // Every FunctionState starts with this id.
952 : static const int kFirstUsableId = 5;
953 :
954 : // Every compiled stub starts with this id.
955 : static const int kStubEntryId = 6;
956 :
957 : // Builtin continuations bailout ids start here. If you need to add a
958 : // non-builtin BailoutId, add it before this id so that this Id has the
959 : // highest number.
960 : static const int kFirstBuiltinContinuationId = 7;
961 :
962 : int id_;
963 : };
964 :
965 :
966 : // ----------------------------------------------------------------------------
967 : // I/O support.
968 :
969 : // Our version of printf().
970 : V8_EXPORT_PRIVATE void PRINTF_FORMAT(1, 2) PrintF(const char* format, ...);
971 : void PRINTF_FORMAT(2, 3) PrintF(FILE* out, const char* format, ...);
972 :
973 : // Prepends the current process ID to the output.
974 : void PRINTF_FORMAT(1, 2) PrintPID(const char* format, ...);
975 :
976 : // Prepends the current process ID and given isolate pointer to the output.
977 : void PRINTF_FORMAT(2, 3) PrintIsolate(void* isolate, const char* format, ...);
978 :
979 : // Safe formatting print. Ensures that str is always null-terminated.
980 : // Returns the number of chars written, or -1 if output was truncated.
981 : int PRINTF_FORMAT(2, 3) SNPrintF(Vector<char> str, const char* format, ...);
982 : V8_EXPORT_PRIVATE int PRINTF_FORMAT(2, 0)
983 : VSNPrintF(Vector<char> str, const char* format, va_list args);
984 :
985 : void StrNCpy(Vector<char> dest, const char* src, size_t n);
986 :
987 : // Our version of fflush.
988 : void Flush(FILE* out);
989 :
990 : inline void Flush() {
991 : Flush(stdout);
992 : }
993 :
994 :
995 : // Read a line of characters after printing the prompt to stdout. The resulting
996 : // char* needs to be disposed off with DeleteArray by the caller.
997 : char* ReadLine(const char* prompt);
998 :
999 :
1000 : // Append size chars from str to the file given by filename.
1001 : // The file is overwritten. Returns the number of chars written.
1002 : int AppendChars(const char* filename,
1003 : const char* str,
1004 : int size,
1005 : bool verbose = true);
1006 :
1007 :
1008 : // Write size chars from str to the file given by filename.
1009 : // The file is overwritten. Returns the number of chars written.
1010 : int WriteChars(const char* filename,
1011 : const char* str,
1012 : int size,
1013 : bool verbose = true);
1014 :
1015 :
1016 : // Write size bytes to the file given by filename.
1017 : // The file is overwritten. Returns the number of bytes written.
1018 : int WriteBytes(const char* filename,
1019 : const byte* bytes,
1020 : int size,
1021 : bool verbose = true);
1022 :
1023 :
1024 : // Write the C code
1025 : // const char* <varname> = "<str>";
1026 : // const int <varname>_len = <len>;
1027 : // to the file given by filename. Only the first len chars are written.
1028 : int WriteAsCFile(const char* filename, const char* varname,
1029 : const char* str, int size, bool verbose = true);
1030 :
1031 :
1032 : // Simple support to read a file into std::string.
1033 : // On return, *exits tells whether the file existed.
1034 : V8_EXPORT_PRIVATE std::string ReadFile(const char* filename, bool* exists,
1035 : bool verbose = true);
1036 : std::string ReadFile(FILE* file, bool* exists, bool verbose = true);
1037 :
1038 : class StringBuilder : public SimpleStringBuilder {
1039 : public:
1040 : explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
1041 : StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
1042 :
1043 : // Add formatted contents to the builder just like printf().
1044 : void PRINTF_FORMAT(2, 3) AddFormatted(const char* format, ...);
1045 :
1046 : // Add formatted contents like printf based on a va_list.
1047 : void PRINTF_FORMAT(2, 0) AddFormattedList(const char* format, va_list list);
1048 :
1049 : private:
1050 : DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
1051 : };
1052 :
1053 :
1054 : bool DoubleToBoolean(double d);
1055 :
1056 : template <typename Char>
1057 : bool TryAddIndexChar(uint32_t* index, Char c);
1058 :
1059 : template <typename Stream>
1060 : bool StringToArrayIndex(Stream* stream, uint32_t* index);
1061 :
1062 : // Returns the current stack top. Works correctly with ASAN and SafeStack.
1063 : // GetCurrentStackPosition() should not be inlined, because it works on stack
1064 : // frames if it were inlined into a function with a huge stack frame it would
1065 : // return an address significantly above the actual current stack position.
1066 : V8_NOINLINE uintptr_t GetCurrentStackPosition();
1067 :
1068 : template <typename V>
1069 : static inline V ByteReverse(V value) {
1070 : size_t size_of_v = sizeof(value);
1071 : switch (size_of_v) {
1072 : case 2:
1073 : #if V8_HAS_BUILTIN_BSWAP16
1074 : return static_cast<V>(__builtin_bswap16(static_cast<uint16_t>(value)));
1075 : #else
1076 : return value << 8 | (value >> 8 & 0x00FF);
1077 : #endif
1078 : case 4:
1079 : #if V8_HAS_BUILTIN_BSWAP32
1080 : return static_cast<V>(__builtin_bswap32(static_cast<uint32_t>(value)));
1081 : #else
1082 : {
1083 : size_t bits_of_v = size_of_v * kBitsPerByte;
1084 : return value << (bits_of_v - 8) |
1085 : ((value << (bits_of_v - 24)) & 0x00FF0000) |
1086 : ((value >> (bits_of_v - 24)) & 0x0000FF00) |
1087 : ((value >> (bits_of_v - 8)) & 0x00000FF);
1088 : }
1089 : #endif
1090 : case 8:
1091 : #if V8_HAS_BUILTIN_BSWAP64
1092 : return static_cast<V>(__builtin_bswap64(static_cast<uint64_t>(value)));
1093 : #else
1094 : {
1095 : size_t bits_of_v = size_of_v * kBitsPerByte;
1096 : return value << (bits_of_v - 8) |
1097 : ((value << (bits_of_v - 24)) & 0x00FF000000000000) |
1098 : ((value << (bits_of_v - 40)) & 0x0000FF0000000000) |
1099 : ((value << (bits_of_v - 56)) & 0x000000FF00000000) |
1100 : ((value >> (bits_of_v - 56)) & 0x00000000FF000000) |
1101 : ((value >> (bits_of_v - 40)) & 0x0000000000FF0000) |
1102 : ((value >> (bits_of_v - 24)) & 0x000000000000FF00) |
1103 : ((value >> (bits_of_v - 8)) & 0x00000000000000FF);
1104 : }
1105 : #endif
1106 : default:
1107 : UNREACHABLE();
1108 : }
1109 : }
1110 :
1111 : V8_EXPORT_PRIVATE bool PassesFilter(Vector<const char> name,
1112 : Vector<const char> filter);
1113 :
1114 : // Zap the specified area with a specific byte pattern. This currently defaults
1115 : // to int3 on x64 and ia32. On other architectures this will produce unspecified
1116 : // instruction sequences.
1117 : // TODO(jgruber): Better support for other architectures.
1118 : V8_INLINE void ZapCode(Address addr, size_t size_in_bytes) {
1119 : static constexpr int kZapByte = 0xCC;
1120 0 : std::memset(reinterpret_cast<void*>(addr), kZapByte, size_in_bytes);
1121 : }
1122 :
1123 : } // namespace internal
1124 : } // namespace v8
1125 :
1126 : #endif // V8_UTILS_H_
|