diff options
Diffstat (limited to 'deps/v8/src/utils.h')
-rw-r--r-- | deps/v8/src/utils.h | 613 |
1 files changed, 47 insertions, 566 deletions
diff --git a/deps/v8/src/utils.h b/deps/v8/src/utils.h index 51c22ffd70..7ba6ba487d 100644 --- a/deps/v8/src/utils.h +++ b/deps/v8/src/utils.h @@ -1,4 +1,3 @@ - // Copyright 2012 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -61,8 +60,10 @@ inline bool CStringEquals(const char* s1, const char* s2) { // Checks if value is in range [lower_limit, higher_limit] using a single // branch. template <typename T, typename U> -inline bool IsInRange(T value, U lower_limit, U higher_limit) { - DCHECK_LE(lower_limit, higher_limit); +inline constexpr bool IsInRange(T value, U lower_limit, U higher_limit) { +#if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR + DCHECK(lower_limit <= higher_limit); +#endif STATIC_ASSERT(sizeof(U) <= sizeof(T)); typedef typename std::make_unsigned<T>::type unsigned_T; // Use static_cast to support enum classes. @@ -72,6 +73,12 @@ inline bool IsInRange(T value, U lower_limit, U higher_limit) { static_cast<unsigned_T>(lower_limit)); } +// Checks if [index, index+length) is in range [0, max). Note that this check +// works even if {index+length} would wrap around. +inline constexpr bool IsInBounds(size_t index, size_t length, size_t max) { + return length <= max && index <= (max - length); +} + // X must be a power of 2. Returns the number of trailing zeros. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> @@ -162,20 +169,6 @@ int HandleObjectPointerCompare(const Handle<T>* a, const Handle<T>* b) { return Compare<T*>(*(*a), *(*b)); } - -template <typename T, typename U> -inline bool IsAligned(T value, U alignment) { - return (value & (alignment - 1)) == 0; -} - -// Returns true if {addr + offset} is aligned. -inline bool IsAddressAligned(Address addr, - intptr_t alignment, - int offset = 0) { - return IsAligned(addr + offset, alignment); -} - - // Returns the maximum of the two parameters. template <typename T> constexpr T Max(T a, T b) { @@ -242,7 +235,11 @@ inline double Modulo(double x, double y) { // dividend is a zero and divisor is nonzero finite => result equals dividend if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) && !(x == 0 && (y != 0 && std::isfinite(y)))) { - x = fmod(x, y); + double result = fmod(x, y); + // Workaround MS bug in VS CRT in some OS versions, https://crbug.com/915045 + // fmod(-17, +/-1) should equal -0.0 but now returns 0.0. + if (x < 0 && result == 0) result = -0.0; + x = result; } return x; #elif defined(V8_OS_AIX) @@ -355,18 +352,20 @@ class BitFieldBase { } // Returns a type U with the bit field value encoded. - static U encode(T value) { + static constexpr U encode(T value) { +#if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR DCHECK(is_valid(value)); +#endif return static_cast<U>(value) << shift; } // Returns a type U with the bit field value updated. - static U update(U previous, T value) { + static constexpr U update(U previous, T value) { return (previous & ~kMask) | encode(value); } // Extracts the bit field from the value. - static T decode(U value) { + static constexpr T decode(U value) { return static_cast<T>((value & kMask) >> shift); } @@ -468,10 +467,10 @@ class BitSetComputer { // macro definition are omitted here to please the compiler) // // #define MAP_FIELDS(V) -// V(kField1Offset, kPointerSize) +// V(kField1Offset, kTaggedSize) // V(kField2Offset, kIntSize) // V(kField3Offset, kIntSize) -// V(kField4Offset, kPointerSize) +// V(kField4Offset, kSystemPointerSize) // V(kSize, 0) // // DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, MAP_FIELDS) @@ -484,6 +483,9 @@ class BitSetComputer { LIST_MACRO(DEFINE_ONE_FIELD_OFFSET) \ }; +// Size of the field defined by DEFINE_FIELD_OFFSET_CONSTANTS +#define FIELD_SIZE(Name) (Name##End + 1 - Name) + // ---------------------------------------------------------------------------- // Hash function. @@ -531,87 +533,6 @@ inline uint32_t ComputeAddressHash(Address address) { } // ---------------------------------------------------------------------------- -// Generated memcpy/memmove - -// Initializes the codegen support that depends on CPU features. -void init_memcopy_functions(); - -#if defined(V8_TARGET_ARCH_IA32) -// Limit below which the extra overhead of the MemCopy function is likely -// to outweigh the benefits of faster copying. -const int kMinComplexMemCopy = 64; - -// Copy memory area. No restrictions. -V8_EXPORT_PRIVATE void MemMove(void* dest, const void* src, size_t size); -typedef void (*MemMoveFunction)(void* dest, const void* src, size_t size); - -// Keep the distinction of "move" vs. "copy" for the benefit of other -// architectures. -V8_INLINE void MemCopy(void* dest, const void* src, size_t size) { - MemMove(dest, src, size); -} -#elif defined(V8_HOST_ARCH_ARM) -typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src, - size_t size); -V8_EXPORT_PRIVATE extern MemCopyUint8Function memcopy_uint8_function; -V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src, - size_t chars) { - memcpy(dest, src, chars); -} -// For values < 16, the assembler function is slower than the inlined C code. -const int kMinComplexMemCopy = 16; -V8_INLINE void MemCopy(void* dest, const void* src, size_t size) { - (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest), - reinterpret_cast<const uint8_t*>(src), size); -} -V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src, - size_t size) { - memmove(dest, src, size); -} - -typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest, const uint8_t* src, - size_t size); -extern MemCopyUint16Uint8Function memcopy_uint16_uint8_function; -void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src, - size_t chars); -// For values < 12, the assembler function is slower than the inlined C code. -const int kMinComplexConvertMemCopy = 12; -V8_INLINE void MemCopyUint16Uint8(uint16_t* dest, const uint8_t* src, - size_t size) { - (*memcopy_uint16_uint8_function)(dest, src, size); -} -#elif defined(V8_HOST_ARCH_MIPS) -typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src, - size_t size); -V8_EXPORT_PRIVATE extern MemCopyUint8Function memcopy_uint8_function; -V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src, - size_t chars) { - memcpy(dest, src, chars); -} -// For values < 16, the assembler function is slower than the inlined C code. -const int kMinComplexMemCopy = 16; -V8_INLINE void MemCopy(void* dest, const void* src, size_t size) { - (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest), - reinterpret_cast<const uint8_t*>(src), size); -} -V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src, - size_t size) { - memmove(dest, src, size); -} -#else -// Copy memory area to disjoint memory area. -V8_INLINE void MemCopy(void* dest, const void* src, size_t size) { - memcpy(dest, src, size); -} -V8_EXPORT_PRIVATE V8_INLINE void MemMove(void* dest, const void* src, - size_t size) { - memmove(dest, src, size); -} -const int kMinComplexMemCopy = 8; -#endif // V8_TARGET_ARCH_IA32 - - -// ---------------------------------------------------------------------------- // Miscellaneous // Memory offset for lower and higher bits in a 64 bit integer. @@ -706,13 +627,12 @@ class EmbeddedVector : public Vector<T> { } // When copying, make underlying Vector to reference our buffer. - EmbeddedVector(const EmbeddedVector& rhs) - : Vector<T>(rhs) { + EmbeddedVector(const EmbeddedVector& rhs) V8_NOEXCEPT : Vector<T>(rhs) { MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize); this->set_start(buffer_); } - EmbeddedVector& operator=(const EmbeddedVector& rhs) { + EmbeddedVector& operator=(const EmbeddedVector& rhs) V8_NOEXCEPT { if (this == &rhs) return *this; Vector<T>::operator=(rhs); MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize); @@ -882,42 +802,6 @@ class SimpleStringBuilder { DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder); }; - -// A poor man's version of STL's bitset: A bit set of enums E (without explicit -// values), fitting into an integral type T. -template <class E, class T = int> -class EnumSet { - public: - explicit EnumSet(T bits = 0) : bits_(bits) {} - bool IsEmpty() const { return bits_ == 0; } - bool Contains(E element) const { return (bits_ & Mask(element)) != 0; } - bool ContainsAnyOf(const EnumSet& set) const { - return (bits_ & set.bits_) != 0; - } - void Add(E element) { bits_ |= Mask(element); } - void Add(const EnumSet& set) { bits_ |= set.bits_; } - void Remove(E element) { bits_ &= ~Mask(element); } - void Remove(const EnumSet& set) { bits_ &= ~set.bits_; } - void RemoveAll() { bits_ = 0; } - void Intersect(const EnumSet& set) { bits_ &= set.bits_; } - T ToIntegral() const { return bits_; } - bool operator==(const EnumSet& set) { return bits_ == set.bits_; } - bool operator!=(const EnumSet& set) { return bits_ != set.bits_; } - EnumSet operator|(const EnumSet& set) const { - return EnumSet(bits_ | set.bits_); - } - - private: - static_assert(std::is_enum<E>::value, "EnumSet can only be used with enums"); - - T Mask(E element) const { - DCHECK_GT(sizeof(T) * CHAR_BIT, static_cast<int>(element)); - return T{1} << static_cast<typename std::underlying_type<E>::type>(element); - } - - T bits_; -}; - // Bit field extraction. inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) { return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1); @@ -979,6 +863,23 @@ INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N) #undef DECLARE_IS_UINT_N #undef DECLARE_TRUNCATE_TO_INT_N +// clang-format off +#define INT_0_TO_127_LIST(V) \ +V(0) V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) V(9) \ +V(10) V(11) V(12) V(13) V(14) V(15) V(16) V(17) V(18) V(19) \ +V(20) V(21) V(22) V(23) V(24) V(25) V(26) V(27) V(28) V(29) \ +V(30) V(31) V(32) V(33) V(34) V(35) V(36) V(37) V(38) V(39) \ +V(40) V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) V(49) \ +V(50) V(51) V(52) V(53) V(54) V(55) V(56) V(57) V(58) V(59) \ +V(60) V(61) V(62) V(63) V(64) V(65) V(66) V(67) V(68) V(69) \ +V(70) V(71) V(72) V(73) V(74) V(75) V(76) V(77) V(78) V(79) \ +V(80) V(81) V(82) V(83) V(84) V(85) V(86) V(87) V(88) V(89) \ +V(90) V(91) V(92) V(93) V(94) V(95) V(96) V(97) V(98) V(99) \ +V(100) V(101) V(102) V(103) V(104) V(105) V(106) V(107) V(108) V(109) \ +V(110) V(111) V(112) V(113) V(114) V(115) V(116) V(117) V(118) V(119) \ +V(120) V(121) V(122) V(123) V(124) V(125) V(126) V(127) +// clang-format on + class FeedbackSlot { public: FeedbackSlot() : id_(kInvalidSlot) {} @@ -1128,435 +1029,12 @@ int WriteAsCFile(const char* filename, const char* varname, const char* str, int size, bool verbose = true); -// ---------------------------------------------------------------------------- -// Memory - -// Copies words from |src| to |dst|. The data spans must not overlap. -template <typename T> -inline void CopyWords(T* dst, const T* src, size_t num_words) { - STATIC_ASSERT(sizeof(T) == kPointerSize); - DCHECK(Min(dst, const_cast<T*>(src)) + num_words <= - Max(dst, const_cast<T*>(src))); - DCHECK_GT(num_words, 0); - - // Use block copying MemCopy if the segment we're copying is - // enough to justify the extra call/setup overhead. - static const size_t kBlockCopyLimit = 16; - - if (num_words < kBlockCopyLimit) { - do { - num_words--; - *dst++ = *src++; - } while (num_words > 0); - } else { - MemCopy(dst, src, num_words * kPointerSize); - } -} - - -// Copies words from |src| to |dst|. No restrictions. -template <typename T> -inline void MoveWords(T* dst, const T* src, size_t num_words) { - STATIC_ASSERT(sizeof(T) == kPointerSize); - DCHECK_GT(num_words, 0); - - // Use block copying MemCopy if the segment we're copying is - // enough to justify the extra call/setup overhead. - static const size_t kBlockCopyLimit = 16; - - if (num_words < kBlockCopyLimit && - ((dst < src) || (dst >= (src + num_words * kPointerSize)))) { - T* end = dst + num_words; - do { - num_words--; - *dst++ = *src++; - } while (num_words > 0); - } else { - MemMove(dst, src, num_words * kPointerSize); - } -} - - -// Copies data from |src| to |dst|. The data spans must not overlap. -template <typename T> -inline void CopyBytes(T* dst, const T* src, size_t num_bytes) { - STATIC_ASSERT(sizeof(T) == 1); - DCHECK(Min(dst, const_cast<T*>(src)) + num_bytes <= - Max(dst, const_cast<T*>(src))); - if (num_bytes == 0) return; - - // Use block copying MemCopy if the segment we're copying is - // enough to justify the extra call/setup overhead. - static const int kBlockCopyLimit = kMinComplexMemCopy; - - if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) { - do { - num_bytes--; - *dst++ = *src++; - } while (num_bytes > 0); - } else { - MemCopy(dst, src, num_bytes); - } -} - - -template <typename T, typename U> -inline void MemsetPointer(T** dest, U* value, int counter) { -#ifdef DEBUG - T* a = nullptr; - U* b = nullptr; - a = b; // Fake assignment to check assignability. - USE(a); -#endif // DEBUG -#if V8_HOST_ARCH_IA32 -#define STOS "stosl" -#elif V8_HOST_ARCH_X64 -#if V8_HOST_ARCH_32_BIT -#define STOS "addr32 stosl" -#else -#define STOS "stosq" -#endif -#endif - -#if defined(MEMORY_SANITIZER) - // MemorySanitizer does not understand inline assembly. -#undef STOS -#endif - -#if defined(__GNUC__) && defined(STOS) - asm volatile( - "cld;" - "rep ; " STOS - : "+&c" (counter), "+&D" (dest) - : "a" (value) - : "memory", "cc"); -#else - for (int i = 0; i < counter; i++) { - dest[i] = value; - } -#endif - -#undef STOS -} - // Simple support to read a file into std::string. // On return, *exits tells whether the file existed. V8_EXPORT_PRIVATE std::string ReadFile(const char* filename, bool* exists, bool verbose = true); std::string ReadFile(FILE* file, bool* exists, bool verbose = true); -template <typename sourcechar, typename sinkchar> -V8_INLINE static void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, - size_t chars); -#if defined(V8_HOST_ARCH_ARM) -V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, - size_t chars); -V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, - size_t chars); -V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, - size_t chars); -#elif defined(V8_HOST_ARCH_MIPS) -V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, - size_t chars); -V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, - size_t chars); -#elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390) -V8_INLINE void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, - size_t chars); -V8_INLINE void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, - size_t chars); -#endif - -// Copy from 8bit/16bit chars to 8bit/16bit chars. -template <typename sourcechar, typename sinkchar> -V8_INLINE void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars); - -template <typename sourcechar, typename sinkchar> -void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars) { - DCHECK_LE(sizeof(sourcechar), 2); - DCHECK_LE(sizeof(sinkchar), 2); - if (sizeof(sinkchar) == 1) { - if (sizeof(sourcechar) == 1) { - CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest), - reinterpret_cast<const uint8_t*>(src), - chars); - } else { - CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest), - reinterpret_cast<const uint16_t*>(src), - chars); - } - } else { - if (sizeof(sourcechar) == 1) { - CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest), - reinterpret_cast<const uint8_t*>(src), - chars); - } else { - CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest), - reinterpret_cast<const uint16_t*>(src), - chars); - } - } -} - -template <typename sourcechar, typename sinkchar> -void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, size_t chars) { - sinkchar* limit = dest + chars; - if ((sizeof(*dest) == sizeof(*src)) && - (chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest)))) { - MemCopy(dest, src, chars * sizeof(*dest)); - } else { - while (dest < limit) *dest++ = static_cast<sinkchar>(*src++); - } -} - - -#if defined(V8_HOST_ARCH_ARM) -void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) { - switch (static_cast<unsigned>(chars)) { - case 0: - break; - case 1: - *dest = *src; - break; - case 2: - memcpy(dest, src, 2); - break; - case 3: - memcpy(dest, src, 3); - break; - case 4: - memcpy(dest, src, 4); - break; - case 5: - memcpy(dest, src, 5); - break; - case 6: - memcpy(dest, src, 6); - break; - case 7: - memcpy(dest, src, 7); - break; - case 8: - memcpy(dest, src, 8); - break; - case 9: - memcpy(dest, src, 9); - break; - case 10: - memcpy(dest, src, 10); - break; - case 11: - memcpy(dest, src, 11); - break; - case 12: - memcpy(dest, src, 12); - break; - case 13: - memcpy(dest, src, 13); - break; - case 14: - memcpy(dest, src, 14); - break; - case 15: - memcpy(dest, src, 15); - break; - default: - MemCopy(dest, src, chars); - break; - } -} - - -void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, size_t chars) { - if (chars >= static_cast<size_t>(kMinComplexConvertMemCopy)) { - MemCopyUint16Uint8(dest, src, chars); - } else { - MemCopyUint16Uint8Wrapper(dest, src, chars); - } -} - - -void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) { - switch (static_cast<unsigned>(chars)) { - case 0: - break; - case 1: - *dest = *src; - break; - case 2: - memcpy(dest, src, 4); - break; - case 3: - memcpy(dest, src, 6); - break; - case 4: - memcpy(dest, src, 8); - break; - case 5: - memcpy(dest, src, 10); - break; - case 6: - memcpy(dest, src, 12); - break; - case 7: - memcpy(dest, src, 14); - break; - default: - MemCopy(dest, src, chars * sizeof(*dest)); - break; - } -} - - -#elif defined(V8_HOST_ARCH_MIPS) -void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) { - if (chars < kMinComplexMemCopy) { - memcpy(dest, src, chars); - } else { - MemCopy(dest, src, chars); - } -} - -void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) { - if (chars < kMinComplexMemCopy) { - memcpy(dest, src, chars * sizeof(*dest)); - } else { - MemCopy(dest, src, chars * sizeof(*dest)); - } -} -#elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390) -#define CASE(n) \ - case n: \ - memcpy(dest, src, n); \ - break -void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) { - switch (static_cast<unsigned>(chars)) { - case 0: - break; - case 1: - *dest = *src; - break; - CASE(2); - CASE(3); - CASE(4); - CASE(5); - CASE(6); - CASE(7); - CASE(8); - CASE(9); - CASE(10); - CASE(11); - CASE(12); - CASE(13); - CASE(14); - CASE(15); - CASE(16); - CASE(17); - CASE(18); - CASE(19); - CASE(20); - CASE(21); - CASE(22); - CASE(23); - CASE(24); - CASE(25); - CASE(26); - CASE(27); - CASE(28); - CASE(29); - CASE(30); - CASE(31); - CASE(32); - CASE(33); - CASE(34); - CASE(35); - CASE(36); - CASE(37); - CASE(38); - CASE(39); - CASE(40); - CASE(41); - CASE(42); - CASE(43); - CASE(44); - CASE(45); - CASE(46); - CASE(47); - CASE(48); - CASE(49); - CASE(50); - CASE(51); - CASE(52); - CASE(53); - CASE(54); - CASE(55); - CASE(56); - CASE(57); - CASE(58); - CASE(59); - CASE(60); - CASE(61); - CASE(62); - CASE(63); - CASE(64); - default: - memcpy(dest, src, chars); - break; - } -} -#undef CASE - -#define CASE(n) \ - case n: \ - memcpy(dest, src, n * 2); \ - break -void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) { - switch (static_cast<unsigned>(chars)) { - case 0: - break; - case 1: - *dest = *src; - break; - CASE(2); - CASE(3); - CASE(4); - CASE(5); - CASE(6); - CASE(7); - CASE(8); - CASE(9); - CASE(10); - CASE(11); - CASE(12); - CASE(13); - CASE(14); - CASE(15); - CASE(16); - CASE(17); - CASE(18); - CASE(19); - CASE(20); - CASE(21); - CASE(22); - CASE(23); - CASE(24); - CASE(25); - CASE(26); - CASE(27); - CASE(28); - CASE(29); - CASE(30); - CASE(31); - CASE(32); - default: - memcpy(dest, src, chars * 2); - break; - } -} -#undef CASE -#endif - - class StringBuilder : public SimpleStringBuilder { public: explicit StringBuilder(int size) : SimpleStringBuilder(size) { } @@ -1575,6 +1053,9 @@ class StringBuilder : public SimpleStringBuilder { bool DoubleToBoolean(double d); +template <typename Char> +bool TryAddIndexChar(uint32_t* index, Char c); + template <typename Stream> bool StringToArrayIndex(Stream* stream, uint32_t* index); |