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