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