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 : #if defined(V8_OS_AIX)
9 : #include <fenv.h> // NOLINT(build/c++11)
10 : #endif
11 : #include <limits.h>
12 : #include <stdlib.h>
13 : #include <string.h>
14 : #include <cmath>
15 : #include <type_traits>
16 :
17 : #include "include/v8.h"
18 : #include "src/allocation.h"
19 : #include "src/base/bits.h"
20 : #include "src/base/compiler-specific.h"
21 : #include "src/base/logging.h"
22 : #include "src/base/macros.h"
23 : #include "src/base/platform/platform.h"
24 : #include "src/globals.h"
25 : #include "src/vector.h"
26 : #include "src/zone/zone.h"
27 :
28 : namespace v8 {
29 : namespace internal {
30 :
31 : // ----------------------------------------------------------------------------
32 : // General helper functions
33 :
34 : // Returns the value (0 .. 15) of a hexadecimal character c.
35 : // If c is not a legal hexadecimal character, returns a value < 0.
36 : inline int HexValue(uc32 c) {
37 52852279 : c -= '0';
38 52852279 : if (static_cast<unsigned>(c) <= 9) return c;
39 6398793 : c = (c | 0x20) - ('a' - '0'); // detect 0x11..0x16 and 0x31..0x36.
40 6398793 : if (static_cast<unsigned>(c) <= 5) return c + 10;
41 : return -1;
42 : }
43 :
44 : inline char HexCharOfValue(int value) {
45 : DCHECK(0 <= value && value <= 16);
46 9113566 : if (value < 10) return value + '0';
47 592717 : return value - 10 + 'A';
48 : }
49 :
50 44890 : inline int BoolToInt(bool b) { return b ? 1 : 0; }
51 :
52 : // Same as strcmp, but can handle NULL arguments.
53 : inline bool CStringEquals(const char* s1, const char* s2) {
54 : return (s1 == s2) || (s1 != nullptr && s2 != nullptr && strcmp(s1, s2) == 0);
55 : }
56 :
57 : // X must be a power of 2. Returns the number of trailing zeros.
58 : template <typename T,
59 : typename = typename std::enable_if<std::is_integral<T>::value>::type>
60 2461 : inline int WhichPowerOf2(T x) {
61 : DCHECK(base::bits::IsPowerOfTwo(x));
62 : int bits = 0;
63 : #ifdef DEBUG
64 : const T original_x = x;
65 : #endif
66 : constexpr int max_bits = sizeof(T) * 8;
67 : static_assert(max_bits <= 64, "integral types are not bigger than 64 bits");
68 : // Avoid shifting by more than the bit width of x to avoid compiler warnings.
69 : #define CHECK_BIGGER(s) \
70 : if (max_bits > s && x >= T{1} << (max_bits > s ? s : 0)) { \
71 : bits += s; \
72 : x >>= max_bits > s ? s : 0; \
73 : }
74 : CHECK_BIGGER(32)
75 2461 : CHECK_BIGGER(16)
76 2461 : CHECK_BIGGER(8)
77 2461 : CHECK_BIGGER(4)
78 : #undef CHECK_BIGGER
79 2461 : switch (x) {
80 0 : default: UNREACHABLE();
81 379 : case 8: bits++; // Fall through.
82 817 : case 4: bits++; // Fall through.
83 1613 : case 2: bits++; // Fall through.
84 : case 1: break;
85 : }
86 : DCHECK_EQ(T{1} << bits, original_x);
87 2461 : return bits;
88 : }
89 :
90 : inline int MostSignificantBit(uint32_t x) {
91 : static const int msb4[] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};
92 : int nibble = 0;
93 : if (x & 0xffff0000) {
94 : nibble += 16;
95 : x >>= 16;
96 : }
97 : if (x & 0xff00) {
98 : nibble += 8;
99 : x >>= 8;
100 : }
101 : if (x & 0xf0) {
102 : nibble += 4;
103 : x >>= 4;
104 : }
105 : return nibble + msb4[x];
106 : }
107 :
108 : template <typename T>
109 804 : static T ArithmeticShiftRight(T x, int shift) {
110 : DCHECK_LE(0, shift);
111 1225 : if (x < 0) {
112 : // Right shift of signed values is implementation defined. Simulate a
113 : // true arithmetic right shift by adding leading sign bits.
114 : using UnsignedT = typename std::make_unsigned<T>::type;
115 298 : UnsignedT mask = ~(static_cast<UnsignedT>(~0) >> shift);
116 298 : return (static_cast<UnsignedT>(x) >> shift) | mask;
117 : } else {
118 927 : return x >> shift;
119 : }
120 : }
121 :
122 : template <typename T>
123 : int Compare(const T& a, const T& b) {
124 4722 : if (a == b)
125 : return 0;
126 4722 : else if (a < b)
127 : return -1;
128 : else
129 : return 1;
130 : }
131 :
132 : // Compare function to compare the object pointer value of two
133 : // handlified objects. The handles are passed as pointers to the
134 : // handles.
135 : template<typename T> class Handle; // Forward declaration.
136 : template <typename T>
137 : int HandleObjectPointerCompare(const Handle<T>* a, const Handle<T>* b) {
138 : return Compare<T*>(*(*a), *(*b));
139 : }
140 :
141 :
142 : template <typename T, typename U>
143 149262 : inline bool IsAligned(T value, U alignment) {
144 6668781 : return (value & (alignment - 1)) == 0;
145 : }
146 :
147 :
148 : // Returns true if (addr + offset) is aligned.
149 : inline bool IsAddressAligned(Address addr,
150 : intptr_t alignment,
151 : int offset = 0) {
152 : intptr_t offs = OffsetFrom(addr + offset);
153 : return IsAligned(offs, alignment);
154 : }
155 :
156 :
157 : // Returns the maximum of the two parameters.
158 : template <typename T>
159 12849 : constexpr T Max(T a, T b) {
160 173884317 : return a < b ? b : a;
161 : }
162 :
163 :
164 : // Returns the minimum of the two parameters.
165 : template <typename T>
166 7655732 : constexpr T Min(T a, T b) {
167 326004949 : return a < b ? a : b;
168 : }
169 :
170 : // Returns the maximum of the two parameters according to JavaScript semantics.
171 : template <typename T>
172 371403 : T JSMax(T x, T y) {
173 371403 : if (std::isnan(x)) return x;
174 363369 : if (std::isnan(y)) return y;
175 711078 : if (std::signbit(x) < std::signbit(y)) return x;
176 268473 : return x > y ? x : y;
177 : }
178 :
179 : // Returns the maximum of the two parameters according to JavaScript semantics.
180 : template <typename T>
181 371403 : T JSMin(T x, T y) {
182 371403 : if (std::isnan(x)) return x;
183 363369 : if (std::isnan(y)) return y;
184 711078 : if (std::signbit(x) < std::signbit(y)) return y;
185 268473 : return x > y ? y : x;
186 : }
187 :
188 : // Returns the absolute value of its argument.
189 : template <typename T,
190 : typename = typename std::enable_if<std::is_signed<T>::value>::type>
191 : typename std::make_unsigned<T>::type Abs(T a) {
192 : // This is a branch-free implementation of the absolute value function and is
193 : // described in Warren's "Hacker's Delight", chapter 2. It avoids undefined
194 : // behavior with the arithmetic negation operation on signed values as well.
195 : typedef typename std::make_unsigned<T>::type unsignedT;
196 7440 : unsignedT x = static_cast<unsignedT>(a);
197 7440 : unsignedT y = static_cast<unsignedT>(a >> (sizeof(T) * 8 - 1));
198 7440 : return (x ^ y) - y;
199 : }
200 :
201 : // Returns the negative absolute value of its argument.
202 : template <typename T,
203 : typename = typename std::enable_if<std::is_signed<T>::value>::type>
204 : T Nabs(T a) {
205 : return a < 0 ? a : -a;
206 : }
207 :
208 : // Floor(-0.0) == 0.0
209 : inline double Floor(double x) {
210 : #if V8_CC_MSVC
211 : if (x == 0) return x; // Fix for issue 3477.
212 : #endif
213 159853 : return std::floor(x);
214 : }
215 :
216 : inline double Modulo(double x, double y) {
217 : #if defined(V8_OS_WIN)
218 : // Workaround MS fmod bugs. ECMA-262 says:
219 : // dividend is finite and divisor is an infinity => result equals dividend
220 : // dividend is a zero and divisor is nonzero finite => result equals dividend
221 : if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) &&
222 : !(x == 0 && (y != 0 && std::isfinite(y)))) {
223 : x = fmod(x, y);
224 : }
225 : return x;
226 : #elif defined(V8_OS_AIX)
227 : // AIX raises an underflow exception for (Number.MIN_VALUE % Number.MAX_VALUE)
228 : feclearexcept(FE_ALL_EXCEPT);
229 : double result = std::fmod(x, y);
230 : int exception = fetestexcept(FE_UNDERFLOW);
231 : return (exception ? x : result);
232 : #else
233 468786 : return std::fmod(x, y);
234 : #endif
235 : }
236 :
237 23513 : inline double Pow(double x, double y) {
238 23513 : if (y == 0.0) return 1.0;
239 23135 : if (std::isnan(y) || ((x == 1 || x == -1) && std::isinf(y))) {
240 : return std::numeric_limits<double>::quiet_NaN();
241 : }
242 : #if (defined(__MINGW64_VERSION_MAJOR) && \
243 : (!defined(__MINGW64_VERSION_RC) || __MINGW64_VERSION_RC < 1)) || \
244 : defined(V8_OS_AIX)
245 : // MinGW64 and AIX have a custom implementation for pow. This handles certain
246 : // special cases that are different.
247 : if ((x == 0.0 || std::isinf(x)) && y != 0.0 && std::isfinite(y)) {
248 : double f;
249 : double result = ((x == 0.0) ^ (y > 0)) ? V8_INFINITY : 0;
250 : /* retain sign if odd integer exponent */
251 : return ((std::modf(y, &f) == 0.0) && (static_cast<int64_t>(y) & 1))
252 : ? copysign(result, x)
253 : : result;
254 : }
255 :
256 : if (x == 2.0) {
257 : int y_int = static_cast<int>(y);
258 : if (y == y_int) {
259 : return std::ldexp(1.0, y_int);
260 : }
261 : }
262 : #endif
263 22996 : return std::pow(x, y);
264 : }
265 :
266 : template <typename T>
267 : T SaturateAdd(T a, T b) {
268 : if (std::is_signed<T>::value) {
269 : if (a > 0 && b > 0) {
270 : if (a > std::numeric_limits<T>::max() - b) {
271 : return std::numeric_limits<T>::max();
272 : }
273 : } else if (a < 0 && b < 0) {
274 : if (a < std::numeric_limits<T>::min() - b) {
275 : return std::numeric_limits<T>::min();
276 : }
277 : }
278 : } else {
279 : CHECK(std::is_unsigned<T>::value);
280 : if (a > std::numeric_limits<T>::max() - b) {
281 : return std::numeric_limits<T>::max();
282 : }
283 : }
284 : return a + b;
285 : }
286 :
287 : template <typename T>
288 : T SaturateSub(T a, T b) {
289 : if (std::is_signed<T>::value) {
290 : if (a > 0 && b < 0) {
291 : if (a > std::numeric_limits<T>::max() + b) {
292 : return std::numeric_limits<T>::max();
293 : }
294 : } else if (a < 0 && b > 0) {
295 : if (a < std::numeric_limits<T>::min() + b) {
296 : return std::numeric_limits<T>::min();
297 : }
298 : }
299 : } else {
300 : CHECK(std::is_unsigned<T>::value);
301 : if (a < b) {
302 : return static_cast<T>(0);
303 : }
304 : }
305 : return a - b;
306 : }
307 :
308 : // ----------------------------------------------------------------------------
309 : // BitField is a help template for encoding and decode bitfield with
310 : // unsigned content.
311 :
312 : template<class T, int shift, int size, class U>
313 : class BitFieldBase {
314 : public:
315 : typedef T FieldType;
316 :
317 : // A type U mask of bit field. To use all bits of a type U of x bits
318 : // in a bitfield without compiler warnings we have to compute 2^x
319 : // without using a shift count of x in the computation.
320 : static const U kOne = static_cast<U>(1U);
321 : static const U kMask = ((kOne << shift) << size) - (kOne << shift);
322 : static const U kShift = shift;
323 : static const U kSize = size;
324 : static const U kNext = kShift + kSize;
325 : static const U kNumValues = kOne << size;
326 :
327 : // Value for the field with all bits set.
328 : static const T kMax = static_cast<T>(kNumValues - 1);
329 :
330 : // Tells whether the provided value fits into the bit field.
331 : static constexpr bool is_valid(T value) {
332 64178808 : return (static_cast<U>(value) & ~static_cast<U>(kMax)) == 0;
333 : }
334 :
335 : // Returns a type U with the bit field value encoded.
336 : static U encode(T value) {
337 : DCHECK(is_valid(value));
338 4308655799 : return static_cast<U>(value) << shift;
339 : }
340 :
341 : // Returns a type U with the bit field value updated.
342 : static U update(U previous, T value) {
343 4333249271 : return (previous & ~kMask) | encode(value);
344 : }
345 :
346 : // Extracts the bit field from the value.
347 61038 : static T decode(U value) {
348 38426053267 : return static_cast<T>((value & kMask) >> shift);
349 : }
350 :
351 : STATIC_ASSERT((kNext - 1) / 8 < sizeof(U));
352 : };
353 :
354 : template <class T, int shift, int size>
355 : class BitField8 : public BitFieldBase<T, shift, size, uint8_t> {};
356 :
357 :
358 : template <class T, int shift, int size>
359 : class BitField16 : public BitFieldBase<T, shift, size, uint16_t> {};
360 :
361 :
362 : template<class T, int shift, int size>
363 : class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
364 :
365 :
366 : template<class T, int shift, int size>
367 : class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
368 :
369 : // Helper macros for defining a contiguous sequence of bit fields. Example:
370 : // (backslashes at the ends of respective lines of this multi-line macro
371 : // definition are omitted here to please the compiler)
372 : //
373 : // #define MAP_BIT_FIELD1(V, _)
374 : // V(IsAbcBit, bool, 1, _)
375 : // V(IsBcdBit, bool, 1, _)
376 : // V(CdeBits, int, 5, _)
377 : // V(DefBits, MutableMode, 1, _)
378 : //
379 : // DEFINE_BIT_FIELDS(MAP_BIT_FIELD1)
380 : // or
381 : // DEFINE_BIT_FIELDS_64(MAP_BIT_FIELD1)
382 : //
383 : #define DEFINE_BIT_FIELD_RANGE_TYPE(Name, Type, Size, _) \
384 : k##Name##Start, k##Name##End = k##Name##Start + Size - 1,
385 :
386 : #define DEFINE_BIT_RANGES(LIST_MACRO) \
387 : struct LIST_MACRO##_Ranges { \
388 : enum { LIST_MACRO(DEFINE_BIT_FIELD_RANGE_TYPE, _) }; \
389 : };
390 :
391 : #define DEFINE_BIT_FIELD_TYPE(Name, Type, Size, RangesName) \
392 : typedef BitField<Type, RangesName::k##Name##Start, Size> Name;
393 :
394 : #define DEFINE_BIT_FIELD_64_TYPE(Name, Type, Size, RangesName) \
395 : typedef BitField64<Type, RangesName::k##Name##Start, Size> Name;
396 :
397 : #define DEFINE_BIT_FIELDS(LIST_MACRO) \
398 : DEFINE_BIT_RANGES(LIST_MACRO) \
399 : LIST_MACRO(DEFINE_BIT_FIELD_TYPE, LIST_MACRO##_Ranges)
400 :
401 : #define DEFINE_BIT_FIELDS_64(LIST_MACRO) \
402 : DEFINE_BIT_RANGES(LIST_MACRO) \
403 : LIST_MACRO(DEFINE_BIT_FIELD_64_TYPE, LIST_MACRO##_Ranges)
404 :
405 : // ----------------------------------------------------------------------------
406 : // BitSetComputer is a help template for encoding and decoding information for
407 : // a variable number of items in an array.
408 : //
409 : // To encode boolean data in a smi array you would use:
410 : // typedef BitSetComputer<bool, 1, kSmiValueSize, uint32_t> BoolComputer;
411 : //
412 : template <class T, int kBitsPerItem, int kBitsPerWord, class U>
413 : class BitSetComputer {
414 : public:
415 : static const int kItemsPerWord = kBitsPerWord / kBitsPerItem;
416 : static const int kMask = (1 << kBitsPerItem) - 1;
417 :
418 : // The number of array elements required to embed T information for each item.
419 : static int word_count(int items) {
420 11529722 : if (items == 0) return 0;
421 1662823 : return (items - 1) / kItemsPerWord + 1;
422 : }
423 :
424 : // The array index to look at for item.
425 : static int index(int base_index, int item) {
426 102945415 : return base_index + item / kItemsPerWord;
427 : }
428 :
429 : // Extract T data for a given item from data.
430 : static T decode(U data, int item) {
431 70932692 : return static_cast<T>((data >> shift(item)) & kMask);
432 : }
433 :
434 : // Return the encoding for a store of value for item in previous.
435 : static U encode(U previous, int item, T value) {
436 : int shift_value = shift(item);
437 32017223 : int set_bits = (static_cast<int>(value) << shift_value);
438 32017223 : return (previous & ~(kMask << shift_value)) | set_bits;
439 : }
440 :
441 102945415 : static int shift(int item) { return (item % kItemsPerWord) * kBitsPerItem; }
442 : };
443 :
444 : // Helper macros for defining a contiguous sequence of field offset constants.
445 : // Example: (backslashes at the ends of respective lines of this multi-line
446 : // macro definition are omitted here to please the compiler)
447 : //
448 : // #define MAP_FIELDS(V)
449 : // V(kField1Offset, kPointerSize)
450 : // V(kField2Offset, kIntSize)
451 : // V(kField3Offset, kIntSize)
452 : // V(kField4Offset, kPointerSize)
453 : // V(kSize, 0)
454 : //
455 : // DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, MAP_FIELDS)
456 : //
457 : #define DEFINE_ONE_FIELD_OFFSET(Name, Size) Name, Name##End = Name + Size - 1,
458 :
459 : #define DEFINE_FIELD_OFFSET_CONSTANTS(StartOffset, LIST_MACRO) \
460 : enum { \
461 : LIST_MACRO##_StartOffset = StartOffset - 1, \
462 : LIST_MACRO(DEFINE_ONE_FIELD_OFFSET) \
463 : };
464 :
465 : // ----------------------------------------------------------------------------
466 : // Hash function.
467 :
468 : static const uint32_t kZeroHashSeed = 0;
469 :
470 : // Thomas Wang, Integer Hash Functions.
471 : // http://www.concentric.net/~Ttwang/tech/inthash.htm
472 : inline uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed) {
473 : uint32_t hash = key;
474 98951577 : hash = hash ^ seed;
475 210446726 : hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
476 210446726 : hash = hash ^ (hash >> 12);
477 210446726 : hash = hash + (hash << 2);
478 210446726 : hash = hash ^ (hash >> 4);
479 210446726 : hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11);
480 210446726 : hash = hash ^ (hash >> 16);
481 210446726 : return hash & 0x3fffffff;
482 : }
483 :
484 : inline uint32_t ComputeIntegerHash(uint32_t key) {
485 : return ComputeIntegerHash(key, kZeroHashSeed);
486 : }
487 :
488 : inline uint32_t ComputeLongHash(uint64_t key) {
489 : uint64_t hash = key;
490 918746 : hash = ~hash + (hash << 18); // hash = (hash << 18) - hash - 1;
491 918746 : hash = hash ^ (hash >> 31);
492 918746 : hash = hash * 21; // hash = (hash + (hash << 2)) + (hash << 4);
493 918746 : hash = hash ^ (hash >> 11);
494 918746 : hash = hash + (hash << 6);
495 918746 : hash = hash ^ (hash >> 22);
496 918746 : return static_cast<uint32_t>(hash);
497 : }
498 :
499 :
500 : inline uint32_t ComputePointerHash(void* ptr) {
501 : return ComputeIntegerHash(
502 10237000 : static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)));
503 : }
504 :
505 :
506 : // ----------------------------------------------------------------------------
507 : // Generated memcpy/memmove
508 :
509 : // Initializes the codegen support that depends on CPU features.
510 : void init_memcopy_functions(Isolate* isolate);
511 :
512 : #if defined(V8_TARGET_ARCH_IA32)
513 : // Limit below which the extra overhead of the MemCopy function is likely
514 : // to outweigh the benefits of faster copying.
515 : const int kMinComplexMemCopy = 64;
516 :
517 : // Copy memory area. No restrictions.
518 : V8_EXPORT_PRIVATE void MemMove(void* dest, const void* src, size_t size);
519 : typedef void (*MemMoveFunction)(void* dest, const void* src, size_t size);
520 :
521 : // Keep the distinction of "move" vs. "copy" for the benefit of other
522 : // architectures.
523 : V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
524 : MemMove(dest, src, size);
525 : }
526 : #elif defined(V8_HOST_ARCH_ARM)
527 : typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
528 : size_t size);
529 : V8_EXPORT_PRIVATE extern MemCopyUint8Function memcopy_uint8_function;
530 : V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
531 : size_t chars) {
532 : memcpy(dest, src, chars);
533 : }
534 : // For values < 16, the assembler function is slower than the inlined C code.
535 : const int kMinComplexMemCopy = 16;
536 : V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
537 : (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
538 : reinterpret_cast<const uint8_t*>(src), size);
539 : }
540 : V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
541 : size_t size) {
542 : memmove(dest, src, size);
543 : }
544 :
545 : typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest, const uint8_t* src,
546 : size_t size);
547 : extern MemCopyUint16Uint8Function memcopy_uint16_uint8_function;
548 : void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
549 : size_t chars);
550 : // For values < 12, the assembler function is slower than the inlined C code.
551 : const int kMinComplexConvertMemCopy = 12;
552 : V8_INLINE void MemCopyUint16Uint8(uint16_t* dest, const uint8_t* src,
553 : size_t size) {
554 : (*memcopy_uint16_uint8_function)(dest, src, size);
555 : }
556 : #elif defined(V8_HOST_ARCH_MIPS)
557 : typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
558 : size_t size);
559 : V8_EXPORT_PRIVATE extern MemCopyUint8Function memcopy_uint8_function;
560 : V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
561 : size_t chars) {
562 : memcpy(dest, src, chars);
563 : }
564 : // For values < 16, the assembler function is slower than the inlined C code.
565 : const int kMinComplexMemCopy = 16;
566 : V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
567 : (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
568 : reinterpret_cast<const uint8_t*>(src), size);
569 : }
570 : V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
571 : size_t size) {
572 : memmove(dest, src, size);
573 : }
574 : #else
575 : // Copy memory area to disjoint memory area.
576 : V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
577 : memcpy(dest, src, size);
578 : }
579 : V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
580 : size_t size) {
581 : memmove(dest, src, size);
582 : }
583 : const int kMinComplexMemCopy = 8;
584 : #endif // V8_TARGET_ARCH_IA32
585 :
586 :
587 : // ----------------------------------------------------------------------------
588 : // Miscellaneous
589 :
590 : // Memory offset for lower and higher bits in a 64 bit integer.
591 : #if defined(V8_TARGET_LITTLE_ENDIAN)
592 : static const int kInt64LowerHalfMemoryOffset = 0;
593 : static const int kInt64UpperHalfMemoryOffset = 4;
594 : #elif defined(V8_TARGET_BIG_ENDIAN)
595 : static const int kInt64LowerHalfMemoryOffset = 4;
596 : static const int kInt64UpperHalfMemoryOffset = 0;
597 : #endif // V8_TARGET_LITTLE_ENDIAN
598 :
599 : // A static resource holds a static instance that can be reserved in
600 : // a local scope using an instance of Access. Attempts to re-reserve
601 : // the instance will cause an error.
602 : template <typename T>
603 : class StaticResource {
604 : public:
605 1064573 : StaticResource() : is_reserved_(false) {}
606 :
607 : private:
608 : template <typename S> friend class Access;
609 : T instance_;
610 : bool is_reserved_;
611 : };
612 :
613 :
614 : // Locally scoped access to a static resource.
615 : template <typename T>
616 : class Access {
617 : public:
618 : explicit Access(StaticResource<T>* resource)
619 : : resource_(resource)
620 5949 : , instance_(&resource->instance_) {
621 : DCHECK(!resource->is_reserved_);
622 5949 : resource->is_reserved_ = true;
623 : }
624 :
625 : ~Access() {
626 5949 : resource_->is_reserved_ = false;
627 : resource_ = nullptr;
628 : instance_ = nullptr;
629 : }
630 :
631 : T* value() { return instance_; }
632 : T* operator -> () { return instance_; }
633 :
634 : private:
635 : StaticResource<T>* resource_;
636 : T* instance_;
637 : };
638 :
639 : // A pointer that can only be set once and doesn't allow NULL values.
640 : template<typename T>
641 : class SetOncePointer {
642 : public:
643 2823504 : SetOncePointer() : pointer_(nullptr) {}
644 :
645 7177360 : bool is_set() const { return pointer_ != nullptr; }
646 :
647 : T* get() const {
648 : DCHECK_NOT_NULL(pointer_);
649 7177360 : return pointer_;
650 : }
651 :
652 : void set(T* value) {
653 : DCHECK(pointer_ == nullptr && value != nullptr);
654 591220 : pointer_ = value;
655 : }
656 :
657 : private:
658 : T* pointer_;
659 : };
660 :
661 :
662 : template <typename T, int kSize>
663 : class EmbeddedVector : public Vector<T> {
664 : public:
665 84 : EmbeddedVector() : Vector<T>(buffer_, kSize) { }
666 :
667 : explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) {
668 0 : for (int i = 0; i < kSize; ++i) {
669 0 : buffer_[i] = initial_value;
670 : }
671 : }
672 :
673 : // When copying, make underlying Vector to reference our buffer.
674 : EmbeddedVector(const EmbeddedVector& rhs)
675 : : Vector<T>(rhs) {
676 : MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
677 : this->set_start(buffer_);
678 : }
679 :
680 : EmbeddedVector& operator=(const EmbeddedVector& rhs) {
681 : if (this == &rhs) return *this;
682 : Vector<T>::operator=(rhs);
683 : MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
684 : this->set_start(buffer_);
685 : return *this;
686 : }
687 :
688 : private:
689 : T buffer_[kSize];
690 : };
691 :
692 : // Compare 8bit/16bit chars to 8bit/16bit chars.
693 : template <typename lchar, typename rchar>
694 : inline int CompareCharsUnsigned(const lchar* lhs, const rchar* rhs,
695 : size_t chars) {
696 845596 : const lchar* limit = lhs + chars;
697 : if (sizeof(*lhs) == sizeof(char) && sizeof(*rhs) == sizeof(char)) {
698 : // memcmp compares byte-by-byte, yielding wrong results for two-byte
699 : // strings on little-endian systems.
700 172799985 : return memcmp(lhs, rhs, chars);
701 : }
702 57378357 : while (lhs < limit) {
703 56553022 : int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
704 56553022 : if (r != 0) return r;
705 56532761 : ++lhs;
706 56532761 : ++rhs;
707 : }
708 : return 0;
709 : }
710 :
711 : template <typename lchar, typename rchar>
712 : inline int CompareChars(const lchar* lhs, const rchar* rhs, size_t chars) {
713 : DCHECK_LE(sizeof(lchar), 2);
714 : DCHECK_LE(sizeof(rchar), 2);
715 : if (sizeof(lchar) == 1) {
716 : if (sizeof(rchar) == 1) {
717 : return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
718 : reinterpret_cast<const uint8_t*>(rhs),
719 : chars);
720 : } else {
721 : return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
722 : reinterpret_cast<const uint16_t*>(rhs),
723 : chars);
724 : }
725 : } else {
726 : if (sizeof(rchar) == 1) {
727 : return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
728 : reinterpret_cast<const uint8_t*>(rhs),
729 : chars);
730 : } else {
731 : return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
732 : reinterpret_cast<const uint16_t*>(rhs),
733 : chars);
734 : }
735 : }
736 : }
737 :
738 :
739 : // Calculate 10^exponent.
740 : inline int TenToThe(int exponent) {
741 : DCHECK_LE(exponent, 9);
742 : DCHECK_GE(exponent, 1);
743 : int answer = 10;
744 : for (int i = 1; i < exponent; i++) answer *= 10;
745 : return answer;
746 : }
747 :
748 :
749 : template<typename ElementType, int NumElements>
750 : class EmbeddedContainer {
751 : public:
752 : EmbeddedContainer() : elems_() { }
753 :
754 : int length() const { return NumElements; }
755 : const ElementType& operator[](int i) const {
756 : DCHECK(i < length());
757 : return elems_[i];
758 : }
759 : ElementType& operator[](int i) {
760 : DCHECK(i < length());
761 : return elems_[i];
762 : }
763 :
764 : private:
765 : ElementType elems_[NumElements];
766 : };
767 :
768 :
769 : template<typename ElementType>
770 : class EmbeddedContainer<ElementType, 0> {
771 : public:
772 : int length() const { return 0; }
773 : const ElementType& operator[](int i) const {
774 : UNREACHABLE();
775 : static ElementType t = 0;
776 : return t;
777 : }
778 : ElementType& operator[](int i) {
779 : UNREACHABLE();
780 : static ElementType t = 0;
781 : return t;
782 : }
783 : };
784 :
785 :
786 : // Helper class for building result strings in a character buffer. The
787 : // purpose of the class is to use safe operations that checks the
788 : // buffer bounds on all operations in debug mode.
789 : // This simple base class does not allow formatted output.
790 : class SimpleStringBuilder {
791 : public:
792 : // Create a string builder with a buffer of the given size. The
793 : // buffer is allocated through NewArray<char> and must be
794 : // deallocated by the caller of Finalize().
795 : explicit SimpleStringBuilder(int size);
796 :
797 : SimpleStringBuilder(char* buffer, int size)
798 5476290 : : buffer_(buffer, size), position_(0) { }
799 :
800 2748675 : ~SimpleStringBuilder() { if (!is_finalized()) Finalize(); }
801 :
802 : int size() const { return buffer_.length(); }
803 :
804 : // Get the current position in the builder.
805 : int position() const {
806 : DCHECK(!is_finalized());
807 : return position_;
808 : }
809 :
810 : // Reset the position.
811 0 : void Reset() { position_ = 0; }
812 :
813 : // Add a single character to the builder. It is not allowed to add
814 : // 0-characters; use the Finalize() method to terminate the string
815 : // instead.
816 : void AddCharacter(char c) {
817 : DCHECK_NE(c, '\0');
818 : DCHECK(!is_finalized() && position_ < buffer_.length());
819 4741864 : buffer_[position_++] = c;
820 : }
821 :
822 : // Add an entire string to the builder. Uses strlen() internally to
823 : // compute the length of the input string.
824 : void AddString(const char* s);
825 :
826 : // Add the first 'n' characters of the given 0-terminated string 's' to the
827 : // builder. The input string must have enough characters.
828 : void AddSubstring(const char* s, int n);
829 :
830 : // Add character padding to the builder. If count is non-positive,
831 : // nothing is added to the builder.
832 : void AddPadding(char c, int count);
833 :
834 : // Add the decimal representation of the value.
835 : void AddDecimalInteger(int value);
836 :
837 : // Finalize the string by 0-terminating it and returning the buffer.
838 : char* Finalize();
839 :
840 : protected:
841 : Vector<char> buffer_;
842 : int position_;
843 :
844 : bool is_finalized() const { return position_ < 0; }
845 :
846 : private:
847 : DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder);
848 : };
849 :
850 :
851 : // A poor man's version of STL's bitset: A bit set of enums E (without explicit
852 : // values), fitting into an integral type T.
853 : template <class E, class T = int>
854 : class EnumSet {
855 : public:
856 4558128 : explicit EnumSet(T bits = 0) : bits_(bits) {}
857 : bool IsEmpty() const { return bits_ == 0; }
858 8405474 : bool Contains(E element) const { return (bits_ & Mask(element)) != 0; }
859 : bool ContainsAnyOf(const EnumSet& set) const {
860 : return (bits_ & set.bits_) != 0;
861 : }
862 659651 : void Add(E element) { bits_ |= Mask(element); }
863 : void Add(const EnumSet& set) { bits_ |= set.bits_; }
864 12195 : void Remove(E element) { bits_ &= ~Mask(element); }
865 : void Remove(const EnumSet& set) { bits_ &= ~set.bits_; }
866 : void RemoveAll() { bits_ = 0; }
867 : void Intersect(const EnumSet& set) { bits_ &= set.bits_; }
868 3547 : T ToIntegral() const { return bits_; }
869 : bool operator==(const EnumSet& set) { return bits_ == set.bits_; }
870 : bool operator!=(const EnumSet& set) { return bits_ != set.bits_; }
871 : EnumSet operator|(const EnumSet& set) const {
872 6 : return EnumSet(bits_ | set.bits_);
873 : }
874 :
875 : private:
876 : static_assert(std::is_enum<E>::value, "EnumSet can only be used with enums");
877 :
878 : T Mask(E element) const {
879 : DCHECK_GT(sizeof(T) * CHAR_BIT, static_cast<int>(element));
880 650706 : return T{1} << static_cast<typename std::underlying_type<E>::type>(element);
881 : }
882 :
883 : T bits_;
884 : };
885 :
886 : // Bit field extraction.
887 : inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) {
888 : return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
889 : }
890 :
891 : inline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) {
892 : return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
893 : }
894 :
895 : inline int32_t signed_bitextract_32(int msb, int lsb, int32_t x) {
896 : return (x << (31 - msb)) >> (lsb + 31 - msb);
897 : }
898 :
899 : inline int signed_bitextract_64(int msb, int lsb, int x) {
900 : // TODO(jbramley): This is broken for big bitfields.
901 : return (x << (63 - msb)) >> (lsb + 63 - msb);
902 : }
903 :
904 : // Check number width.
905 : inline bool is_intn(int64_t x, unsigned n) {
906 : DCHECK((0 < n) && (n < 64));
907 : int64_t limit = static_cast<int64_t>(1) << (n - 1);
908 50594584 : return (-limit <= x) && (x < limit);
909 : }
910 :
911 : inline bool is_uintn(int64_t x, unsigned n) {
912 : DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
913 21249259 : return !(x >> n);
914 : }
915 :
916 : template <class T>
917 : inline T truncate_to_intn(T x, unsigned n) {
918 : DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
919 : return (x & ((static_cast<T>(1) << n) - 1));
920 : }
921 :
922 : #define INT_1_TO_63_LIST(V) \
923 : V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \
924 : V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \
925 : V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \
926 : V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32) \
927 : V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \
928 : V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \
929 : V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \
930 : V(57) V(58) V(59) V(60) V(61) V(62) V(63)
931 :
932 : #define DECLARE_IS_INT_N(N) \
933 : inline bool is_int##N(int64_t x) { return is_intn(x, N); }
934 : #define DECLARE_IS_UINT_N(N) \
935 : template <class T> \
936 : inline bool is_uint##N(T x) { return is_uintn(x, N); }
937 : #define DECLARE_TRUNCATE_TO_INT_N(N) \
938 : template <class T> \
939 : inline T truncate_to_int##N(T x) { return truncate_to_intn(x, N); }
940 : INT_1_TO_63_LIST(DECLARE_IS_INT_N)
941 3318429 : INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
942 : INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
943 : #undef DECLARE_IS_INT_N
944 : #undef DECLARE_IS_UINT_N
945 : #undef DECLARE_TRUNCATE_TO_INT_N
946 :
947 : class FeedbackSlot {
948 : public:
949 2314126 : FeedbackSlot() : id_(kInvalidSlot) {}
950 1779215 : explicit FeedbackSlot(int id) : id_(id) {}
951 :
952 1634672 : int ToInt() const { return id_; }
953 :
954 : static FeedbackSlot Invalid() { return FeedbackSlot(); }
955 2517525 : bool IsInvalid() const { return id_ == kInvalidSlot; }
956 :
957 18 : bool operator==(FeedbackSlot that) const { return this->id_ == that.id_; }
958 : bool operator!=(FeedbackSlot that) const { return !(*this == that); }
959 :
960 0 : friend size_t hash_value(FeedbackSlot slot) { return slot.ToInt(); }
961 : friend std::ostream& operator<<(std::ostream& os, FeedbackSlot);
962 :
963 : private:
964 : static const int kInvalidSlot = -1;
965 :
966 : int id_;
967 : };
968 :
969 :
970 : class BailoutId {
971 : public:
972 6853322 : explicit BailoutId(int id) : id_(id) { }
973 3294395 : int ToInt() const { return id_; }
974 :
975 : static BailoutId None() { return BailoutId(kNoneId); }
976 : static BailoutId ScriptContext() { return BailoutId(kScriptContextId); }
977 : static BailoutId FunctionContext() { return BailoutId(kFunctionContextId); }
978 : static BailoutId FunctionEntry() { return BailoutId(kFunctionEntryId); }
979 : static BailoutId Declarations() { return BailoutId(kDeclarationsId); }
980 : static BailoutId FirstUsable() { return BailoutId(kFirstUsableId); }
981 : static BailoutId StubEntry() { return BailoutId(kStubEntryId); }
982 :
983 : // Special bailout id support for deopting into the {JSConstructStub} stub.
984 : // The following hard-coded deoptimization points are supported by the stub:
985 : // - {ConstructStubCreate} maps to {construct_stub_create_deopt_pc_offset}.
986 : // - {ConstructStubInvoke} maps to {construct_stub_invoke_deopt_pc_offset}.
987 : static BailoutId ConstructStubCreate() { return BailoutId(1); }
988 : static BailoutId ConstructStubInvoke() { return BailoutId(2); }
989 : bool IsValidForConstructStub() const {
990 : return id_ == ConstructStubCreate().ToInt() ||
991 : id_ == ConstructStubInvoke().ToInt();
992 : }
993 :
994 6317849 : bool IsNone() const { return id_ == kNoneId; }
995 2 : bool operator==(const BailoutId& other) const { return id_ == other.id_; }
996 2156 : bool operator!=(const BailoutId& other) const { return id_ != other.id_; }
997 : friend size_t hash_value(BailoutId);
998 : V8_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream&, BailoutId);
999 :
1000 : private:
1001 : friend class Builtins;
1002 :
1003 : static const int kNoneId = -1;
1004 :
1005 : // Using 0 could disguise errors.
1006 : static const int kScriptContextId = 1;
1007 : static const int kFunctionContextId = 2;
1008 : static const int kFunctionEntryId = 3;
1009 :
1010 : // This AST id identifies the point after the declarations have been visited.
1011 : // We need it to capture the environment effects of declarations that emit
1012 : // code (function declarations).
1013 : static const int kDeclarationsId = 4;
1014 :
1015 : // Every FunctionState starts with this id.
1016 : static const int kFirstUsableId = 5;
1017 :
1018 : // Every compiled stub starts with this id.
1019 : static const int kStubEntryId = 6;
1020 :
1021 : // Builtin continuations bailout ids start here. If you need to add a
1022 : // non-builtin BailoutId, add it before this id so that this Id has the
1023 : // highest number.
1024 : static const int kFirstBuiltinContinuationId = 7;
1025 :
1026 : int id_;
1027 : };
1028 :
1029 :
1030 : // ----------------------------------------------------------------------------
1031 : // I/O support.
1032 :
1033 : // Our version of printf().
1034 : V8_EXPORT_PRIVATE void PRINTF_FORMAT(1, 2) PrintF(const char* format, ...);
1035 : void PRINTF_FORMAT(2, 3) PrintF(FILE* out, const char* format, ...);
1036 :
1037 : // Prepends the current process ID to the output.
1038 : void PRINTF_FORMAT(1, 2) PrintPID(const char* format, ...);
1039 :
1040 : // Prepends the current process ID and given isolate pointer to the output.
1041 : void PRINTF_FORMAT(2, 3) PrintIsolate(void* isolate, const char* format, ...);
1042 :
1043 : // Safe formatting print. Ensures that str is always null-terminated.
1044 : // Returns the number of chars written, or -1 if output was truncated.
1045 : int PRINTF_FORMAT(2, 3) SNPrintF(Vector<char> str, const char* format, ...);
1046 : V8_EXPORT_PRIVATE int PRINTF_FORMAT(2, 0)
1047 : VSNPrintF(Vector<char> str, const char* format, va_list args);
1048 :
1049 : void StrNCpy(Vector<char> dest, const char* src, size_t n);
1050 :
1051 : // Our version of fflush.
1052 : void Flush(FILE* out);
1053 :
1054 : inline void Flush() {
1055 : Flush(stdout);
1056 : }
1057 :
1058 :
1059 : // Read a line of characters after printing the prompt to stdout. The resulting
1060 : // char* needs to be disposed off with DeleteArray by the caller.
1061 : char* ReadLine(const char* prompt);
1062 :
1063 :
1064 : // Read and return the raw bytes in a file. the size of the buffer is returned
1065 : // in size.
1066 : // The returned buffer must be freed by the caller.
1067 : byte* ReadBytes(const char* filename, int* size, bool verbose = true);
1068 :
1069 :
1070 : // Append size chars from str to the file given by filename.
1071 : // The file is overwritten. Returns the number of chars written.
1072 : int AppendChars(const char* filename,
1073 : const char* str,
1074 : int size,
1075 : bool verbose = true);
1076 :
1077 :
1078 : // Write size chars from str to the file given by filename.
1079 : // The file is overwritten. Returns the number of chars written.
1080 : int WriteChars(const char* filename,
1081 : const char* str,
1082 : int size,
1083 : bool verbose = true);
1084 :
1085 :
1086 : // Write size bytes to the file given by filename.
1087 : // The file is overwritten. Returns the number of bytes written.
1088 : int WriteBytes(const char* filename,
1089 : const byte* bytes,
1090 : int size,
1091 : bool verbose = true);
1092 :
1093 :
1094 : // Write the C code
1095 : // const char* <varname> = "<str>";
1096 : // const int <varname>_len = <len>;
1097 : // to the file given by filename. Only the first len chars are written.
1098 : int WriteAsCFile(const char* filename, const char* varname,
1099 : const char* str, int size, bool verbose = true);
1100 :
1101 :
1102 : // ----------------------------------------------------------------------------
1103 : // Memory
1104 :
1105 : // Copies words from |src| to |dst|. The data spans must not overlap.
1106 : template <typename T>
1107 139668189 : inline void CopyWords(T* dst, const T* src, size_t num_words) {
1108 : STATIC_ASSERT(sizeof(T) == kPointerSize);
1109 : DCHECK(Min(dst, const_cast<T*>(src)) + num_words <=
1110 : Max(dst, const_cast<T*>(src)));
1111 : DCHECK_GT(num_words, 0);
1112 :
1113 : // Use block copying MemCopy if the segment we're copying is
1114 : // enough to justify the extra call/setup overhead.
1115 : static const size_t kBlockCopyLimit = 16;
1116 :
1117 139668189 : if (num_words < kBlockCopyLimit) {
1118 576232237 : do {
1119 576232237 : num_words--;
1120 576232237 : *dst++ = *src++;
1121 : } while (num_words > 0);
1122 : } else {
1123 4815024 : MemCopy(dst, src, num_words * kPointerSize);
1124 : }
1125 139668189 : }
1126 :
1127 :
1128 : // Copies words from |src| to |dst|. No restrictions.
1129 : template <typename T>
1130 : inline void MoveWords(T* dst, const T* src, size_t num_words) {
1131 : STATIC_ASSERT(sizeof(T) == kPointerSize);
1132 : DCHECK_GT(num_words, 0);
1133 :
1134 : // Use block copying MemCopy if the segment we're copying is
1135 : // enough to justify the extra call/setup overhead.
1136 : static const size_t kBlockCopyLimit = 16;
1137 :
1138 : if (num_words < kBlockCopyLimit &&
1139 : ((dst < src) || (dst >= (src + num_words * kPointerSize)))) {
1140 : T* end = dst + num_words;
1141 : do {
1142 : num_words--;
1143 : *dst++ = *src++;
1144 : } while (num_words > 0);
1145 : } else {
1146 : MemMove(dst, src, num_words * kPointerSize);
1147 : }
1148 : }
1149 :
1150 :
1151 : // Copies data from |src| to |dst|. The data spans must not overlap.
1152 : template <typename T>
1153 5542321 : inline void CopyBytes(T* dst, const T* src, size_t num_bytes) {
1154 : STATIC_ASSERT(sizeof(T) == 1);
1155 : DCHECK(Min(dst, const_cast<T*>(src)) + num_bytes <=
1156 : Max(dst, const_cast<T*>(src)));
1157 11084642 : if (num_bytes == 0) return;
1158 :
1159 : // Use block copying MemCopy if the segment we're copying is
1160 : // enough to justify the extra call/setup overhead.
1161 : static const int kBlockCopyLimit = kMinComplexMemCopy;
1162 :
1163 5240575 : if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) {
1164 4646291 : do {
1165 4646291 : num_bytes--;
1166 4646291 : *dst++ = *src++;
1167 : } while (num_bytes > 0);
1168 : } else {
1169 : MemCopy(dst, src, num_bytes);
1170 : }
1171 : }
1172 :
1173 :
1174 : template <typename T, typename U>
1175 0 : inline void MemsetPointer(T** dest, U* value, int counter) {
1176 : #ifdef DEBUG
1177 : T* a = nullptr;
1178 : U* b = nullptr;
1179 : a = b; // Fake assignment to check assignability.
1180 : USE(a);
1181 : #endif // DEBUG
1182 : #if V8_HOST_ARCH_IA32
1183 : #define STOS "stosl"
1184 : #elif V8_HOST_ARCH_X64
1185 : #if V8_HOST_ARCH_32_BIT
1186 : #define STOS "addr32 stosl"
1187 : #else
1188 : #define STOS "stosq"
1189 : #endif
1190 : #endif
1191 :
1192 : #if defined(MEMORY_SANITIZER)
1193 : // MemorySanitizer does not understand inline assembly.
1194 : #undef STOS
1195 : #endif
1196 :
1197 : #if defined(__GNUC__) && defined(STOS)
1198 : asm volatile(
1199 : "cld;"
1200 : "rep ; " STOS
1201 : : "+&c" (counter), "+&D" (dest)
1202 : : "a" (value)
1203 67126801 : : "memory", "cc");
1204 : #else
1205 : for (int i = 0; i < counter; i++) {
1206 : dest[i] = value;
1207 : }
1208 : #endif
1209 :
1210 : #undef STOS
1211 0 : }
1212 :
1213 :
1214 : // Simple support to read a file into a 0-terminated C-string.
1215 : // The returned buffer must be freed by the caller.
1216 : // On return, *exits tells whether the file existed.
1217 : V8_EXPORT_PRIVATE Vector<const char> ReadFile(const char* filename,
1218 : bool* exists,
1219 : bool verbose = true);
1220 : Vector<const char> ReadFile(FILE* file,
1221 : bool* exists,
1222 : bool verbose = true);
1223 :
1224 :
1225 : template <typename sourcechar, typename sinkchar>
1226 : INLINE(static void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src,
1227 : size_t chars));
1228 : #if defined(V8_HOST_ARCH_ARM)
1229 : INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars));
1230 : INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src,
1231 : size_t chars));
1232 : INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1233 : size_t chars));
1234 : #elif defined(V8_HOST_ARCH_MIPS)
1235 : INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars));
1236 : INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1237 : size_t chars));
1238 : #elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390)
1239 : INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars));
1240 : INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1241 : size_t chars));
1242 : #endif
1243 :
1244 : // Copy from 8bit/16bit chars to 8bit/16bit chars.
1245 : template <typename sourcechar, typename sinkchar>
1246 : INLINE(void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars));
1247 :
1248 : template <typename sourcechar, typename sinkchar>
1249 : void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars) {
1250 : DCHECK_LE(sizeof(sourcechar), 2);
1251 : DCHECK_LE(sizeof(sinkchar), 2);
1252 : if (sizeof(sinkchar) == 1) {
1253 : if (sizeof(sourcechar) == 1) {
1254 : CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1255 : reinterpret_cast<const uint8_t*>(src),
1256 : chars);
1257 : } else {
1258 : CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1259 : reinterpret_cast<const uint16_t*>(src),
1260 : chars);
1261 : }
1262 : } else {
1263 : if (sizeof(sourcechar) == 1) {
1264 : CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1265 : reinterpret_cast<const uint8_t*>(src),
1266 : chars);
1267 : } else {
1268 : CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1269 : reinterpret_cast<const uint16_t*>(src),
1270 : chars);
1271 : }
1272 : }
1273 : }
1274 :
1275 : template <typename sourcechar, typename sinkchar>
1276 : void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, size_t chars) {
1277 343677553 : sinkchar* limit = dest + chars;
1278 204465240 : if ((sizeof(*dest) == sizeof(*src)) &&
1279 : (chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest)))) {
1280 : MemCopy(dest, src, chars * sizeof(*dest));
1281 : } else {
1282 5581019065 : while (dest < limit) *dest++ = static_cast<sinkchar>(*src++);
1283 : }
1284 : }
1285 :
1286 :
1287 : #if defined(V8_HOST_ARCH_ARM)
1288 : void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
1289 : switch (static_cast<unsigned>(chars)) {
1290 : case 0:
1291 : break;
1292 : case 1:
1293 : *dest = *src;
1294 : break;
1295 : case 2:
1296 : memcpy(dest, src, 2);
1297 : break;
1298 : case 3:
1299 : memcpy(dest, src, 3);
1300 : break;
1301 : case 4:
1302 : memcpy(dest, src, 4);
1303 : break;
1304 : case 5:
1305 : memcpy(dest, src, 5);
1306 : break;
1307 : case 6:
1308 : memcpy(dest, src, 6);
1309 : break;
1310 : case 7:
1311 : memcpy(dest, src, 7);
1312 : break;
1313 : case 8:
1314 : memcpy(dest, src, 8);
1315 : break;
1316 : case 9:
1317 : memcpy(dest, src, 9);
1318 : break;
1319 : case 10:
1320 : memcpy(dest, src, 10);
1321 : break;
1322 : case 11:
1323 : memcpy(dest, src, 11);
1324 : break;
1325 : case 12:
1326 : memcpy(dest, src, 12);
1327 : break;
1328 : case 13:
1329 : memcpy(dest, src, 13);
1330 : break;
1331 : case 14:
1332 : memcpy(dest, src, 14);
1333 : break;
1334 : case 15:
1335 : memcpy(dest, src, 15);
1336 : break;
1337 : default:
1338 : MemCopy(dest, src, chars);
1339 : break;
1340 : }
1341 : }
1342 :
1343 :
1344 : void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, size_t chars) {
1345 : if (chars >= static_cast<size_t>(kMinComplexConvertMemCopy)) {
1346 : MemCopyUint16Uint8(dest, src, chars);
1347 : } else {
1348 : MemCopyUint16Uint8Wrapper(dest, src, chars);
1349 : }
1350 : }
1351 :
1352 :
1353 : void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
1354 : switch (static_cast<unsigned>(chars)) {
1355 : case 0:
1356 : break;
1357 : case 1:
1358 : *dest = *src;
1359 : break;
1360 : case 2:
1361 : memcpy(dest, src, 4);
1362 : break;
1363 : case 3:
1364 : memcpy(dest, src, 6);
1365 : break;
1366 : case 4:
1367 : memcpy(dest, src, 8);
1368 : break;
1369 : case 5:
1370 : memcpy(dest, src, 10);
1371 : break;
1372 : case 6:
1373 : memcpy(dest, src, 12);
1374 : break;
1375 : case 7:
1376 : memcpy(dest, src, 14);
1377 : break;
1378 : default:
1379 : MemCopy(dest, src, chars * sizeof(*dest));
1380 : break;
1381 : }
1382 : }
1383 :
1384 :
1385 : #elif defined(V8_HOST_ARCH_MIPS)
1386 : void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
1387 : if (chars < kMinComplexMemCopy) {
1388 : memcpy(dest, src, chars);
1389 : } else {
1390 : MemCopy(dest, src, chars);
1391 : }
1392 : }
1393 :
1394 : void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
1395 : if (chars < kMinComplexMemCopy) {
1396 : memcpy(dest, src, chars * sizeof(*dest));
1397 : } else {
1398 : MemCopy(dest, src, chars * sizeof(*dest));
1399 : }
1400 : }
1401 : #elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390)
1402 : #define CASE(n) \
1403 : case n: \
1404 : memcpy(dest, src, n); \
1405 : break
1406 : void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
1407 : switch (static_cast<unsigned>(chars)) {
1408 : case 0:
1409 : break;
1410 : case 1:
1411 : *dest = *src;
1412 : break;
1413 : CASE(2);
1414 : CASE(3);
1415 : CASE(4);
1416 : CASE(5);
1417 : CASE(6);
1418 : CASE(7);
1419 : CASE(8);
1420 : CASE(9);
1421 : CASE(10);
1422 : CASE(11);
1423 : CASE(12);
1424 : CASE(13);
1425 : CASE(14);
1426 : CASE(15);
1427 : CASE(16);
1428 : CASE(17);
1429 : CASE(18);
1430 : CASE(19);
1431 : CASE(20);
1432 : CASE(21);
1433 : CASE(22);
1434 : CASE(23);
1435 : CASE(24);
1436 : CASE(25);
1437 : CASE(26);
1438 : CASE(27);
1439 : CASE(28);
1440 : CASE(29);
1441 : CASE(30);
1442 : CASE(31);
1443 : CASE(32);
1444 : CASE(33);
1445 : CASE(34);
1446 : CASE(35);
1447 : CASE(36);
1448 : CASE(37);
1449 : CASE(38);
1450 : CASE(39);
1451 : CASE(40);
1452 : CASE(41);
1453 : CASE(42);
1454 : CASE(43);
1455 : CASE(44);
1456 : CASE(45);
1457 : CASE(46);
1458 : CASE(47);
1459 : CASE(48);
1460 : CASE(49);
1461 : CASE(50);
1462 : CASE(51);
1463 : CASE(52);
1464 : CASE(53);
1465 : CASE(54);
1466 : CASE(55);
1467 : CASE(56);
1468 : CASE(57);
1469 : CASE(58);
1470 : CASE(59);
1471 : CASE(60);
1472 : CASE(61);
1473 : CASE(62);
1474 : CASE(63);
1475 : CASE(64);
1476 : default:
1477 : memcpy(dest, src, chars);
1478 : break;
1479 : }
1480 : }
1481 : #undef CASE
1482 :
1483 : #define CASE(n) \
1484 : case n: \
1485 : memcpy(dest, src, n * 2); \
1486 : break
1487 : void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
1488 : switch (static_cast<unsigned>(chars)) {
1489 : case 0:
1490 : break;
1491 : case 1:
1492 : *dest = *src;
1493 : break;
1494 : CASE(2);
1495 : CASE(3);
1496 : CASE(4);
1497 : CASE(5);
1498 : CASE(6);
1499 : CASE(7);
1500 : CASE(8);
1501 : CASE(9);
1502 : CASE(10);
1503 : CASE(11);
1504 : CASE(12);
1505 : CASE(13);
1506 : CASE(14);
1507 : CASE(15);
1508 : CASE(16);
1509 : CASE(17);
1510 : CASE(18);
1511 : CASE(19);
1512 : CASE(20);
1513 : CASE(21);
1514 : CASE(22);
1515 : CASE(23);
1516 : CASE(24);
1517 : CASE(25);
1518 : CASE(26);
1519 : CASE(27);
1520 : CASE(28);
1521 : CASE(29);
1522 : CASE(30);
1523 : CASE(31);
1524 : CASE(32);
1525 : default:
1526 : memcpy(dest, src, chars * 2);
1527 : break;
1528 : }
1529 : }
1530 : #undef CASE
1531 : #endif
1532 :
1533 :
1534 : class StringBuilder : public SimpleStringBuilder {
1535 : public:
1536 : explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
1537 : StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
1538 :
1539 : // Add formatted contents to the builder just like printf().
1540 : void PRINTF_FORMAT(2, 3) AddFormatted(const char* format, ...);
1541 :
1542 : // Add formatted contents like printf based on a va_list.
1543 : void PRINTF_FORMAT(2, 0) AddFormattedList(const char* format, va_list list);
1544 :
1545 : private:
1546 : DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
1547 : };
1548 :
1549 :
1550 : bool DoubleToBoolean(double d);
1551 :
1552 : template <typename Stream>
1553 : bool StringToArrayIndex(Stream* stream, uint32_t* index);
1554 :
1555 : // Returns current value of top of the stack. Works correctly with ASAN.
1556 : DISABLE_ASAN
1557 407273267 : inline uintptr_t GetCurrentStackPosition() {
1558 : // Takes the address of the limit variable in order to find out where
1559 : // the top of stack is right now.
1560 1123086645 : uintptr_t limit = reinterpret_cast<uintptr_t>(&limit);
1561 407273267 : return limit;
1562 : }
1563 :
1564 : template <typename V>
1565 : static inline V ReadUnalignedValue(const void* p) {
1566 : #if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM)
1567 44502688 : return *reinterpret_cast<const V*>(p);
1568 : #else // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM
1569 : V r;
1570 : memmove(&r, p, sizeof(V));
1571 : return r;
1572 : #endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM
1573 : }
1574 :
1575 : template <typename V>
1576 : static inline void WriteUnalignedValue(void* p, V value) {
1577 : #if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM)
1578 18567345 : *(reinterpret_cast<V*>(p)) = value;
1579 : #else // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM
1580 : memmove(p, &value, sizeof(V));
1581 : #endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_ARM
1582 : }
1583 :
1584 : static inline double ReadFloatValue(const void* p) {
1585 : return ReadUnalignedValue<float>(p);
1586 : }
1587 :
1588 : static inline double ReadDoubleValue(const void* p) {
1589 : return ReadUnalignedValue<double>(p);
1590 : }
1591 :
1592 : static inline void WriteDoubleValue(void* p, double value) {
1593 : WriteUnalignedValue(p, value);
1594 : }
1595 :
1596 : static inline uint16_t ReadUnalignedUInt16(const void* p) {
1597 : return ReadUnalignedValue<uint16_t>(p);
1598 : }
1599 :
1600 : static inline void WriteUnalignedUInt16(void* p, uint16_t value) {
1601 : WriteUnalignedValue(p, value);
1602 : }
1603 :
1604 : static inline uint32_t ReadUnalignedUInt32(const void* p) {
1605 : return ReadUnalignedValue<uint32_t>(p);
1606 : }
1607 :
1608 : static inline void WriteUnalignedUInt32(void* p, uint32_t value) {
1609 : WriteUnalignedValue(p, value);
1610 : }
1611 :
1612 : template <typename V>
1613 : static inline V ReadLittleEndianValue(const void* p) {
1614 : #if defined(V8_TARGET_LITTLE_ENDIAN)
1615 : return ReadUnalignedValue<V>(p);
1616 : #elif defined(V8_TARGET_BIG_ENDIAN)
1617 : V ret = 0;
1618 : const byte* src = reinterpret_cast<const byte*>(p);
1619 : byte* dst = reinterpret_cast<byte*>(&ret);
1620 : for (size_t i = 0; i < sizeof(V); i++) {
1621 : dst[i] = src[sizeof(V) - i - 1];
1622 : }
1623 : return ret;
1624 : #endif // V8_TARGET_LITTLE_ENDIAN
1625 : }
1626 :
1627 : template <typename V>
1628 : static inline void WriteLittleEndianValue(void* p, V value) {
1629 : #if defined(V8_TARGET_LITTLE_ENDIAN)
1630 : WriteUnalignedValue<V>(p, value);
1631 : #elif defined(V8_TARGET_BIG_ENDIAN)
1632 : byte* src = reinterpret_cast<byte*>(&value);
1633 : byte* dst = reinterpret_cast<byte*>(p);
1634 : for (size_t i = 0; i < sizeof(V); i++) {
1635 : dst[i] = src[sizeof(V) - i - 1];
1636 : }
1637 : #endif // V8_TARGET_LITTLE_ENDIAN
1638 : }
1639 :
1640 : // Represents a linked list that threads through the nodes in the linked list.
1641 : // Entries in the list are pointers to nodes. The nodes need to have a T**
1642 : // next() method that returns the location where the next value is stored.
1643 : template <typename T>
1644 : class ThreadedList final {
1645 : public:
1646 28613106 : ThreadedList() : head_(nullptr), tail_(&head_) {}
1647 8529616 : void Add(T* v) {
1648 : DCHECK_NULL(*tail_);
1649 : DCHECK_NULL(*v->next());
1650 62751881 : *tail_ = v;
1651 62751881 : tail_ = v->next();
1652 8529616 : }
1653 :
1654 : void Clear() {
1655 4437898 : head_ = nullptr;
1656 4437898 : tail_ = &head_;
1657 : }
1658 :
1659 : class Iterator final {
1660 : public:
1661 : Iterator& operator++() {
1662 76571223 : entry_ = (*entry_)->next();
1663 : return *this;
1664 : }
1665 : bool operator!=(const Iterator& other) { return entry_ != other.entry_; }
1666 76619325 : T* operator*() { return *entry_; }
1667 154206 : T* operator->() { return *entry_; }
1668 : Iterator& operator=(T* entry) {
1669 0 : T* next = *(*entry_)->next();
1670 0 : *entry->next() = next;
1671 0 : *entry_ = entry;
1672 : return *this;
1673 : }
1674 :
1675 : private:
1676 : explicit Iterator(T** entry) : entry_(entry) {}
1677 :
1678 : T** entry_;
1679 :
1680 : friend class ThreadedList;
1681 : };
1682 :
1683 : class ConstIterator final {
1684 : public:
1685 7861111 : ConstIterator& operator++() {
1686 7911335 : entry_ = (*entry_)->next();
1687 7861111 : return *this;
1688 : }
1689 13524053 : bool operator!=(const ConstIterator& other) {
1690 13524053 : return entry_ != other.entry_;
1691 : }
1692 7912235 : const T* operator*() const { return *entry_; }
1693 :
1694 : private:
1695 : explicit ConstIterator(T* const* entry) : entry_(entry) {}
1696 :
1697 : T* const* entry_;
1698 :
1699 : friend class ThreadedList;
1700 : };
1701 :
1702 20649273 : Iterator begin() { return Iterator(&head_); }
1703 : Iterator end() { return Iterator(tail_); }
1704 :
1705 5692971 : ConstIterator begin() const { return ConstIterator(&head_); }
1706 5662943 : ConstIterator end() const { return ConstIterator(tail_); }
1707 :
1708 : void Rewind(Iterator reset_point) {
1709 1554688 : tail_ = reset_point.entry_;
1710 1554688 : *tail_ = nullptr;
1711 : }
1712 :
1713 777278 : void MoveTail(ThreadedList<T>* parent, Iterator location) {
1714 777278 : if (parent->end() != location) {
1715 : DCHECK_NULL(*tail_);
1716 264 : *tail_ = *location;
1717 132 : tail_ = parent->tail_;
1718 : parent->Rewind(location);
1719 : }
1720 : }
1721 :
1722 : bool is_empty() const { return head_ == nullptr; }
1723 :
1724 : // Slow. For testing purposes.
1725 220 : int LengthForTest() {
1726 : int result = 0;
1727 360 : for (Iterator t = begin(); t != end(); ++t) ++result;
1728 : return result;
1729 : }
1730 : T* AtForTest(int i) {
1731 : Iterator t = begin();
1732 2100 : while (i-- > 0) ++t;
1733 : return *t;
1734 : }
1735 :
1736 : private:
1737 : T* head_;
1738 : T** tail_;
1739 : DISALLOW_COPY_AND_ASSIGN(ThreadedList);
1740 : };
1741 :
1742 : // Can be used to create a threaded list of |T|.
1743 : template <typename T>
1744 : class ThreadedListZoneEntry final : public ZoneObject {
1745 : public:
1746 547499 : explicit ThreadedListZoneEntry(T value) : value_(value), next_(nullptr) {}
1747 :
1748 : T value() { return value_; }
1749 : ThreadedListZoneEntry<T>** next() { return &next_; }
1750 :
1751 : private:
1752 : T value_;
1753 : ThreadedListZoneEntry<T>* next_;
1754 : DISALLOW_COPY_AND_ASSIGN(ThreadedListZoneEntry);
1755 : };
1756 :
1757 : } // namespace internal
1758 : } // namespace v8
1759 :
1760 : #endif // V8_UTILS_H_
|