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