From 816be1e373b964082e4bab4928df15adcb5e244d Mon Sep 17 00:00:00 2001 From: x00416111 Date: Fri, 11 Jul 2025 16:32:31 +0800 Subject: [PATCH] Fix throw OOM in gc thread Expand twice space for copy gc Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/ICK5X1 Change-Id: Ieefbc4375252a7dcdd96bcd4fa21de563fc82e12 Signed-off-by: x00416111 --- .../heap/allocator/alloc_buffer.h | 4 ++-- .../heap/allocator/memory_map.cpp | 1 - .../heap/allocator/region_manager.cpp | 14 +++++++++++- .../heap/allocator/region_manager.h | 8 ++++--- .../heap/allocator/region_space.cpp | 22 ++++++++++++------- .../heap/allocator/region_space.h | 4 ++-- .../heap/collector/heuristic_gc_policy.cpp | 2 ++ .../heap/collector/trace_collector.cpp | 4 ++++ common_components/heap/heap.cpp | 3 +++ common_components/heap/heap.h | 2 ++ .../heap/w_collector/w_collector.cpp | 2 -- ecmascript/mem/mem_map_allocator.cpp | 10 ++++++++- 12 files changed, 56 insertions(+), 20 deletions(-) diff --git a/common_components/heap/allocator/alloc_buffer.h b/common_components/heap/allocator/alloc_buffer.h index 3d8a8f9af1..f8e7a794de 100755 --- a/common_components/heap/allocator/alloc_buffer.h +++ b/common_components/heap/allocator/alloc_buffer.h @@ -155,8 +155,8 @@ public: private: // slow path HeapAddress TryAllocateOnce(size_t totalSize, AllocType allocType); - HeapAddress AllocateImpl(size_t totalSize, AllocType allocType); - HeapAddress AllocateRawPointerObject(size_t totalSize); + HeapAddress AllocateImpl(size_t totalSize, AllocType allocType, bool isCopy = false); + HeapAddress AllocateRawPointerObject(size_t totalSize, bool isCopy = false); // tlRegion in AllocBuffer is a shortcut for fast allocation. // we should handle failure in RegionManager diff --git a/common_components/heap/allocator/memory_map.cpp b/common_components/heap/allocator/memory_map.cpp index 90420c26bf..67e7c9964d 100755 --- a/common_components/heap/allocator/memory_map.cpp +++ b/common_components/heap/allocator/memory_map.cpp @@ -81,7 +81,6 @@ MemoryMap* MemoryMap::MapMemory(size_t reqSize, size_t initSize, const Option& o MemoryMap* MemoryMap::MapMemoryAlignInner4G(uint64_t reqSize, uint64_t initSize, const Option& opt) { static constexpr uint64_t MAX_SUPPORT_CAPACITY = 4ULL * GB; - LOGF_CHECK(reqSize <= MAX_SUPPORT_CAPACITY) << "Max support capacity 4G"; void* mappedAddr = nullptr; reqSize = AllocUtilRndUp(reqSize, ALLOC_UTIL_PAGE_SIZE); diff --git a/common_components/heap/allocator/region_manager.cpp b/common_components/heap/allocator/region_manager.cpp index 24e7ea0be7..0d8a6ddae8 100755 --- a/common_components/heap/allocator/region_manager.cpp +++ b/common_components/heap/allocator/region_manager.cpp @@ -551,7 +551,8 @@ void RegionManager::ForEachAwaitingJitFortUnsafe(const std::function totalHeapSize) { + if (!isCopy) { + (void)inactiveZone_.fetch_sub(size); + return nullptr; + } else { + Heap::GetHeap().SetForceThrowOOM(true); + } + } + if (addr < regionHeapEnd_ - size) { region = RegionDesc::InitRegionAt(addr, num, type); size_t idx = region->GetUnitIdx(); diff --git a/common_components/heap/allocator/region_manager.h b/common_components/heap/allocator/region_manager.h index 7c8025df61..28a391209a 100755 --- a/common_components/heap/allocator/region_manager.h +++ b/common_components/heap/allocator/region_manager.h @@ -138,11 +138,12 @@ public: } } // take a region with *num* units for allocation - RegionDesc* TakeRegion(size_t num, RegionDesc::UnitRole, bool expectPhysicalMem = false, bool allowgc = true); + RegionDesc* TakeRegion(size_t num, RegionDesc::UnitRole, bool expectPhysicalMem = false, bool allowgc = true, + bool isCopy = false); - RegionDesc* TakeRegion(bool expectPhysicalMem, bool allowgc) + RegionDesc* TakeRegion(bool expectPhysicalMem, bool allowgc, bool isCopy = false) { - return TakeRegion(1, RegionDesc::UnitRole::SMALL_SIZED_UNITS, expectPhysicalMem, allowgc); + return TakeRegion(1, RegionDesc::UnitRole::SMALL_SIZED_UNITS, expectPhysicalMem, allowgc, isCopy); } void AddRecentPinnedRegion(RegionDesc* region) @@ -352,6 +353,7 @@ public: size_t GetDirtyUnitCount() const { return freeRegionManager_.GetDirtyUnitCount(); } size_t GetInactiveUnitCount() const { return (regionHeapEnd_ - inactiveZone_) / RegionDesc::UNIT_SIZE; } + size_t GetActiveSize() const { return inactiveZone_ - regionHeapStart_; } inline size_t GetLargeObjectSize() const { diff --git a/common_components/heap/allocator/region_space.cpp b/common_components/heap/allocator/region_space.cpp index 7b45c57dfa..f941d13230 100755 --- a/common_components/heap/allocator/region_space.cpp +++ b/common_components/heap/allocator/region_space.cpp @@ -25,11 +25,10 @@ #include "common_components/heap/heap.h" namespace common { - template -RegionDesc* RegionSpace::AllocateThreadLocalRegion(bool expectPhysicalMem) +RegionDesc* RegionSpace::AllocateThreadLocalRegion(bool expectPhysicalMem, bool isCopy) { - RegionDesc* region = regionManager_.TakeRegion(expectPhysicalMem, true); + RegionDesc* region = regionManager_.TakeRegion(expectPhysicalMem, true, isCopy); if constexpr (type == AllocBufferType::TO) { if (region != nullptr) { toSpace_.AddThreadLocalRegion(region); @@ -271,6 +270,13 @@ void RegionSpace::Init(const RuntimeParam& param) MemoryMap::Option opt = MemoryMap::DEFAULT_OPTIONS; opt.tag = "region_heap"; size_t heapSize = param.heapParam.heapSize * KB; + +#if defined(PANDA_TARGET_64) + static constexpr uint64_t MAX_SUPPORT_CAPACITY = 4ULL * GB; + // 2: double heap size + LOGF_CHECK((heapSize / 2)<= MAX_SUPPORT_CAPACITY) << "Max support capacity 4G"; +#endif + size_t totalSize = RegionManager::GetHeapMemorySize(heapSize); size_t regionNum = RegionManager::GetHeapUnitCount(heapSize); #if defined(COMMON_ASAN_SUPPORT) @@ -369,7 +375,7 @@ HeapAddress AllocationBuffer::ToSpaceAllocate(size_t totalSize) heapSpace.HandleFullThreadLocalRegion(tlToRegion_); tlToRegion_ = RegionDesc::NullRegion(); - RegionDesc* r = heapSpace.AllocateThreadLocalRegion(false); + RegionDesc* r = heapSpace.AllocateThreadLocalRegion(false, true); if (UNLIKELY_CC(r == nullptr)) { return 0; } @@ -412,7 +418,7 @@ HeapAddress AllocationBuffer::Allocate(size_t totalSize, AllocType allocType) } // try an allocation but do not handle failure -HeapAddress AllocationBuffer::AllocateImpl(size_t totalSize, AllocType allocType) +HeapAddress AllocationBuffer::AllocateImpl(size_t totalSize, AllocType allocType, bool isCopy) { RegionSpace& heapSpace = reinterpret_cast(Heap::GetHeap().GetAllocator()); @@ -421,7 +427,7 @@ HeapAddress AllocationBuffer::AllocateImpl(size_t totalSize, AllocType allocType heapSpace.HandleFullThreadLocalRegion(tlRegion_); tlRegion_ = RegionDesc::NullRegion(); - RegionDesc* r = heapSpace.AllocateThreadLocalRegion(false); + RegionDesc* r = heapSpace.AllocateThreadLocalRegion(false, isCopy); if (UNLIKELY_CC(r == nullptr)) { return 0; } @@ -443,7 +449,7 @@ HeapAddress AllocationBuffer::AllocateImpl(size_t totalSize, AllocType allocType UNREACHABLE(); } -HeapAddress AllocationBuffer::AllocateRawPointerObject(size_t totalSize) +HeapAddress AllocationBuffer::AllocateRawPointerObject(size_t totalSize, bool isCopy) { RegionDesc* region = tlRawPointerRegions_.GetHeadRegion(); if (region != nullptr) { @@ -456,7 +462,7 @@ HeapAddress AllocationBuffer::AllocateRawPointerObject(size_t totalSize) size_t needRegionNum = totalSize / RegionDesc::UNIT_SIZE + 1; // region should have at least 2 unit needRegionNum = (needRegionNum == 1) ? 2 : needRegionNum; - region = manager.TakeRegion(needRegionNum, RegionDesc::UnitRole::SMALL_SIZED_UNITS); + region = manager.TakeRegion(needRegionNum, RegionDesc::UnitRole::SMALL_SIZED_UNITS, isCopy); if (region == nullptr) { return 0; } diff --git a/common_components/heap/allocator/region_space.h b/common_components/heap/allocator/region_space.h index e250cc2000..be4c1e9ad7 100755 --- a/common_components/heap/allocator/region_space.h +++ b/common_components/heap/allocator/region_space.h @@ -74,7 +74,7 @@ public: void Init(const RuntimeParam ¶m) override; template - RegionDesc* AllocateThreadLocalRegion(bool expectPhysicalMem = false); + RegionDesc* AllocateThreadLocalRegion(bool expectPhysicalMem = false, bool isCopy = false); template void HandleFullThreadLocalRegion(RegionDesc* region) noexcept @@ -376,7 +376,7 @@ public: private: enum class TryAllocationThreshold { RESCHEDULE = 3, - TRIGGER_OOM = 5, + TRIGGER_OOM = 3, }; HeapAddress TryAllocateOnce(size_t allocSize, AllocType allocType); bool ShouldRetryAllocation(size_t& tryTimes) const; diff --git a/common_components/heap/collector/heuristic_gc_policy.cpp b/common_components/heap/collector/heuristic_gc_policy.cpp index 5ddf98f95c..ad900667ff 100644 --- a/common_components/heap/collector/heuristic_gc_policy.cpp +++ b/common_components/heap/collector/heuristic_gc_policy.cpp @@ -34,6 +34,8 @@ void HeuristicGCPolicy::Init() { HeapParam &heapParam = BaseRuntime::GetInstance()->GetHeapParam(); heapSize_ = heapParam.heapSize * KB; + // 2: only half heapSize used allocate + heapSize_ = heapSize_ / 2; } bool HeuristicGCPolicy::ShouldRestrainGCOnStartup() diff --git a/common_components/heap/collector/trace_collector.cpp b/common_components/heap/collector/trace_collector.cpp index fb9d1122d5..4af62919f0 100755 --- a/common_components/heap/collector/trace_collector.cpp +++ b/common_components/heap/collector/trace_collector.cpp @@ -752,6 +752,10 @@ void TraceCollector::RunGarbageCollection(uint64_t gcIndex, GCReason reason, GCT } UpdateGCStats(); + + if (Heap::GetHeap().GetForceThrowOOM()) { + Heap::throwOOM(); + } } void TraceCollector::CopyFromSpace() diff --git a/common_components/heap/heap.cpp b/common_components/heap/heap.cpp index 1f2342399e..2c89b2e112 100644 --- a/common_components/heap/heap.cpp +++ b/common_components/heap/heap.cpp @@ -91,6 +91,8 @@ public: RegionDesc *region = RegionDesc::GetRegionDescAt(reinterpret_cast(addr)); return region->IsInRecentSpace(); } + bool GetForceThrowOOM() const override { return isForceThrowOOM_; }; + void SetForceThrowOOM(bool val) override { isForceThrowOOM_ = val; }; HeapAddress Allocate(size_t size, AllocType allocType, bool allowGC = true) override; @@ -154,6 +156,7 @@ private: std::atomic isGCEnabled_ = { true }; GCReason gcReason_ = GCReason::GC_REASON_INVALID; + bool isForceThrowOOM_ = { false }; }; // end class HeapImpl static ImmortalWrapper g_heapInstance; diff --git a/common_components/heap/heap.h b/common_components/heap/heap.h index 58d69eab33..b448678833 100755 --- a/common_components/heap/heap.h +++ b/common_components/heap/heap.h @@ -182,6 +182,8 @@ public: virtual void SetGCReason(GCReason reason) = 0; virtual bool InRecentSpace(const void *addr) = 0; + virtual bool GetForceThrowOOM() const = 0; + virtual void SetForceThrowOOM(bool val) = 0; static void OnHeapCreated(HeapAddress startAddr) { diff --git a/common_components/heap/w_collector/w_collector.cpp b/common_components/heap/w_collector/w_collector.cpp index d1206c1301..afdc50c558 100755 --- a/common_components/heap/w_collector/w_collector.cpp +++ b/common_components/heap/w_collector/w_collector.cpp @@ -299,7 +299,6 @@ public: if (collector_->IsFromObject(oldObj)) { BaseObject* toVersion = collector_->TryForwardObject(oldObj); if (toVersion == nullptr) { - Heap::throwOOM(); return; } HeapProfilerListener::GetInstance().OnMoveEvent(reinterpret_cast(oldObj), @@ -963,7 +962,6 @@ BaseObject* WCollector::CopyObjectAfterExclusive(BaseObject* obj) } BaseObject* toObj = fwdTable_.RouteObject(obj, size); if (toObj == nullptr) { - Heap::throwOOM(); // ConcurrentGC obj->UnlockExclusive(BaseStateWord::ForwardState::NORMAL); return toObj; diff --git a/ecmascript/mem/mem_map_allocator.cpp b/ecmascript/mem/mem_map_allocator.cpp index 6951f26fa1..a1aac74197 100644 --- a/ecmascript/mem/mem_map_allocator.cpp +++ b/ecmascript/mem/mem_map_allocator.cpp @@ -343,7 +343,15 @@ void MemMapAllocator::AdapterSuitablePoolCapacity(bool isLargeHeap) } else { poolSize = GetPoolSize(MAX_MEM_POOL_CAPACITY); } - capacity_ = std::min(physicalSize * DEFAULT_CAPACITY_RATE, poolSize); + if (g_isEnableCMCGC) { + constexpr double capacityRate = 0.4; + capacity_ = std::min(physicalSize * capacityRate, poolSize); + // 2: double size, for cmc copy + capacity_ *= 2; + } else { + capacity_ = std::min(physicalSize * DEFAULT_CAPACITY_RATE, poolSize); + } + LOG_GC(INFO) << "Ark Auto adapter memory pool capacity:" << capacity_; } -- Gitee