14 #include <type_traits> 16 #include "include/v8.h" 17 #include "src/allocation.h" 18 #include "src/base/bits.h" 19 #include "src/base/compiler-specific.h" 20 #include "src/base/logging.h" 21 #include "src/base/macros.h" 22 #include "src/base/platform/platform.h" 23 #include "src/base/v8-fallthrough.h" 24 #include "src/globals.h" 25 #include "src/objects/slots.h" 26 #include "src/vector.h" 28 #if defined(V8_OS_AIX) 40 inline int HexValue(uc32 c) {
42 if (static_cast<unsigned>(c) <= 9)
return c;
43 c = (c | 0x20) - (
'a' -
'0');
44 if (static_cast<unsigned>(c) <= 5)
return c + 10;
48 inline char HexCharOfValue(
int value) {
49 DCHECK(0 <= value && value <= 16);
50 if (value < 10)
return value +
'0';
51 return value - 10 +
'A';
54 inline int BoolToInt(
bool b) {
return b ? 1 : 0; }
57 inline bool CStringEquals(
const char* s1,
const char* s2) {
58 return (s1 == s2) || (s1 !=
nullptr && s2 !=
nullptr && strcmp(s1, s2) == 0);
63 template <
typename T,
typename U>
64 inline constexpr
bool IsInRange(T value, U lower_limit, U higher_limit) {
65 #if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR 66 DCHECK(lower_limit <= higher_limit);
68 STATIC_ASSERT(
sizeof(U) <=
sizeof(T));
69 typedef typename std::make_unsigned<T>::type unsigned_T;
71 return static_cast<unsigned_T
>(
static_cast<unsigned_T
>(value) -
72 static_cast<unsigned_T>(lower_limit)) <=
73 static_cast<unsigned_T>(static_cast<unsigned_T>(higher_limit) -
74 static_cast<unsigned_T
>(lower_limit));
79 typename =
typename std::enable_if<std::is_integral<T>::value>::type>
80 inline int WhichPowerOf2(T x) {
81 DCHECK(base::bits::IsPowerOfTwo(x));
84 const T original_x = x;
86 constexpr
int max_bits =
sizeof(T) * 8;
87 static_assert(max_bits <= 64,
"integral types are not bigger than 64 bits");
89 #define CHECK_BIGGER(s) \ 90 if (max_bits > s && x >= T{1} << (max_bits > s ? s : 0)) { \ 92 x >>= max_bits > s ? s : 0; \ 100 default: UNREACHABLE();
112 DCHECK_EQ(T{1} << bits, original_x);
116 inline int MostSignificantBit(
uint32_t x) {
117 static const int msb4[] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};
119 if (x & 0xffff0000) {
131 return nibble + msb4[x];
134 template <
typename T>
135 static T ArithmeticShiftRight(T x,
int shift) {
140 using UnsignedT =
typename std::make_unsigned<T>::type;
141 UnsignedT mask = ~(
static_cast<UnsignedT
>(~0) >> shift);
142 return (static_cast<UnsignedT>(x) >> shift) | mask;
148 template <
typename T>
149 int Compare(
const T& a,
const T& b) {
161 template<
typename T>
class Handle;
162 template <
typename T>
163 int HandleObjectPointerCompare(
const Handle<T>* a,
const Handle<T>* b) {
164 return Compare<T*>(*(*a), *(*b));
168 template <
typename T>
169 constexpr T Max(T a, T b) {
170 return a < b ? b : a;
175 template <
typename T>
176 constexpr T Min(T a, T b) {
177 return a < b ? a : b;
181 template <
typename T>
183 if (std::isnan(x))
return x;
184 if (std::isnan(y))
return y;
185 if (std::signbit(x) < std::signbit(y))
return x;
186 return x > y ? x : y;
190 template <
typename T>
192 if (std::isnan(x))
return x;
193 if (std::isnan(y))
return y;
194 if (std::signbit(x) < std::signbit(y))
return y;
195 return x > y ? y : x;
199 template <
typename T,
200 typename =
typename std::enable_if<std::is_signed<T>::value>::type>
201 typename std::make_unsigned<T>::type Abs(T a) {
205 typedef typename std::make_unsigned<T>::type unsignedT;
206 unsignedT x =
static_cast<unsignedT
>(a);
207 unsignedT y =
static_cast<unsignedT
>(a >> (
sizeof(T) * 8 - 1));
212 template <
typename T,
213 typename =
typename std::enable_if<std::is_signed<T>::value>::type>
215 return a < 0 ? a : -a;
219 inline double Floor(
double x) {
221 if (x == 0)
return x;
223 return std::floor(x);
226 inline double Modulo(
double x,
double y) {
227 #if defined(V8_OS_WIN) 231 if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) &&
232 !(x == 0 && (y != 0 && std::isfinite(y)))) {
236 #elif defined(V8_OS_AIX) 238 feclearexcept(FE_ALL_EXCEPT);
239 double result = std::fmod(x, y);
240 int exception = fetestexcept(FE_UNDERFLOW);
241 return (exception ? x : result);
243 return std::fmod(x, y);
247 inline double Pow(
double x,
double y) {
248 if (y == 0.0)
return 1.0;
249 if (std::isnan(y) || ((x == 1 || x == -1) && std::isinf(y))) {
250 return std::numeric_limits<double>::quiet_NaN();
252 #if (defined(__MINGW64_VERSION_MAJOR) && \ 253 (!defined(__MINGW64_VERSION_RC) || __MINGW64_VERSION_RC < 1)) || \ 257 if ((x == 0.0 || std::isinf(x)) && y != 0.0 && std::isfinite(y)) {
259 double result = ((x == 0.0) ^ (y > 0)) ? V8_INFINITY : 0;
261 return ((std::modf(y, &f) == 0.0) && (
static_cast<int64_t>(y) & 1))
262 ? copysign(result, x)
267 int y_int =
static_cast<int>(y);
269 return std::ldexp(1.0, y_int);
273 return std::pow(x, y);
276 template <
typename T>
277 T SaturateAdd(T a, T b) {
278 if (std::is_signed<T>::value) {
279 if (a > 0 && b > 0) {
280 if (a > std::numeric_limits<T>::max() - b) {
281 return std::numeric_limits<T>::max();
283 }
else if (a < 0 && b < 0) {
284 if (a < std::numeric_limits<T>::min() - b) {
285 return std::numeric_limits<T>::min();
289 CHECK(std::is_unsigned<T>::value);
290 if (a > std::numeric_limits<T>::max() - b) {
291 return std::numeric_limits<T>::max();
297 template <
typename T>
298 T SaturateSub(T a, T b) {
299 if (std::is_signed<T>::value) {
300 if (a >= 0 && b < 0) {
301 if (a > std::numeric_limits<T>::max() + b) {
302 return std::numeric_limits<T>::max();
304 }
else if (a < 0 && b > 0) {
305 if (a < std::numeric_limits<T>::min() + b) {
306 return std::numeric_limits<T>::min();
310 CHECK(std::is_unsigned<T>::value);
312 return static_cast<T
>(0);
322 template<
class T,
int shift,
int size,
class U>
330 static const U kOne =
static_cast<U
>(1U);
331 static const U kMask = ((kOne << shift) << size) - (kOne << shift);
332 static const U kShift = shift;
333 static const U kSize = size;
334 static const U kNext = kShift + kSize;
335 static const U kNumValues = kOne << size;
338 static const T kMax =
static_cast<T
>(kNumValues - 1);
341 static constexpr
bool is_valid(T value) {
342 return (static_cast<U>(value) & ~static_cast<U>(kMax)) == 0;
346 static U encode(T value) {
347 DCHECK(is_valid(value));
348 return static_cast<U
>(value) << shift;
352 static U update(U previous, T value) {
353 return (previous & ~kMask) | encode(value);
357 static T decode(U value) {
358 return static_cast<T
>((value & kMask) >> shift);
361 STATIC_ASSERT((kNext - 1) / 8 <
sizeof(U));
364 template <
class T,
int shift,
int size>
368 template <
class T,
int shift,
int size>
372 template<
class T,
int shift,
int size>
376 template<
class T,
int shift,
int size>
393 #define DEFINE_BIT_FIELD_RANGE_TYPE(Name, Type, Size, _) \ 394 k##Name##Start, k##Name##End = k##Name##Start + Size - 1, 396 #define DEFINE_BIT_RANGES(LIST_MACRO) \ 397 struct LIST_MACRO##_Ranges { \ 398 enum { LIST_MACRO(DEFINE_BIT_FIELD_RANGE_TYPE, _) kBitsCount }; \ 401 #define DEFINE_BIT_FIELD_TYPE(Name, Type, Size, RangesName) \ 402 typedef BitField<Type, RangesName::k##Name##Start, Size> Name; 404 #define DEFINE_BIT_FIELD_64_TYPE(Name, Type, Size, RangesName) \ 405 typedef BitField64<Type, RangesName::k##Name##Start, Size> Name; 407 #define DEFINE_BIT_FIELDS(LIST_MACRO) \ 408 DEFINE_BIT_RANGES(LIST_MACRO) \ 409 LIST_MACRO(DEFINE_BIT_FIELD_TYPE, LIST_MACRO##_Ranges) 411 #define DEFINE_BIT_FIELDS_64(LIST_MACRO) \ 412 DEFINE_BIT_RANGES(LIST_MACRO) \ 413 LIST_MACRO(DEFINE_BIT_FIELD_64_TYPE, LIST_MACRO##_Ranges) 422 template <
class T,
int kBitsPerItem,
int kBitsPerWord,
class U>
425 static const int kItemsPerWord = kBitsPerWord / kBitsPerItem;
426 static const int kMask = (1 << kBitsPerItem) - 1;
429 static int word_count(
int items) {
430 if (items == 0)
return 0;
431 return (items - 1) / kItemsPerWord + 1;
435 static int index(
int base_index,
int item) {
436 return base_index + item / kItemsPerWord;
440 static T decode(U data,
int item) {
441 return static_cast<T>((data >> shift(item)) & kMask);
445 static U encode(U previous,
int item,
T value) {
446 int shift_value = shift(item);
447 int set_bits = (
static_cast<int>(value) << shift_value);
448 return (previous & ~(kMask << shift_value)) | set_bits;
451 static int shift(
int item) {
return (item % kItemsPerWord) * kBitsPerItem; }
467 #define DEFINE_ONE_FIELD_OFFSET(Name, Size) Name, Name##End = Name + (Size)-1, 469 #define DEFINE_FIELD_OFFSET_CONSTANTS(StartOffset, LIST_MACRO) \ 471 LIST_MACRO##_StartOffset = StartOffset - 1, \ 472 LIST_MACRO(DEFINE_ONE_FIELD_OFFSET) \ 476 #define FIELD_SIZE(Name) (Name##End + 1 - Name) 481 static const uint64_t kZeroHashSeed = 0;
487 hash = ~hash + (hash << 15);
488 hash = hash ^ (hash >> 12);
489 hash = hash + (hash << 2);
490 hash = hash ^ (hash >> 4);
492 hash = hash ^ (hash >> 16);
493 return hash & 0x3fffffff;
496 inline uint32_t ComputeLongHash(uint64_t key) {
498 hash = ~hash + (hash << 18);
499 hash = hash ^ (hash >> 31);
501 hash = hash ^ (hash >> 11);
502 hash = hash + (hash << 6);
503 hash = hash ^ (hash >> 22);
504 return static_cast<uint32_t>(hash & 0x3fffffff);
508 return ComputeLongHash(static_cast<uint64_t>(key) ^ seed);
511 inline uint32_t ComputePointerHash(
void* ptr) {
512 return ComputeUnseededHash(
513 static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)));
516 inline uint32_t ComputeAddressHash(Address address) {
517 return ComputeUnseededHash(static_cast<uint32_t>(address & 0xFFFFFFFFul));
524 void init_memcopy_functions();
526 #if defined(V8_TARGET_ARCH_IA32) 529 const int kMinComplexMemCopy = 64;
532 V8_EXPORT_PRIVATE
void MemMove(
void* dest,
const void* src,
size_t size);
533 typedef void (*MemMoveFunction)(
void* dest,
const void* src,
size_t size);
537 V8_INLINE
void MemCopy(
void* dest,
const void* src,
size_t size) {
538 MemMove(dest, src, size);
540 #elif defined(V8_HOST_ARCH_ARM) 541 typedef void (*MemCopyUint8Function)(uint8_t* dest,
const uint8_t* src,
543 V8_EXPORT_PRIVATE
extern MemCopyUint8Function memcopy_uint8_function;
544 V8_INLINE
void MemCopyUint8Wrapper(uint8_t* dest,
const uint8_t* src,
546 memcpy(dest, src, chars);
549 const int kMinComplexMemCopy = 16;
550 V8_INLINE
void MemCopy(
void* dest,
const void* src,
size_t size) {
551 (*memcopy_uint8_function)(
reinterpret_cast<uint8_t*
>(dest),
552 reinterpret_cast<const uint8_t*>(src), size);
554 V8_EXPORT_PRIVATE V8_INLINE
void MemMove(
void* dest,
const void* src,
556 memmove(dest, src, size);
559 typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest,
const uint8_t* src,
561 extern MemCopyUint16Uint8Function memcopy_uint16_uint8_function;
562 void MemCopyUint16Uint8Wrapper(uint16_t* dest,
const uint8_t* src,
565 const int kMinComplexConvertMemCopy = 12;
566 V8_INLINE
void MemCopyUint16Uint8(uint16_t* dest,
const uint8_t* src,
568 (*memcopy_uint16_uint8_function)(dest, src, size);
570 #elif defined(V8_HOST_ARCH_MIPS) 571 typedef void (*MemCopyUint8Function)(uint8_t* dest,
const uint8_t* src,
573 V8_EXPORT_PRIVATE
extern MemCopyUint8Function memcopy_uint8_function;
574 V8_INLINE
void MemCopyUint8Wrapper(uint8_t* dest,
const uint8_t* src,
576 memcpy(dest, src, chars);
579 const int kMinComplexMemCopy = 16;
580 V8_INLINE
void MemCopy(
void* dest,
const void* src,
size_t size) {
581 (*memcopy_uint8_function)(
reinterpret_cast<uint8_t*
>(dest),
582 reinterpret_cast<const uint8_t*>(src), size);
584 V8_EXPORT_PRIVATE V8_INLINE
void MemMove(
void* dest,
const void* src,
586 memmove(dest, src, size);
590 V8_INLINE
void MemCopy(
void* dest,
const void* src,
size_t size) {
591 memcpy(dest, src, size);
593 V8_EXPORT_PRIVATE V8_INLINE
void MemMove(
void* dest,
const void* src,
595 memmove(dest, src, size);
597 const int kMinComplexMemCopy = 8;
598 #endif // V8_TARGET_ARCH_IA32 605 #if defined(V8_TARGET_LITTLE_ENDIAN) 606 static const int kInt64LowerHalfMemoryOffset = 0;
607 static const int kInt64UpperHalfMemoryOffset = 4;
608 #elif defined(V8_TARGET_BIG_ENDIAN) 609 static const int kInt64LowerHalfMemoryOffset = 4;
610 static const int kInt64UpperHalfMemoryOffset = 0;
611 #endif // V8_TARGET_LITTLE_ENDIAN 616 template <
typename T>
622 template <
typename S>
friend class Access;
629 template <
typename T>
633 : resource_(resource)
634 , instance_(&resource->instance_) {
635 DCHECK(!resource->is_reserved_);
636 resource->is_reserved_ =
true;
640 resource_->is_reserved_ =
false;
645 T* value() {
return instance_; }
646 T* operator -> () {
return instance_; }
659 bool is_set()
const {
return pointer_ !=
nullptr; }
662 DCHECK_NOT_NULL(pointer_);
667 DCHECK(pointer_ ==
nullptr && value !=
nullptr);
671 T* operator=(
T* value) {
676 bool operator==(std::nullptr_t)
const {
return pointer_ ==
nullptr; }
677 bool operator!=(std::nullptr_t)
const {
return pointer_ !=
nullptr; }
680 T* pointer_ =
nullptr;
684 template <
typename T,
int kSize>
690 for (
int i = 0;
i < kSize; ++
i) {
691 buffer_[
i] = initial_value;
698 MemCopy(buffer_, rhs.buffer_,
sizeof(
T) * kSize);
699 this->set_start(buffer_);
703 if (
this == &rhs)
return *
this;
705 MemCopy(buffer_, rhs.buffer_,
sizeof(
T) * kSize);
706 this->set_start(buffer_);
715 template <
typename l
char,
typename r
char>
716 inline int CompareCharsUnsigned(
const lchar* lhs,
const rchar* rhs,
718 const lchar* limit = lhs + chars;
719 if (
sizeof(*lhs) ==
sizeof(
char) &&
sizeof(*rhs) ==
sizeof(
char)) {
722 return memcmp(lhs, rhs, chars);
724 while (lhs < limit) {
725 int r =
static_cast<int>(*lhs) -
static_cast<int>(*rhs);
726 if (r != 0)
return r;
733 template <
typename l
char,
typename r
char>
734 inline int CompareChars(
const lchar* lhs,
const rchar* rhs,
size_t chars) {
735 DCHECK_LE(
sizeof(lchar), 2);
736 DCHECK_LE(
sizeof(rchar), 2);
737 if (
sizeof(lchar) == 1) {
738 if (
sizeof(rchar) == 1) {
739 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
740 reinterpret_cast<const uint8_t*>(rhs),
743 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
744 reinterpret_cast<const uint16_t*>(rhs),
748 if (
sizeof(rchar) == 1) {
749 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
750 reinterpret_cast<const uint8_t*>(rhs),
753 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
754 reinterpret_cast<const uint16_t*>(rhs),
762 inline int TenToThe(
int exponent) {
763 DCHECK_LE(exponent, 9);
764 DCHECK_GE(exponent, 1);
766 for (
int i = 1;
i < exponent;
i++) answer *= 10;
771 template<
typename ElementType,
int NumElements>
776 int length()
const {
return NumElements; }
777 const ElementType& operator[](
int i)
const {
778 DCHECK(
i < length());
781 ElementType& operator[](
int i) {
782 DCHECK(
i < length());
787 ElementType elems_[NumElements];
791 template<
typename ElementType>
794 int length()
const {
return 0; }
795 const ElementType& operator[](
int i)
const {
797 static ElementType t = 0;
800 ElementType& operator[](
int i) {
802 static ElementType t = 0;
820 : buffer_(buffer, size), position_(0) { }
824 int size()
const {
return buffer_.length(); }
827 int position()
const {
828 DCHECK(!is_finalized());
833 void Reset() { position_ = 0; }
838 void AddCharacter(
char c) {
840 DCHECK(!is_finalized() && position_ < buffer_.length());
841 buffer_[position_++] = c;
846 void AddString(
const char* s);
850 void AddSubstring(
const char* s,
int n);
854 void AddPadding(
char c,
int count);
857 void AddDecimalInteger(
int value);
866 bool is_finalized()
const {
return position_ < 0; }
875 template <
class E,
class T =
int>
878 explicit EnumSet(
T bits = 0) : bits_(bits) {}
879 bool IsEmpty()
const {
return bits_ == 0; }
880 bool Contains(E element)
const {
return (bits_ & Mask(element)) != 0; }
881 bool ContainsAnyOf(
const EnumSet&
set)
const {
882 return (bits_ &
set.bits_) != 0;
884 void Add(E element) { bits_ |= Mask(element); }
885 void Add(
const EnumSet&
set) { bits_ |=
set.bits_; }
886 void Remove(E element) { bits_ &= ~Mask(element); }
887 void Remove(
const EnumSet&
set) { bits_ &= ~set.bits_; }
888 void RemoveAll() { bits_ = 0; }
889 void Intersect(
const EnumSet&
set) { bits_ &=
set.bits_; }
890 T ToIntegral()
const {
return bits_; }
891 bool operator==(
const EnumSet&
set) {
return bits_ ==
set.bits_; }
892 bool operator!=(
const EnumSet&
set) {
return bits_ !=
set.bits_; }
894 return EnumSet(bits_ |
set.bits_);
898 static_assert(std::is_enum<E>::value,
"EnumSet can only be used with enums");
900 T Mask(E element)
const {
901 DCHECK_GT(
sizeof(
T) * CHAR_BIT, static_cast<int>(element));
902 return T{1} <<
static_cast<typename std::underlying_type<E>::type
>(element);
910 return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
913 inline uint64_t unsigned_bitextract_64(
int msb,
int lsb, uint64_t x) {
914 return (x >> lsb) & ((
static_cast<uint64_t
>(1) << (1 + msb - lsb)) - 1);
917 inline int32_t signed_bitextract_32(
int msb,
int lsb, int32_t x) {
918 return (x << (31 - msb)) >> (lsb + 31 - msb);
921 inline int signed_bitextract_64(
int msb,
int lsb,
int x) {
923 return (x << (63 - msb)) >> (lsb + 63 - msb);
927 inline bool is_intn(
int64_t x,
unsigned n) {
928 DCHECK((0 < n) && (n < 64));
930 return (-limit <= x) && (x < limit);
933 inline bool is_uintn(
int64_t x,
unsigned n) {
934 DCHECK((0 < n) && (n < (
sizeof(x) * kBitsPerByte)));
939 inline T truncate_to_intn(T x,
unsigned n) {
940 DCHECK((0 < n) && (n < (
sizeof(x) * kBitsPerByte)));
941 return (x & ((static_cast<T>(1) << n) - 1));
944 #define INT_1_TO_63_LIST(V) \ 945 V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \ 946 V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \ 947 V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \ 948 V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32) \ 949 V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \ 950 V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \ 951 V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \ 952 V(57) V(58) V(59) V(60) V(61) V(62) V(63) 954 #define DECLARE_IS_INT_N(N) \ 955 inline bool is_int##N(int64_t x) { return is_intn(x, N); } 956 #define DECLARE_IS_UINT_N(N) \ 958 inline bool is_uint##N(T x) { return is_uintn(x, N); } 959 #define DECLARE_TRUNCATE_TO_INT_N(N) \ 961 inline T truncate_to_int##N(T x) { return truncate_to_intn(x, N); } 962 INT_1_TO_63_LIST(DECLARE_IS_INT_N)
963 INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
964 INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
965 #undef DECLARE_IS_INT_N 966 #undef DECLARE_IS_UINT_N 967 #undef DECLARE_TRUNCATE_TO_INT_N 970 #define INT_0_TO_127_LIST(V) \ 971 V(0) V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) V(9) \ 972 V(10) V(11) V(12) V(13) V(14) V(15) V(16) V(17) V(18) V(19) \ 973 V(20) V(21) V(22) V(23) V(24) V(25) V(26) V(27) V(28) V(29) \ 974 V(30) V(31) V(32) V(33) V(34) V(35) V(36) V(37) V(38) V(39) \ 975 V(40) V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) V(49) \ 976 V(50) V(51) V(52) V(53) V(54) V(55) V(56) V(57) V(58) V(59) \ 977 V(60) V(61) V(62) V(63) V(64) V(65) V(66) V(67) V(68) V(69) \ 978 V(70) V(71) V(72) V(73) V(74) V(75) V(76) V(77) V(78) V(79) \ 979 V(80) V(81) V(82) V(83) V(84) V(85) V(86) V(87) V(88) V(89) \ 980 V(90) V(91) V(92) V(93) V(94) V(95) V(96) V(97) V(98) V(99) \ 981 V(100) V(101) V(102) V(103) V(104) V(105) V(106) V(107) V(108) V(109) \ 982 V(110) V(111) V(112) V(113) V(114) V(115) V(116) V(117) V(118) V(119) \ 983 V(120) V(121) V(122) V(123) V(124) V(125) V(126) V(127) 991 int ToInt()
const {
return id_; }
994 bool IsInvalid()
const {
return id_ == kInvalidSlot; }
996 bool operator==(
FeedbackSlot that)
const {
return this->id_ == that.id_; }
997 bool operator!=(
FeedbackSlot that)
const {
return !(*
this == that); }
999 friend size_t hash_value(
FeedbackSlot slot) {
return slot.ToInt(); }
1000 friend std::ostream& operator<<(std::ostream& os,
FeedbackSlot);
1003 static const int kInvalidSlot = -1;
1011 explicit BailoutId(
int id) : id_(
id) { }
1012 int ToInt()
const {
return id_; }
1028 bool IsValidForConstructStub()
const {
1029 return id_ == ConstructStubCreate().ToInt() ||
1030 id_ == ConstructStubInvoke().ToInt();
1033 bool IsNone()
const {
return id_ == kNoneId; }
1034 bool operator==(
const BailoutId& other)
const {
return id_ == other.id_; }
1035 bool operator!=(
const BailoutId& other)
const {
return id_ != other.id_; }
1037 V8_EXPORT_PRIVATE
friend std::ostream& operator<<(std::ostream&,
BailoutId);
1042 static const int kNoneId = -1;
1045 static const int kScriptContextId = 1;
1046 static const int kFunctionContextId = 2;
1047 static const int kFunctionEntryId = 3;
1052 static const int kDeclarationsId = 4;
1055 static const int kFirstUsableId = 5;
1058 static const int kStubEntryId = 6;
1063 static const int kFirstBuiltinContinuationId = 7;
1073 V8_EXPORT_PRIVATE
void PRINTF_FORMAT(1, 2) PrintF(const
char* format, ...);
1074 void PRINTF_FORMAT(2, 3) PrintF(FILE* out, const
char* format, ...);
1077 void PRINTF_FORMAT(1, 2) PrintPID(const
char* format, ...);
1080 void PRINTF_FORMAT(2, 3) PrintIsolate(
void* isolate, const
char* format, ...);
1084 int PRINTF_FORMAT(2, 3) SNPrintF(
Vector<
char> str, const
char* format, ...);
1085 V8_EXPORT_PRIVATE
int PRINTF_FORMAT(2, 0)
1086 VSNPrintF(
Vector<
char> str, const
char* format, va_list args);
1088 void StrNCpy(
Vector<
char> dest, const
char* src,
size_t n);
1091 void Flush(FILE* out);
1093 inline
void Flush() {
1100 char* ReadLine(
const char* prompt);
1105 int AppendChars(
const char* filename,
1108 bool verbose =
true);
1113 int WriteChars(
const char* filename,
1116 bool verbose =
true);
1121 int WriteBytes(
const char* filename,
1124 bool verbose =
true);
1131 int WriteAsCFile(
const char* filename,
const char* varname,
1132 const char* str,
int size,
bool verbose =
true);
1140 inline void CopyWords(Address dst,
const Address src,
size_t num_words) {
1141 DCHECK(IsAligned(dst, kPointerSize));
1142 DCHECK(IsAligned(src, kPointerSize));
1143 DCHECK(Min(dst, src) + num_words * kPointerSize <= Max(dst, src));
1144 DCHECK_GT(num_words, 0);
1148 static const size_t kBlockCopyLimit = 16;
1150 Address* dst_ptr =
reinterpret_cast<Address*
>(dst);
1151 Address* src_ptr =
reinterpret_cast<Address*
>(src);
1152 if (num_words < kBlockCopyLimit) {
1155 *dst_ptr++ = *src_ptr++;
1156 }
while (num_words > 0);
1158 MemCopy(dst_ptr, src_ptr, num_words * kPointerSize);
1163 template <
typename T>
1164 inline void CopyBytes(T* dst,
const T* src,
size_t num_bytes) {
1165 STATIC_ASSERT(
sizeof(T) == 1);
1166 DCHECK(Min(dst, const_cast<T*>(src)) + num_bytes <=
1167 Max(dst, const_cast<T*>(src)));
1168 if (num_bytes == 0)
return;
1172 static const int kBlockCopyLimit = kMinComplexMemCopy;
1174 if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) {
1178 }
while (num_bytes > 0);
1180 MemCopy(dst, src, num_bytes);
1184 inline void MemsetPointer(Address* dest, Address value,
size_t counter) {
1185 #if V8_HOST_ARCH_IA32 1186 #define STOS "stosl" 1187 #elif V8_HOST_ARCH_X64 1188 #if V8_HOST_ARCH_32_BIT 1189 #define STOS "addr32 stosl" 1191 #define STOS "stosq" 1195 #if defined(MEMORY_SANITIZER) 1200 #if defined(__GNUC__) && defined(STOS) 1204 :
"+&c" (counter),
"+&D" (dest)
1208 for (
size_t i = 0;
i < counter;
i++) {
1216 template <
typename T,
typename U>
1217 inline void MemsetPointer(T** dest, U* value,
size_t counter) {
1224 MemsetPointer(reinterpret_cast<Address*>(dest),
1225 reinterpret_cast<Address>(value), counter);
1228 inline void MemsetPointer(ObjectSlot start, Object* value,
size_t counter) {
1229 MemsetPointer(start.location(),
reinterpret_cast<Address
>(value), counter);
1234 V8_EXPORT_PRIVATE std::string ReadFile(
const char* filename,
bool* exists,
1235 bool verbose =
true);
1236 std::string ReadFile(FILE* file,
bool* exists,
bool verbose =
true);
1238 template <
typename source
char,
typename sink
char>
1239 V8_INLINE
static void CopyCharsUnsigned(sinkchar* dest,
const sourcechar* src,
1241 #if defined(V8_HOST_ARCH_ARM) 1242 V8_INLINE
void CopyCharsUnsigned(uint8_t* dest,
const uint8_t* src,
1244 V8_INLINE
void CopyCharsUnsigned(uint16_t* dest,
const uint8_t* src,
1246 V8_INLINE
void CopyCharsUnsigned(uint16_t* dest,
const uint16_t* src,
1248 #elif defined(V8_HOST_ARCH_MIPS) 1249 V8_INLINE
void CopyCharsUnsigned(uint8_t* dest,
const uint8_t* src,
1251 V8_INLINE
void CopyCharsUnsigned(uint16_t* dest,
const uint16_t* src,
1253 #elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390) 1254 V8_INLINE
void CopyCharsUnsigned(uint8_t* dest,
const uint8_t* src,
1256 V8_INLINE
void CopyCharsUnsigned(uint16_t* dest,
const uint16_t* src,
1261 template <
typename source
char,
typename sink
char>
1262 V8_INLINE
void CopyChars(sinkchar* dest,
const sourcechar* src,
size_t chars);
1264 template <
typename source
char,
typename sink
char>
1265 void CopyChars(sinkchar* dest,
const sourcechar* src,
size_t chars) {
1266 DCHECK_LE(
sizeof(sourcechar), 2);
1267 DCHECK_LE(
sizeof(sinkchar), 2);
1268 if (
sizeof(sinkchar) == 1) {
1269 if (
sizeof(sourcechar) == 1) {
1270 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1271 reinterpret_cast<const uint8_t*>(src),
1274 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1275 reinterpret_cast<const uint16_t*>(src),
1279 if (
sizeof(sourcechar) == 1) {
1280 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1281 reinterpret_cast<const uint8_t*>(src),
1284 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1285 reinterpret_cast<const uint16_t*>(src),
1291 template <
typename source
char,
typename sink
char>
1292 void CopyCharsUnsigned(sinkchar* dest,
const sourcechar* src,
size_t chars) {
1293 sinkchar* limit = dest + chars;
1294 if ((
sizeof(*dest) ==
sizeof(*src)) &&
1295 (chars >= static_cast<int>(kMinComplexMemCopy /
sizeof(*dest)))) {
1296 MemCopy(dest, src, chars *
sizeof(*dest));
1298 while (dest < limit) *dest++ =
static_cast<sinkchar
>(*src++);
1303 #if defined(V8_HOST_ARCH_ARM) 1304 void CopyCharsUnsigned(uint8_t* dest,
const uint8_t* src,
size_t chars) {
1305 switch (static_cast<unsigned>(chars)) {
1312 memcpy(dest, src, 2);
1315 memcpy(dest, src, 3);
1318 memcpy(dest, src, 4);
1321 memcpy(dest, src, 5);
1324 memcpy(dest, src, 6);
1327 memcpy(dest, src, 7);
1330 memcpy(dest, src, 8);
1333 memcpy(dest, src, 9);
1336 memcpy(dest, src, 10);
1339 memcpy(dest, src, 11);
1342 memcpy(dest, src, 12);
1345 memcpy(dest, src, 13);
1348 memcpy(dest, src, 14);
1351 memcpy(dest, src, 15);
1354 MemCopy(dest, src, chars);
1360 void CopyCharsUnsigned(uint16_t* dest,
const uint8_t* src,
size_t chars) {
1361 if (chars >= static_cast<size_t>(kMinComplexConvertMemCopy)) {
1362 MemCopyUint16Uint8(dest, src, chars);
1364 MemCopyUint16Uint8Wrapper(dest, src, chars);
1369 void CopyCharsUnsigned(uint16_t* dest,
const uint16_t* src,
size_t chars) {
1370 switch (static_cast<unsigned>(chars)) {
1377 memcpy(dest, src, 4);
1380 memcpy(dest, src, 6);
1383 memcpy(dest, src, 8);
1386 memcpy(dest, src, 10);
1389 memcpy(dest, src, 12);
1392 memcpy(dest, src, 14);
1395 MemCopy(dest, src, chars *
sizeof(*dest));
1401 #elif defined(V8_HOST_ARCH_MIPS) 1402 void CopyCharsUnsigned(uint8_t* dest,
const uint8_t* src,
size_t chars) {
1403 if (chars < kMinComplexMemCopy) {
1404 memcpy(dest, src, chars);
1406 MemCopy(dest, src, chars);
1410 void CopyCharsUnsigned(uint16_t* dest,
const uint16_t* src,
size_t chars) {
1411 if (chars < kMinComplexMemCopy) {
1412 memcpy(dest, src, chars *
sizeof(*dest));
1414 MemCopy(dest, src, chars *
sizeof(*dest));
1417 #elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390) 1420 memcpy(dest, src, n); \ 1422 void CopyCharsUnsigned(uint8_t* dest,
const uint8_t* src,
size_t chars) {
1423 switch (static_cast<unsigned>(chars)) {
1493 memcpy(dest, src, chars);
1501 memcpy(dest, src, n * 2); \ 1503 void CopyCharsUnsigned(uint16_t* dest,
const uint16_t* src,
size_t chars) {
1504 switch (static_cast<unsigned>(chars)) {
1542 memcpy(dest, src, chars * 2);
1556 void PRINTF_FORMAT(2, 3) AddFormatted(
const char* format, ...);
1559 void PRINTF_FORMAT(2, 0) AddFormattedList(
const char* format, va_list list);
1566 bool DoubleToBoolean(
double d);
1568 template <
typename Char>
1569 bool TryAddIndexChar(
uint32_t* index, Char c);
1571 template <
typename Stream>
1572 bool StringToArrayIndex(Stream* stream,
uint32_t* index);
1578 V8_NOINLINE
uintptr_t GetCurrentStackPosition();
1580 template <
typename V>
1581 static inline V ByteReverse(V value) {
1582 size_t size_of_v =
sizeof(value);
1583 switch (size_of_v) {
1585 #if V8_HAS_BUILTIN_BSWAP16 1586 return static_cast<V
>(__builtin_bswap16(static_cast<uint16_t>(value)));
1588 return value << 8 | (value >> 8 & 0x00FF);
1591 #if V8_HAS_BUILTIN_BSWAP32 1592 return static_cast<V
>(__builtin_bswap32(static_cast<uint32_t>(value)));
1595 size_t bits_of_v = size_of_v * kBitsPerByte;
1596 return value << (bits_of_v - 8) |
1597 ((value << (bits_of_v - 24)) & 0x00FF0000) |
1598 ((value >> (bits_of_v - 24)) & 0x0000FF00) |
1599 ((value >> (bits_of_v - 8)) & 0x00000FF);
1603 #if V8_HAS_BUILTIN_BSWAP64 1604 return static_cast<V>(__builtin_bswap64(static_cast<uint64_t>(value)));
1607 size_t bits_of_v = size_of_v * kBitsPerByte;
1608 return value << (bits_of_v - 8) |
1609 ((value << (bits_of_v - 24)) & 0x00FF000000000000) |
1610 ((value << (bits_of_v - 40)) & 0x0000FF0000000000) |
1611 ((value << (bits_of_v - 56)) & 0x000000FF00000000) |
1612 ((value >> (bits_of_v - 56)) & 0x00000000FF000000) |
1613 ((value >> (bits_of_v - 40)) & 0x0000000000FF0000) |
1614 ((value >> (bits_of_v - 24)) & 0x000000000000FF00) |
1615 ((value >> (bits_of_v - 8)) & 0x00000000000000FF);
1623 V8_EXPORT_PRIVATE
bool PassesFilter(Vector<const char> name,
1624 Vector<const char> filter);
1630 V8_INLINE
void ZapCode(Address addr,
size_t size_in_bytes) {
1631 static constexpr
int kZapByte = 0xCC;
1632 std::memset(reinterpret_cast<void*>(addr), kZapByte, size_in_bytes);
1638 #endif // V8_UTILS_H_