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 66387700 : c -= '0';
41 66387700 : if (static_cast<unsigned>(c) <= 9) return c;
42 8076213 : c = (c | 0x20) - ('a' - '0'); // detect 0x11..0x16 and 0x31..0x36.
43 8076213 : 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 8201226 : if (value < 10) return value + '0';
50 533385 : return value - 10 + 'A';
51 : }
52 :
53 37097 : 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 2321788435 : 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 8325415023 : 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 6372875 : 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 21298 : 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 18530 : CHECK_BIGGER(32)
100 21298 : CHECK_BIGGER(16)
101 21298 : CHECK_BIGGER(8)
102 21298 : CHECK_BIGGER(4)
103 : #undef CHECK_BIGGER
104 21298 : switch (x) {
105 0 : default: UNREACHABLE();
106 : case 8:
107 8975 : bits++;
108 : V8_FALLTHROUGH;
109 : case 4:
110 9416 : bits++;
111 : V8_FALLTHROUGH;
112 : case 2:
113 13114 : bits++;
114 : V8_FALLTHROUGH;
115 : case 1: break;
116 : }
117 : DCHECK_EQ(T{1} << bits, original_x);
118 21298 : 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 23952 : static T ArithmeticShiftRight(T x, int shift) {
141 : DCHECK_LE(0, shift);
142 24324 : 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 5610 : UnsignedT mask = ~(static_cast<UnsignedT>(~0) >> shift);
147 5610 : return (static_cast<UnsignedT>(x) >> shift) | mask;
148 : } else {
149 18714 : 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 247386 : constexpr T Max(T a, T b) {
175 167009079 : return a < b ? b : a;
176 : }
177 :
178 :
179 : // Returns the minimum of the two parameters.
180 : template <typename T>
181 7007018 : constexpr T Min(T a, T b) {
182 324071167 : return a < b ? a : b;
183 : }
184 :
185 : // Returns the maximum of the two parameters according to JavaScript semantics.
186 : template <typename T>
187 435048 : T JSMax(T x, T y) {
188 435048 : if (std::isnan(x)) return x;
189 425764 : if (std::isnan(y)) return y;
190 833416 : if (std::signbit(x) < std::signbit(y)) return x;
191 314612 : return x > y ? x : y;
192 : }
193 :
194 : // Returns the maximum of the two parameters according to JavaScript semantics.
195 : template <typename T>
196 435048 : T JSMin(T x, T y) {
197 435048 : if (std::isnan(x)) return x;
198 425764 : if (std::isnan(y)) return y;
199 833416 : if (std::signbit(x) < std::signbit(y)) return y;
200 314612 : 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 5281 : unsignedT x = static_cast<unsignedT>(a);
212 5281 : unsignedT y = static_cast<unsignedT>(a >> (sizeof(T) * 8 - 1));
213 5281 : 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 144304 : 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 724270 : return std::fmod(x, y);
253 : #endif
254 : }
255 :
256 : template <typename T>
257 9378 : T SaturateAdd(T a, T b) {
258 : if (std::is_signed<T>::value) {
259 9378 : if (a > 0 && b > 0) {
260 2310 : if (a > std::numeric_limits<T>::max() - b) {
261 : return std::numeric_limits<T>::max();
262 : }
263 7068 : } else if (a < 0 && b < 0) {
264 1653 : if (a < std::numeric_limits<T>::min() - b) {
265 : return std::numeric_limits<T>::min();
266 : }
267 : }
268 : } else {
269 : CHECK(std::is_unsigned<T>::value);
270 9369 : if (a > std::numeric_limits<T>::max() - b) {
271 : return std::numeric_limits<T>::max();
272 : }
273 : }
274 12784 : return a + b;
275 : }
276 :
277 : template <typename T>
278 9440 : T SaturateSub(T a, T b) {
279 : if (std::is_signed<T>::value) {
280 9440 : if (a >= 0 && b < 0) {
281 2244 : if (a > std::numeric_limits<T>::max() + b) {
282 : return std::numeric_limits<T>::max();
283 : }
284 7196 : } else if (a < 0 && b > 0) {
285 1841 : if (a < std::numeric_limits<T>::min() + b) {
286 : return std::numeric_limits<T>::min();
287 : }
288 : }
289 : } else {
290 : CHECK(std::is_unsigned<T>::value);
291 9369 : if (a < b) {
292 : return static_cast<T>(0);
293 : }
294 : }
295 12617 : return a - b;
296 : }
297 :
298 : // ----------------------------------------------------------------------------
299 : // BitField is a help template for encoding and decode bitfield with
300 : // unsigned content.
301 :
302 : template<class T, int shift, int size, class U>
303 : class BitFieldBase {
304 : public:
305 : typedef T FieldType;
306 :
307 : // A type U mask of bit field. To use all bits of a type U of x bits
308 : // in a bitfield without compiler warnings we have to compute 2^x
309 : // without using a shift count of x in the computation.
310 : static const U kOne = static_cast<U>(1U);
311 : static const U kMask = ((kOne << shift) << size) - (kOne << shift);
312 : static const U kShift = shift;
313 : static const U kSize = size;
314 : static const U kNext = kShift + kSize;
315 : static const U kNumValues = kOne << size;
316 :
317 : // Value for the field with all bits set.
318 : static const T kMax = static_cast<T>(kNumValues - 1);
319 :
320 : // Tells whether the provided value fits into the bit field.
321 : static constexpr bool is_valid(T value) {
322 76071812 : return (static_cast<U>(value) & ~static_cast<U>(kMax)) == 0;
323 : }
324 :
325 : // Returns a type U with the bit field value encoded.
326 37051 : static constexpr U encode(T value) {
327 : #if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
328 : DCHECK(is_valid(value));
329 : #endif
330 5316312506 : return static_cast<U>(value) << shift;
331 : }
332 :
333 : // Returns a type U with the bit field value updated.
334 5779 : static constexpr U update(U previous, T value) {
335 5579673011 : return (previous & ~kMask) | encode(value);
336 : }
337 :
338 : // Extracts the bit field from the value.
339 25214494 : static constexpr T decode(U value) {
340 48348578601 : return static_cast<T>((value & kMask) >> shift);
341 : }
342 :
343 : STATIC_ASSERT((kNext - 1) / 8 < sizeof(U));
344 : };
345 :
346 : template <class T, int shift, int size>
347 : class BitField8 : public BitFieldBase<T, shift, size, uint8_t> {};
348 :
349 :
350 : template <class T, int shift, int size>
351 : class BitField16 : public BitFieldBase<T, shift, size, uint16_t> {};
352 :
353 :
354 : template<class T, int shift, int size>
355 : class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
356 :
357 :
358 : template<class T, int shift, int size>
359 : class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
360 :
361 : // Helper macros for defining a contiguous sequence of bit fields. Example:
362 : // (backslashes at the ends of respective lines of this multi-line macro
363 : // definition are omitted here to please the compiler)
364 : //
365 : // #define MAP_BIT_FIELD1(V, _)
366 : // V(IsAbcBit, bool, 1, _)
367 : // V(IsBcdBit, bool, 1, _)
368 : // V(CdeBits, int, 5, _)
369 : // V(DefBits, MutableMode, 1, _)
370 : //
371 : // DEFINE_BIT_FIELDS(MAP_BIT_FIELD1)
372 : // or
373 : // DEFINE_BIT_FIELDS_64(MAP_BIT_FIELD1)
374 : //
375 : #define DEFINE_BIT_FIELD_RANGE_TYPE(Name, Type, Size, _) \
376 : k##Name##Start, k##Name##End = k##Name##Start + Size - 1,
377 :
378 : #define DEFINE_BIT_RANGES(LIST_MACRO) \
379 : struct LIST_MACRO##_Ranges { \
380 : enum { LIST_MACRO(DEFINE_BIT_FIELD_RANGE_TYPE, _) kBitsCount }; \
381 : };
382 :
383 : #define DEFINE_BIT_FIELD_TYPE(Name, Type, Size, RangesName) \
384 : typedef BitField<Type, RangesName::k##Name##Start, Size> Name;
385 :
386 : #define DEFINE_BIT_FIELD_64_TYPE(Name, Type, Size, RangesName) \
387 : typedef BitField64<Type, RangesName::k##Name##Start, Size> Name;
388 :
389 : #define DEFINE_BIT_FIELDS(LIST_MACRO) \
390 : DEFINE_BIT_RANGES(LIST_MACRO) \
391 : LIST_MACRO(DEFINE_BIT_FIELD_TYPE, LIST_MACRO##_Ranges)
392 :
393 : #define DEFINE_BIT_FIELDS_64(LIST_MACRO) \
394 : DEFINE_BIT_RANGES(LIST_MACRO) \
395 : LIST_MACRO(DEFINE_BIT_FIELD_64_TYPE, LIST_MACRO##_Ranges)
396 :
397 : // ----------------------------------------------------------------------------
398 : // BitSetComputer is a help template for encoding and decoding information for
399 : // a variable number of items in an array.
400 : //
401 : // To encode boolean data in a smi array you would use:
402 : // typedef BitSetComputer<bool, 1, kSmiValueSize, uint32_t> BoolComputer;
403 : //
404 : template <class T, int kBitsPerItem, int kBitsPerWord, class U>
405 : class BitSetComputer {
406 : public:
407 : static const int kItemsPerWord = kBitsPerWord / kBitsPerItem;
408 : static const int kMask = (1 << kBitsPerItem) - 1;
409 :
410 : // The number of array elements required to embed T information for each item.
411 : static int word_count(int items) {
412 7033896 : if (items == 0) return 0;
413 7022375 : return (items - 1) / kItemsPerWord + 1;
414 : }
415 :
416 : // The array index to look at for item.
417 : static int index(int base_index, int item) {
418 75924991 : return base_index + item / kItemsPerWord;
419 : }
420 :
421 : // Extract T data for a given item from data.
422 : static T decode(U data, int item) {
423 47852368 : return static_cast<T>((data >> shift(item)) & kMask);
424 : }
425 :
426 : // Return the encoding for a store of value for item in previous.
427 : static U encode(U previous, int item, T value) {
428 : int shift_value = shift(item);
429 28076793 : int set_bits = (static_cast<int>(value) << shift_value);
430 28076793 : return (previous & ~(kMask << shift_value)) | set_bits;
431 : }
432 :
433 75924991 : static int shift(int item) { return (item % kItemsPerWord) * kBitsPerItem; }
434 : };
435 :
436 : // Helper macros for defining a contiguous sequence of field offset constants.
437 : // Example: (backslashes at the ends of respective lines of this multi-line
438 : // macro definition are omitted here to please the compiler)
439 : //
440 : // #define MAP_FIELDS(V)
441 : // V(kField1Offset, kTaggedSize)
442 : // V(kField2Offset, kIntSize)
443 : // V(kField3Offset, kIntSize)
444 : // V(kField4Offset, kSystemPointerSize)
445 : // V(kSize, 0)
446 : //
447 : // DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, MAP_FIELDS)
448 : //
449 : #define DEFINE_ONE_FIELD_OFFSET(Name, Size) Name, Name##End = Name + (Size)-1,
450 :
451 : #define DEFINE_FIELD_OFFSET_CONSTANTS(StartOffset, LIST_MACRO) \
452 : enum { \
453 : LIST_MACRO##_StartOffset = StartOffset - 1, \
454 : LIST_MACRO(DEFINE_ONE_FIELD_OFFSET) \
455 : };
456 :
457 : // Size of the field defined by DEFINE_FIELD_OFFSET_CONSTANTS
458 : #define FIELD_SIZE(Name) (Name##End + 1 - Name)
459 :
460 : // ----------------------------------------------------------------------------
461 : // Hash function.
462 :
463 : static const uint64_t kZeroHashSeed = 0;
464 :
465 : // Thomas Wang, Integer Hash Functions.
466 : // http://www.concentric.net/~Ttwang/tech/inthash.htm`
467 : inline uint32_t ComputeUnseededHash(uint32_t key) {
468 : uint32_t hash = key;
469 92295942 : hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
470 92295942 : hash = hash ^ (hash >> 12);
471 92295942 : hash = hash + (hash << 2);
472 92295942 : hash = hash ^ (hash >> 4);
473 92295942 : hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11);
474 92295942 : hash = hash ^ (hash >> 16);
475 92295942 : return hash & 0x3fffffff;
476 : }
477 :
478 : inline uint32_t ComputeLongHash(uint64_t key) {
479 : uint64_t hash = key;
480 150201314 : hash = ~hash + (hash << 18); // hash = (hash << 18) - hash - 1;
481 150201314 : hash = hash ^ (hash >> 31);
482 150201314 : hash = hash * 21; // hash = (hash + (hash << 2)) + (hash << 4);
483 150201314 : hash = hash ^ (hash >> 11);
484 150201314 : hash = hash + (hash << 6);
485 150201314 : hash = hash ^ (hash >> 22);
486 150201314 : return static_cast<uint32_t>(hash & 0x3fffffff);
487 : }
488 :
489 : inline uint32_t ComputeSeededHash(uint32_t key, uint64_t seed) {
490 : #ifdef V8_USE_SIPHASH
491 : return halfsiphash(key, seed);
492 : #else
493 146170020 : return ComputeLongHash(static_cast<uint64_t>(key) ^ seed);
494 : #endif // V8_USE_SIPHASH
495 : }
496 :
497 : inline uint32_t ComputePointerHash(void* ptr) {
498 : return ComputeUnseededHash(
499 21309 : static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)));
500 : }
501 :
502 : inline uint32_t ComputeAddressHash(Address address) {
503 10545187 : return ComputeUnseededHash(static_cast<uint32_t>(address & 0xFFFFFFFFul));
504 : }
505 :
506 : // ----------------------------------------------------------------------------
507 : // Miscellaneous
508 :
509 : // Memory offset for lower and higher bits in a 64 bit integer.
510 : #if defined(V8_TARGET_LITTLE_ENDIAN)
511 : static const int kInt64LowerHalfMemoryOffset = 0;
512 : static const int kInt64UpperHalfMemoryOffset = 4;
513 : #elif defined(V8_TARGET_BIG_ENDIAN)
514 : static const int kInt64LowerHalfMemoryOffset = 4;
515 : static const int kInt64UpperHalfMemoryOffset = 0;
516 : #endif // V8_TARGET_LITTLE_ENDIAN
517 :
518 : // A static resource holds a static instance that can be reserved in
519 : // a local scope using an instance of Access. Attempts to re-reserve
520 : // the instance will cause an error.
521 : template <typename T>
522 : class StaticResource {
523 : public:
524 61049 : StaticResource() : is_reserved_(false) {}
525 :
526 : private:
527 : template <typename S> friend class Access;
528 : T instance_;
529 : bool is_reserved_;
530 : };
531 :
532 :
533 : // Locally scoped access to a static resource.
534 : template <typename T>
535 : class Access {
536 : public:
537 : explicit Access(StaticResource<T>* resource)
538 : : resource_(resource)
539 10 : , instance_(&resource->instance_) {
540 : DCHECK(!resource->is_reserved_);
541 10 : resource->is_reserved_ = true;
542 : }
543 :
544 : ~Access() {
545 10 : resource_->is_reserved_ = false;
546 : resource_ = nullptr;
547 : instance_ = nullptr;
548 : }
549 :
550 : T* value() { return instance_; }
551 : T* operator -> () { return instance_; }
552 :
553 : private:
554 : StaticResource<T>* resource_;
555 : T* instance_;
556 : };
557 :
558 : // A pointer that can only be set once and doesn't allow NULL values.
559 : template<typename T>
560 : class SetOncePointer {
561 : public:
562 : SetOncePointer() = default;
563 :
564 7515956 : bool is_set() const { return pointer_ != nullptr; }
565 :
566 : T* get() const {
567 : DCHECK_NOT_NULL(pointer_);
568 9407224 : return pointer_;
569 : }
570 :
571 : void set(T* value) {
572 : DCHECK(pointer_ == nullptr && value != nullptr);
573 1332363 : pointer_ = value;
574 : }
575 :
576 : T* operator=(T* value) {
577 : set(value);
578 : return value;
579 : }
580 :
581 70851 : bool operator==(std::nullptr_t) const { return pointer_ == nullptr; }
582 : bool operator!=(std::nullptr_t) const { return pointer_ != nullptr; }
583 :
584 : private:
585 : T* pointer_ = nullptr;
586 : };
587 :
588 :
589 : template <typename T, int kSize>
590 : class EmbeddedVector : public Vector<T> {
591 : public:
592 1448768331 : EmbeddedVector() : Vector<T>(buffer_, kSize) { }
593 :
594 238302144 : explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) {
595 238302880 : for (int i = 0; i < kSize; ++i) {
596 238302880 : buffer_[i] = initial_value;
597 : }
598 : }
599 :
600 : // When copying, make underlying Vector to reference our buffer.
601 : EmbeddedVector(const EmbeddedVector& rhs) V8_NOEXCEPT : Vector<T>(rhs) {
602 : MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
603 : this->set_start(buffer_);
604 : }
605 :
606 : EmbeddedVector& operator=(const EmbeddedVector& rhs) V8_NOEXCEPT {
607 : if (this == &rhs) return *this;
608 : Vector<T>::operator=(rhs);
609 : MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
610 : this->set_start(buffer_);
611 : return *this;
612 : }
613 :
614 : private:
615 : T buffer_[kSize];
616 : };
617 :
618 : // Compare 8bit/16bit chars to 8bit/16bit chars.
619 : template <typename lchar, typename rchar>
620 : inline int CompareCharsUnsigned(const lchar* lhs, const rchar* rhs,
621 : size_t chars) {
622 816324 : const lchar* limit = lhs + chars;
623 : if (sizeof(*lhs) == sizeof(char) && sizeof(*rhs) == sizeof(char)) {
624 : // memcmp compares byte-by-byte, yielding wrong results for two-byte
625 : // strings on little-endian systems.
626 149469658 : return memcmp(lhs, rhs, chars);
627 : }
628 3875880 : while (lhs < limit) {
629 3077822 : int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
630 3077822 : if (r != 0) return r;
631 3059556 : ++lhs;
632 3059556 : ++rhs;
633 : }
634 : return 0;
635 : }
636 :
637 : template <typename lchar, typename rchar>
638 : inline int CompareChars(const lchar* lhs, const rchar* rhs, size_t chars) {
639 : DCHECK_LE(sizeof(lchar), 2);
640 : DCHECK_LE(sizeof(rchar), 2);
641 : if (sizeof(lchar) == 1) {
642 : if (sizeof(rchar) == 1) {
643 : return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
644 : reinterpret_cast<const uint8_t*>(rhs),
645 : chars);
646 : } else {
647 : return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
648 : reinterpret_cast<const uint16_t*>(rhs),
649 : chars);
650 : }
651 : } else {
652 : if (sizeof(rchar) == 1) {
653 : return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
654 : reinterpret_cast<const uint8_t*>(rhs),
655 : chars);
656 : } else {
657 : return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
658 : reinterpret_cast<const uint16_t*>(rhs),
659 : chars);
660 : }
661 : }
662 : }
663 :
664 :
665 : // Calculate 10^exponent.
666 : inline int TenToThe(int exponent) {
667 : DCHECK_LE(exponent, 9);
668 : DCHECK_GE(exponent, 1);
669 : int answer = 10;
670 : for (int i = 1; i < exponent; i++) answer *= 10;
671 : return answer;
672 : }
673 :
674 :
675 : template<typename ElementType, int NumElements>
676 : class EmbeddedContainer {
677 : public:
678 : EmbeddedContainer() : elems_() { }
679 :
680 : int length() const { return NumElements; }
681 : const ElementType& operator[](int i) const {
682 : DCHECK(i < length());
683 : return elems_[i];
684 : }
685 : ElementType& operator[](int i) {
686 : DCHECK(i < length());
687 : return elems_[i];
688 : }
689 :
690 : private:
691 : ElementType elems_[NumElements];
692 : };
693 :
694 :
695 : template<typename ElementType>
696 : class EmbeddedContainer<ElementType, 0> {
697 : public:
698 : int length() const { return 0; }
699 : const ElementType& operator[](int i) const {
700 : UNREACHABLE();
701 : static ElementType t = 0;
702 : return t;
703 : }
704 : ElementType& operator[](int i) {
705 : UNREACHABLE();
706 : static ElementType t = 0;
707 : return t;
708 : }
709 : };
710 :
711 :
712 : // Helper class for building result strings in a character buffer. The
713 : // purpose of the class is to use safe operations that checks the
714 : // buffer bounds on all operations in debug mode.
715 : // This simple base class does not allow formatted output.
716 : class SimpleStringBuilder {
717 : public:
718 : // Create a string builder with a buffer of the given size. The
719 : // buffer is allocated through NewArray<char> and must be
720 : // deallocated by the caller of Finalize().
721 : explicit SimpleStringBuilder(int size);
722 :
723 : SimpleStringBuilder(char* buffer, int size)
724 2264220 : : buffer_(buffer, size), position_(0) { }
725 :
726 1142049 : ~SimpleStringBuilder() { if (!is_finalized()) Finalize(); }
727 :
728 : int size() const { return buffer_.length(); }
729 :
730 : // Get the current position in the builder.
731 : int position() const {
732 : DCHECK(!is_finalized());
733 : return position_;
734 : }
735 :
736 : // Reset the position.
737 0 : void Reset() { position_ = 0; }
738 :
739 : // Add a single character to the builder. It is not allowed to add
740 : // 0-characters; use the Finalize() method to terminate the string
741 : // instead.
742 : void AddCharacter(char c) {
743 : DCHECK_NE(c, '\0');
744 : DCHECK(!is_finalized() && position_ < buffer_.length());
745 4232632 : buffer_[position_++] = c;
746 : }
747 :
748 : // Add an entire string to the builder. Uses strlen() internally to
749 : // compute the length of the input string.
750 : void AddString(const char* s);
751 :
752 : // Add the first 'n' characters of the given 0-terminated string 's' to the
753 : // builder. The input string must have enough characters.
754 : void AddSubstring(const char* s, int n);
755 :
756 : // Add character padding to the builder. If count is non-positive,
757 : // nothing is added to the builder.
758 : void AddPadding(char c, int count);
759 :
760 : // Add the decimal representation of the value.
761 : void AddDecimalInteger(int value);
762 :
763 : // Finalize the string by 0-terminating it and returning the buffer.
764 : char* Finalize();
765 :
766 : protected:
767 : Vector<char> buffer_;
768 : int position_;
769 :
770 : bool is_finalized() const { return position_ < 0; }
771 :
772 : private:
773 : DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder);
774 : };
775 :
776 : // Bit field extraction.
777 : inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) {
778 : return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
779 : }
780 :
781 : inline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) {
782 : return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
783 : }
784 :
785 : inline int32_t signed_bitextract_32(int msb, int lsb, int32_t x) {
786 : return (x << (31 - msb)) >> (lsb + 31 - msb);
787 : }
788 :
789 : inline int signed_bitextract_64(int msb, int lsb, int x) {
790 : // TODO(jbramley): This is broken for big bitfields.
791 : return (x << (63 - msb)) >> (lsb + 63 - msb);
792 : }
793 :
794 : // Check number width.
795 : inline bool is_intn(int64_t x, unsigned n) {
796 : DCHECK((0 < n) && (n < 64));
797 : int64_t limit = static_cast<int64_t>(1) << (n - 1);
798 66850015 : return (-limit <= x) && (x < limit);
799 : }
800 :
801 : inline bool is_uintn(int64_t x, unsigned n) {
802 : DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
803 19648963 : return !(x >> n);
804 : }
805 :
806 : template <class T>
807 : inline T truncate_to_intn(T x, unsigned n) {
808 : DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
809 : return (x & ((static_cast<T>(1) << n) - 1));
810 : }
811 :
812 : #define INT_1_TO_63_LIST(V) \
813 : V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \
814 : V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \
815 : V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \
816 : V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32) \
817 : V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \
818 : V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \
819 : V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \
820 : V(57) V(58) V(59) V(60) V(61) V(62) V(63)
821 :
822 : #define DECLARE_IS_INT_N(N) \
823 : inline bool is_int##N(int64_t x) { return is_intn(x, N); }
824 : #define DECLARE_IS_UINT_N(N) \
825 : template <class T> \
826 : inline bool is_uint##N(T x) { return is_uintn(x, N); }
827 : #define DECLARE_TRUNCATE_TO_INT_N(N) \
828 : template <class T> \
829 : inline T truncate_to_int##N(T x) { return truncate_to_intn(x, N); }
830 : INT_1_TO_63_LIST(DECLARE_IS_INT_N)
831 5026933 : INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
832 : INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
833 : #undef DECLARE_IS_INT_N
834 : #undef DECLARE_IS_UINT_N
835 : #undef DECLARE_TRUNCATE_TO_INT_N
836 :
837 : // clang-format off
838 : #define INT_0_TO_127_LIST(V) \
839 : V(0) V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) V(9) \
840 : V(10) V(11) V(12) V(13) V(14) V(15) V(16) V(17) V(18) V(19) \
841 : V(20) V(21) V(22) V(23) V(24) V(25) V(26) V(27) V(28) V(29) \
842 : V(30) V(31) V(32) V(33) V(34) V(35) V(36) V(37) V(38) V(39) \
843 : V(40) V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) V(49) \
844 : V(50) V(51) V(52) V(53) V(54) V(55) V(56) V(57) V(58) V(59) \
845 : V(60) V(61) V(62) V(63) V(64) V(65) V(66) V(67) V(68) V(69) \
846 : V(70) V(71) V(72) V(73) V(74) V(75) V(76) V(77) V(78) V(79) \
847 : V(80) V(81) V(82) V(83) V(84) V(85) V(86) V(87) V(88) V(89) \
848 : V(90) V(91) V(92) V(93) V(94) V(95) V(96) V(97) V(98) V(99) \
849 : V(100) V(101) V(102) V(103) V(104) V(105) V(106) V(107) V(108) V(109) \
850 : V(110) V(111) V(112) V(113) V(114) V(115) V(116) V(117) V(118) V(119) \
851 : V(120) V(121) V(122) V(123) V(124) V(125) V(126) V(127)
852 : // clang-format on
853 :
854 : class FeedbackSlot {
855 : public:
856 301882499 : FeedbackSlot() : id_(kInvalidSlot) {}
857 2140155 : explicit FeedbackSlot(int id) : id_(id) {}
858 :
859 1499935 : int ToInt() const { return id_; }
860 :
861 : static FeedbackSlot Invalid() { return FeedbackSlot(); }
862 4165025 : bool IsInvalid() const { return id_ == kInvalidSlot; }
863 :
864 15 : bool operator==(FeedbackSlot that) const { return this->id_ == that.id_; }
865 : bool operator!=(FeedbackSlot that) const { return !(*this == that); }
866 :
867 0 : friend size_t hash_value(FeedbackSlot slot) { return slot.ToInt(); }
868 : friend std::ostream& operator<<(std::ostream& os, FeedbackSlot);
869 :
870 : private:
871 : static const int kInvalidSlot = -1;
872 :
873 : int id_;
874 : };
875 :
876 :
877 : class BailoutId {
878 : public:
879 7189515 : explicit BailoutId(int id) : id_(id) { }
880 3890209 : int ToInt() const { return id_; }
881 :
882 : static BailoutId None() { return BailoutId(kNoneId); }
883 : static BailoutId ScriptContext() { return BailoutId(kScriptContextId); }
884 : static BailoutId FunctionContext() { return BailoutId(kFunctionContextId); }
885 : static BailoutId FunctionEntry() { return BailoutId(kFunctionEntryId); }
886 : static BailoutId Declarations() { return BailoutId(kDeclarationsId); }
887 : static BailoutId FirstUsable() { return BailoutId(kFirstUsableId); }
888 : static BailoutId StubEntry() { return BailoutId(kStubEntryId); }
889 :
890 : // Special bailout id support for deopting into the {JSConstructStub} stub.
891 : // The following hard-coded deoptimization points are supported by the stub:
892 : // - {ConstructStubCreate} maps to {construct_stub_create_deopt_pc_offset}.
893 : // - {ConstructStubInvoke} maps to {construct_stub_invoke_deopt_pc_offset}.
894 : static BailoutId ConstructStubCreate() { return BailoutId(1); }
895 : static BailoutId ConstructStubInvoke() { return BailoutId(2); }
896 : bool IsValidForConstructStub() const {
897 : return id_ == ConstructStubCreate().ToInt() ||
898 : id_ == ConstructStubInvoke().ToInt();
899 : }
900 :
901 9396134 : bool IsNone() const { return id_ == kNoneId; }
902 2 : bool operator==(const BailoutId& other) const { return id_ == other.id_; }
903 : bool operator!=(const BailoutId& other) const { return id_ != other.id_; }
904 : friend size_t hash_value(BailoutId);
905 : V8_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream&, BailoutId);
906 :
907 : private:
908 : friend class Builtins;
909 :
910 : static const int kNoneId = -1;
911 :
912 : // Using 0 could disguise errors.
913 : static const int kScriptContextId = 1;
914 : static const int kFunctionContextId = 2;
915 : static const int kFunctionEntryId = 3;
916 :
917 : // This AST id identifies the point after the declarations have been visited.
918 : // We need it to capture the environment effects of declarations that emit
919 : // code (function declarations).
920 : static const int kDeclarationsId = 4;
921 :
922 : // Every FunctionState starts with this id.
923 : static const int kFirstUsableId = 5;
924 :
925 : // Every compiled stub starts with this id.
926 : static const int kStubEntryId = 6;
927 :
928 : // Builtin continuations bailout ids start here. If you need to add a
929 : // non-builtin BailoutId, add it before this id so that this Id has the
930 : // highest number.
931 : static const int kFirstBuiltinContinuationId = 7;
932 :
933 : int id_;
934 : };
935 :
936 :
937 : // ----------------------------------------------------------------------------
938 : // I/O support.
939 :
940 : // Our version of printf().
941 : V8_EXPORT_PRIVATE void PRINTF_FORMAT(1, 2) PrintF(const char* format, ...);
942 : void PRINTF_FORMAT(2, 3) PrintF(FILE* out, const char* format, ...);
943 :
944 : // Prepends the current process ID to the output.
945 : void PRINTF_FORMAT(1, 2) PrintPID(const char* format, ...);
946 :
947 : // Prepends the current process ID and given isolate pointer to the output.
948 : void PRINTF_FORMAT(2, 3) PrintIsolate(void* isolate, const char* format, ...);
949 :
950 : // Safe formatting print. Ensures that str is always null-terminated.
951 : // Returns the number of chars written, or -1 if output was truncated.
952 : int PRINTF_FORMAT(2, 3) SNPrintF(Vector<char> str, const char* format, ...);
953 : V8_EXPORT_PRIVATE int PRINTF_FORMAT(2, 0)
954 : VSNPrintF(Vector<char> str, const char* format, va_list args);
955 :
956 : void StrNCpy(Vector<char> dest, const char* src, size_t n);
957 :
958 : // Our version of fflush.
959 : void Flush(FILE* out);
960 :
961 : inline void Flush() {
962 : Flush(stdout);
963 : }
964 :
965 :
966 : // Read a line of characters after printing the prompt to stdout. The resulting
967 : // char* needs to be disposed off with DeleteArray by the caller.
968 : char* ReadLine(const char* prompt);
969 :
970 :
971 : // Append size chars from str to the file given by filename.
972 : // The file is overwritten. Returns the number of chars written.
973 : int AppendChars(const char* filename,
974 : const char* str,
975 : int size,
976 : bool verbose = true);
977 :
978 :
979 : // Write size chars from str to the file given by filename.
980 : // The file is overwritten. Returns the number of chars written.
981 : int WriteChars(const char* filename,
982 : const char* str,
983 : int size,
984 : bool verbose = true);
985 :
986 :
987 : // Write size bytes to the file given by filename.
988 : // The file is overwritten. Returns the number of bytes written.
989 : int WriteBytes(const char* filename,
990 : const byte* bytes,
991 : int size,
992 : bool verbose = true);
993 :
994 :
995 : // Write the C code
996 : // const char* <varname> = "<str>";
997 : // const int <varname>_len = <len>;
998 : // to the file given by filename. Only the first len chars are written.
999 : int WriteAsCFile(const char* filename, const char* varname,
1000 : const char* str, int size, bool verbose = true);
1001 :
1002 :
1003 : // Simple support to read a file into std::string.
1004 : // On return, *exits tells whether the file existed.
1005 : V8_EXPORT_PRIVATE std::string ReadFile(const char* filename, bool* exists,
1006 : bool verbose = true);
1007 : std::string ReadFile(FILE* file, bool* exists, bool verbose = true);
1008 :
1009 : class StringBuilder : public SimpleStringBuilder {
1010 : public:
1011 : explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
1012 : StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
1013 :
1014 : // Add formatted contents to the builder just like printf().
1015 : void PRINTF_FORMAT(2, 3) AddFormatted(const char* format, ...);
1016 :
1017 : // Add formatted contents like printf based on a va_list.
1018 : void PRINTF_FORMAT(2, 0) AddFormattedList(const char* format, va_list list);
1019 :
1020 : private:
1021 : DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
1022 : };
1023 :
1024 :
1025 : bool DoubleToBoolean(double d);
1026 :
1027 : template <typename Char>
1028 : bool TryAddIndexChar(uint32_t* index, Char c);
1029 :
1030 : template <typename Stream>
1031 : bool StringToArrayIndex(Stream* stream, uint32_t* index);
1032 :
1033 : // Returns the current stack top. Works correctly with ASAN and SafeStack.
1034 : // GetCurrentStackPosition() should not be inlined, because it works on stack
1035 : // frames if it were inlined into a function with a huge stack frame it would
1036 : // return an address significantly above the actual current stack position.
1037 : V8_NOINLINE uintptr_t GetCurrentStackPosition();
1038 :
1039 : static inline uint16_t ByteReverse16(uint16_t value) {
1040 : #if V8_HAS_BUILTIN_BSWAP16
1041 : return __builtin_bswap16(value);
1042 : #else
1043 : return value << 8 | (value >> 8 & 0x00FF);
1044 : #endif
1045 : }
1046 :
1047 : static inline uint32_t ByteReverse32(uint32_t value) {
1048 : #if V8_HAS_BUILTIN_BSWAP32
1049 : return __builtin_bswap32(value);
1050 : #else
1051 : return value << 24 |
1052 : ((value << 8) & 0x00FF0000) |
1053 : ((value >> 8) & 0x0000FF00) |
1054 : ((value >> 24) & 0x00000FF);
1055 : #endif
1056 : }
1057 :
1058 : static inline uint64_t ByteReverse64(uint64_t value) {
1059 : #if V8_HAS_BUILTIN_BSWAP64
1060 : return __builtin_bswap64(value);
1061 : #else
1062 : size_t bits_of_v = sizeof(value) * kBitsPerByte;
1063 : return value << (bits_of_v - 8) |
1064 : ((value << (bits_of_v - 24)) & 0x00FF000000000000) |
1065 : ((value << (bits_of_v - 40)) & 0x0000FF0000000000) |
1066 : ((value << (bits_of_v - 56)) & 0x000000FF00000000) |
1067 : ((value >> (bits_of_v - 56)) & 0x00000000FF000000) |
1068 : ((value >> (bits_of_v - 40)) & 0x0000000000FF0000) |
1069 : ((value >> (bits_of_v - 24)) & 0x000000000000FF00) |
1070 : ((value >> (bits_of_v - 8)) & 0x00000000000000FF);
1071 : #endif
1072 : }
1073 :
1074 : template <typename V>
1075 : static inline V ByteReverse(V value) {
1076 : size_t size_of_v = sizeof(value);
1077 : switch (size_of_v) {
1078 : case 1:
1079 : return value;
1080 : case 2:
1081 : return static_cast<V>(ByteReverse16(static_cast<uint16_t>(value)));
1082 : case 4:
1083 : return static_cast<V>(ByteReverse32(static_cast<uint32_t>(value)));
1084 : case 8:
1085 : return static_cast<V>(ByteReverse64(static_cast<uint64_t>(value)));
1086 : default:
1087 : UNREACHABLE();
1088 : }
1089 : }
1090 :
1091 : V8_EXPORT_PRIVATE bool PassesFilter(Vector<const char> name,
1092 : Vector<const char> filter);
1093 :
1094 : // Zap the specified area with a specific byte pattern. This currently defaults
1095 : // to int3 on x64 and ia32. On other architectures this will produce unspecified
1096 : // instruction sequences.
1097 : // TODO(jgruber): Better support for other architectures.
1098 : V8_INLINE void ZapCode(Address addr, size_t size_in_bytes) {
1099 : static constexpr int kZapByte = 0xCC;
1100 0 : std::memset(reinterpret_cast<void*>(addr), kZapByte, size_in_bytes);
1101 : }
1102 :
1103 : } // namespace internal
1104 : } // namespace v8
1105 :
1106 : #endif // V8_UTILS_H_
|