1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/mem/shared_heap/shared_concurrent_sweeper.h" 17#include "ecmascript/mem/heap.h" 18 19namespace panda::ecmascript { 20SharedConcurrentSweeper::SharedConcurrentSweeper(SharedHeap *heap, EnableConcurrentSweepType type) 21 : sHeap_(heap), 22 enableType_(type) 23{ 24} 25 26void SharedConcurrentSweeper::PostTask(bool isFullGC) 27{ 28 auto tid = DaemonThread::GetInstance()->GetThreadId(); 29 if (ConcurrentSweepEnabled()) { 30 if (!isFullGC) { 31 Taskpool::GetCurrentTaskpool()->PostTask( 32 std::make_unique<SweeperTask>(tid, this, SHARED_OLD_SPACE)); 33 } 34 Taskpool::GetCurrentTaskpool()->PostTask( 35 std::make_unique<SweeperTask>(tid, this, SHARED_NON_MOVABLE)); 36 } 37} 38 39void SharedConcurrentSweeper::Sweep(bool isFullGC) 40{ 41 isFullGC_ = isFullGC; 42 if (ConcurrentSweepEnabled()) { 43 // Add all region to region list. Ensure all task finish 44 if (!isFullGC_) { 45 sHeap_->GetOldSpace()->PrepareSweeping(); 46 for (int spaceIndex = 0; spaceIndex < SHARED_SWEEPING_SPACE_NUM; spaceIndex++) { 47 remainingTaskNum_[spaceIndex] = SHARED_SWEEPING_SPACE_NUM; 48 } 49 } else { 50 remainingTaskNum_[0] = 0; // No need sweep shared old space in FullGC. 51 remainingTaskNum_[1] = 1; // Need sweep nonmovable space in FullGC. 52 } 53 sHeap_->GetNonMovableSpace()->PrepareSweeping(); 54 // Prepare 55 isSweeping_ = true; 56 } else { 57 if (!isFullGC_) { 58 sHeap_->GetOldSpace()->Sweep(); 59 } 60 sHeap_->GetNonMovableSpace()->Sweep(); 61 } 62 sHeap_->GetHugeObjectSpace()->Sweep(); 63} 64 65void SharedConcurrentSweeper::AsyncSweepSpace(MemSpaceType type, bool isMain) 66{ 67 auto space = sHeap_->GetSpaceWithType(type); 68 space->AsyncSweep(isMain); 69 int spaceIndex = type - SHARED_SWEEPING_SPACE_BEGIN; 70 LockHolder holder(mutexs_[spaceIndex]); 71 if (--remainingTaskNum_[spaceIndex] == 0) { 72 cvs_[spaceIndex].SignalAll(); 73 } 74} 75 76void SharedConcurrentSweeper::WaitAllTaskFinished() 77{ 78 if (!isSweeping_) { 79 return; 80 } 81 int spaceIndex = isFullGC_ ? 1 : 0; 82 for (; spaceIndex < SHARED_SWEEPING_SPACE_NUM; spaceIndex++) { 83 if (remainingTaskNum_[spaceIndex] > 0) { 84 LockHolder holder(mutexs_[spaceIndex]); 85 while (remainingTaskNum_[spaceIndex] > 0) { 86 cvs_[spaceIndex].Wait(&mutexs_[spaceIndex]); 87 } 88 } 89 } 90} 91 92// call in suspendAll thread. 93void SharedConcurrentSweeper::EnsureAllTaskFinished() 94{ 95 if (!isSweeping_) { 96 return; 97 } 98 int spaceIndex = isFullGC_ ? 1 : 0; 99 for (; spaceIndex < SHARED_SWEEPING_SPACE_NUM; spaceIndex++) { 100 int type = spaceIndex + SHARED_SWEEPING_SPACE_BEGIN; 101 WaitingTaskFinish(static_cast<MemSpaceType>(type)); 102 } 103 isSweeping_ = false; 104 if (IsRequestDisabled()) { 105 enableType_ = EnableConcurrentSweepType::DISABLE; 106 } 107} 108 109// call in mutator thread 110void SharedConcurrentSweeper::EnsureTaskFinished(MemSpaceType type) 111{ 112 if (!isSweeping_) { 113 return; 114 } 115 WaitingTaskFinish(type); 116} 117 118void SharedConcurrentSweeper::WaitingTaskFinish(MemSpaceType type) 119{ 120 int spaceIndex = type - SHARED_SWEEPING_SPACE_BEGIN; 121 if (remainingTaskNum_[spaceIndex] > 0) { 122 { 123 LockHolder holder(mutexs_[spaceIndex]); 124 remainingTaskNum_[spaceIndex]++; 125 } 126 AsyncSweepSpace(type, true); 127 LockHolder holder(mutexs_[spaceIndex]); 128 while (remainingTaskNum_[spaceIndex] > 0) { 129 cvs_[spaceIndex].Wait(&mutexs_[spaceIndex]); 130 } 131 } 132 SharedSparseSpace *space = sHeap_->GetSpaceWithType(type); 133 space->FinishFillSweptRegion(); 134} 135 136void SharedConcurrentSweeper::TryFillSweptRegion() 137{ 138 if (!isFullGC_) { 139 sHeap_->GetOldSpace()->TryFillSweptRegion(); 140 } 141 sHeap_->GetNonMovableSpace()->TryFillSweptRegion(); 142} 143 144bool SharedConcurrentSweeper::SweeperTask::Run([[maybe_unused]] uint32_t threadIndex) 145{ 146 if (type_ == SHARED_NON_MOVABLE) { 147 sweeper_->AsyncSweepSpace(SHARED_NON_MOVABLE, false); 148 if (!sweeper_->isFullGC_) { 149 sweeper_->AsyncSweepSpace(SHARED_OLD_SPACE, false); 150 } 151 } else { 152 ASSERT(type_ == SHARED_OLD_SPACE); 153 if (!sweeper_->isFullGC_) { 154 sweeper_->AsyncSweepSpace(SHARED_OLD_SPACE, false); 155 } 156 sweeper_->AsyncSweepSpace(SHARED_NON_MOVABLE, false); 157 } 158 159 return true; 160} 161 162void SharedConcurrentSweeper::EnableConcurrentSweep(EnableConcurrentSweepType type) 163{ 164 if (IsConfigDisabled()) { 165 return; 166 } 167 if (ConcurrentSweepEnabled() && isSweeping_ && type == EnableConcurrentSweepType::DISABLE) { 168 enableType_ = EnableConcurrentSweepType::REQUEST_DISABLE; 169 } else { 170 enableType_ = type; 171 } 172} 173} // namespace panda::ecmascript 174