11cb0ef41Sopenharmony_ci// Copyright 2012 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_UTILS_UTILS_H_ 61cb0ef41Sopenharmony_ci#define V8_UTILS_UTILS_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <limits.h> 91cb0ef41Sopenharmony_ci#include <stdlib.h> 101cb0ef41Sopenharmony_ci#include <string.h> 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci#include <cmath> 131cb0ef41Sopenharmony_ci#include <string> 141cb0ef41Sopenharmony_ci#include <type_traits> 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci#include "src/base/bits.h" 171cb0ef41Sopenharmony_ci#include "src/base/compiler-specific.h" 181cb0ef41Sopenharmony_ci#include "src/base/logging.h" 191cb0ef41Sopenharmony_ci#include "src/base/macros.h" 201cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h" 211cb0ef41Sopenharmony_ci#include "src/base/safe_conversions.h" 221cb0ef41Sopenharmony_ci#include "src/base/v8-fallthrough.h" 231cb0ef41Sopenharmony_ci#include "src/base/vector.h" 241cb0ef41Sopenharmony_ci#include "src/common/globals.h" 251cb0ef41Sopenharmony_ci#include "src/utils/allocation.h" 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci#if defined(V8_USE_SIPHASH) 281cb0ef41Sopenharmony_ci#include "src/third_party/siphash/halfsiphash.h" 291cb0ef41Sopenharmony_ci#endif 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci#if defined(V8_OS_AIX) 321cb0ef41Sopenharmony_ci#include <fenv.h> // NOLINT(build/c++11) 331cb0ef41Sopenharmony_ci#endif 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_cinamespace v8 { 361cb0ef41Sopenharmony_cinamespace internal { 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci// ---------------------------------------------------------------------------- 391cb0ef41Sopenharmony_ci// General helper functions 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_citemplate <typename T> 421cb0ef41Sopenharmony_cistatic T ArithmeticShiftRight(T x, int shift) { 431cb0ef41Sopenharmony_ci DCHECK_LE(0, shift); 441cb0ef41Sopenharmony_ci if (x < 0) { 451cb0ef41Sopenharmony_ci // Right shift of signed values is implementation defined. Simulate a 461cb0ef41Sopenharmony_ci // true arithmetic right shift by adding leading sign bits. 471cb0ef41Sopenharmony_ci using UnsignedT = typename std::make_unsigned<T>::type; 481cb0ef41Sopenharmony_ci UnsignedT mask = ~(static_cast<UnsignedT>(~0) >> shift); 491cb0ef41Sopenharmony_ci return (static_cast<UnsignedT>(x) >> shift) | mask; 501cb0ef41Sopenharmony_ci } else { 511cb0ef41Sopenharmony_ci return x >> shift; 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci} 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci// Returns the maximum of the two parameters according to JavaScript semantics. 561cb0ef41Sopenharmony_citemplate <typename T> 571cb0ef41Sopenharmony_ciT JSMax(T x, T y) { 581cb0ef41Sopenharmony_ci if (std::isnan(x)) return x; 591cb0ef41Sopenharmony_ci if (std::isnan(y)) return y; 601cb0ef41Sopenharmony_ci if (std::signbit(x) < std::signbit(y)) return x; 611cb0ef41Sopenharmony_ci return x > y ? x : y; 621cb0ef41Sopenharmony_ci} 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci// Returns the maximum of the two parameters according to JavaScript semantics. 651cb0ef41Sopenharmony_citemplate <typename T> 661cb0ef41Sopenharmony_ciT JSMin(T x, T y) { 671cb0ef41Sopenharmony_ci if (std::isnan(x)) return x; 681cb0ef41Sopenharmony_ci if (std::isnan(y)) return y; 691cb0ef41Sopenharmony_ci if (std::signbit(x) < std::signbit(y)) return y; 701cb0ef41Sopenharmony_ci return x > y ? y : x; 711cb0ef41Sopenharmony_ci} 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci// Returns the absolute value of its argument. 741cb0ef41Sopenharmony_citemplate <typename T, 751cb0ef41Sopenharmony_ci typename = typename std::enable_if<std::is_signed<T>::value>::type> 761cb0ef41Sopenharmony_citypename std::make_unsigned<T>::type Abs(T a) { 771cb0ef41Sopenharmony_ci // This is a branch-free implementation of the absolute value function and is 781cb0ef41Sopenharmony_ci // described in Warren's "Hacker's Delight", chapter 2. It avoids undefined 791cb0ef41Sopenharmony_ci // behavior with the arithmetic negation operation on signed values as well. 801cb0ef41Sopenharmony_ci using unsignedT = typename std::make_unsigned<T>::type; 811cb0ef41Sopenharmony_ci unsignedT x = static_cast<unsignedT>(a); 821cb0ef41Sopenharmony_ci unsignedT y = static_cast<unsignedT>(a >> (sizeof(T) * 8 - 1)); 831cb0ef41Sopenharmony_ci return (x ^ y) - y; 841cb0ef41Sopenharmony_ci} 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ciinline double Modulo(double x, double y) { 871cb0ef41Sopenharmony_ci#if defined(V8_OS_WIN) 881cb0ef41Sopenharmony_ci // Workaround MS fmod bugs. ECMA-262 says: 891cb0ef41Sopenharmony_ci // dividend is finite and divisor is an infinity => result equals dividend 901cb0ef41Sopenharmony_ci // dividend is a zero and divisor is nonzero finite => result equals dividend 911cb0ef41Sopenharmony_ci if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) && 921cb0ef41Sopenharmony_ci !(x == 0 && (y != 0 && std::isfinite(y)))) { 931cb0ef41Sopenharmony_ci double result = fmod(x, y); 941cb0ef41Sopenharmony_ci // Workaround MS bug in VS CRT in some OS versions, https://crbug.com/915045 951cb0ef41Sopenharmony_ci // fmod(-17, +/-1) should equal -0.0 but now returns 0.0. 961cb0ef41Sopenharmony_ci if (x < 0 && result == 0) result = -0.0; 971cb0ef41Sopenharmony_ci x = result; 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci return x; 1001cb0ef41Sopenharmony_ci#elif defined(V8_OS_AIX) 1011cb0ef41Sopenharmony_ci // AIX raises an underflow exception for (Number.MIN_VALUE % Number.MAX_VALUE) 1021cb0ef41Sopenharmony_ci feclearexcept(FE_ALL_EXCEPT); 1031cb0ef41Sopenharmony_ci double result = std::fmod(x, y); 1041cb0ef41Sopenharmony_ci int exception = fetestexcept(FE_UNDERFLOW); 1051cb0ef41Sopenharmony_ci return (exception ? x : result); 1061cb0ef41Sopenharmony_ci#else 1071cb0ef41Sopenharmony_ci return std::fmod(x, y); 1081cb0ef41Sopenharmony_ci#endif 1091cb0ef41Sopenharmony_ci} 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_citemplate <typename T> 1121cb0ef41Sopenharmony_ciT SaturateAdd(T a, T b) { 1131cb0ef41Sopenharmony_ci if (std::is_signed<T>::value) { 1141cb0ef41Sopenharmony_ci if (a > 0 && b > 0) { 1151cb0ef41Sopenharmony_ci if (a > std::numeric_limits<T>::max() - b) { 1161cb0ef41Sopenharmony_ci return std::numeric_limits<T>::max(); 1171cb0ef41Sopenharmony_ci } 1181cb0ef41Sopenharmony_ci } else if (a < 0 && b < 0) { 1191cb0ef41Sopenharmony_ci if (a < std::numeric_limits<T>::min() - b) { 1201cb0ef41Sopenharmony_ci return std::numeric_limits<T>::min(); 1211cb0ef41Sopenharmony_ci } 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci } else { 1241cb0ef41Sopenharmony_ci CHECK(std::is_unsigned<T>::value); 1251cb0ef41Sopenharmony_ci if (a > std::numeric_limits<T>::max() - b) { 1261cb0ef41Sopenharmony_ci return std::numeric_limits<T>::max(); 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci return a + b; 1301cb0ef41Sopenharmony_ci} 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_citemplate <typename T> 1331cb0ef41Sopenharmony_ciT SaturateSub(T a, T b) { 1341cb0ef41Sopenharmony_ci if (std::is_signed<T>::value) { 1351cb0ef41Sopenharmony_ci if (a >= 0 && b < 0) { 1361cb0ef41Sopenharmony_ci if (a > std::numeric_limits<T>::max() + b) { 1371cb0ef41Sopenharmony_ci return std::numeric_limits<T>::max(); 1381cb0ef41Sopenharmony_ci } 1391cb0ef41Sopenharmony_ci } else if (a < 0 && b > 0) { 1401cb0ef41Sopenharmony_ci if (a < std::numeric_limits<T>::min() + b) { 1411cb0ef41Sopenharmony_ci return std::numeric_limits<T>::min(); 1421cb0ef41Sopenharmony_ci } 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci } else { 1451cb0ef41Sopenharmony_ci CHECK(std::is_unsigned<T>::value); 1461cb0ef41Sopenharmony_ci if (a < b) { 1471cb0ef41Sopenharmony_ci return static_cast<T>(0); 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci return a - b; 1511cb0ef41Sopenharmony_ci} 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_citemplate <typename T> 1541cb0ef41Sopenharmony_ciT SaturateRoundingQMul(T a, T b) { 1551cb0ef41Sopenharmony_ci // Saturating rounding multiplication for Q-format numbers. See 1561cb0ef41Sopenharmony_ci // https://en.wikipedia.org/wiki/Q_(number_format) for a description. 1571cb0ef41Sopenharmony_ci // Specifically this supports Q7, Q15, and Q31. This follows the 1581cb0ef41Sopenharmony_ci // implementation in simulator-logic-arm64.cc (sqrdmulh) to avoid overflow 1591cb0ef41Sopenharmony_ci // when a == b == int32 min. 1601cb0ef41Sopenharmony_ci static_assert(std::is_integral<T>::value, "only integral types"); 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci constexpr int size_in_bits = sizeof(T) * 8; 1631cb0ef41Sopenharmony_ci int round_const = 1 << (size_in_bits - 2); 1641cb0ef41Sopenharmony_ci int64_t product = a * b; 1651cb0ef41Sopenharmony_ci product += round_const; 1661cb0ef41Sopenharmony_ci product >>= (size_in_bits - 1); 1671cb0ef41Sopenharmony_ci return base::saturated_cast<T>(product); 1681cb0ef41Sopenharmony_ci} 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci// Multiply two numbers, returning a result that is twice as wide, no overflow. 1711cb0ef41Sopenharmony_ci// Put Wide first so we can use function template argument deduction for Narrow, 1721cb0ef41Sopenharmony_ci// and callers can provide only Wide. 1731cb0ef41Sopenharmony_citemplate <typename Wide, typename Narrow> 1741cb0ef41Sopenharmony_ciWide MultiplyLong(Narrow a, Narrow b) { 1751cb0ef41Sopenharmony_ci static_assert( 1761cb0ef41Sopenharmony_ci std::is_integral<Narrow>::value && std::is_integral<Wide>::value, 1771cb0ef41Sopenharmony_ci "only integral types"); 1781cb0ef41Sopenharmony_ci static_assert(std::is_signed<Narrow>::value == std::is_signed<Wide>::value, 1791cb0ef41Sopenharmony_ci "both must have same signedness"); 1801cb0ef41Sopenharmony_ci static_assert(sizeof(Narrow) * 2 == sizeof(Wide), "only twice as long"); 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci return static_cast<Wide>(a) * static_cast<Wide>(b); 1831cb0ef41Sopenharmony_ci} 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci// Add two numbers, returning a result that is twice as wide, no overflow. 1861cb0ef41Sopenharmony_ci// Put Wide first so we can use function template argument deduction for Narrow, 1871cb0ef41Sopenharmony_ci// and callers can provide only Wide. 1881cb0ef41Sopenharmony_citemplate <typename Wide, typename Narrow> 1891cb0ef41Sopenharmony_ciWide AddLong(Narrow a, Narrow b) { 1901cb0ef41Sopenharmony_ci static_assert( 1911cb0ef41Sopenharmony_ci std::is_integral<Narrow>::value && std::is_integral<Wide>::value, 1921cb0ef41Sopenharmony_ci "only integral types"); 1931cb0ef41Sopenharmony_ci static_assert(std::is_signed<Narrow>::value == std::is_signed<Wide>::value, 1941cb0ef41Sopenharmony_ci "both must have same signedness"); 1951cb0ef41Sopenharmony_ci static_assert(sizeof(Narrow) * 2 == sizeof(Wide), "only twice as long"); 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci return static_cast<Wide>(a) + static_cast<Wide>(b); 1981cb0ef41Sopenharmony_ci} 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_citemplate <typename T> 2011cb0ef41Sopenharmony_ciinline T RoundingAverageUnsigned(T a, T b) { 2021cb0ef41Sopenharmony_ci static_assert(std::is_unsigned<T>::value, "Only for unsiged types"); 2031cb0ef41Sopenharmony_ci static_assert(sizeof(T) < sizeof(uint64_t), "Must be smaller than uint64_t"); 2041cb0ef41Sopenharmony_ci return (static_cast<uint64_t>(a) + static_cast<uint64_t>(b) + 1) >> 1; 2051cb0ef41Sopenharmony_ci} 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci// Helper macros for defining a contiguous sequence of field offset constants. 2081cb0ef41Sopenharmony_ci// Example: (backslashes at the ends of respective lines of this multi-line 2091cb0ef41Sopenharmony_ci// macro definition are omitted here to please the compiler) 2101cb0ef41Sopenharmony_ci// 2111cb0ef41Sopenharmony_ci// #define MAP_FIELDS(V) 2121cb0ef41Sopenharmony_ci// V(kField1Offset, kTaggedSize) 2131cb0ef41Sopenharmony_ci// V(kField2Offset, kIntSize) 2141cb0ef41Sopenharmony_ci// V(kField3Offset, kIntSize) 2151cb0ef41Sopenharmony_ci// V(kField4Offset, kSystemPointerSize) 2161cb0ef41Sopenharmony_ci// V(kSize, 0) 2171cb0ef41Sopenharmony_ci// 2181cb0ef41Sopenharmony_ci// DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, MAP_FIELDS) 2191cb0ef41Sopenharmony_ci// 2201cb0ef41Sopenharmony_ci#define DEFINE_ONE_FIELD_OFFSET(Name, Size, ...) \ 2211cb0ef41Sopenharmony_ci Name, Name##End = Name + (Size)-1, 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci#define DEFINE_FIELD_OFFSET_CONSTANTS(StartOffset, LIST_MACRO) \ 2241cb0ef41Sopenharmony_ci enum { \ 2251cb0ef41Sopenharmony_ci LIST_MACRO##_StartOffset = StartOffset - 1, \ 2261cb0ef41Sopenharmony_ci LIST_MACRO(DEFINE_ONE_FIELD_OFFSET) \ 2271cb0ef41Sopenharmony_ci }; 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci// Size of the field defined by DEFINE_FIELD_OFFSET_CONSTANTS 2301cb0ef41Sopenharmony_ci#define FIELD_SIZE(Name) (Name##End + 1 - Name) 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci// Compare two offsets with static cast 2331cb0ef41Sopenharmony_ci#define STATIC_ASSERT_FIELD_OFFSETS_EQUAL(Offset1, Offset2) \ 2341cb0ef41Sopenharmony_ci STATIC_ASSERT(static_cast<int>(Offset1) == Offset2) 2351cb0ef41Sopenharmony_ci// ---------------------------------------------------------------------------- 2361cb0ef41Sopenharmony_ci// Hash function. 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_cistatic const uint64_t kZeroHashSeed = 0; 2391cb0ef41Sopenharmony_ci 2401cb0ef41Sopenharmony_ci// Thomas Wang, Integer Hash Functions. 2411cb0ef41Sopenharmony_ci// http://www.concentric.net/~Ttwang/tech/inthash.htm` 2421cb0ef41Sopenharmony_ciinline uint32_t ComputeUnseededHash(uint32_t key) { 2431cb0ef41Sopenharmony_ci uint32_t hash = key; 2441cb0ef41Sopenharmony_ci hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1; 2451cb0ef41Sopenharmony_ci hash = hash ^ (hash >> 12); 2461cb0ef41Sopenharmony_ci hash = hash + (hash << 2); 2471cb0ef41Sopenharmony_ci hash = hash ^ (hash >> 4); 2481cb0ef41Sopenharmony_ci hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11); 2491cb0ef41Sopenharmony_ci hash = hash ^ (hash >> 16); 2501cb0ef41Sopenharmony_ci return hash & 0x3fffffff; 2511cb0ef41Sopenharmony_ci} 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ciinline uint32_t ComputeLongHash(uint64_t key) { 2541cb0ef41Sopenharmony_ci uint64_t hash = key; 2551cb0ef41Sopenharmony_ci hash = ~hash + (hash << 18); // hash = (hash << 18) - hash - 1; 2561cb0ef41Sopenharmony_ci hash = hash ^ (hash >> 31); 2571cb0ef41Sopenharmony_ci hash = hash * 21; // hash = (hash + (hash << 2)) + (hash << 4); 2581cb0ef41Sopenharmony_ci hash = hash ^ (hash >> 11); 2591cb0ef41Sopenharmony_ci hash = hash + (hash << 6); 2601cb0ef41Sopenharmony_ci hash = hash ^ (hash >> 22); 2611cb0ef41Sopenharmony_ci return static_cast<uint32_t>(hash & 0x3fffffff); 2621cb0ef41Sopenharmony_ci} 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ciinline uint32_t ComputeSeededHash(uint32_t key, uint64_t seed) { 2651cb0ef41Sopenharmony_ci#ifdef V8_USE_SIPHASH 2661cb0ef41Sopenharmony_ci return halfsiphash(key, seed); 2671cb0ef41Sopenharmony_ci#else 2681cb0ef41Sopenharmony_ci return ComputeLongHash(static_cast<uint64_t>(key) ^ seed); 2691cb0ef41Sopenharmony_ci#endif // V8_USE_SIPHASH 2701cb0ef41Sopenharmony_ci} 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ciinline uint32_t ComputePointerHash(void* ptr) { 2731cb0ef41Sopenharmony_ci return ComputeUnseededHash( 2741cb0ef41Sopenharmony_ci static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr))); 2751cb0ef41Sopenharmony_ci} 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ciinline uint32_t ComputeAddressHash(Address address) { 2781cb0ef41Sopenharmony_ci return ComputeUnseededHash(static_cast<uint32_t>(address & 0xFFFFFFFFul)); 2791cb0ef41Sopenharmony_ci} 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci// ---------------------------------------------------------------------------- 2821cb0ef41Sopenharmony_ci// Miscellaneous 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ci// Memory offset for lower and higher bits in a 64 bit integer. 2851cb0ef41Sopenharmony_ci#if defined(V8_TARGET_LITTLE_ENDIAN) 2861cb0ef41Sopenharmony_cistatic const int kInt64LowerHalfMemoryOffset = 0; 2871cb0ef41Sopenharmony_cistatic const int kInt64UpperHalfMemoryOffset = 4; 2881cb0ef41Sopenharmony_ci#elif defined(V8_TARGET_BIG_ENDIAN) 2891cb0ef41Sopenharmony_cistatic const int kInt64LowerHalfMemoryOffset = 4; 2901cb0ef41Sopenharmony_cistatic const int kInt64UpperHalfMemoryOffset = 0; 2911cb0ef41Sopenharmony_ci#endif // V8_TARGET_LITTLE_ENDIAN 2921cb0ef41Sopenharmony_ci 2931cb0ef41Sopenharmony_ci// A pointer that can only be set once and doesn't allow NULL values. 2941cb0ef41Sopenharmony_citemplate <typename T> 2951cb0ef41Sopenharmony_ciclass SetOncePointer { 2961cb0ef41Sopenharmony_ci public: 2971cb0ef41Sopenharmony_ci SetOncePointer() = default; 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci bool is_set() const { return pointer_ != nullptr; } 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci T* get() const { 3021cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(pointer_); 3031cb0ef41Sopenharmony_ci return pointer_; 3041cb0ef41Sopenharmony_ci } 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci void set(T* value) { 3071cb0ef41Sopenharmony_ci DCHECK(pointer_ == nullptr && value != nullptr); 3081cb0ef41Sopenharmony_ci pointer_ = value; 3091cb0ef41Sopenharmony_ci } 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci SetOncePointer& operator=(T* value) { 3121cb0ef41Sopenharmony_ci set(value); 3131cb0ef41Sopenharmony_ci return *this; 3141cb0ef41Sopenharmony_ci } 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci bool operator==(std::nullptr_t) const { return pointer_ == nullptr; } 3171cb0ef41Sopenharmony_ci bool operator!=(std::nullptr_t) const { return pointer_ != nullptr; } 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci private: 3201cb0ef41Sopenharmony_ci T* pointer_ = nullptr; 3211cb0ef41Sopenharmony_ci}; 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_ci// Compare 8bit/16bit chars to 8bit/16bit chars. 3241cb0ef41Sopenharmony_citemplate <typename lchar, typename rchar> 3251cb0ef41Sopenharmony_ciinline bool CompareCharsEqualUnsigned(const lchar* lhs, const rchar* rhs, 3261cb0ef41Sopenharmony_ci size_t chars) { 3271cb0ef41Sopenharmony_ci STATIC_ASSERT(std::is_unsigned<lchar>::value); 3281cb0ef41Sopenharmony_ci STATIC_ASSERT(std::is_unsigned<rchar>::value); 3291cb0ef41Sopenharmony_ci if (sizeof(*lhs) == sizeof(*rhs)) { 3301cb0ef41Sopenharmony_ci // memcmp compares byte-by-byte, but for equality it doesn't matter whether 3311cb0ef41Sopenharmony_ci // two-byte char comparison is little- or big-endian. 3321cb0ef41Sopenharmony_ci return memcmp(lhs, rhs, chars * sizeof(*lhs)) == 0; 3331cb0ef41Sopenharmony_ci } 3341cb0ef41Sopenharmony_ci for (const lchar* limit = lhs + chars; lhs < limit; ++lhs, ++rhs) { 3351cb0ef41Sopenharmony_ci if (*lhs != *rhs) return false; 3361cb0ef41Sopenharmony_ci } 3371cb0ef41Sopenharmony_ci return true; 3381cb0ef41Sopenharmony_ci} 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_citemplate <typename lchar, typename rchar> 3411cb0ef41Sopenharmony_ciinline bool CompareCharsEqual(const lchar* lhs, const rchar* rhs, 3421cb0ef41Sopenharmony_ci size_t chars) { 3431cb0ef41Sopenharmony_ci using ulchar = typename std::make_unsigned<lchar>::type; 3441cb0ef41Sopenharmony_ci using urchar = typename std::make_unsigned<rchar>::type; 3451cb0ef41Sopenharmony_ci return CompareCharsEqualUnsigned(reinterpret_cast<const ulchar*>(lhs), 3461cb0ef41Sopenharmony_ci reinterpret_cast<const urchar*>(rhs), chars); 3471cb0ef41Sopenharmony_ci} 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_ci// Compare 8bit/16bit chars to 8bit/16bit chars. 3501cb0ef41Sopenharmony_citemplate <typename lchar, typename rchar> 3511cb0ef41Sopenharmony_ciinline int CompareCharsUnsigned(const lchar* lhs, const rchar* rhs, 3521cb0ef41Sopenharmony_ci size_t chars) { 3531cb0ef41Sopenharmony_ci STATIC_ASSERT(std::is_unsigned<lchar>::value); 3541cb0ef41Sopenharmony_ci STATIC_ASSERT(std::is_unsigned<rchar>::value); 3551cb0ef41Sopenharmony_ci if (sizeof(*lhs) == sizeof(char) && sizeof(*rhs) == sizeof(char)) { 3561cb0ef41Sopenharmony_ci // memcmp compares byte-by-byte, yielding wrong results for two-byte 3571cb0ef41Sopenharmony_ci // strings on little-endian systems. 3581cb0ef41Sopenharmony_ci return memcmp(lhs, rhs, chars); 3591cb0ef41Sopenharmony_ci } 3601cb0ef41Sopenharmony_ci for (const lchar* limit = lhs + chars; lhs < limit; ++lhs, ++rhs) { 3611cb0ef41Sopenharmony_ci int r = static_cast<int>(*lhs) - static_cast<int>(*rhs); 3621cb0ef41Sopenharmony_ci if (r != 0) return r; 3631cb0ef41Sopenharmony_ci } 3641cb0ef41Sopenharmony_ci return 0; 3651cb0ef41Sopenharmony_ci} 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_citemplate <typename lchar, typename rchar> 3681cb0ef41Sopenharmony_ciinline int CompareChars(const lchar* lhs, const rchar* rhs, size_t chars) { 3691cb0ef41Sopenharmony_ci using ulchar = typename std::make_unsigned<lchar>::type; 3701cb0ef41Sopenharmony_ci using urchar = typename std::make_unsigned<rchar>::type; 3711cb0ef41Sopenharmony_ci return CompareCharsUnsigned(reinterpret_cast<const ulchar*>(lhs), 3721cb0ef41Sopenharmony_ci reinterpret_cast<const urchar*>(rhs), chars); 3731cb0ef41Sopenharmony_ci} 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_ci// Calculate 10^exponent. 3761cb0ef41Sopenharmony_ciinline int TenToThe(int exponent) { 3771cb0ef41Sopenharmony_ci DCHECK_LE(exponent, 9); 3781cb0ef41Sopenharmony_ci DCHECK_GE(exponent, 1); 3791cb0ef41Sopenharmony_ci int answer = 10; 3801cb0ef41Sopenharmony_ci for (int i = 1; i < exponent; i++) answer *= 10; 3811cb0ef41Sopenharmony_ci return answer; 3821cb0ef41Sopenharmony_ci} 3831cb0ef41Sopenharmony_ci 3841cb0ef41Sopenharmony_ci// Bit field extraction. 3851cb0ef41Sopenharmony_ciinline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) { 3861cb0ef41Sopenharmony_ci return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1); 3871cb0ef41Sopenharmony_ci} 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ciinline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) { 3901cb0ef41Sopenharmony_ci return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1); 3911cb0ef41Sopenharmony_ci} 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ciinline int32_t signed_bitextract_32(int msb, int lsb, uint32_t x) { 3941cb0ef41Sopenharmony_ci return static_cast<int32_t>(x << (31 - msb)) >> (lsb + 31 - msb); 3951cb0ef41Sopenharmony_ci} 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_ci// Check number width. 3981cb0ef41Sopenharmony_ciinline bool is_intn(int64_t x, unsigned n) { 3991cb0ef41Sopenharmony_ci DCHECK((0 < n) && (n < 64)); 4001cb0ef41Sopenharmony_ci int64_t limit = static_cast<int64_t>(1) << (n - 1); 4011cb0ef41Sopenharmony_ci return (-limit <= x) && (x < limit); 4021cb0ef41Sopenharmony_ci} 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ciinline bool is_uintn(int64_t x, unsigned n) { 4051cb0ef41Sopenharmony_ci DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte))); 4061cb0ef41Sopenharmony_ci return !(x >> n); 4071cb0ef41Sopenharmony_ci} 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_citemplate <class T> 4101cb0ef41Sopenharmony_ciinline T truncate_to_intn(T x, unsigned n) { 4111cb0ef41Sopenharmony_ci DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte))); 4121cb0ef41Sopenharmony_ci return (x & ((static_cast<T>(1) << n) - 1)); 4131cb0ef41Sopenharmony_ci} 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_ci// clang-format off 4161cb0ef41Sopenharmony_ci#define INT_1_TO_63_LIST(V) \ 4171cb0ef41Sopenharmony_ci V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) V(9) V(10) \ 4181cb0ef41Sopenharmony_ci V(11) V(12) V(13) V(14) V(15) V(16) V(17) V(18) V(19) V(20) \ 4191cb0ef41Sopenharmony_ci V(21) V(22) V(23) V(24) V(25) V(26) V(27) V(28) V(29) V(30) \ 4201cb0ef41Sopenharmony_ci V(31) V(32) V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \ 4211cb0ef41Sopenharmony_ci V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) V(49) V(50) \ 4221cb0ef41Sopenharmony_ci V(51) V(52) V(53) V(54) V(55) V(56) V(57) V(58) V(59) V(60) \ 4231cb0ef41Sopenharmony_ci V(61) V(62) V(63) 4241cb0ef41Sopenharmony_ci// clang-format on 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_ci#define DECLARE_IS_INT_N(N) \ 4271cb0ef41Sopenharmony_ci inline bool is_int##N(int64_t x) { return is_intn(x, N); } 4281cb0ef41Sopenharmony_ci#define DECLARE_IS_UINT_N(N) \ 4291cb0ef41Sopenharmony_ci template <class T> \ 4301cb0ef41Sopenharmony_ci inline bool is_uint##N(T x) { \ 4311cb0ef41Sopenharmony_ci return is_uintn(x, N); \ 4321cb0ef41Sopenharmony_ci } 4331cb0ef41Sopenharmony_ci#define DECLARE_TRUNCATE_TO_INT_N(N) \ 4341cb0ef41Sopenharmony_ci template <class T> \ 4351cb0ef41Sopenharmony_ci inline T truncate_to_int##N(T x) { \ 4361cb0ef41Sopenharmony_ci return truncate_to_intn(x, N); \ 4371cb0ef41Sopenharmony_ci } 4381cb0ef41Sopenharmony_ciINT_1_TO_63_LIST(DECLARE_IS_INT_N) 4391cb0ef41Sopenharmony_ciINT_1_TO_63_LIST(DECLARE_IS_UINT_N) 4401cb0ef41Sopenharmony_ciINT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N) 4411cb0ef41Sopenharmony_ci#undef DECLARE_IS_INT_N 4421cb0ef41Sopenharmony_ci#undef DECLARE_IS_UINT_N 4431cb0ef41Sopenharmony_ci#undef DECLARE_TRUNCATE_TO_INT_N 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_ci// clang-format off 4461cb0ef41Sopenharmony_ci#define INT_0_TO_127_LIST(V) \ 4471cb0ef41Sopenharmony_ciV(0) V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) V(9) \ 4481cb0ef41Sopenharmony_ciV(10) V(11) V(12) V(13) V(14) V(15) V(16) V(17) V(18) V(19) \ 4491cb0ef41Sopenharmony_ciV(20) V(21) V(22) V(23) V(24) V(25) V(26) V(27) V(28) V(29) \ 4501cb0ef41Sopenharmony_ciV(30) V(31) V(32) V(33) V(34) V(35) V(36) V(37) V(38) V(39) \ 4511cb0ef41Sopenharmony_ciV(40) V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) V(49) \ 4521cb0ef41Sopenharmony_ciV(50) V(51) V(52) V(53) V(54) V(55) V(56) V(57) V(58) V(59) \ 4531cb0ef41Sopenharmony_ciV(60) V(61) V(62) V(63) V(64) V(65) V(66) V(67) V(68) V(69) \ 4541cb0ef41Sopenharmony_ciV(70) V(71) V(72) V(73) V(74) V(75) V(76) V(77) V(78) V(79) \ 4551cb0ef41Sopenharmony_ciV(80) V(81) V(82) V(83) V(84) V(85) V(86) V(87) V(88) V(89) \ 4561cb0ef41Sopenharmony_ciV(90) V(91) V(92) V(93) V(94) V(95) V(96) V(97) V(98) V(99) \ 4571cb0ef41Sopenharmony_ciV(100) V(101) V(102) V(103) V(104) V(105) V(106) V(107) V(108) V(109) \ 4581cb0ef41Sopenharmony_ciV(110) V(111) V(112) V(113) V(114) V(115) V(116) V(117) V(118) V(119) \ 4591cb0ef41Sopenharmony_ciV(120) V(121) V(122) V(123) V(124) V(125) V(126) V(127) 4601cb0ef41Sopenharmony_ci// clang-format on 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ciclass FeedbackSlot { 4631cb0ef41Sopenharmony_ci public: 4641cb0ef41Sopenharmony_ci FeedbackSlot() : id_(kInvalidSlot) {} 4651cb0ef41Sopenharmony_ci explicit FeedbackSlot(int id) : id_(id) {} 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_ci int ToInt() const { return id_; } 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci static FeedbackSlot Invalid() { return FeedbackSlot(); } 4701cb0ef41Sopenharmony_ci bool IsInvalid() const { return id_ == kInvalidSlot; } 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ci bool operator==(FeedbackSlot that) const { return this->id_ == that.id_; } 4731cb0ef41Sopenharmony_ci bool operator!=(FeedbackSlot that) const { return !(*this == that); } 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci friend size_t hash_value(FeedbackSlot slot) { return slot.ToInt(); } 4761cb0ef41Sopenharmony_ci V8_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os, 4771cb0ef41Sopenharmony_ci FeedbackSlot); 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci FeedbackSlot WithOffset(int offset) const { 4801cb0ef41Sopenharmony_ci return FeedbackSlot(id_ + offset); 4811cb0ef41Sopenharmony_ci } 4821cb0ef41Sopenharmony_ci 4831cb0ef41Sopenharmony_ci private: 4841cb0ef41Sopenharmony_ci static const int kInvalidSlot = -1; 4851cb0ef41Sopenharmony_ci 4861cb0ef41Sopenharmony_ci int id_; 4871cb0ef41Sopenharmony_ci}; 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, FeedbackSlot); 4901cb0ef41Sopenharmony_ci 4911cb0ef41Sopenharmony_ciclass BytecodeOffset { 4921cb0ef41Sopenharmony_ci public: 4931cb0ef41Sopenharmony_ci explicit constexpr BytecodeOffset(int id) : id_(id) {} 4941cb0ef41Sopenharmony_ci constexpr int ToInt() const { return id_; } 4951cb0ef41Sopenharmony_ci 4961cb0ef41Sopenharmony_ci static constexpr BytecodeOffset None() { return BytecodeOffset(kNoneId); } 4971cb0ef41Sopenharmony_ci 4981cb0ef41Sopenharmony_ci // Special bailout id support for deopting into the {JSConstructStub} stub. 4991cb0ef41Sopenharmony_ci // The following hard-coded deoptimization points are supported by the stub: 5001cb0ef41Sopenharmony_ci // - {ConstructStubCreate} maps to {construct_stub_create_deopt_pc_offset}. 5011cb0ef41Sopenharmony_ci // - {ConstructStubInvoke} maps to {construct_stub_invoke_deopt_pc_offset}. 5021cb0ef41Sopenharmony_ci static BytecodeOffset ConstructStubCreate() { return BytecodeOffset(1); } 5031cb0ef41Sopenharmony_ci static BytecodeOffset ConstructStubInvoke() { return BytecodeOffset(2); } 5041cb0ef41Sopenharmony_ci bool IsValidForConstructStub() const { 5051cb0ef41Sopenharmony_ci return id_ == ConstructStubCreate().ToInt() || 5061cb0ef41Sopenharmony_ci id_ == ConstructStubInvoke().ToInt(); 5071cb0ef41Sopenharmony_ci } 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_ci constexpr bool IsNone() const { return id_ == kNoneId; } 5101cb0ef41Sopenharmony_ci bool operator==(const BytecodeOffset& other) const { 5111cb0ef41Sopenharmony_ci return id_ == other.id_; 5121cb0ef41Sopenharmony_ci } 5131cb0ef41Sopenharmony_ci bool operator!=(const BytecodeOffset& other) const { 5141cb0ef41Sopenharmony_ci return id_ != other.id_; 5151cb0ef41Sopenharmony_ci } 5161cb0ef41Sopenharmony_ci friend size_t hash_value(BytecodeOffset); 5171cb0ef41Sopenharmony_ci V8_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream&, 5181cb0ef41Sopenharmony_ci BytecodeOffset); 5191cb0ef41Sopenharmony_ci 5201cb0ef41Sopenharmony_ci private: 5211cb0ef41Sopenharmony_ci friend class Builtins; 5221cb0ef41Sopenharmony_ci 5231cb0ef41Sopenharmony_ci static const int kNoneId = -1; 5241cb0ef41Sopenharmony_ci 5251cb0ef41Sopenharmony_ci // Using 0 could disguise errors. 5261cb0ef41Sopenharmony_ci // Builtin continuations bailout ids start here. If you need to add a 5271cb0ef41Sopenharmony_ci // non-builtin BytecodeOffset, add it before this id so that this Id has the 5281cb0ef41Sopenharmony_ci // highest number. 5291cb0ef41Sopenharmony_ci static const int kFirstBuiltinContinuationId = 1; 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_ci int id_; 5321cb0ef41Sopenharmony_ci}; 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ci// ---------------------------------------------------------------------------- 5351cb0ef41Sopenharmony_ci// I/O support. 5361cb0ef41Sopenharmony_ci 5371cb0ef41Sopenharmony_ci// Our version of printf(). 5381cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE void PRINTF_FORMAT(1, 2) PrintF(const char* format, ...); 5391cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE void PRINTF_FORMAT(2, 3) 5401cb0ef41Sopenharmony_ci PrintF(FILE* out, const char* format, ...); 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_ci// Prepends the current process ID to the output. 5431cb0ef41Sopenharmony_civoid PRINTF_FORMAT(1, 2) PrintPID(const char* format, ...); 5441cb0ef41Sopenharmony_ci 5451cb0ef41Sopenharmony_ci// Prepends the current process ID and given isolate pointer to the output. 5461cb0ef41Sopenharmony_civoid PRINTF_FORMAT(2, 3) PrintIsolate(void* isolate, const char* format, ...); 5471cb0ef41Sopenharmony_ci 5481cb0ef41Sopenharmony_ci// Read a line of characters after printing the prompt to stdout. The resulting 5491cb0ef41Sopenharmony_ci// char* needs to be disposed off with DeleteArray by the caller. 5501cb0ef41Sopenharmony_cichar* ReadLine(const char* prompt); 5511cb0ef41Sopenharmony_ci 5521cb0ef41Sopenharmony_ci// Write size chars from str to the file given by filename. 5531cb0ef41Sopenharmony_ci// The file is overwritten. Returns the number of chars written. 5541cb0ef41Sopenharmony_ciint WriteChars(const char* filename, const char* str, int size, 5551cb0ef41Sopenharmony_ci bool verbose = true); 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_ci// Write size bytes to the file given by filename. 5581cb0ef41Sopenharmony_ci// The file is overwritten. Returns the number of bytes written. 5591cb0ef41Sopenharmony_ciint WriteBytes(const char* filename, const byte* bytes, int size, 5601cb0ef41Sopenharmony_ci bool verbose = true); 5611cb0ef41Sopenharmony_ci 5621cb0ef41Sopenharmony_ci// Simple support to read a file into std::string. 5631cb0ef41Sopenharmony_ci// On return, *exits tells whether the file existed. 5641cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::string ReadFile(const char* filename, bool* exists, 5651cb0ef41Sopenharmony_ci bool verbose = true); 5661cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::string ReadFile(FILE* file, bool* exists, 5671cb0ef41Sopenharmony_ci bool verbose = true); 5681cb0ef41Sopenharmony_ci 5691cb0ef41Sopenharmony_cibool DoubleToBoolean(double d); 5701cb0ef41Sopenharmony_ci 5711cb0ef41Sopenharmony_citemplate <typename Char> 5721cb0ef41Sopenharmony_cibool TryAddIndexChar(uint32_t* index, Char c); 5731cb0ef41Sopenharmony_ci 5741cb0ef41Sopenharmony_cienum ToIndexMode { kToArrayIndex, kToIntegerIndex }; 5751cb0ef41Sopenharmony_ci 5761cb0ef41Sopenharmony_ci// {index_t} is meant to be {uint32_t} or {size_t}. 5771cb0ef41Sopenharmony_citemplate <typename Stream, typename index_t, 5781cb0ef41Sopenharmony_ci enum ToIndexMode mode = kToArrayIndex> 5791cb0ef41Sopenharmony_cibool StringToIndex(Stream* stream, index_t* index); 5801cb0ef41Sopenharmony_ci 5811cb0ef41Sopenharmony_ci// Returns the current stack top. Works correctly with ASAN and SafeStack. 5821cb0ef41Sopenharmony_ci// GetCurrentStackPosition() should not be inlined, because it works on stack 5831cb0ef41Sopenharmony_ci// frames if it were inlined into a function with a huge stack frame it would 5841cb0ef41Sopenharmony_ci// return an address significantly above the actual current stack position. 5851cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE V8_NOINLINE uintptr_t GetCurrentStackPosition(); 5861cb0ef41Sopenharmony_ci 5871cb0ef41Sopenharmony_cistatic inline uint16_t ByteReverse16(uint16_t value) { 5881cb0ef41Sopenharmony_ci#if V8_HAS_BUILTIN_BSWAP16 5891cb0ef41Sopenharmony_ci return __builtin_bswap16(value); 5901cb0ef41Sopenharmony_ci#else 5911cb0ef41Sopenharmony_ci return value << 8 | (value >> 8 & 0x00FF); 5921cb0ef41Sopenharmony_ci#endif 5931cb0ef41Sopenharmony_ci} 5941cb0ef41Sopenharmony_ci 5951cb0ef41Sopenharmony_cistatic inline uint32_t ByteReverse32(uint32_t value) { 5961cb0ef41Sopenharmony_ci#if V8_HAS_BUILTIN_BSWAP32 5971cb0ef41Sopenharmony_ci return __builtin_bswap32(value); 5981cb0ef41Sopenharmony_ci#else 5991cb0ef41Sopenharmony_ci return value << 24 | ((value << 8) & 0x00FF0000) | 6001cb0ef41Sopenharmony_ci ((value >> 8) & 0x0000FF00) | ((value >> 24) & 0x00000FF); 6011cb0ef41Sopenharmony_ci#endif 6021cb0ef41Sopenharmony_ci} 6031cb0ef41Sopenharmony_ci 6041cb0ef41Sopenharmony_cistatic inline uint64_t ByteReverse64(uint64_t value) { 6051cb0ef41Sopenharmony_ci#if V8_HAS_BUILTIN_BSWAP64 6061cb0ef41Sopenharmony_ci return __builtin_bswap64(value); 6071cb0ef41Sopenharmony_ci#else 6081cb0ef41Sopenharmony_ci size_t bits_of_v = sizeof(value) * kBitsPerByte; 6091cb0ef41Sopenharmony_ci return value << (bits_of_v - 8) | 6101cb0ef41Sopenharmony_ci ((value << (bits_of_v - 24)) & 0x00FF000000000000) | 6111cb0ef41Sopenharmony_ci ((value << (bits_of_v - 40)) & 0x0000FF0000000000) | 6121cb0ef41Sopenharmony_ci ((value << (bits_of_v - 56)) & 0x000000FF00000000) | 6131cb0ef41Sopenharmony_ci ((value >> (bits_of_v - 56)) & 0x00000000FF000000) | 6141cb0ef41Sopenharmony_ci ((value >> (bits_of_v - 40)) & 0x0000000000FF0000) | 6151cb0ef41Sopenharmony_ci ((value >> (bits_of_v - 24)) & 0x000000000000FF00) | 6161cb0ef41Sopenharmony_ci ((value >> (bits_of_v - 8)) & 0x00000000000000FF); 6171cb0ef41Sopenharmony_ci#endif 6181cb0ef41Sopenharmony_ci} 6191cb0ef41Sopenharmony_ci 6201cb0ef41Sopenharmony_citemplate <typename V> 6211cb0ef41Sopenharmony_cistatic inline V ByteReverse(V value) { 6221cb0ef41Sopenharmony_ci size_t size_of_v = sizeof(value); 6231cb0ef41Sopenharmony_ci switch (size_of_v) { 6241cb0ef41Sopenharmony_ci case 1: 6251cb0ef41Sopenharmony_ci return value; 6261cb0ef41Sopenharmony_ci case 2: 6271cb0ef41Sopenharmony_ci return static_cast<V>(ByteReverse16(static_cast<uint16_t>(value))); 6281cb0ef41Sopenharmony_ci case 4: 6291cb0ef41Sopenharmony_ci return static_cast<V>(ByteReverse32(static_cast<uint32_t>(value))); 6301cb0ef41Sopenharmony_ci case 8: 6311cb0ef41Sopenharmony_ci return static_cast<V>(ByteReverse64(static_cast<uint64_t>(value))); 6321cb0ef41Sopenharmony_ci default: 6331cb0ef41Sopenharmony_ci UNREACHABLE(); 6341cb0ef41Sopenharmony_ci } 6351cb0ef41Sopenharmony_ci} 6361cb0ef41Sopenharmony_ci 6371cb0ef41Sopenharmony_ci#if V8_OS_AIX 6381cb0ef41Sopenharmony_ci// glibc on aix has a bug when using ceil, trunc or nearbyint: 6391cb0ef41Sopenharmony_ci// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97086 6401cb0ef41Sopenharmony_citemplate <typename T> 6411cb0ef41Sopenharmony_ciT FpOpWorkaround(T input, T value) { 6421cb0ef41Sopenharmony_ci if (/*if -*/ std::signbit(input) && value == 0.0 && 6431cb0ef41Sopenharmony_ci /*if +*/ !std::signbit(value)) { 6441cb0ef41Sopenharmony_ci return -0.0; 6451cb0ef41Sopenharmony_ci } 6461cb0ef41Sopenharmony_ci return value; 6471cb0ef41Sopenharmony_ci} 6481cb0ef41Sopenharmony_ci#endif 6491cb0ef41Sopenharmony_ci 6501cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE bool PassesFilter(base::Vector<const char> name, 6511cb0ef41Sopenharmony_ci base::Vector<const char> filter); 6521cb0ef41Sopenharmony_ci 6531cb0ef41Sopenharmony_ci// Zap the specified area with a specific byte pattern. This currently defaults 6541cb0ef41Sopenharmony_ci// to int3 on x64 and ia32. On other architectures this will produce unspecified 6551cb0ef41Sopenharmony_ci// instruction sequences. 6561cb0ef41Sopenharmony_ci// TODO(jgruber): Better support for other architectures. 6571cb0ef41Sopenharmony_ciV8_INLINE void ZapCode(Address addr, size_t size_in_bytes) { 6581cb0ef41Sopenharmony_ci static constexpr int kZapByte = 0xCC; 6591cb0ef41Sopenharmony_ci std::memset(reinterpret_cast<void*>(addr), kZapByte, size_in_bytes); 6601cb0ef41Sopenharmony_ci} 6611cb0ef41Sopenharmony_ci 6621cb0ef41Sopenharmony_ciinline bool RoundUpToPageSize(size_t byte_length, size_t page_size, 6631cb0ef41Sopenharmony_ci size_t max_allowed_byte_length, size_t* pages) { 6641cb0ef41Sopenharmony_ci size_t bytes_wanted = RoundUp(byte_length, page_size); 6651cb0ef41Sopenharmony_ci if (bytes_wanted > max_allowed_byte_length) { 6661cb0ef41Sopenharmony_ci return false; 6671cb0ef41Sopenharmony_ci } 6681cb0ef41Sopenharmony_ci *pages = bytes_wanted / page_size; 6691cb0ef41Sopenharmony_ci return true; 6701cb0ef41Sopenharmony_ci} 6711cb0ef41Sopenharmony_ci 6721cb0ef41Sopenharmony_ci} // namespace internal 6731cb0ef41Sopenharmony_ci} // namespace v8 6741cb0ef41Sopenharmony_ci 6751cb0ef41Sopenharmony_ci#endif // V8_UTILS_UTILS_H_ 676