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