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