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