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