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