• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_UTILS_H_
6 #define V8_UTILS_H_
7 
8 #include <limits.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <cmath>
12 #include <string>
13 #include <type_traits>
14 
15 #include "include/v8.h"
16 #include "src/allocation.h"
17 #include "src/base/bits.h"
18 #include "src/base/compiler-specific.h"
19 #include "src/base/logging.h"
20 #include "src/base/macros.h"
21 #include "src/base/platform/platform.h"
22 #include "src/base/v8-fallthrough.h"
23 #include "src/globals.h"
24 #include "src/vector.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
ComputeIntegerHash(uint32_t key,uint64_t seed)480 inline uint32_t ComputeIntegerHash(uint32_t key, uint64_t seed) {
481   uint32_t hash = key;
482   hash = hash ^ static_cast<uint32_t>(seed);
483   hash = ~hash + (hash << 15);  // hash = (hash << 15) - hash - 1;
484   hash = hash ^ (hash >> 12);
485   hash = hash + (hash << 2);
486   hash = hash ^ (hash >> 4);
487   hash = hash * 2057;  // hash = (hash + (hash << 3)) + (hash << 11);
488   hash = hash ^ (hash >> 16);
489   return hash & 0x3fffffff;
490 }
491 
ComputeIntegerHash(uint32_t key)492 inline uint32_t ComputeIntegerHash(uint32_t key) {
493   return ComputeIntegerHash(key, kZeroHashSeed);
494 }
495 
ComputeLongHash(uint64_t key)496 inline uint32_t ComputeLongHash(uint64_t key) {
497   uint64_t hash = key;
498   hash = ~hash + (hash << 18);  // hash = (hash << 18) - hash - 1;
499   hash = hash ^ (hash >> 31);
500   hash = hash * 21;  // hash = (hash + (hash << 2)) + (hash << 4);
501   hash = hash ^ (hash >> 11);
502   hash = hash + (hash << 6);
503   hash = hash ^ (hash >> 22);
504   return static_cast<uint32_t>(hash);
505 }
506 
507 
ComputePointerHash(void * ptr)508 inline uint32_t ComputePointerHash(void* ptr) {
509   return ComputeIntegerHash(
510       static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)));
511 }
512 
ComputeAddressHash(Address address)513 inline uint32_t ComputeAddressHash(Address address) {
514   return ComputeIntegerHash(static_cast<uint32_t>(address & 0xFFFFFFFFul));
515 }
516 
517 // ----------------------------------------------------------------------------
518 // Generated memcpy/memmove
519 
520 // Initializes the codegen support that depends on CPU features.
521 void init_memcopy_functions(Isolate* isolate);
522 
523 #if defined(V8_TARGET_ARCH_IA32)
524 // Limit below which the extra overhead of the MemCopy function is likely
525 // to outweigh the benefits of faster copying.
526 const int kMinComplexMemCopy = 64;
527 
528 // Copy memory area. No restrictions.
529 V8_EXPORT_PRIVATE void MemMove(void* dest, const void* src, size_t size);
530 typedef void (*MemMoveFunction)(void* dest, const void* src, size_t size);
531 
532 // Keep the distinction of "move" vs. "copy" for the benefit of other
533 // architectures.
MemCopy(void * dest,const void * src,size_t size)534 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
535   MemMove(dest, src, size);
536 }
537 #elif defined(V8_HOST_ARCH_ARM)
538 typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
539                                      size_t size);
540 V8_EXPORT_PRIVATE extern MemCopyUint8Function memcopy_uint8_function;
MemCopyUint8Wrapper(uint8_t * dest,const uint8_t * src,size_t chars)541 V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
542                                    size_t chars) {
543   memcpy(dest, src, chars);
544 }
545 // For values < 16, the assembler function is slower than the inlined C code.
546 const int kMinComplexMemCopy = 16;
MemCopy(void * dest,const void * src,size_t size)547 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
548   (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
549                             reinterpret_cast<const uint8_t*>(src), size);
550 }
MemMove(void * dest,const void * src,size_t size)551 V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
552                                          size_t size) {
553   memmove(dest, src, size);
554 }
555 
556 typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest, const uint8_t* src,
557                                            size_t size);
558 extern MemCopyUint16Uint8Function memcopy_uint16_uint8_function;
559 void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
560                                size_t chars);
561 // For values < 12, the assembler function is slower than the inlined C code.
562 const int kMinComplexConvertMemCopy = 12;
MemCopyUint16Uint8(uint16_t * dest,const uint8_t * src,size_t size)563 V8_INLINE void MemCopyUint16Uint8(uint16_t* dest, const uint8_t* src,
564                                   size_t size) {
565   (*memcopy_uint16_uint8_function)(dest, src, size);
566 }
567 #elif defined(V8_HOST_ARCH_MIPS)
568 typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
569                                      size_t size);
570 V8_EXPORT_PRIVATE extern MemCopyUint8Function memcopy_uint8_function;
MemCopyUint8Wrapper(uint8_t * dest,const uint8_t * src,size_t chars)571 V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
572                                    size_t chars) {
573   memcpy(dest, src, chars);
574 }
575 // For values < 16, the assembler function is slower than the inlined C code.
576 const int kMinComplexMemCopy = 16;
MemCopy(void * dest,const void * src,size_t size)577 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
578   (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
579                             reinterpret_cast<const uint8_t*>(src), size);
580 }
MemMove(void * dest,const void * src,size_t size)581 V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
582                                          size_t size) {
583   memmove(dest, src, size);
584 }
585 #else
586 // Copy memory area to disjoint memory area.
MemCopy(void * dest,const void * src,size_t size)587 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
588   memcpy(dest, src, size);
589 }
MemMove(void * dest,const void * src,size_t size)590 V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src,
591                                          size_t size) {
592   memmove(dest, src, size);
593 }
594 const int kMinComplexMemCopy = 8;
595 #endif  // V8_TARGET_ARCH_IA32
596 
597 
598 // ----------------------------------------------------------------------------
599 // Miscellaneous
600 
601 // Memory offset for lower and higher bits in a 64 bit integer.
602 #if defined(V8_TARGET_LITTLE_ENDIAN)
603 static const int kInt64LowerHalfMemoryOffset = 0;
604 static const int kInt64UpperHalfMemoryOffset = 4;
605 #elif defined(V8_TARGET_BIG_ENDIAN)
606 static const int kInt64LowerHalfMemoryOffset = 4;
607 static const int kInt64UpperHalfMemoryOffset = 0;
608 #endif  // V8_TARGET_LITTLE_ENDIAN
609 
610 // A static resource holds a static instance that can be reserved in
611 // a local scope using an instance of Access.  Attempts to re-reserve
612 // the instance will cause an error.
613 template <typename T>
614 class StaticResource {
615  public:
StaticResource()616   StaticResource() : is_reserved_(false)  {}
617 
618  private:
619   template <typename S> friend class Access;
620   T instance_;
621   bool is_reserved_;
622 };
623 
624 
625 // Locally scoped access to a static resource.
626 template <typename T>
627 class Access {
628  public:
Access(StaticResource<T> * resource)629   explicit Access(StaticResource<T>* resource)
630     : resource_(resource)
631     , instance_(&resource->instance_) {
632     DCHECK(!resource->is_reserved_);
633     resource->is_reserved_ = true;
634   }
635 
~Access()636   ~Access() {
637     resource_->is_reserved_ = false;
638     resource_ = nullptr;
639     instance_ = nullptr;
640   }
641 
value()642   T* value()  { return instance_; }
643   T* operator -> ()  { return instance_; }
644 
645  private:
646   StaticResource<T>* resource_;
647   T* instance_;
648 };
649 
650 // A pointer that can only be set once and doesn't allow NULL values.
651 template<typename T>
652 class SetOncePointer {
653  public:
654   SetOncePointer() = default;
655 
is_set()656   bool is_set() const { return pointer_ != nullptr; }
657 
get()658   T* get() const {
659     DCHECK_NOT_NULL(pointer_);
660     return pointer_;
661   }
662 
set(T * value)663   void set(T* value) {
664     DCHECK(pointer_ == nullptr && value != nullptr);
665     pointer_ = value;
666   }
667 
668   T* operator=(T* value) {
669     set(value);
670     return value;
671   }
672 
673   bool operator==(std::nullptr_t) const { return pointer_ == nullptr; }
674   bool operator!=(std::nullptr_t) const { return pointer_ != nullptr; }
675 
676  private:
677   T* pointer_ = nullptr;
678 };
679 
680 
681 template <typename T, int kSize>
682 class EmbeddedVector : public Vector<T> {
683  public:
EmbeddedVector()684   EmbeddedVector() : Vector<T>(buffer_, kSize) { }
685 
EmbeddedVector(T initial_value)686   explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) {
687     for (int i = 0; i < kSize; ++i) {
688       buffer_[i] = initial_value;
689     }
690   }
691 
692   // When copying, make underlying Vector to reference our buffer.
EmbeddedVector(const EmbeddedVector & rhs)693   EmbeddedVector(const EmbeddedVector& rhs)
694       : Vector<T>(rhs) {
695     MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
696     this->set_start(buffer_);
697   }
698 
699   EmbeddedVector& operator=(const EmbeddedVector& rhs) {
700     if (this == &rhs) return *this;
701     Vector<T>::operator=(rhs);
702     MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
703     this->set_start(buffer_);
704     return *this;
705   }
706 
707  private:
708   T buffer_[kSize];
709 };
710 
711 // Compare 8bit/16bit chars to 8bit/16bit chars.
712 template <typename lchar, typename rchar>
CompareCharsUnsigned(const lchar * lhs,const rchar * rhs,size_t chars)713 inline int CompareCharsUnsigned(const lchar* lhs, const rchar* rhs,
714                                 size_t chars) {
715   const lchar* limit = lhs + chars;
716   if (sizeof(*lhs) == sizeof(char) && sizeof(*rhs) == sizeof(char)) {
717     // memcmp compares byte-by-byte, yielding wrong results for two-byte
718     // strings on little-endian systems.
719     return memcmp(lhs, rhs, chars);
720   }
721   while (lhs < limit) {
722     int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
723     if (r != 0) return r;
724     ++lhs;
725     ++rhs;
726   }
727   return 0;
728 }
729 
730 template <typename lchar, typename rchar>
CompareChars(const lchar * lhs,const rchar * rhs,size_t chars)731 inline int CompareChars(const lchar* lhs, const rchar* rhs, size_t chars) {
732   DCHECK_LE(sizeof(lchar), 2);
733   DCHECK_LE(sizeof(rchar), 2);
734   if (sizeof(lchar) == 1) {
735     if (sizeof(rchar) == 1) {
736       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
737                                   reinterpret_cast<const uint8_t*>(rhs),
738                                   chars);
739     } else {
740       return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
741                                   reinterpret_cast<const uint16_t*>(rhs),
742                                   chars);
743     }
744   } else {
745     if (sizeof(rchar) == 1) {
746       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
747                                   reinterpret_cast<const uint8_t*>(rhs),
748                                   chars);
749     } else {
750       return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
751                                   reinterpret_cast<const uint16_t*>(rhs),
752                                   chars);
753     }
754   }
755 }
756 
757 
758 // Calculate 10^exponent.
TenToThe(int exponent)759 inline int TenToThe(int exponent) {
760   DCHECK_LE(exponent, 9);
761   DCHECK_GE(exponent, 1);
762   int answer = 10;
763   for (int i = 1; i < exponent; i++) answer *= 10;
764   return answer;
765 }
766 
767 
768 template<typename ElementType, int NumElements>
769 class EmbeddedContainer {
770  public:
EmbeddedContainer()771   EmbeddedContainer() : elems_() { }
772 
length()773   int length() const { return NumElements; }
774   const ElementType& operator[](int i) const {
775     DCHECK(i < length());
776     return elems_[i];
777   }
778   ElementType& operator[](int i) {
779     DCHECK(i < length());
780     return elems_[i];
781   }
782 
783  private:
784   ElementType elems_[NumElements];
785 };
786 
787 
788 template<typename ElementType>
789 class EmbeddedContainer<ElementType, 0> {
790  public:
length()791   int length() const { return 0; }
792   const ElementType& operator[](int i) const {
793     UNREACHABLE();
794     static ElementType t = 0;
795     return t;
796   }
797   ElementType& operator[](int i) {
798     UNREACHABLE();
799     static ElementType t = 0;
800     return t;
801   }
802 };
803 
804 
805 // Helper class for building result strings in a character buffer. The
806 // purpose of the class is to use safe operations that checks the
807 // buffer bounds on all operations in debug mode.
808 // This simple base class does not allow formatted output.
809 class SimpleStringBuilder {
810  public:
811   // Create a string builder with a buffer of the given size. The
812   // buffer is allocated through NewArray<char> and must be
813   // deallocated by the caller of Finalize().
814   explicit SimpleStringBuilder(int size);
815 
SimpleStringBuilder(char * buffer,int size)816   SimpleStringBuilder(char* buffer, int size)
817       : buffer_(buffer, size), position_(0) { }
818 
~SimpleStringBuilder()819   ~SimpleStringBuilder() { if (!is_finalized()) Finalize(); }
820 
size()821   int size() const { return buffer_.length(); }
822 
823   // Get the current position in the builder.
position()824   int position() const {
825     DCHECK(!is_finalized());
826     return position_;
827   }
828 
829   // Reset the position.
Reset()830   void Reset() { position_ = 0; }
831 
832   // Add a single character to the builder. It is not allowed to add
833   // 0-characters; use the Finalize() method to terminate the string
834   // instead.
AddCharacter(char c)835   void AddCharacter(char c) {
836     DCHECK_NE(c, '\0');
837     DCHECK(!is_finalized() && position_ < buffer_.length());
838     buffer_[position_++] = c;
839   }
840 
841   // Add an entire string to the builder. Uses strlen() internally to
842   // compute the length of the input string.
843   void AddString(const char* s);
844 
845   // Add the first 'n' characters of the given 0-terminated string 's' to the
846   // builder. The input string must have enough characters.
847   void AddSubstring(const char* s, int n);
848 
849   // Add character padding to the builder. If count is non-positive,
850   // nothing is added to the builder.
851   void AddPadding(char c, int count);
852 
853   // Add the decimal representation of the value.
854   void AddDecimalInteger(int value);
855 
856   // Finalize the string by 0-terminating it and returning the buffer.
857   char* Finalize();
858 
859  protected:
860   Vector<char> buffer_;
861   int position_;
862 
is_finalized()863   bool is_finalized() const { return position_ < 0; }
864 
865  private:
866   DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder);
867 };
868 
869 
870 // A poor man's version of STL's bitset: A bit set of enums E (without explicit
871 // values), fitting into an integral type T.
872 template <class E, class T = int>
873 class EnumSet {
874  public:
bits_(bits)875   explicit EnumSet(T bits = 0) : bits_(bits) {}
IsEmpty()876   bool IsEmpty() const { return bits_ == 0; }
Contains(E element)877   bool Contains(E element) const { return (bits_ & Mask(element)) != 0; }
ContainsAnyOf(const EnumSet & set)878   bool ContainsAnyOf(const EnumSet& set) const {
879     return (bits_ & set.bits_) != 0;
880   }
Add(E element)881   void Add(E element) { bits_ |= Mask(element); }
Add(const EnumSet & set)882   void Add(const EnumSet& set) { bits_ |= set.bits_; }
Remove(E element)883   void Remove(E element) { bits_ &= ~Mask(element); }
Remove(const EnumSet & set)884   void Remove(const EnumSet& set) { bits_ &= ~set.bits_; }
RemoveAll()885   void RemoveAll() { bits_ = 0; }
Intersect(const EnumSet & set)886   void Intersect(const EnumSet& set) { bits_ &= set.bits_; }
ToIntegral()887   T ToIntegral() const { return bits_; }
888   bool operator==(const EnumSet& set) { return bits_ == set.bits_; }
889   bool operator!=(const EnumSet& set) { return bits_ != set.bits_; }
890   EnumSet operator|(const EnumSet& set) const {
891     return EnumSet(bits_ | set.bits_);
892   }
893 
894  private:
895   static_assert(std::is_enum<E>::value, "EnumSet can only be used with enums");
896 
Mask(E element)897   T Mask(E element) const {
898     DCHECK_GT(sizeof(T) * CHAR_BIT, static_cast<int>(element));
899     return T{1} << static_cast<typename std::underlying_type<E>::type>(element);
900   }
901 
902   T bits_;
903 };
904 
905 // Bit field extraction.
unsigned_bitextract_32(int msb,int lsb,uint32_t x)906 inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) {
907   return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
908 }
909 
unsigned_bitextract_64(int msb,int lsb,uint64_t x)910 inline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) {
911   return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
912 }
913 
signed_bitextract_32(int msb,int lsb,int32_t x)914 inline int32_t signed_bitextract_32(int msb, int lsb, int32_t x) {
915   return (x << (31 - msb)) >> (lsb + 31 - msb);
916 }
917 
signed_bitextract_64(int msb,int lsb,int x)918 inline int signed_bitextract_64(int msb, int lsb, int x) {
919   // TODO(jbramley): This is broken for big bitfields.
920   return (x << (63 - msb)) >> (lsb + 63 - msb);
921 }
922 
923 // Check number width.
is_intn(int64_t x,unsigned n)924 inline bool is_intn(int64_t x, unsigned n) {
925   DCHECK((0 < n) && (n < 64));
926   int64_t limit = static_cast<int64_t>(1) << (n - 1);
927   return (-limit <= x) && (x < limit);
928 }
929 
is_uintn(int64_t x,unsigned n)930 inline bool is_uintn(int64_t x, unsigned n) {
931   DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
932   return !(x >> n);
933 }
934 
935 template <class T>
truncate_to_intn(T x,unsigned n)936 inline T truncate_to_intn(T x, unsigned n) {
937   DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
938   return (x & ((static_cast<T>(1) << n) - 1));
939 }
940 
941 #define INT_1_TO_63_LIST(V)                                                    \
942 V(1)  V(2)  V(3)  V(4)  V(5)  V(6)  V(7)  V(8)                                 \
943 V(9)  V(10) V(11) V(12) V(13) V(14) V(15) V(16)                                \
944 V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24)                                \
945 V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32)                                \
946 V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40)                                \
947 V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48)                                \
948 V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56)                                \
949 V(57) V(58) V(59) V(60) V(61) V(62) V(63)
950 
951 #define DECLARE_IS_INT_N(N)                                                    \
952 inline bool is_int##N(int64_t x) { return is_intn(x, N); }
953 #define DECLARE_IS_UINT_N(N)                                                   \
954 template <class T>                                                             \
955 inline bool is_uint##N(T x) { return is_uintn(x, N); }
956 #define DECLARE_TRUNCATE_TO_INT_N(N)                                           \
957 template <class T>                                                             \
958 inline T truncate_to_int##N(T x) { return truncate_to_intn(x, N); }
959 INT_1_TO_63_LIST(DECLARE_IS_INT_N)
INT_1_TO_63_LIST(DECLARE_IS_UINT_N)960 INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
961 INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
962 #undef DECLARE_IS_INT_N
963 #undef DECLARE_IS_UINT_N
964 #undef DECLARE_TRUNCATE_TO_INT_N
965 
966 class FeedbackSlot {
967  public:
968   FeedbackSlot() : id_(kInvalidSlot) {}
969   explicit FeedbackSlot(int id) : id_(id) {}
970 
971   int ToInt() const { return id_; }
972 
973   static FeedbackSlot Invalid() { return FeedbackSlot(); }
974   bool IsInvalid() const { return id_ == kInvalidSlot; }
975 
976   bool operator==(FeedbackSlot that) const { return this->id_ == that.id_; }
977   bool operator!=(FeedbackSlot that) const { return !(*this == that); }
978 
979   friend size_t hash_value(FeedbackSlot slot) { return slot.ToInt(); }
980   friend std::ostream& operator<<(std::ostream& os, FeedbackSlot);
981 
982  private:
983   static const int kInvalidSlot = -1;
984 
985   int id_;
986 };
987 
988 
989 class BailoutId {
990  public:
BailoutId(int id)991   explicit BailoutId(int id) : id_(id) { }
ToInt()992   int ToInt() const { return id_; }
993 
None()994   static BailoutId None() { return BailoutId(kNoneId); }
ScriptContext()995   static BailoutId ScriptContext() { return BailoutId(kScriptContextId); }
FunctionContext()996   static BailoutId FunctionContext() { return BailoutId(kFunctionContextId); }
FunctionEntry()997   static BailoutId FunctionEntry() { return BailoutId(kFunctionEntryId); }
Declarations()998   static BailoutId Declarations() { return BailoutId(kDeclarationsId); }
FirstUsable()999   static BailoutId FirstUsable() { return BailoutId(kFirstUsableId); }
StubEntry()1000   static BailoutId StubEntry() { return BailoutId(kStubEntryId); }
1001 
1002   // Special bailout id support for deopting into the {JSConstructStub} stub.
1003   // The following hard-coded deoptimization points are supported by the stub:
1004   //  - {ConstructStubCreate} maps to {construct_stub_create_deopt_pc_offset}.
1005   //  - {ConstructStubInvoke} maps to {construct_stub_invoke_deopt_pc_offset}.
ConstructStubCreate()1006   static BailoutId ConstructStubCreate() { return BailoutId(1); }
ConstructStubInvoke()1007   static BailoutId ConstructStubInvoke() { return BailoutId(2); }
IsValidForConstructStub()1008   bool IsValidForConstructStub() const {
1009     return id_ == ConstructStubCreate().ToInt() ||
1010            id_ == ConstructStubInvoke().ToInt();
1011   }
1012 
IsNone()1013   bool IsNone() const { return id_ == kNoneId; }
1014   bool operator==(const BailoutId& other) const { return id_ == other.id_; }
1015   bool operator!=(const BailoutId& other) const { return id_ != other.id_; }
1016   friend size_t hash_value(BailoutId);
1017   V8_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream&, BailoutId);
1018 
1019  private:
1020   friend class Builtins;
1021 
1022   static const int kNoneId = -1;
1023 
1024   // Using 0 could disguise errors.
1025   static const int kScriptContextId = 1;
1026   static const int kFunctionContextId = 2;
1027   static const int kFunctionEntryId = 3;
1028 
1029   // This AST id identifies the point after the declarations have been visited.
1030   // We need it to capture the environment effects of declarations that emit
1031   // code (function declarations).
1032   static const int kDeclarationsId = 4;
1033 
1034   // Every FunctionState starts with this id.
1035   static const int kFirstUsableId = 5;
1036 
1037   // Every compiled stub starts with this id.
1038   static const int kStubEntryId = 6;
1039 
1040   // Builtin continuations bailout ids start here. If you need to add a
1041   // non-builtin BailoutId, add it before this id so that this Id has the
1042   // highest number.
1043   static const int kFirstBuiltinContinuationId = 7;
1044 
1045   int id_;
1046 };
1047 
1048 
1049 // ----------------------------------------------------------------------------
1050 // I/O support.
1051 
1052 // Our version of printf().
1053 V8_EXPORT_PRIVATE void PRINTF_FORMAT(1, 2) PrintF(const char* format, ...);
1054 void PRINTF_FORMAT(2, 3) PrintF(FILE* out, const char* format, ...);
1055 
1056 // Prepends the current process ID to the output.
1057 void PRINTF_FORMAT(1, 2) PrintPID(const char* format, ...);
1058 
1059 // Prepends the current process ID and given isolate pointer to the output.
1060 void PRINTF_FORMAT(2, 3) PrintIsolate(void* isolate, const char* format, ...);
1061 
1062 // Safe formatting print. Ensures that str is always null-terminated.
1063 // Returns the number of chars written, or -1 if output was truncated.
1064 int PRINTF_FORMAT(2, 3) SNPrintF(Vector<char> str, const char* format, ...);
1065 V8_EXPORT_PRIVATE int PRINTF_FORMAT(2, 0)
1066     VSNPrintF(Vector<char> str, const char* format, va_list args);
1067 
1068 void StrNCpy(Vector<char> dest, const char* src, size_t n);
1069 
1070 // Our version of fflush.
1071 void Flush(FILE* out);
1072 
Flush()1073 inline void Flush() {
1074   Flush(stdout);
1075 }
1076 
1077 
1078 // Read a line of characters after printing the prompt to stdout. The resulting
1079 // char* needs to be disposed off with DeleteArray by the caller.
1080 char* ReadLine(const char* prompt);
1081 
1082 
1083 // Append size chars from str to the file given by filename.
1084 // The file is overwritten. Returns the number of chars written.
1085 int AppendChars(const char* filename,
1086                 const char* str,
1087                 int size,
1088                 bool verbose = true);
1089 
1090 
1091 // Write size chars from str to the file given by filename.
1092 // The file is overwritten. Returns the number of chars written.
1093 int WriteChars(const char* filename,
1094                const char* str,
1095                int size,
1096                bool verbose = true);
1097 
1098 
1099 // Write size bytes to the file given by filename.
1100 // The file is overwritten. Returns the number of bytes written.
1101 int WriteBytes(const char* filename,
1102                const byte* bytes,
1103                int size,
1104                bool verbose = true);
1105 
1106 
1107 // Write the C code
1108 // const char* <varname> = "<str>";
1109 // const int <varname>_len = <len>;
1110 // to the file given by filename. Only the first len chars are written.
1111 int WriteAsCFile(const char* filename, const char* varname,
1112                  const char* str, int size, bool verbose = true);
1113 
1114 
1115 // ----------------------------------------------------------------------------
1116 // Memory
1117 
1118 // Copies words from |src| to |dst|. The data spans must not overlap.
1119 template <typename T>
CopyWords(T * dst,const T * src,size_t num_words)1120 inline void CopyWords(T* dst, const T* src, size_t num_words) {
1121   STATIC_ASSERT(sizeof(T) == kPointerSize);
1122   DCHECK(Min(dst, const_cast<T*>(src)) + num_words <=
1123          Max(dst, const_cast<T*>(src)));
1124   DCHECK_GT(num_words, 0);
1125 
1126   // Use block copying MemCopy if the segment we're copying is
1127   // enough to justify the extra call/setup overhead.
1128   static const size_t kBlockCopyLimit = 16;
1129 
1130   if (num_words < kBlockCopyLimit) {
1131     do {
1132       num_words--;
1133       *dst++ = *src++;
1134     } while (num_words > 0);
1135   } else {
1136     MemCopy(dst, src, num_words * kPointerSize);
1137   }
1138 }
1139 
1140 
1141 // Copies words from |src| to |dst|. No restrictions.
1142 template <typename T>
MoveWords(T * dst,const T * src,size_t num_words)1143 inline void MoveWords(T* dst, const T* src, size_t num_words) {
1144   STATIC_ASSERT(sizeof(T) == kPointerSize);
1145   DCHECK_GT(num_words, 0);
1146 
1147   // Use block copying MemCopy if the segment we're copying is
1148   // enough to justify the extra call/setup overhead.
1149   static const size_t kBlockCopyLimit = 16;
1150 
1151   if (num_words < kBlockCopyLimit &&
1152       ((dst < src) || (dst >= (src + num_words * kPointerSize)))) {
1153     T* end = dst + num_words;
1154     do {
1155       num_words--;
1156       *dst++ = *src++;
1157     } while (num_words > 0);
1158   } else {
1159     MemMove(dst, src, num_words * kPointerSize);
1160   }
1161 }
1162 
1163 
1164 // Copies data from |src| to |dst|.  The data spans must not overlap.
1165 template <typename T>
CopyBytes(T * dst,const T * src,size_t num_bytes)1166 inline void CopyBytes(T* dst, const T* src, size_t num_bytes) {
1167   STATIC_ASSERT(sizeof(T) == 1);
1168   DCHECK(Min(dst, const_cast<T*>(src)) + num_bytes <=
1169          Max(dst, const_cast<T*>(src)));
1170   if (num_bytes == 0) return;
1171 
1172   // Use block copying MemCopy if the segment we're copying is
1173   // enough to justify the extra call/setup overhead.
1174   static const int kBlockCopyLimit = kMinComplexMemCopy;
1175 
1176   if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) {
1177     do {
1178       num_bytes--;
1179       *dst++ = *src++;
1180     } while (num_bytes > 0);
1181   } else {
1182     MemCopy(dst, src, num_bytes);
1183   }
1184 }
1185 
1186 
1187 template <typename T, typename U>
MemsetPointer(T ** dest,U * value,int counter)1188 inline void MemsetPointer(T** dest, U* value, int counter) {
1189 #ifdef DEBUG
1190   T* a = nullptr;
1191   U* b = nullptr;
1192   a = b;  // Fake assignment to check assignability.
1193   USE(a);
1194 #endif  // DEBUG
1195 #if V8_HOST_ARCH_IA32
1196 #define STOS "stosl"
1197 #elif V8_HOST_ARCH_X64
1198 #if V8_HOST_ARCH_32_BIT
1199 #define STOS "addr32 stosl"
1200 #else
1201 #define STOS "stosq"
1202 #endif
1203 #endif
1204 
1205 #if defined(MEMORY_SANITIZER)
1206   // MemorySanitizer does not understand inline assembly.
1207 #undef STOS
1208 #endif
1209 
1210 #if defined(__GNUC__) && defined(STOS)
1211   asm volatile(
1212       "cld;"
1213       "rep ; " STOS
1214       : "+&c" (counter), "+&D" (dest)
1215       : "a" (value)
1216       : "memory", "cc");
1217 #else
1218   for (int i = 0; i < counter; i++) {
1219     dest[i] = value;
1220   }
1221 #endif
1222 
1223 #undef STOS
1224 }
1225 
1226 // Simple support to read a file into std::string.
1227 // On return, *exits tells whether the file existed.
1228 V8_EXPORT_PRIVATE std::string ReadFile(const char* filename, bool* exists,
1229                                        bool verbose = true);
1230 std::string ReadFile(FILE* file, bool* exists, bool verbose = true);
1231 
1232 template <typename sourcechar, typename sinkchar>
1233 V8_INLINE static void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src,
1234                                         size_t chars);
1235 #if defined(V8_HOST_ARCH_ARM)
1236 V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src,
1237                                  size_t chars);
1238 V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src,
1239                                  size_t chars);
1240 V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1241                                  size_t chars);
1242 #elif defined(V8_HOST_ARCH_MIPS)
1243 V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src,
1244                                  size_t chars);
1245 V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1246                                  size_t chars);
1247 #elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390)
1248 V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src,
1249                                  size_t chars);
1250 V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1251                                  size_t chars);
1252 #endif
1253 
1254 // Copy from 8bit/16bit chars to 8bit/16bit chars.
1255 template <typename sourcechar, typename sinkchar>
1256 V8_INLINE void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars);
1257 
1258 template <typename sourcechar, typename sinkchar>
CopyChars(sinkchar * dest,const sourcechar * src,size_t chars)1259 void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars) {
1260   DCHECK_LE(sizeof(sourcechar), 2);
1261   DCHECK_LE(sizeof(sinkchar), 2);
1262   if (sizeof(sinkchar) == 1) {
1263     if (sizeof(sourcechar) == 1) {
1264       CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1265                         reinterpret_cast<const uint8_t*>(src),
1266                         chars);
1267     } else {
1268       CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1269                         reinterpret_cast<const uint16_t*>(src),
1270                         chars);
1271     }
1272   } else {
1273     if (sizeof(sourcechar) == 1) {
1274       CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1275                         reinterpret_cast<const uint8_t*>(src),
1276                         chars);
1277     } else {
1278       CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1279                         reinterpret_cast<const uint16_t*>(src),
1280                         chars);
1281     }
1282   }
1283 }
1284 
1285 template <typename sourcechar, typename sinkchar>
CopyCharsUnsigned(sinkchar * dest,const sourcechar * src,size_t chars)1286 void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, size_t chars) {
1287   sinkchar* limit = dest + chars;
1288   if ((sizeof(*dest) == sizeof(*src)) &&
1289       (chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest)))) {
1290     MemCopy(dest, src, chars * sizeof(*dest));
1291   } else {
1292     while (dest < limit) *dest++ = static_cast<sinkchar>(*src++);
1293   }
1294 }
1295 
1296 
1297 #if defined(V8_HOST_ARCH_ARM)
CopyCharsUnsigned(uint8_t * dest,const uint8_t * src,size_t chars)1298 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
1299   switch (static_cast<unsigned>(chars)) {
1300     case 0:
1301       break;
1302     case 1:
1303       *dest = *src;
1304       break;
1305     case 2:
1306       memcpy(dest, src, 2);
1307       break;
1308     case 3:
1309       memcpy(dest, src, 3);
1310       break;
1311     case 4:
1312       memcpy(dest, src, 4);
1313       break;
1314     case 5:
1315       memcpy(dest, src, 5);
1316       break;
1317     case 6:
1318       memcpy(dest, src, 6);
1319       break;
1320     case 7:
1321       memcpy(dest, src, 7);
1322       break;
1323     case 8:
1324       memcpy(dest, src, 8);
1325       break;
1326     case 9:
1327       memcpy(dest, src, 9);
1328       break;
1329     case 10:
1330       memcpy(dest, src, 10);
1331       break;
1332     case 11:
1333       memcpy(dest, src, 11);
1334       break;
1335     case 12:
1336       memcpy(dest, src, 12);
1337       break;
1338     case 13:
1339       memcpy(dest, src, 13);
1340       break;
1341     case 14:
1342       memcpy(dest, src, 14);
1343       break;
1344     case 15:
1345       memcpy(dest, src, 15);
1346       break;
1347     default:
1348       MemCopy(dest, src, chars);
1349       break;
1350   }
1351 }
1352 
1353 
CopyCharsUnsigned(uint16_t * dest,const uint8_t * src,size_t chars)1354 void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, size_t chars) {
1355   if (chars >= static_cast<size_t>(kMinComplexConvertMemCopy)) {
1356     MemCopyUint16Uint8(dest, src, chars);
1357   } else {
1358     MemCopyUint16Uint8Wrapper(dest, src, chars);
1359   }
1360 }
1361 
1362 
CopyCharsUnsigned(uint16_t * dest,const uint16_t * src,size_t chars)1363 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
1364   switch (static_cast<unsigned>(chars)) {
1365     case 0:
1366       break;
1367     case 1:
1368       *dest = *src;
1369       break;
1370     case 2:
1371       memcpy(dest, src, 4);
1372       break;
1373     case 3:
1374       memcpy(dest, src, 6);
1375       break;
1376     case 4:
1377       memcpy(dest, src, 8);
1378       break;
1379     case 5:
1380       memcpy(dest, src, 10);
1381       break;
1382     case 6:
1383       memcpy(dest, src, 12);
1384       break;
1385     case 7:
1386       memcpy(dest, src, 14);
1387       break;
1388     default:
1389       MemCopy(dest, src, chars * sizeof(*dest));
1390       break;
1391   }
1392 }
1393 
1394 
1395 #elif defined(V8_HOST_ARCH_MIPS)
CopyCharsUnsigned(uint8_t * dest,const uint8_t * src,size_t chars)1396 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
1397   if (chars < kMinComplexMemCopy) {
1398     memcpy(dest, src, chars);
1399   } else {
1400     MemCopy(dest, src, chars);
1401   }
1402 }
1403 
CopyCharsUnsigned(uint16_t * dest,const uint16_t * src,size_t chars)1404 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
1405   if (chars < kMinComplexMemCopy) {
1406     memcpy(dest, src, chars * sizeof(*dest));
1407   } else {
1408     MemCopy(dest, src, chars * sizeof(*dest));
1409   }
1410 }
1411 #elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390)
1412 #define CASE(n)           \
1413   case n:                 \
1414     memcpy(dest, src, n); \
1415     break
CopyCharsUnsigned(uint8_t * dest,const uint8_t * src,size_t chars)1416 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
1417   switch (static_cast<unsigned>(chars)) {
1418     case 0:
1419       break;
1420     case 1:
1421       *dest = *src;
1422       break;
1423       CASE(2);
1424       CASE(3);
1425       CASE(4);
1426       CASE(5);
1427       CASE(6);
1428       CASE(7);
1429       CASE(8);
1430       CASE(9);
1431       CASE(10);
1432       CASE(11);
1433       CASE(12);
1434       CASE(13);
1435       CASE(14);
1436       CASE(15);
1437       CASE(16);
1438       CASE(17);
1439       CASE(18);
1440       CASE(19);
1441       CASE(20);
1442       CASE(21);
1443       CASE(22);
1444       CASE(23);
1445       CASE(24);
1446       CASE(25);
1447       CASE(26);
1448       CASE(27);
1449       CASE(28);
1450       CASE(29);
1451       CASE(30);
1452       CASE(31);
1453       CASE(32);
1454       CASE(33);
1455       CASE(34);
1456       CASE(35);
1457       CASE(36);
1458       CASE(37);
1459       CASE(38);
1460       CASE(39);
1461       CASE(40);
1462       CASE(41);
1463       CASE(42);
1464       CASE(43);
1465       CASE(44);
1466       CASE(45);
1467       CASE(46);
1468       CASE(47);
1469       CASE(48);
1470       CASE(49);
1471       CASE(50);
1472       CASE(51);
1473       CASE(52);
1474       CASE(53);
1475       CASE(54);
1476       CASE(55);
1477       CASE(56);
1478       CASE(57);
1479       CASE(58);
1480       CASE(59);
1481       CASE(60);
1482       CASE(61);
1483       CASE(62);
1484       CASE(63);
1485       CASE(64);
1486     default:
1487       memcpy(dest, src, chars);
1488       break;
1489   }
1490 }
1491 #undef CASE
1492 
1493 #define CASE(n)               \
1494   case n:                     \
1495     memcpy(dest, src, n * 2); \
1496     break
CopyCharsUnsigned(uint16_t * dest,const uint16_t * src,size_t chars)1497 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
1498   switch (static_cast<unsigned>(chars)) {
1499     case 0:
1500       break;
1501     case 1:
1502       *dest = *src;
1503       break;
1504       CASE(2);
1505       CASE(3);
1506       CASE(4);
1507       CASE(5);
1508       CASE(6);
1509       CASE(7);
1510       CASE(8);
1511       CASE(9);
1512       CASE(10);
1513       CASE(11);
1514       CASE(12);
1515       CASE(13);
1516       CASE(14);
1517       CASE(15);
1518       CASE(16);
1519       CASE(17);
1520       CASE(18);
1521       CASE(19);
1522       CASE(20);
1523       CASE(21);
1524       CASE(22);
1525       CASE(23);
1526       CASE(24);
1527       CASE(25);
1528       CASE(26);
1529       CASE(27);
1530       CASE(28);
1531       CASE(29);
1532       CASE(30);
1533       CASE(31);
1534       CASE(32);
1535     default:
1536       memcpy(dest, src, chars * 2);
1537       break;
1538   }
1539 }
1540 #undef CASE
1541 #endif
1542 
1543 
1544 class StringBuilder : public SimpleStringBuilder {
1545  public:
StringBuilder(int size)1546   explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
StringBuilder(char * buffer,int size)1547   StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
1548 
1549   // Add formatted contents to the builder just like printf().
1550   void PRINTF_FORMAT(2, 3) AddFormatted(const char* format, ...);
1551 
1552   // Add formatted contents like printf based on a va_list.
1553   void PRINTF_FORMAT(2, 0) AddFormattedList(const char* format, va_list list);
1554 
1555  private:
1556   DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
1557 };
1558 
1559 
1560 bool DoubleToBoolean(double d);
1561 
1562 template <typename Stream>
1563 bool StringToArrayIndex(Stream* stream, uint32_t* index);
1564 
1565 // Returns the current stack top. Works correctly with ASAN and SafeStack.
1566 // GetCurrentStackPosition() should not be inlined, because it works on stack
1567 // frames if it were inlined into a function with a huge stack frame it would
1568 // return an address significantly above the actual current stack position.
1569 V8_NOINLINE uintptr_t GetCurrentStackPosition();
1570 
1571 template <typename V>
ByteReverse(V value)1572 static inline V ByteReverse(V value) {
1573   size_t size_of_v = sizeof(value);
1574   switch (size_of_v) {
1575     case 2:
1576 #if V8_HAS_BUILTIN_BSWAP16
1577       return static_cast<V>(__builtin_bswap16(static_cast<uint16_t>(value)));
1578 #else
1579       return value << 8 | (value >> 8 & 0x00FF);
1580 #endif
1581     case 4:
1582 #if V8_HAS_BUILTIN_BSWAP32
1583       return static_cast<V>(__builtin_bswap32(static_cast<uint32_t>(value)));
1584 #else
1585     {
1586       size_t bits_of_v = size_of_v * kBitsPerByte;
1587       return value << (bits_of_v - 8) |
1588              ((value << (bits_of_v - 24)) & 0x00FF0000) |
1589              ((value >> (bits_of_v - 24)) & 0x0000FF00) |
1590              ((value >> (bits_of_v - 8)) & 0x00000FF);
1591     }
1592 #endif
1593     case 8:
1594 #if V8_HAS_BUILTIN_BSWAP64
1595       return static_cast<V>(__builtin_bswap64(static_cast<uint64_t>(value)));
1596 #else
1597     {
1598       size_t bits_of_v = size_of_v * kBitsPerByte;
1599       return value << (bits_of_v - 8) |
1600              ((value << (bits_of_v - 24)) & 0x00FF000000000000) |
1601              ((value << (bits_of_v - 40)) & 0x0000FF0000000000) |
1602              ((value << (bits_of_v - 56)) & 0x000000FF00000000) |
1603              ((value >> (bits_of_v - 56)) & 0x00000000FF000000) |
1604              ((value >> (bits_of_v - 40)) & 0x0000000000FF0000) |
1605              ((value >> (bits_of_v - 24)) & 0x000000000000FF00) |
1606              ((value >> (bits_of_v - 8)) & 0x00000000000000FF);
1607     }
1608 #endif
1609     default:
1610       UNREACHABLE();
1611   }
1612 }
1613 
1614 // Represents a linked list that threads through the nodes in the linked list.
1615 // Entries in the list are pointers to nodes. The nodes need to have a T**
1616 // next() method that returns the location where the next value is stored.
1617 template <typename T>
1618 class ThreadedList final {
1619  public:
ThreadedList()1620   ThreadedList() : head_(nullptr), tail_(&head_) {}
Add(T * v)1621   void Add(T* v) {
1622     DCHECK_NULL(*tail_);
1623     DCHECK_NULL(*v->next());
1624     *tail_ = v;
1625     tail_ = v->next();
1626   }
1627 
Clear()1628   void Clear() {
1629     head_ = nullptr;
1630     tail_ = &head_;
1631   }
1632 
1633   class Iterator final {
1634    public:
1635     Iterator& operator++() {
1636       entry_ = (*entry_)->next();
1637       return *this;
1638     }
1639     bool operator!=(const Iterator& other) { return entry_ != other.entry_; }
1640     T* operator*() { return *entry_; }
1641     T* operator->() { return *entry_; }
1642     Iterator& operator=(T* entry) {
1643       T* next = *(*entry_)->next();
1644       *entry->next() = next;
1645       *entry_ = entry;
1646       return *this;
1647     }
1648 
1649    private:
Iterator(T ** entry)1650     explicit Iterator(T** entry) : entry_(entry) {}
1651 
1652     T** entry_;
1653 
1654     friend class ThreadedList;
1655   };
1656 
1657   class ConstIterator final {
1658    public:
1659     ConstIterator& operator++() {
1660       entry_ = (*entry_)->next();
1661       return *this;
1662     }
1663     bool operator!=(const ConstIterator& other) {
1664       return entry_ != other.entry_;
1665     }
1666     const T* operator*() const { return *entry_; }
1667 
1668    private:
ConstIterator(T * const * entry)1669     explicit ConstIterator(T* const* entry) : entry_(entry) {}
1670 
1671     T* const* entry_;
1672 
1673     friend class ThreadedList;
1674   };
1675 
begin()1676   Iterator begin() { return Iterator(&head_); }
end()1677   Iterator end() { return Iterator(tail_); }
1678 
begin()1679   ConstIterator begin() const { return ConstIterator(&head_); }
end()1680   ConstIterator end() const { return ConstIterator(tail_); }
1681 
Rewind(Iterator reset_point)1682   void Rewind(Iterator reset_point) {
1683     tail_ = reset_point.entry_;
1684     *tail_ = nullptr;
1685   }
1686 
MoveTail(ThreadedList<T> * parent,Iterator location)1687   void MoveTail(ThreadedList<T>* parent, Iterator location) {
1688     if (parent->end() != location) {
1689       DCHECK_NULL(*tail_);
1690       *tail_ = *location;
1691       tail_ = parent->tail_;
1692       parent->Rewind(location);
1693     }
1694   }
1695 
is_empty()1696   bool is_empty() const { return head_ == nullptr; }
1697 
1698   // Slow. For testing purposes.
LengthForTest()1699   int LengthForTest() {
1700     int result = 0;
1701     for (Iterator t = begin(); t != end(); ++t) ++result;
1702     return result;
1703   }
AtForTest(int i)1704   T* AtForTest(int i) {
1705     Iterator t = begin();
1706     while (i-- > 0) ++t;
1707     return *t;
1708   }
1709 
1710  private:
1711   T* head_;
1712   T** tail_;
1713   DISALLOW_COPY_AND_ASSIGN(ThreadedList);
1714 };
1715 
1716 V8_EXPORT_PRIVATE bool PassesFilter(Vector<const char> name,
1717                                     Vector<const char> filter);
1718 
1719 // Zap the specified area with a specific byte pattern. This currently defaults
1720 // to int3 on x64 and ia32. On other architectures this will produce unspecified
1721 // instruction sequences.
1722 // TODO(jgruber): Better support for other architectures.
ZapCode(Address addr,size_t size_in_bytes)1723 V8_INLINE void ZapCode(Address addr, size_t size_in_bytes) {
1724   static constexpr int kZapByte = 0xCC;
1725   std::memset(reinterpret_cast<void*>(addr), kZapByte, size_in_bytes);
1726 }
1727 
1728 }  // namespace internal
1729 }  // namespace v8
1730 
1731 #endif  // V8_UTILS_H_
1732