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