LCOV - code coverage report
Current view: top level - src - utils.h (source / functions) Hit Total Coverage
Test: app.info Lines: 166 176 94.3 %
Date: 2017-10-20 Functions: 32 35 91.4 %

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

Generated by: LCOV version 1.10