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.
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"
21 #include "src/vector.h"
26 // ----------------------------------------------------------------------------
27 // General helper functions
30 inline int BoolToInt(bool b) { return b ? 1 : 0; }
33 // Same as strcmp, but can handle NULL arguments.
34 inline bool CStringEquals(const char* s1, const char* s2) {
35 return (s1 == s2) || (s1 != NULL && s2 != NULL && strcmp(s1, s2) == 0);
39 // X must be a power of 2. Returns the number of trailing zeros.
40 inline int WhichPowerOf2(uint32_t x) {
41 DCHECK(base::bits::IsPowerOfTwo32(x));
59 default: UNREACHABLE();
60 case 8: bits++; // Fall through.
61 case 4: bits++; // Fall through.
62 case 2: bits++; // Fall through.
65 DCHECK_EQ(1 << bits, original_x);
70 inline int MostSignificantBit(uint32_t x) {
71 static const int msb4[] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};
85 return nibble + msb4[x];
89 // The C++ standard leaves the semantics of '>>' undefined for
90 // negative signed operands. Most implementations do the right thing,
92 inline int ArithmeticShiftRight(int x, int s) {
98 int Compare(const T& a, const T& b) {
108 template <typename T>
109 int PointerValueCompare(const T* a, const T* b) {
110 return Compare<T>(*a, *b);
114 // Compare function to compare the object pointer value of two
115 // handlified objects. The handles are passed as pointers to the
117 template<typename T> class Handle; // Forward declaration.
118 template <typename T>
119 int HandleObjectPointerCompare(const Handle<T>* a, const Handle<T>* b) {
120 return Compare<T*>(*(*a), *(*b));
124 template <typename T, typename U>
125 inline bool IsAligned(T value, U alignment) {
126 return (value & (alignment - 1)) == 0;
130 // Returns true if (addr + offset) is aligned.
131 inline bool IsAddressAligned(Address addr,
134 intptr_t offs = OffsetFrom(addr + offset);
135 return IsAligned(offs, alignment);
139 // Returns the maximum of the two parameters.
140 template <typename T>
142 return a < b ? b : a;
146 // Returns the minimum of the two parameters.
147 template <typename T>
149 return a < b ? a : b;
153 // Returns the absolute value of its argument.
154 template <typename T>
156 return a < 0 ? -a : a;
160 // Floor(-0.0) == 0.0
161 inline double Floor(double x) {
163 if (x == 0) return x; // Fix for issue 3477.
165 return std::floor(x);
169 // TODO(svenpanne) Clean up the whole power-of-2 mess.
170 inline int32_t WhichPowerOf2Abs(int32_t x) {
171 return (x == kMinInt) ? 31 : WhichPowerOf2(Abs(x));
175 // Obtains the unsigned type corresponding to T
176 // available in C++11 as std::make_unsigned
178 struct make_unsigned {
183 // Template specializations necessary to have make_unsigned work
184 template<> struct make_unsigned<int32_t> {
185 typedef uint32_t type;
189 template<> struct make_unsigned<int64_t> {
190 typedef uint64_t type;
194 // ----------------------------------------------------------------------------
195 // BitField is a help template for encoding and decode bitfield with
198 template<class T, int shift, int size, class U>
201 // A type U mask of bit field. To use all bits of a type U of x bits
202 // in a bitfield without compiler warnings we have to compute 2^x
203 // without using a shift count of x in the computation.
204 static const U kOne = static_cast<U>(1U);
205 static const U kMask = ((kOne << shift) << size) - (kOne << shift);
206 static const U kShift = shift;
207 static const U kSize = size;
208 static const U kNext = kShift + kSize;
210 // Value for the field with all bits set.
211 static const T kMax = static_cast<T>((1U << size) - 1);
213 // Tells whether the provided value fits into the bit field.
214 static bool is_valid(T value) {
215 return (static_cast<U>(value) & ~static_cast<U>(kMax)) == 0;
218 // Returns a type U with the bit field value encoded.
219 static U encode(T value) {
220 DCHECK(is_valid(value));
221 return static_cast<U>(value) << shift;
224 // Returns a type U with the bit field value updated.
225 static U update(U previous, T value) {
226 return (previous & ~kMask) | encode(value);
229 // Extracts the bit field from the value.
230 static T decode(U value) {
231 return static_cast<T>((value & kMask) >> shift);
236 template <class T, int shift, int size>
237 class BitField8 : public BitFieldBase<T, shift, size, uint8_t> {};
240 template <class T, int shift, int size>
241 class BitField16 : public BitFieldBase<T, shift, size, uint16_t> {};
244 template<class T, int shift, int size>
245 class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
248 template<class T, int shift, int size>
249 class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
252 // ----------------------------------------------------------------------------
253 // BitSetComputer is a help template for encoding and decoding information for
254 // a variable number of items in an array.
256 // To encode boolean data in a smi array you would use:
257 // typedef BitSetComputer<bool, 1, kSmiValueSize, uint32_t> BoolComputer;
259 template <class T, int kBitsPerItem, int kBitsPerWord, class U>
260 class BitSetComputer {
262 static const int kItemsPerWord = kBitsPerWord / kBitsPerItem;
263 static const int kMask = (1 << kBitsPerItem) - 1;
265 // The number of array elements required to embed T information for each item.
266 static int word_count(int items) {
267 if (items == 0) return 0;
268 return (items - 1) / kItemsPerWord + 1;
271 // The array index to look at for item.
272 static int index(int base_index, int item) {
273 return base_index + item / kItemsPerWord;
276 // Extract T data for a given item from data.
277 static T decode(U data, int item) {
278 return static_cast<T>((data >> shift(item)) & kMask);
281 // Return the encoding for a store of value for item in previous.
282 static U encode(U previous, int item, T value) {
283 int shift_value = shift(item);
284 int set_bits = (static_cast<int>(value) << shift_value);
285 return (previous & ~(kMask << shift_value)) | set_bits;
288 static int shift(int item) { return (item % kItemsPerWord) * kBitsPerItem; }
292 // ----------------------------------------------------------------------------
295 static const uint32_t kZeroHashSeed = 0;
297 // Thomas Wang, Integer Hash Functions.
298 // http://www.concentric.net/~Ttwang/tech/inthash.htm
299 inline uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed) {
302 hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
303 hash = hash ^ (hash >> 12);
304 hash = hash + (hash << 2);
305 hash = hash ^ (hash >> 4);
306 hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11);
307 hash = hash ^ (hash >> 16);
312 inline uint32_t ComputeLongHash(uint64_t key) {
314 hash = ~hash + (hash << 18); // hash = (hash << 18) - hash - 1;
315 hash = hash ^ (hash >> 31);
316 hash = hash * 21; // hash = (hash + (hash << 2)) + (hash << 4);
317 hash = hash ^ (hash >> 11);
318 hash = hash + (hash << 6);
319 hash = hash ^ (hash >> 22);
320 return static_cast<uint32_t>(hash);
324 inline uint32_t ComputePointerHash(void* ptr) {
325 return ComputeIntegerHash(
326 static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)),
327 v8::internal::kZeroHashSeed);
331 // ----------------------------------------------------------------------------
332 // Generated memcpy/memmove
334 // Initializes the codegen support that depends on CPU features. This is
335 // called after CPU initialization.
336 void init_memcopy_functions();
338 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X87)
339 // Limit below which the extra overhead of the MemCopy function is likely
340 // to outweigh the benefits of faster copying.
341 const int kMinComplexMemCopy = 64;
343 // Copy memory area. No restrictions.
344 void MemMove(void* dest, const void* src, size_t size);
345 typedef void (*MemMoveFunction)(void* dest, const void* src, size_t size);
347 // Keep the distinction of "move" vs. "copy" for the benefit of other
349 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
350 MemMove(dest, src, size);
352 #elif defined(V8_HOST_ARCH_ARM)
353 typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
355 extern MemCopyUint8Function memcopy_uint8_function;
356 V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
358 memcpy(dest, src, chars);
360 // For values < 16, the assembler function is slower than the inlined C code.
361 const int kMinComplexMemCopy = 16;
362 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
363 (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
364 reinterpret_cast<const uint8_t*>(src), size);
366 V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
367 memmove(dest, src, size);
370 typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest, const uint8_t* src,
372 extern MemCopyUint16Uint8Function memcopy_uint16_uint8_function;
373 void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
375 // For values < 12, the assembler function is slower than the inlined C code.
376 const int kMinComplexConvertMemCopy = 12;
377 V8_INLINE void MemCopyUint16Uint8(uint16_t* dest, const uint8_t* src,
379 (*memcopy_uint16_uint8_function)(dest, src, size);
381 #elif defined(V8_HOST_ARCH_MIPS)
382 typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
384 extern MemCopyUint8Function memcopy_uint8_function;
385 V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
387 memcpy(dest, src, chars);
389 // For values < 16, the assembler function is slower than the inlined C code.
390 const int kMinComplexMemCopy = 16;
391 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
392 (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
393 reinterpret_cast<const uint8_t*>(src), size);
395 V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
396 memmove(dest, src, size);
399 // Copy memory area to disjoint memory area.
400 V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
401 memcpy(dest, src, size);
403 V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
404 memmove(dest, src, size);
406 const int kMinComplexMemCopy = 16 * kPointerSize;
407 #endif // V8_TARGET_ARCH_IA32
410 // ----------------------------------------------------------------------------
413 // A static resource holds a static instance that can be reserved in
414 // a local scope using an instance of Access. Attempts to re-reserve
415 // the instance will cause an error.
416 template <typename T>
417 class StaticResource {
419 StaticResource() : is_reserved_(false) {}
422 template <typename S> friend class Access;
428 // Locally scoped access to a static resource.
429 template <typename T>
432 explicit Access(StaticResource<T>* resource)
433 : resource_(resource)
434 , instance_(&resource->instance_) {
435 DCHECK(!resource->is_reserved_);
436 resource->is_reserved_ = true;
440 resource_->is_reserved_ = false;
445 T* value() { return instance_; }
446 T* operator -> () { return instance_; }
449 StaticResource<T>* resource_;
454 // A pointer that can only be set once and doesn't allow NULL values.
456 class SetOncePointer {
458 SetOncePointer() : pointer_(NULL) { }
460 bool is_set() const { return pointer_ != NULL; }
463 DCHECK(pointer_ != NULL);
468 DCHECK(pointer_ == NULL && value != NULL);
477 template <typename T, int kSize>
478 class EmbeddedVector : public Vector<T> {
480 EmbeddedVector() : Vector<T>(buffer_, kSize) { }
482 explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) {
483 for (int i = 0; i < kSize; ++i) {
484 buffer_[i] = initial_value;
488 // When copying, make underlying Vector to reference our buffer.
489 EmbeddedVector(const EmbeddedVector& rhs)
491 MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
492 this->set_start(buffer_);
495 EmbeddedVector& operator=(const EmbeddedVector& rhs) {
496 if (this == &rhs) return *this;
497 Vector<T>::operator=(rhs);
498 MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
499 this->set_start(buffer_);
509 * A class that collects values into a backing store.
510 * Specialized versions of the class can allow access to the backing store
512 * There is no guarantee that the backing store is contiguous (and, as a
513 * consequence, no guarantees that consecutively added elements are adjacent
514 * in memory). The collector may move elements unless it has guaranteed not
517 template <typename T, int growth_factor = 2, int max_growth = 1 * MB>
520 explicit Collector(int initial_capacity = kMinCapacity)
521 : index_(0), size_(0) {
522 current_chunk_ = Vector<T>::New(initial_capacity);
525 virtual ~Collector() {
526 // Free backing store (in reverse allocation order).
527 current_chunk_.Dispose();
528 for (int i = chunks_.length() - 1; i >= 0; i--) {
529 chunks_.at(i).Dispose();
533 // Add a single element.
534 inline void Add(T value) {
535 if (index_ >= current_chunk_.length()) {
538 current_chunk_[index_] = value;
543 // Add a block of contiguous elements and return a Vector backed by the
545 // A basic Collector will keep this vector valid as long as the Collector
547 inline Vector<T> AddBlock(int size, T initial_value) {
549 if (size > current_chunk_.length() - index_) {
552 T* position = current_chunk_.start() + index_;
555 for (int i = 0; i < size; i++) {
556 position[i] = initial_value;
558 return Vector<T>(position, size);
562 // Add a contiguous block of elements and return a vector backed
563 // by the added block.
564 // A basic Collector will keep this vector valid as long as the Collector
566 inline Vector<T> AddBlock(Vector<const T> source) {
567 if (source.length() > current_chunk_.length() - index_) {
568 Grow(source.length());
570 T* position = current_chunk_.start() + index_;
571 index_ += source.length();
572 size_ += source.length();
573 for (int i = 0; i < source.length(); i++) {
574 position[i] = source[i];
576 return Vector<T>(position, source.length());
580 // Write the contents of the collector into the provided vector.
581 void WriteTo(Vector<T> destination) {
582 DCHECK(size_ <= destination.length());
584 for (int i = 0; i < chunks_.length(); i++) {
585 Vector<T> chunk = chunks_.at(i);
586 for (int j = 0; j < chunk.length(); j++) {
587 destination[position] = chunk[j];
591 for (int i = 0; i < index_; i++) {
592 destination[position] = current_chunk_[i];
597 // Allocate a single contiguous vector, copy all the collected
598 // elements to the vector, and return it.
599 // The caller is responsible for freeing the memory of the returned
600 // vector (e.g., using Vector::Dispose).
601 Vector<T> ToVector() {
602 Vector<T> new_store = Vector<T>::New(size_);
607 // Resets the collector to be empty.
608 virtual void Reset();
610 // Total number of elements added to collector so far.
611 inline int size() { return size_; }
614 static const int kMinCapacity = 16;
615 List<Vector<T> > chunks_;
616 Vector<T> current_chunk_; // Block of memory currently being written into.
617 int index_; // Current index in current chunk.
618 int size_; // Total number of elements in collector.
620 // Creates a new current chunk, and stores the old chunk in the chunks_ list.
621 void Grow(int min_capacity) {
622 DCHECK(growth_factor > 1);
624 int current_length = current_chunk_.length();
625 if (current_length < kMinCapacity) {
626 // The collector started out as empty.
627 new_capacity = min_capacity * growth_factor;
628 if (new_capacity < kMinCapacity) new_capacity = kMinCapacity;
630 int growth = current_length * (growth_factor - 1);
631 if (growth > max_growth) {
634 new_capacity = current_length + growth;
635 if (new_capacity < min_capacity) {
636 new_capacity = min_capacity + growth;
639 NewChunk(new_capacity);
640 DCHECK(index_ + min_capacity <= current_chunk_.length());
643 // Before replacing the current chunk, give a subclass the option to move
644 // some of the current data into the new chunk. The function may update
645 // the current index_ value to represent data no longer in the current chunk.
646 // Returns the initial index of the new chunk (after copied data).
647 virtual void NewChunk(int new_capacity) {
648 Vector<T> new_chunk = Vector<T>::New(new_capacity);
650 chunks_.Add(current_chunk_.SubVector(0, index_));
652 current_chunk_.Dispose();
654 current_chunk_ = new_chunk;
661 * A collector that allows sequences of values to be guaranteed to
663 * If the backing store grows while a sequence is active, the current
664 * sequence might be moved, but after the sequence is ended, it will
666 * NOTICE: Blocks allocated using Collector::AddBlock(int) can move
667 * as well, if inside an active sequence where another element is added.
669 template <typename T, int growth_factor = 2, int max_growth = 1 * MB>
670 class SequenceCollector : public Collector<T, growth_factor, max_growth> {
672 explicit SequenceCollector(int initial_capacity)
673 : Collector<T, growth_factor, max_growth>(initial_capacity),
674 sequence_start_(kNoSequence) { }
676 virtual ~SequenceCollector() {}
678 void StartSequence() {
679 DCHECK(sequence_start_ == kNoSequence);
680 sequence_start_ = this->index_;
683 Vector<T> EndSequence() {
684 DCHECK(sequence_start_ != kNoSequence);
685 int sequence_start = sequence_start_;
686 sequence_start_ = kNoSequence;
687 if (sequence_start == this->index_) return Vector<T>();
688 return this->current_chunk_.SubVector(sequence_start, this->index_);
691 // Drops the currently added sequence, and all collected elements in it.
692 void DropSequence() {
693 DCHECK(sequence_start_ != kNoSequence);
694 int sequence_length = this->index_ - sequence_start_;
695 this->index_ = sequence_start_;
696 this->size_ -= sequence_length;
697 sequence_start_ = kNoSequence;
700 virtual void Reset() {
701 sequence_start_ = kNoSequence;
702 this->Collector<T, growth_factor, max_growth>::Reset();
706 static const int kNoSequence = -1;
709 // Move the currently active sequence to the new chunk.
710 virtual void NewChunk(int new_capacity) {
711 if (sequence_start_ == kNoSequence) {
712 // Fall back on default behavior if no sequence has been started.
713 this->Collector<T, growth_factor, max_growth>::NewChunk(new_capacity);
716 int sequence_length = this->index_ - sequence_start_;
717 Vector<T> new_chunk = Vector<T>::New(sequence_length + new_capacity);
718 DCHECK(sequence_length < new_chunk.length());
719 for (int i = 0; i < sequence_length; i++) {
720 new_chunk[i] = this->current_chunk_[sequence_start_ + i];
722 if (sequence_start_ > 0) {
723 this->chunks_.Add(this->current_chunk_.SubVector(0, sequence_start_));
725 this->current_chunk_.Dispose();
727 this->current_chunk_ = new_chunk;
728 this->index_ = sequence_length;
734 // Compare 8bit/16bit chars to 8bit/16bit chars.
735 template <typename lchar, typename rchar>
736 inline int CompareCharsUnsigned(const lchar* lhs, const rchar* rhs,
738 const lchar* limit = lhs + chars;
739 if (sizeof(*lhs) == sizeof(char) && sizeof(*rhs) == sizeof(char)) {
740 // memcmp compares byte-by-byte, yielding wrong results for two-byte
741 // strings on little-endian systems.
742 return memcmp(lhs, rhs, chars);
744 while (lhs < limit) {
745 int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
746 if (r != 0) return r;
753 template <typename lchar, typename rchar>
754 inline int CompareChars(const lchar* lhs, const rchar* rhs, size_t chars) {
755 DCHECK(sizeof(lchar) <= 2);
756 DCHECK(sizeof(rchar) <= 2);
757 if (sizeof(lchar) == 1) {
758 if (sizeof(rchar) == 1) {
759 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
760 reinterpret_cast<const uint8_t*>(rhs),
763 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
764 reinterpret_cast<const uint16_t*>(rhs),
768 if (sizeof(rchar) == 1) {
769 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
770 reinterpret_cast<const uint8_t*>(rhs),
773 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
774 reinterpret_cast<const uint16_t*>(rhs),
781 // Calculate 10^exponent.
782 inline int TenToThe(int exponent) {
783 DCHECK(exponent <= 9);
784 DCHECK(exponent >= 1);
786 for (int i = 1; i < exponent; i++) answer *= 10;
791 template<typename ElementType, int NumElements>
792 class EmbeddedContainer {
794 EmbeddedContainer() : elems_() { }
796 int length() const { return NumElements; }
797 const ElementType& operator[](int i) const {
798 DCHECK(i < length());
801 ElementType& operator[](int i) {
802 DCHECK(i < length());
807 ElementType elems_[NumElements];
811 template<typename ElementType>
812 class EmbeddedContainer<ElementType, 0> {
814 int length() const { return 0; }
815 const ElementType& operator[](int i) const {
817 static ElementType t = 0;
820 ElementType& operator[](int i) {
822 static ElementType t = 0;
828 // Helper class for building result strings in a character buffer. The
829 // purpose of the class is to use safe operations that checks the
830 // buffer bounds on all operations in debug mode.
831 // This simple base class does not allow formatted output.
832 class SimpleStringBuilder {
834 // Create a string builder with a buffer of the given size. The
835 // buffer is allocated through NewArray<char> and must be
836 // deallocated by the caller of Finalize().
837 explicit SimpleStringBuilder(int size);
839 SimpleStringBuilder(char* buffer, int size)
840 : buffer_(buffer, size), position_(0) { }
842 ~SimpleStringBuilder() { if (!is_finalized()) Finalize(); }
844 int size() const { return buffer_.length(); }
846 // Get the current position in the builder.
847 int position() const {
848 DCHECK(!is_finalized());
852 // Reset the position.
853 void Reset() { position_ = 0; }
855 // Add a single character to the builder. It is not allowed to add
856 // 0-characters; use the Finalize() method to terminate the string
858 void AddCharacter(char c) {
860 DCHECK(!is_finalized() && position_ < buffer_.length());
861 buffer_[position_++] = c;
864 // Add an entire string to the builder. Uses strlen() internally to
865 // compute the length of the input string.
866 void AddString(const char* s);
868 // Add the first 'n' characters of the given 0-terminated string 's' to the
869 // builder. The input string must have enough characters.
870 void AddSubstring(const char* s, int n);
872 // Add character padding to the builder. If count is non-positive,
873 // nothing is added to the builder.
874 void AddPadding(char c, int count);
876 // Add the decimal representation of the value.
877 void AddDecimalInteger(int value);
879 // Finalize the string by 0-terminating it and returning the buffer.
883 Vector<char> buffer_;
886 bool is_finalized() const { return position_ < 0; }
889 DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder);
893 // A poor man's version of STL's bitset: A bit set of enums E (without explicit
894 // values), fitting into an integral type T.
895 template <class E, class T = int>
898 explicit EnumSet(T bits = 0) : bits_(bits) {}
899 bool IsEmpty() const { return bits_ == 0; }
900 bool Contains(E element) const { return (bits_ & Mask(element)) != 0; }
901 bool ContainsAnyOf(const EnumSet& set) const {
902 return (bits_ & set.bits_) != 0;
904 void Add(E element) { bits_ |= Mask(element); }
905 void Add(const EnumSet& set) { bits_ |= set.bits_; }
906 void Remove(E element) { bits_ &= ~Mask(element); }
907 void Remove(const EnumSet& set) { bits_ &= ~set.bits_; }
908 void RemoveAll() { bits_ = 0; }
909 void Intersect(const EnumSet& set) { bits_ &= set.bits_; }
910 T ToIntegral() const { return bits_; }
911 bool operator==(const EnumSet& set) { return bits_ == set.bits_; }
912 bool operator!=(const EnumSet& set) { return bits_ != set.bits_; }
913 EnumSet<E, T> operator|(const EnumSet& set) const {
914 return EnumSet<E, T>(bits_ | set.bits_);
918 T Mask(E element) const {
919 // The strange typing in DCHECK is necessary to avoid stupid warnings, see:
920 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43680
921 DCHECK(static_cast<int>(element) < static_cast<int>(sizeof(T) * CHAR_BIT));
922 return static_cast<T>(1) << element;
928 // Bit field extraction.
929 inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) {
930 return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
933 inline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) {
934 return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
937 inline int32_t signed_bitextract_32(int msb, int lsb, int32_t x) {
938 return (x << (31 - msb)) >> (lsb + 31 - msb);
941 inline int signed_bitextract_64(int msb, int lsb, int x) {
942 // TODO(jbramley): This is broken for big bitfields.
943 return (x << (63 - msb)) >> (lsb + 63 - msb);
946 // Check number width.
947 inline bool is_intn(int64_t x, unsigned n) {
948 DCHECK((0 < n) && (n < 64));
949 int64_t limit = static_cast<int64_t>(1) << (n - 1);
950 return (-limit <= x) && (x < limit);
953 inline bool is_uintn(int64_t x, unsigned n) {
954 DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
959 inline T truncate_to_intn(T x, unsigned n) {
960 DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
961 return (x & ((static_cast<T>(1) << n) - 1));
964 #define INT_1_TO_63_LIST(V) \
965 V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \
966 V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \
967 V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \
968 V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32) \
969 V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \
970 V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \
971 V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \
972 V(57) V(58) V(59) V(60) V(61) V(62) V(63)
974 #define DECLARE_IS_INT_N(N) \
975 inline bool is_int##N(int64_t x) { return is_intn(x, N); }
976 #define DECLARE_IS_UINT_N(N) \
978 inline bool is_uint##N(T x) { return is_uintn(x, N); }
979 #define DECLARE_TRUNCATE_TO_INT_N(N) \
981 inline T truncate_to_int##N(T x) { return truncate_to_intn(x, N); }
982 INT_1_TO_63_LIST(DECLARE_IS_INT_N)
983 INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
984 INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
985 #undef DECLARE_IS_INT_N
986 #undef DECLARE_IS_UINT_N
987 #undef DECLARE_TRUNCATE_TO_INT_N
989 class TypeFeedbackId {
991 explicit TypeFeedbackId(int id) : id_(id) { }
992 int ToInt() const { return id_; }
994 static TypeFeedbackId None() { return TypeFeedbackId(kNoneId); }
995 bool IsNone() const { return id_ == kNoneId; }
998 static const int kNoneId = -1;
1004 template <int dummy_parameter>
1007 explicit VectorSlot(int id) : id_(id) {}
1008 int ToInt() const { return id_; }
1010 static VectorSlot Invalid() { return VectorSlot(kInvalidSlot); }
1011 bool IsInvalid() const { return id_ == kInvalidSlot; }
1013 VectorSlot next() const {
1014 DCHECK(id_ != kInvalidSlot);
1015 return VectorSlot(id_ + 1);
1018 bool operator==(const VectorSlot& other) const { return id_ == other.id_; }
1021 static const int kInvalidSlot = -1;
1027 typedef VectorSlot<0> FeedbackVectorSlot;
1028 typedef VectorSlot<1> FeedbackVectorICSlot;
1033 explicit BailoutId(int id) : id_(id) { }
1034 int ToInt() const { return id_; }
1036 static BailoutId None() { return BailoutId(kNoneId); }
1037 static BailoutId FunctionEntry() { return BailoutId(kFunctionEntryId); }
1038 static BailoutId Declarations() { return BailoutId(kDeclarationsId); }
1039 static BailoutId FirstUsable() { return BailoutId(kFirstUsableId); }
1040 static BailoutId StubEntry() { return BailoutId(kStubEntryId); }
1042 bool IsNone() const { return id_ == kNoneId; }
1043 bool operator==(const BailoutId& other) const { return id_ == other.id_; }
1044 bool operator!=(const BailoutId& other) const { return id_ != other.id_; }
1045 friend size_t hash_value(BailoutId);
1046 friend std::ostream& operator<<(std::ostream&, BailoutId);
1049 static const int kNoneId = -1;
1051 // Using 0 could disguise errors.
1052 static const int kFunctionEntryId = 2;
1054 // This AST id identifies the point after the declarations have been visited.
1055 // We need it to capture the environment effects of declarations that emit
1056 // code (function declarations).
1057 static const int kDeclarationsId = 3;
1059 // Every FunctionState starts with this id.
1060 static const int kFirstUsableId = 4;
1062 // Every compiled stub starts with this id.
1063 static const int kStubEntryId = 5;
1070 class ContainerPointerWrapper {
1072 typedef typename C::iterator iterator;
1073 typedef typename C::reverse_iterator reverse_iterator;
1074 explicit ContainerPointerWrapper(C* container) : container_(container) {}
1075 iterator begin() { return container_->begin(); }
1076 iterator end() { return container_->end(); }
1077 reverse_iterator rbegin() { return container_->rbegin(); }
1078 reverse_iterator rend() { return container_->rend(); }
1084 // ----------------------------------------------------------------------------
1088 // On gcc we can ask the compiler to check the types of %d-style format
1089 // specifiers and their associated arguments. TODO(erikcorry) fix this
1090 // so it works on MacOSX.
1091 #if defined(__MACH__) && defined(__APPLE__)
1092 #define PRINTF_CHECKING
1093 #define FPRINTF_CHECKING
1094 #define PRINTF_METHOD_CHECKING
1095 #define FPRINTF_METHOD_CHECKING
1097 #define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
1098 #define FPRINTF_CHECKING __attribute__ ((format (printf, 2, 3)))
1099 #define PRINTF_METHOD_CHECKING __attribute__ ((format (printf, 2, 3)))
1100 #define FPRINTF_METHOD_CHECKING __attribute__ ((format (printf, 3, 4)))
1103 #define PRINTF_CHECKING
1104 #define FPRINTF_CHECKING
1105 #define PRINTF_METHOD_CHECKING
1106 #define FPRINTF_METHOD_CHECKING
1109 // Our version of printf().
1110 void PRINTF_CHECKING PrintF(const char* format, ...);
1111 void FPRINTF_CHECKING PrintF(FILE* out, const char* format, ...);
1113 // Prepends the current process ID to the output.
1114 void PRINTF_CHECKING PrintPID(const char* format, ...);
1116 // Safe formatting print. Ensures that str is always null-terminated.
1117 // Returns the number of chars written, or -1 if output was truncated.
1118 int FPRINTF_CHECKING SNPrintF(Vector<char> str, const char* format, ...);
1119 int VSNPrintF(Vector<char> str, const char* format, va_list args);
1121 void StrNCpy(Vector<char> dest, const char* src, size_t n);
1123 // Our version of fflush.
1124 void Flush(FILE* out);
1126 inline void Flush() {
1131 // Read a line of characters after printing the prompt to stdout. The resulting
1132 // char* needs to be disposed off with DeleteArray by the caller.
1133 char* ReadLine(const char* prompt);
1136 // Read and return the raw bytes in a file. the size of the buffer is returned
1138 // The returned buffer must be freed by the caller.
1139 byte* ReadBytes(const char* filename, int* size, bool verbose = true);
1142 // Append size chars from str to the file given by filename.
1143 // The file is overwritten. Returns the number of chars written.
1144 int AppendChars(const char* filename,
1147 bool verbose = true);
1150 // Write size chars from str to the file given by filename.
1151 // The file is overwritten. Returns the number of chars written.
1152 int WriteChars(const char* filename,
1155 bool verbose = true);
1158 // Write size bytes to the file given by filename.
1159 // The file is overwritten. Returns the number of bytes written.
1160 int WriteBytes(const char* filename,
1163 bool verbose = true);
1167 // const char* <varname> = "<str>";
1168 // const int <varname>_len = <len>;
1169 // to the file given by filename. Only the first len chars are written.
1170 int WriteAsCFile(const char* filename, const char* varname,
1171 const char* str, int size, bool verbose = true);
1174 // ----------------------------------------------------------------------------
1177 template <typename T>
1178 inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms,
1180 return Vector< Handle<Object> >(
1181 reinterpret_cast<v8::internal::Handle<Object>*>(elms), length);
1185 // ----------------------------------------------------------------------------
1188 // Copies words from |src| to |dst|. The data spans must not overlap.
1189 template <typename T>
1190 inline void CopyWords(T* dst, const T* src, size_t num_words) {
1191 STATIC_ASSERT(sizeof(T) == kPointerSize);
1192 // TODO(mvstanton): disabled because mac builds are bogus failing on this
1193 // assert. They are doing a signed comparison. Investigate in
1195 // DCHECK(Min(dst, const_cast<T*>(src)) + num_words <=
1196 // Max(dst, const_cast<T*>(src)));
1197 DCHECK(num_words > 0);
1199 // Use block copying MemCopy if the segment we're copying is
1200 // enough to justify the extra call/setup overhead.
1201 static const size_t kBlockCopyLimit = 16;
1203 if (num_words < kBlockCopyLimit) {
1207 } while (num_words > 0);
1209 MemCopy(dst, src, num_words * kPointerSize);
1214 // Copies words from |src| to |dst|. No restrictions.
1215 template <typename T>
1216 inline void MoveWords(T* dst, const T* src, size_t num_words) {
1217 STATIC_ASSERT(sizeof(T) == kPointerSize);
1218 DCHECK(num_words > 0);
1220 // Use block copying MemCopy if the segment we're copying is
1221 // enough to justify the extra call/setup overhead.
1222 static const size_t kBlockCopyLimit = 16;
1224 if (num_words < kBlockCopyLimit &&
1225 ((dst < src) || (dst >= (src + num_words * kPointerSize)))) {
1226 T* end = dst + num_words;
1230 } while (num_words > 0);
1232 MemMove(dst, src, num_words * kPointerSize);
1237 // Copies data from |src| to |dst|. The data spans must not overlap.
1238 template <typename T>
1239 inline void CopyBytes(T* dst, const T* src, size_t num_bytes) {
1240 STATIC_ASSERT(sizeof(T) == 1);
1241 DCHECK(Min(dst, const_cast<T*>(src)) + num_bytes <=
1242 Max(dst, const_cast<T*>(src)));
1243 if (num_bytes == 0) return;
1245 // Use block copying MemCopy if the segment we're copying is
1246 // enough to justify the extra call/setup overhead.
1247 static const int kBlockCopyLimit = kMinComplexMemCopy;
1249 if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) {
1253 } while (num_bytes > 0);
1255 MemCopy(dst, src, num_bytes);
1260 template <typename T, typename U>
1261 inline void MemsetPointer(T** dest, U* value, int counter) {
1265 a = b; // Fake assignment to check assignability.
1268 #if V8_HOST_ARCH_IA32
1269 #define STOS "stosl"
1270 #elif V8_HOST_ARCH_X64
1271 #if V8_HOST_ARCH_32_BIT
1272 #define STOS "addr32 stosl"
1274 #define STOS "stosq"
1277 #if defined(__native_client__)
1278 // This STOS sequence does not validate for x86_64 Native Client.
1279 // Here we #undef STOS to force use of the slower C version.
1280 // TODO(bradchen): Profile V8 and implement a faster REP STOS
1281 // here if the profile indicates it matters.
1285 #if defined(MEMORY_SANITIZER)
1286 // MemorySanitizer does not understand inline assembly.
1290 #if defined(__GNUC__) && defined(STOS)
1294 : "+&c" (counter), "+&D" (dest)
1298 for (int i = 0; i < counter; i++) {
1307 // Simple support to read a file into a 0-terminated C-string.
1308 // The returned buffer must be freed by the caller.
1309 // On return, *exits tells whether the file existed.
1310 Vector<const char> ReadFile(const char* filename,
1312 bool verbose = true);
1313 Vector<const char> ReadFile(FILE* file,
1315 bool verbose = true);
1318 template <typename sourcechar, typename sinkchar>
1319 INLINE(static void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src,
1321 #if defined(V8_HOST_ARCH_ARM)
1322 INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars));
1323 INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src,
1325 INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1327 #elif defined(V8_HOST_ARCH_MIPS)
1328 INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars));
1329 INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1331 #elif defined(V8_HOST_ARCH_PPC)
1332 INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars));
1333 INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1337 // Copy from 8bit/16bit chars to 8bit/16bit chars.
1338 template <typename sourcechar, typename sinkchar>
1339 INLINE(void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars));
1341 template <typename sourcechar, typename sinkchar>
1342 void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars) {
1343 DCHECK(sizeof(sourcechar) <= 2);
1344 DCHECK(sizeof(sinkchar) <= 2);
1345 if (sizeof(sinkchar) == 1) {
1346 if (sizeof(sourcechar) == 1) {
1347 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1348 reinterpret_cast<const uint8_t*>(src),
1351 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1352 reinterpret_cast<const uint16_t*>(src),
1356 if (sizeof(sourcechar) == 1) {
1357 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1358 reinterpret_cast<const uint8_t*>(src),
1361 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1362 reinterpret_cast<const uint16_t*>(src),
1368 template <typename sourcechar, typename sinkchar>
1369 void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, size_t chars) {
1370 sinkchar* limit = dest + chars;
1371 if ((sizeof(*dest) == sizeof(*src)) &&
1372 (chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest)))) {
1373 MemCopy(dest, src, chars * sizeof(*dest));
1375 while (dest < limit) *dest++ = static_cast<sinkchar>(*src++);
1380 #if defined(V8_HOST_ARCH_ARM)
1381 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
1382 switch (static_cast<unsigned>(chars)) {
1389 memcpy(dest, src, 2);
1392 memcpy(dest, src, 3);
1395 memcpy(dest, src, 4);
1398 memcpy(dest, src, 5);
1401 memcpy(dest, src, 6);
1404 memcpy(dest, src, 7);
1407 memcpy(dest, src, 8);
1410 memcpy(dest, src, 9);
1413 memcpy(dest, src, 10);
1416 memcpy(dest, src, 11);
1419 memcpy(dest, src, 12);
1422 memcpy(dest, src, 13);
1425 memcpy(dest, src, 14);
1428 memcpy(dest, src, 15);
1431 MemCopy(dest, src, chars);
1437 void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, size_t chars) {
1438 if (chars >= static_cast<size_t>(kMinComplexConvertMemCopy)) {
1439 MemCopyUint16Uint8(dest, src, chars);
1441 MemCopyUint16Uint8Wrapper(dest, src, chars);
1446 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
1447 switch (static_cast<unsigned>(chars)) {
1454 memcpy(dest, src, 4);
1457 memcpy(dest, src, 6);
1460 memcpy(dest, src, 8);
1463 memcpy(dest, src, 10);
1466 memcpy(dest, src, 12);
1469 memcpy(dest, src, 14);
1472 MemCopy(dest, src, chars * sizeof(*dest));
1478 #elif defined(V8_HOST_ARCH_MIPS)
1479 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
1480 if (chars < kMinComplexMemCopy) {
1481 memcpy(dest, src, chars);
1483 MemCopy(dest, src, chars);
1487 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
1488 if (chars < kMinComplexMemCopy) {
1489 memcpy(dest, src, chars * sizeof(*dest));
1491 MemCopy(dest, src, chars * sizeof(*dest));
1494 #elif defined(V8_HOST_ARCH_PPC)
1497 memcpy(dest, src, n); \
1499 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
1500 switch (static_cast<unsigned>(chars)) {
1570 memcpy(dest, src, chars);
1578 memcpy(dest, src, n * 2); \
1580 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
1581 switch (static_cast<unsigned>(chars)) {
1619 memcpy(dest, src, chars * 2);
1627 class StringBuilder : public SimpleStringBuilder {
1629 explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
1630 StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
1632 // Add formatted contents to the builder just like printf().
1633 void AddFormatted(const char* format, ...);
1635 // Add formatted contents like printf based on a va_list.
1636 void AddFormattedList(const char* format, va_list list);
1638 DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
1642 bool DoubleToBoolean(double d);
1644 template <typename Stream>
1645 bool StringToArrayIndex(Stream* stream, uint32_t* index) {
1646 uint16_t ch = stream->GetNext();
1648 // If the string begins with a '0' character, it must only consist
1649 // of it to be a legal array index.
1652 return !stream->HasMore();
1655 // Convert string to uint32 array index; character by character.
1657 if (d < 0 || d > 9) return false;
1658 uint32_t result = d;
1659 while (stream->HasMore()) {
1660 d = stream->GetNext() - '0';
1661 if (d < 0 || d > 9) return false;
1662 // Check that the new result is below the 32 bit limit.
1663 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
1664 result = (result * 10) + d;
1672 // Returns current value of top of the stack. Works correctly with ASAN.
1674 inline uintptr_t GetCurrentStackPosition() {
1675 // Takes the address of the limit variable in order to find out where
1676 // the top of stack is right now.
1677 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit);
1681 } // namespace internal
1684 #endif // V8_UTILS_H_