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