diff --git a/runtime/base/number_helper.cpp b/runtime/base/number_helper.cpp index 20b55df38fabac4595fc10ac090272a1aaac69a8..2e2bdd1df2378737e636228d1cc0ef73767c9a9c 100644 --- a/runtime/base/number_helper.cpp +++ b/runtime/base/number_helper.cpp @@ -750,6 +750,35 @@ double NumberHelper::StringToDouble(const uint8_t *start, const uint8_t *end, ui return Strtod(buffer.c_str(), exponent, radix); } +static double PowHelper(uint64_t number, int16_t exponent, uint8_t radix) +{ + const double log_2_radix {std::log2(radix)}; + + double exp_rem = log_2_radix * exponent; + int exp_i = (int)exp_rem; + exp_rem = exp_rem - exp_i; + + // NOLINTNEXTLINE(readability-magic-numbers) + JSDoubleOperator u((double)number * std::pow(2.0, exp_rem)); + + exp_i = u.GetExponent() + exp_i; + if (((exp_i & ~base::DOUBLE_EXPONENT_MASK) != 0) || exp_i == 0) { // NOLINT(hicpp-signed-bitwise) + if (exp_i > 0) { + return std::numeric_limits::infinity(); + } + if (exp_i < -static_cast(base::DOUBLE_SIGNIFICAND_SIZE)) { + return -std::numeric_limits::infinity(); + } + u.SetExponent(0); + // NOLINTNEXTLINE(hicpp-signed-bitwise) + u.SetSignificand((u.GetSignificand() | base::DOUBLE_HIDDEN_BIT) >> (1 - exp_i)); + } else { + u.SetExponent(exp_i); + } + + return u.GetDouble(); +} + double NumberHelper::Strtod(const char *str, int exponent, uint8_t radix) { ASSERT(str != nullptr); @@ -783,6 +812,9 @@ double NumberHelper::Strtod(const char *str, int exponent, uint8_t radix) } else { result = number * std::pow(radix, exponent); } + if (!std::isfinite(result)) { + result = PowHelper(number, exponent, radix); + } return sign == Sign::NEG ? -result : result; } diff --git a/runtime/base/number_helper.h b/runtime/base/number_helper.h index a68ab871aa506f999f245e10b1e363414cca93a2..0e27fdd9c83da3ab4c47a38bbb1384fa5ce0322b 100644 --- a/runtime/base/number_helper.h +++ b/runtime/base/number_helper.h @@ -57,6 +57,8 @@ static constexpr double NAN_VALUE = coretypes::TaggedValue::VALUE_NAN; // Helper defines for double using coretypes::DOUBLE_EXPONENT_BIAS; using coretypes::DOUBLE_EXPONENT_MASK; +using coretypes::DOUBLE_EXPONENT_MAX; +using coretypes::DOUBLE_EXPONENT_SIZE; using coretypes::DOUBLE_HIDDEN_BIT; using coretypes::DOUBLE_MAX_PRECISION; using coretypes::DOUBLE_SIGN_MASK; @@ -101,5 +103,59 @@ private: static bool IsNonspace(uint16_t c); static bool GotoNonspace(uint8_t **ptr, const uint8_t *end); }; + +class JSDoubleOperator { +public: + explicit JSDoubleOperator(double val) // NOLINT(cppcoreguidelines-pro-type-member-init) + { + u.fval = val; // NOLINT(cppcoreguidelines-pro-type-union-access) + } + JSDoubleOperator() // NOLINT(cppcoreguidelines-pro-type-member-init) + { + u.uval = 0; // NOLINT(cppcoreguidelines-pro-type-union-access) + } + + int16_t GetExponent() const + { + return u.bits.exponent; // NOLINT(cppcoreguidelines-pro-type-union-access) + } + + uint64_t GetSignificand() const + { + return u.bits.significand; // NOLINT(cppcoreguidelines-pro-type-union-access) + } + + void SetExponent(int16_t val) + { + u.bits.exponent = val; // NOLINT(cppcoreguidelines-pro-type-union-access) + } + + void SetSignificand(uint64_t val) + { + u.bits.significand = val; // NOLINT(cppcoreguidelines-pro-type-union-access) + } + + void SetDouble(double val) + { + u.fval = val; // NOLINT(cppcoreguidelines-pro-type-union-access) + } + + double GetDouble() const + { + return u.fval; // NOLINT(cppcoreguidelines-pro-type-union-access) + } + +private: + union { + struct { + uint64_t significand : DOUBLE_SIGNIFICAND_SIZE; + uint16_t exponent : DOUBLE_EXPONENT_SIZE; + int sign : 1; + } bits __attribute__((packed)); + uint64_t uval; + double fval; + } __attribute__((may_alias, packed)) u; +}; + } // namespace panda::ecmascript::base #endif // ECMASCRIPT_BASE_NUMBER_HELPER_H diff --git a/runtime/builtins/builtins_arraybuffer.cpp b/runtime/builtins/builtins_arraybuffer.cpp index c020cd977785b7651a306d139d11f19f325a330d..4c966c09a4f7a2a17f8f02e2b1c30c9fe2be1655 100644 --- a/runtime/builtins/builtins_arraybuffer.cpp +++ b/runtime/builtins/builtins_arraybuffer.cpp @@ -439,42 +439,6 @@ void BuiltinsArrayBuffer::SetTypeData(uint8_t *block, T value, int32_t index) } } -template -T BuiltinsArrayBuffer::LittleEndianToBigEndian(T liValue) -{ - uint8_t sizeCount = sizeof(T); - T biValue; - switch (sizeCount) { - case NumberSize::UINT16: - biValue = ((liValue & 0x00FF) << BITS_EIGHT) // NOLINT - | ((liValue & 0xFF00) >> BITS_EIGHT); // NOLINT - break; - case NumberSize::UINT32: - biValue = ((liValue & 0x000000FF) << BITS_TWENTY_FOUR) // NOLINT - | ((liValue & 0x0000FF00) << BITS_EIGHT) // NOLINT - | ((liValue & 0x00FF0000) >> BITS_EIGHT) // NOLINT - | ((liValue & 0xFF000000) >> BITS_TWENTY_FOUR); // NOLINT - break; - default: - UNREACHABLE(); - break; - } - return biValue; -} - -template -T BuiltinsArrayBuffer::LittleEndianToBigEndian64Bit(T liValue) -{ - return ((liValue & 0x00000000000000FF) << BITS_FIFTY_SIX) // NOLINT - | ((liValue & 0x000000000000FF00) << BITS_FORTY) // NOLINT - | ((liValue & 0x0000000000FF0000) << BITS_TWENTY_FOUR) // NOLINT - | ((liValue & 0x00000000FF000000) << BITS_EIGHT) // NOLINT - | ((liValue & 0x000000FF00000000) >> BITS_EIGHT) // NOLINT - | ((liValue & 0x0000FF0000000000) >> BITS_TWENTY_FOUR) // NOLINT - | ((liValue & 0x00FF000000000000) >> BITS_FORTY) // NOLINT - | ((liValue & 0xFF00000000000000) >> BITS_FIFTY_SIX); // NOLINT -} - template // NOLINTNEXTLINE(readability-non-const-parameter) JSTaggedValue BuiltinsArrayBuffer::GetValueFromBufferForInteger(uint8_t *block, int32_t byteIndex, bool littleEndian) @@ -489,7 +453,7 @@ JSTaggedValue BuiltinsArrayBuffer::GetValueFromBufferForInteger(uint8_t *block, // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) T res = UnalignedLoad(reinterpret_cast(block + byteIndex)); if (!littleEndian) { - res = LittleEndianToBigEndian(res); + res = BSWAP(res); } // uint32_t maybe overflow with TaggedInt @@ -522,8 +486,7 @@ JSTaggedValue BuiltinsArrayBuffer::GetValueFromBufferForFloat(uint8_t *block, in } if (!littleEndian) { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) - uint32_t res = LittleEndianToBigEndian(unionValue.uValue); - return GetTaggedDouble(bit_cast(res)); + return GetTaggedDouble(bit_cast(BSWAP(unionValue.uValue))); } // NOLINTNEXTLINE(readability-misleading-indentation) } else if constexpr (std::is_same_v) { @@ -536,8 +499,7 @@ JSTaggedValue BuiltinsArrayBuffer::GetValueFromBufferForFloat(uint8_t *block, in } if (!littleEndian) { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) - uint64_t res = LittleEndianToBigEndian64Bit(unionValue.uValue); - return GetTaggedDouble(bit_cast(res)); + return GetTaggedDouble(bit_cast(BSWAP(unionValue.uValue))); } } // NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) @@ -552,7 +514,7 @@ JSTaggedValue BuiltinsArrayBuffer::GetValueFromBufferForBigInt(JSThread *thread, // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) auto pTmp = *reinterpret_cast(block + byteIndex); if (!littleEndian) { - pTmp = LittleEndianToBigEndian64Bit(pTmp); + pTmp = BSWAP(pTmp); } // NOLINTNEXTLINE(readability-braces-around-statements,bugprone-suspicious-semicolon) if constexpr (std::is_same_v) { @@ -615,7 +577,7 @@ void BuiltinsArrayBuffer::SetValueInBufferForInteger(double val, uint8_t *block, } if (!littleEndian) { - res = LittleEndianToBigEndian(res); + res = BSWAP(res); } SetTypeData(block, res, byteIndex); } @@ -632,13 +594,11 @@ void BuiltinsArrayBuffer::SetValueInBufferForFloat(double val, uint8_t *block, i if (!littleEndian) { // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) if constexpr (std::is_same_v) { - auto res = bit_cast(data); - data = bit_cast(LittleEndianToBigEndian(res)); + data = bit_cast(BSWAP(bit_cast(data))); } // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) if constexpr (std::is_same_v) { - auto res = bit_cast(data); - data = bit_cast(LittleEndianToBigEndian64Bit(res)); + data = bit_cast(BSWAP(bit_cast(data))); } } SetTypeData(block, data, byteIndex); @@ -660,7 +620,7 @@ void BuiltinsArrayBuffer::SetValueInBufferForBigInt(JSThread *thread, const JSHa } RETURN_IF_ABRUPT_COMPLETION(thread); if (!littleEndian) { - value = LittleEndianToBigEndian64Bit(value); + value = BSWAP(value); } SetTypeData(block, value, byteIndex); } diff --git a/runtime/builtins/builtins_arraybuffer.h b/runtime/builtins/builtins_arraybuffer.h index a414c707a185990bda0cc218ce88ed0ea1b0b0eb..7b06a85c1ee487f4c2c2757f9c81c04a912d41ad 100644 --- a/runtime/builtins/builtins_arraybuffer.h +++ b/runtime/builtins/builtins_arraybuffer.h @@ -30,11 +30,11 @@ using DataViewType = ecmascript::DataViewType; union UnionType32 { uint32_t uValue; float value; -}; +} __attribute__((packed, may_alias)); union UnionType64 { uint64_t uValue; double value; -}; +} __attribute__((packed, may_alias)); class BuiltinsArrayBuffer : public ecmascript::base::BuiltinsBase { public: enum NumberSize : uint8_t { diff --git a/runtime/ecma_vm.cpp b/runtime/ecma_vm.cpp index 49898a7b85b299295ab3a64f4666c89beda00afd..c98d4a265c2c07618348490598f9565ca7498fcc 100644 --- a/runtime/ecma_vm.cpp +++ b/runtime/ecma_vm.cpp @@ -1017,6 +1017,11 @@ void EcmaVM::UpdateVmRefs() } } }; + auto single_ptr_visitor = []([[maybe_unused]] Root type, ObjectHeader **object) { + if ((*object)->IsForwarded()) { + *object = TaggedObject::Cast(panda::mem::GetForwardAddress(*object)); + } + }; auto range_visitor = [&single_visitor](Root type, ObjectSlot start, ObjectSlot end) { for (ObjectSlot slot = start; slot < end; slot++) { @@ -1030,11 +1035,11 @@ void EcmaVM::UpdateVmRefs() // as gc roots // NOLINTNEXTLINE(modernize-loop-convert) for (size_t i = 0; i < array_buffer_data_list_.size(); ++i) { - single_visitor(Root::ROOT_VM, ObjectSlot(ToUintPtr(&array_buffer_data_list_[i]))); + single_ptr_visitor(Root::ROOT_VM, reinterpret_cast(&array_buffer_data_list_[i])); } for (auto &entry : finalization_registries_) { - single_visitor(Root::ROOT_VM, ObjectSlot(ToUintPtr(&entry))); + single_ptr_visitor(Root::ROOT_VM, reinterpret_cast(&entry)); } } diff --git a/runtime/js_hclass.h b/runtime/js_hclass.h index 0f73c3fcf729c17288f9382da8cb0d4158a9f69b..e7cc42e7b1470777fc0f0e1d687102bbbfcf327d 100644 --- a/runtime/js_hclass.h +++ b/runtime/js_hclass.h @@ -1150,7 +1150,7 @@ private: HClass hclass_; }; -static_assert(JSHClass::BIT_FIELD_OFFSET % static_cast(MemAlignment::MEM_ALIGN_OBJECT) == 0); +static_assert(JSHClass::BIT_FIELD_OFFSET % GetAlignmentInBytes(TAGGED_OBJECT_ALIGNMENT) == 0); static_assert(JSHClass::BIT_FIELD_OFFSET == JSHClass::GetHClassOffset() + HClass::GetDataOffset()); static_assert(JSHClass::OBJECT_SIZE_OFFSET == JSHClass::GetHClassOffset() + BaseClass::GetObjectSizeOffset()); static_assert(JSHClass::GetHClassOffset() == coretypes::DynClass::GetHClassOffset()); diff --git a/runtime/mem/mem.h b/runtime/mem/mem.h index 804721737eb82b17f7040f368d140d4c07ccb47c..0a5d0c036729addb4c2f05bf0db06a00c4c41014 100644 --- a/runtime/mem/mem.h +++ b/runtime/mem/mem.h @@ -27,10 +27,8 @@ #define LOG_ECMA_MEM(type) LOG(type, ECMASCRIPT) << __func__ << " Line:" << __LINE__ << " " namespace panda::ecmascript { -enum class MemAlignment : uint8_t { - MEM_ALIGN_OBJECT = 8, - MEM_ALIGN_REGION = 16, -}; + +constexpr Alignment TAGGED_OBJECT_ALIGNMENT = GetLogAlignment(alignof(coretypes::TaggedType)); } // namespace panda::ecmascript diff --git a/runtime/mem/mem_manager-inl.h b/runtime/mem/mem_manager-inl.h index a80fcbc62e8f24703c94823d440c97a8c00d2ec8..d7d83423e2c10bda02da02e3b2af5cec75a30c6d 100644 --- a/runtime/mem/mem_manager-inl.h +++ b/runtime/mem/mem_manager-inl.h @@ -32,7 +32,7 @@ TaggedObject *MemManager::AllocateYoungGenerationOrHugeObject(JSHClass *hclass) TaggedObject *MemManager::AllocateYoungGenerationOrHugeObject(JSHClass *hclass, size_t size) { - auto object = heap_manager_->AllocateObject(hclass->GetHClass(), size, DEFAULT_ALIGNMENT, thread_); + auto object = heap_manager_->AllocateObject(hclass->GetHClass(), size, TAGGED_OBJECT_ALIGNMENT, thread_); // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) return TaggedObject::Cast(object); } @@ -46,9 +46,10 @@ TaggedObject *MemManager::AllocateNonMovableOrHugeObject(JSHClass *hclass, size_ { ObjectHeader *object = nullptr; if (hclass == nullptr) { - object = heap_manager_->AllocateNonMovableObject(nullptr, size, DEFAULT_ALIGNMENT, thread_); + object = heap_manager_->AllocateNonMovableObject(nullptr, size, TAGGED_OBJECT_ALIGNMENT, thread_); } else { - object = heap_manager_->AllocateNonMovableObject(hclass->GetHClass(), size, DEFAULT_ALIGNMENT, thread_); + object = + heap_manager_->AllocateNonMovableObject(hclass->GetHClass(), size, TAGGED_OBJECT_ALIGNMENT, thread_); } // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) return TaggedObject::Cast(object); @@ -67,14 +68,14 @@ TaggedObject *MemManager::AllocateNonMovableOrHugeObject(JSHClass *hclass) TaggedObject *MemManager::AllocateOldGenerationOrHugeObject(JSHClass *hclass, size_t size) { - auto object = heap_manager_->AllocateObject(hclass->GetHClass(), size, DEFAULT_ALIGNMENT, thread_); + auto object = heap_manager_->AllocateObject(hclass->GetHClass(), size, TAGGED_OBJECT_ALIGNMENT, thread_); // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) return TaggedObject::Cast(object); } TaggedObject *MemManager::AllocateHugeObject(JSHClass *hclass, size_t size) { - auto object = heap_manager_->AllocateObject(hclass->GetHClass(), size, DEFAULT_ALIGNMENT, thread_); + auto object = heap_manager_->AllocateObject(hclass->GetHClass(), size, TAGGED_OBJECT_ALIGNMENT, thread_); // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) return TaggedObject::Cast(object); } diff --git a/runtime/tagged_array.h b/runtime/tagged_array.h index 491d36029b63b8954c6898d25445c6588c466c46..1881e68a8eb214375973b7fe6229298da7707307 100644 --- a/runtime/tagged_array.h +++ b/runtime/tagged_array.h @@ -98,6 +98,6 @@ private: }; static_assert(TaggedArray::LENGTH_OFFSET == sizeof(TaggedObject)); -static_assert((TaggedArray::DATA_OFFSET % static_cast(MemAlignment::MEM_ALIGN_OBJECT)) == 0); +static_assert((TaggedArray::DATA_OFFSET % GetAlignmentInBytes(TAGGED_OBJECT_ALIGNMENT)) == 0); } // namespace panda::ecmascript #endif // ECMASCRIPT_TAGGED_ARRAY_H diff --git a/tests/runtime/mem/g1gc_barrier_test.cpp b/tests/runtime/mem/g1gc_barrier_test.cpp index 744149846d4e5c64f9189fba2415541ce98b8437..268da1288e8b9e15ae0c9545c0dd4311e82d5399 100644 --- a/tests/runtime/mem/g1gc_barrier_test.cpp +++ b/tests/runtime/mem/g1gc_barrier_test.cpp @@ -57,7 +57,7 @@ public: size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); mem::HeapManager *heap_manager = thread_->GetVM()->GetHeapManager(); auto *array = reinterpret_cast( - heap_manager->AllocateObject(array_class_->GetHClass(), size, DEFAULT_ALIGNMENT, thread_)); + heap_manager->AllocateObject(array_class_->GetHClass(), size, TAGGED_OBJECT_ALIGNMENT, thread_)); array->SetLength(length); return array; }