From 5b471131384dd7a60f4b152dc73be5d781f8d225 Mon Sep 17 00:00:00 2001 From: chentianyu Date: Sat, 9 Aug 2025 18:02:26 +0800 Subject: [PATCH] fix deserialize multi non-mov region Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/ICS6VA Signed-off-by: chentianyu Change-Id: Iab6921784d26ec09c6dca93ec004506c25905bfe --- ecmascript/serializer/base_deserializer.cpp | 71 ++++++++++--------- ecmascript/serializer/base_deserializer.h | 2 + .../serializer/tests/serializer_test.cpp | 43 +++++++++++ 3 files changed, 84 insertions(+), 32 deletions(-) diff --git a/ecmascript/serializer/base_deserializer.cpp b/ecmascript/serializer/base_deserializer.cpp index f57a644d64..f414bf355b 100644 --- a/ecmascript/serializer/base_deserializer.cpp +++ b/ecmascript/serializer/base_deserializer.cpp @@ -477,7 +477,7 @@ uintptr_t BaseDeserializer::RelocateObjectAddr(SerializedObjectSpace space, size case SerializedObjectSpace::OLD_SPACE: { if (oldSpaceBeginAddr_ + objSize > AlignUp(oldSpaceBeginAddr_, DEFAULT_REGION_SIZE)) { ASSERT(oldRegionIndex_ < regionVector_.size()); - oldSpaceBeginAddr_ = reinterpret_cast(regionVector_[oldRegionIndex_++])->GetBegin(); + oldSpaceBeginAddr_ = regionVector_[oldRegionIndex_++]; } res = oldSpaceBeginAddr_; oldSpaceBeginAddr_ += objSize; @@ -486,8 +486,7 @@ uintptr_t BaseDeserializer::RelocateObjectAddr(SerializedObjectSpace space, size case SerializedObjectSpace::NON_MOVABLE_SPACE: { if (nonMovableSpaceBeginAddr_ + objSize > AlignUp(nonMovableSpaceBeginAddr_, DEFAULT_REGION_SIZE)) { ASSERT(nonMovableRegionIndex_ < regionVector_.size()); - nonMovableSpaceBeginAddr_ = - reinterpret_cast(regionVector_[nonMovableRegionIndex_++])->GetBegin(); + nonMovableSpaceBeginAddr_ = regionVector_[nonMovableRegionIndex_++]; } res = nonMovableSpaceBeginAddr_; nonMovableSpaceBeginAddr_ += objSize; @@ -496,8 +495,7 @@ uintptr_t BaseDeserializer::RelocateObjectAddr(SerializedObjectSpace space, size case SerializedObjectSpace::MACHINE_CODE_SPACE: { if (machineCodeSpaceBeginAddr_ + objSize > AlignUp(machineCodeSpaceBeginAddr_, DEFAULT_REGION_SIZE)) { ASSERT(machineCodeRegionIndex_ < regionVector_.size()); - machineCodeSpaceBeginAddr_ = - reinterpret_cast(regionVector_[machineCodeRegionIndex_++])->GetBegin(); + machineCodeSpaceBeginAddr_ = regionVector_[machineCodeRegionIndex_++]; } res = machineCodeSpaceBeginAddr_; machineCodeSpaceBeginAddr_ += objSize; @@ -514,7 +512,7 @@ uintptr_t BaseDeserializer::RelocateObjectAddr(SerializedObjectSpace space, size case SerializedObjectSpace::SHARED_OLD_SPACE: { if (sOldSpaceBeginAddr_ + objSize > AlignUp(sOldSpaceBeginAddr_, DEFAULT_REGION_SIZE)) { ASSERT(sOldRegionIndex_ < regionVector_.size()); - sOldSpaceBeginAddr_ = reinterpret_cast(regionVector_[sOldRegionIndex_++])->GetBegin(); + sOldSpaceBeginAddr_ = regionVector_[sOldRegionIndex_++]; } res = sOldSpaceBeginAddr_; sOldSpaceBeginAddr_ += objSize; @@ -523,8 +521,7 @@ uintptr_t BaseDeserializer::RelocateObjectAddr(SerializedObjectSpace space, size case SerializedObjectSpace::SHARED_NON_MOVABLE_SPACE: { if (sNonMovableSpaceBeginAddr_ + objSize > AlignUp(sNonMovableSpaceBeginAddr_, DEFAULT_REGION_SIZE)) { ASSERT(sNonMovableRegionIndex_ < regionVector_.size()); - sNonMovableSpaceBeginAddr_ = - reinterpret_cast(regionVector_[sNonMovableRegionIndex_++])->GetBegin(); + sNonMovableSpaceBeginAddr_ = regionVector_[sNonMovableRegionIndex_++]; } res = sNonMovableSpaceBeginAddr_; sNonMovableSpaceBeginAddr_ += objSize; @@ -771,6 +768,7 @@ uintptr_t BaseDeserializer::AllocateMultiCMCRegion(size_t spaceObjSize, size_t & void BaseDeserializer::AllocateMultiRegion(SparseSpace *space, size_t spaceObjSize, size_t ®ionIndex, SerializedObjectSpace spaceType) { + ASSERT(spaceType != SerializedObjectSpace::NON_MOVABLE_SPACE); regionIndex = regionVector_.size(); size_t regionAlignedSize = SerializeData::AlignUpRegionAvailableSize(spaceObjSize); size_t regionNum = regionAlignedSize / Region::GetRegionAvailableSize(); @@ -780,22 +778,12 @@ void BaseDeserializer::AllocateMultiRegion(SparseSpace *space, size_t spaceObjSi auto regionAliveObjSize = Region::GetRegionAvailableSize() - regionRemainSizeVector[index++]; space->GetCurrentRegion()->IncreaseAliveObject(regionAliveObjSize); space->ResetTopPointer(space->GetCurrentRegion()->GetBegin() + regionAliveObjSize); - Region *currentRegion = nullptr; - if (spaceType == SerializedObjectSpace::NON_MOVABLE_SPACE) { - uintptr_t obj = space->Allocate(Region::GetRegionAvailableSize(), false); - if (obj) { - currentRegion = Region::ObjectAddressToRange(obj); - } else { - DeserializeFatalOutOfMemory(spaceObjSize); - } - } else { - if (!space->Expand()) { - DeserializeFatalOutOfMemory(spaceObjSize); - } - currentRegion = space->GetCurrentRegion(); + if (!space->Expand()) { + DeserializeFatalOutOfMemory(spaceObjSize); } + Region *currentRegion = space->GetCurrentRegion(); FreeObject::FillFreeObject(heap_, currentRegion->GetBegin(), currentRegion->GetSize()); - regionVector_.push_back(ToUintPtr(currentRegion)); + regionVector_.push_back(currentRegion->GetBegin()); regionNum--; } size_t lastRegionRemainSize = regionAlignedSize - spaceObjSize; @@ -803,6 +791,30 @@ void BaseDeserializer::AllocateMultiRegion(SparseSpace *space, size_t spaceObjSi space->ResetTopPointer(space->GetCurrentRegion()->GetEnd() - lastRegionRemainSize); } +void BaseDeserializer::AllocateMultiNonmovableRegion(SparseSpace *space, size_t spaceObjSize, size_t ®ionIndex, + [[maybe_unused]] SerializedObjectSpace spaceType) +{ + ASSERT(spaceType == SerializedObjectSpace::NON_MOVABLE_SPACE); + regionIndex = regionVector_.size(); + size_t allocatedSize = 0; + while (allocatedSize < spaceObjSize) { + size_t leftSize = spaceObjSize - allocatedSize; + size_t size = std::min(leftSize, Region::GetRegionAvailableSize()); + uintptr_t obj = space->Allocate(size, false); + if (obj > 0) { + if (allocatedSize == 0) { + // The first region + nonMovableSpaceBeginAddr_ = obj; + } else { + regionVector_.push_back(obj); + } + } else { + DeserializeFatalOutOfMemory(spaceObjSize); + } + allocatedSize += size; + } +} + void BaseDeserializer::AllocateMultiSharedRegion(SharedSparseSpace *space, size_t spaceObjSize, size_t ®ionIndex, SerializedObjectSpace spaceType) { @@ -825,7 +837,7 @@ void BaseDeserializer::AllocateMultiSharedRegion(SharedSparseSpace *space, size_ region->SetHighWaterMark(region->GetEnd() - regionRemainSizeVector[index++]); } region->IncreaseAliveObject(region->GetAllocatedBytes()); - regionVector_.push_back(ToUintPtr(region)); + regionVector_.push_back(region->GetBegin()); allocateRegions.push_back(region); regionNum--; } @@ -854,13 +866,8 @@ void BaseDeserializer::AllocateToNonMovableSpace(size_t nonMovableSpaceSize) SparseSpace *space = heap_->GetNonMovableSpace(); uintptr_t object = space->Allocate(nonMovableSpaceSize, false); if (UNLIKELY(object == 0U)) { - if (space->CommittedSizeExceed()) { - DeserializeFatalOutOfMemory(nonMovableSpaceSize); - } - nonMovableSpaceBeginAddr_ = space->GetCurrentRegion()->GetBegin(); - FreeObject::FillFreeObject(heap_, nonMovableSpaceBeginAddr_, space->GetCurrentRegion()->GetSize()); - AllocateMultiRegion(space, nonMovableSpaceSize, nonMovableRegionIndex_, - SerializedObjectSpace::NON_MOVABLE_SPACE); + AllocateMultiNonmovableRegion(space, nonMovableSpaceSize, nonMovableRegionIndex_, + SerializedObjectSpace::NON_MOVABLE_SPACE); } else { FreeObject::FillFreeObject(heap_, object, nonMovableSpaceSize); nonMovableSpaceBeginAddr_ = object; @@ -891,7 +898,7 @@ void BaseDeserializer::AllocateToSharedOldSpace(size_t sOldSpaceSize) uintptr_t object = space->AllocateNoGCAndExpand(thread_, sOldSpaceSize); if (UNLIKELY(object == 0U)) { AllocateMultiSharedRegion(space, sOldSpaceSize, sOldRegionIndex_, SerializedObjectSpace::SHARED_OLD_SPACE); - sOldSpaceBeginAddr_ = reinterpret_cast(regionVector_[sOldRegionIndex_++])->GetBegin(); + sOldSpaceBeginAddr_ = regionVector_[sOldRegionIndex_++]; } else { if (thread_->IsSharedConcurrentMarkingOrFinished()) { Region *region = Region::ObjectAddressToRange(object); @@ -909,7 +916,7 @@ void BaseDeserializer::AllocateToSharedNonMovableSpace(size_t sNonMovableSpaceSi if (UNLIKELY(object == 0U)) { AllocateMultiSharedRegion(space, sNonMovableSpaceSize, sNonMovableRegionIndex_, SerializedObjectSpace::SHARED_NON_MOVABLE_SPACE); - sNonMovableSpaceBeginAddr_ = reinterpret_cast(regionVector_[sNonMovableRegionIndex_++])->GetBegin(); + sNonMovableSpaceBeginAddr_ = regionVector_[sNonMovableRegionIndex_++]; } else { if (thread_->IsSharedConcurrentMarkingOrFinished()) { Region *region = Region::ObjectAddressToRange(object); diff --git a/ecmascript/serializer/base_deserializer.h b/ecmascript/serializer/base_deserializer.h index f8cc78d8ef..83b1c3c462 100644 --- a/ecmascript/serializer/base_deserializer.h +++ b/ecmascript/serializer/base_deserializer.h @@ -117,6 +117,8 @@ private: uintptr_t AllocateMultiCMCRegion(size_t spaceObjSize, size_t ®ionIndex, RegionType regionType); void AllocateMultiRegion(SparseSpace *space, size_t spaceObjSize, size_t ®ionIndex, SerializedObjectSpace spaceType); + void AllocateMultiNonmovableRegion(SparseSpace *space, size_t spaceObjSize, size_t ®ionIndex, + SerializedObjectSpace spaceType); void AllocateMultiSharedRegion(SharedSparseSpace *space, size_t spaceObjSize, size_t ®ionIndex, SerializedObjectSpace spaceType); void AllocateToOldSpace(size_t oldSpaceSize); diff --git a/ecmascript/serializer/tests/serializer_test.cpp b/ecmascript/serializer/tests/serializer_test.cpp index a264d75638..8773cf217a 100644 --- a/ecmascript/serializer/tests/serializer_test.cpp +++ b/ecmascript/serializer/tests/serializer_test.cpp @@ -587,6 +587,23 @@ public: Destroy(); } + void SerializeMultiNonmovableRegionTest(SerializeData *data) + { + Init(); + BaseDeserializer deserializer(thread, data); + JSHandle res = deserializer.ReadValue(); + EXPECT_TRUE(!res.IsEmpty()); + EXPECT_TRUE(res->IsJSObject()); + JSTaggedValue elements = JSHandle(res)->GetElements(thread); + EXPECT_TRUE(elements.IsTaggedArray()); + EXPECT_EQ(JSHandle(thread, elements)->GetLength(), 10 * 1024); // 10 * 1024: array length + JSTaggedValue value = JSHandle(thread, elements)->Get(thread, 0); + EXPECT_TRUE(value.IsTaggedArray()); + uint32_t length = JSHandle(thread, value)->GetLength(); + EXPECT_EQ(length, 11 * 1024); // 11 * 1024: array length + Destroy(); + } + void SerializeMultiSharedRegionTest(SerializeData *data) { Init(); @@ -2745,6 +2762,32 @@ HWTEST_F_L0(JSSerializerTest, SerializeJSSharedMapBasic) delete serializer; }; +HWTEST_F_L0(JSSerializerTest, SerializeMultiNonmovableRegion) +{ + ObjectFactory *factory = ecmaVm->GetFactory(); + JSHandle array = factory->NewTaggedArray(10 * 1024, JSTaggedValue::Hole(), + MemSpaceType::NON_MOVABLE); // 10 * 1024: array length + for (int i = 0; i < 5; i++) { + JSHandle element = factory->NewTaggedArray((11 + i) * 1024, JSTaggedValue::Hole(), + MemSpaceType::NON_MOVABLE); + array->Set(thread, i, element); + } + JSHandle hClassHandle(thread->GlobalConstants()->GetHandledObjectClass()); + JSHandle object = factory->NewJSObject(hClassHandle); + object->SetElements(thread, array); + ValueSerializer *serializer = new ValueSerializer(thread, false, true); + bool success = serializer->WriteValue(thread, JSHandle(object), + JSHandle(thread, JSTaggedValue::Undefined()), + JSHandle(thread, JSTaggedValue::Undefined())); + EXPECT_TRUE(success); + std::unique_ptr data = serializer->Release(); + JSDeserializerTest jsDeserializerTest; + std::thread t1(&JSDeserializerTest::SerializeMultiNonmovableRegionTest, jsDeserializerTest, data.release()); + ecmascript::ThreadSuspensionScope scope(thread); + t1.join(); + delete serializer; +}; + HWTEST_F_L0(JSSerializerTest, SerializeMultiSharedRegion) { ObjectFactory *factory = ecmaVm->GetFactory(); -- Gitee