Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / v8 / src / utils.h
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_