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