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