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