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