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