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