LCOV - code coverage report
Current view: top level - src - utils.h (source / functions) Hit Total Coverage
Test: app.info Lines: 193 205 94.1 %
Date: 2017-04-26 Functions: 31 174 17.8 %

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

Generated by: LCOV version 1.10