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