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