14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/mem/shared_heap/shared_concurrent_sweeper.h"
174514f5e3Sopenharmony_ci#include "ecmascript/mem/heap.h"
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_cinamespace panda::ecmascript {
204514f5e3Sopenharmony_ciSharedConcurrentSweeper::SharedConcurrentSweeper(SharedHeap *heap, EnableConcurrentSweepType type)
214514f5e3Sopenharmony_ci    : sHeap_(heap),
224514f5e3Sopenharmony_ci      enableType_(type)
234514f5e3Sopenharmony_ci{
244514f5e3Sopenharmony_ci}
254514f5e3Sopenharmony_ci
264514f5e3Sopenharmony_civoid SharedConcurrentSweeper::PostTask(bool isFullGC)
274514f5e3Sopenharmony_ci{
284514f5e3Sopenharmony_ci    auto tid = DaemonThread::GetInstance()->GetThreadId();
294514f5e3Sopenharmony_ci    if (ConcurrentSweepEnabled()) {
304514f5e3Sopenharmony_ci        if (!isFullGC) {
314514f5e3Sopenharmony_ci            Taskpool::GetCurrentTaskpool()->PostTask(
324514f5e3Sopenharmony_ci                std::make_unique<SweeperTask>(tid, this, SHARED_OLD_SPACE));
334514f5e3Sopenharmony_ci        }
344514f5e3Sopenharmony_ci        Taskpool::GetCurrentTaskpool()->PostTask(
354514f5e3Sopenharmony_ci            std::make_unique<SweeperTask>(tid, this, SHARED_NON_MOVABLE));
364514f5e3Sopenharmony_ci    }
374514f5e3Sopenharmony_ci}
384514f5e3Sopenharmony_ci
394514f5e3Sopenharmony_civoid SharedConcurrentSweeper::Sweep(bool isFullGC)
404514f5e3Sopenharmony_ci{
414514f5e3Sopenharmony_ci    isFullGC_ = isFullGC;
424514f5e3Sopenharmony_ci    if (ConcurrentSweepEnabled()) {
434514f5e3Sopenharmony_ci        // Add all region to region list. Ensure all task finish
444514f5e3Sopenharmony_ci        if (!isFullGC_) {
454514f5e3Sopenharmony_ci            sHeap_->GetOldSpace()->PrepareSweeping();
464514f5e3Sopenharmony_ci            for (int spaceIndex = 0; spaceIndex < SHARED_SWEEPING_SPACE_NUM; spaceIndex++) {
474514f5e3Sopenharmony_ci                remainingTaskNum_[spaceIndex] = SHARED_SWEEPING_SPACE_NUM;
484514f5e3Sopenharmony_ci            }
494514f5e3Sopenharmony_ci        } else {
504514f5e3Sopenharmony_ci            remainingTaskNum_[0] = 0;  // No need sweep shared old space in FullGC.
514514f5e3Sopenharmony_ci            remainingTaskNum_[1] = 1;  // Need sweep nonmovable space in FullGC.
524514f5e3Sopenharmony_ci        }
534514f5e3Sopenharmony_ci        sHeap_->GetNonMovableSpace()->PrepareSweeping();
544514f5e3Sopenharmony_ci        // Prepare
554514f5e3Sopenharmony_ci        isSweeping_ = true;
564514f5e3Sopenharmony_ci    } else {
574514f5e3Sopenharmony_ci        if (!isFullGC_) {
584514f5e3Sopenharmony_ci            sHeap_->GetOldSpace()->Sweep();
594514f5e3Sopenharmony_ci        }
604514f5e3Sopenharmony_ci        sHeap_->GetNonMovableSpace()->Sweep();
614514f5e3Sopenharmony_ci    }
624514f5e3Sopenharmony_ci    sHeap_->GetHugeObjectSpace()->Sweep();
634514f5e3Sopenharmony_ci}
644514f5e3Sopenharmony_ci
654514f5e3Sopenharmony_civoid SharedConcurrentSweeper::AsyncSweepSpace(MemSpaceType type, bool isMain)
664514f5e3Sopenharmony_ci{
674514f5e3Sopenharmony_ci    auto space = sHeap_->GetSpaceWithType(type);
684514f5e3Sopenharmony_ci    space->AsyncSweep(isMain);
694514f5e3Sopenharmony_ci    int spaceIndex = type - SHARED_SWEEPING_SPACE_BEGIN;
704514f5e3Sopenharmony_ci    LockHolder holder(mutexs_[spaceIndex]);
714514f5e3Sopenharmony_ci    if (--remainingTaskNum_[spaceIndex] == 0) {
724514f5e3Sopenharmony_ci        cvs_[spaceIndex].SignalAll();
734514f5e3Sopenharmony_ci    }
744514f5e3Sopenharmony_ci}
754514f5e3Sopenharmony_ci
764514f5e3Sopenharmony_civoid SharedConcurrentSweeper::WaitAllTaskFinished()
774514f5e3Sopenharmony_ci{
784514f5e3Sopenharmony_ci    if (!isSweeping_) {
794514f5e3Sopenharmony_ci        return;
804514f5e3Sopenharmony_ci    }
814514f5e3Sopenharmony_ci    int spaceIndex = isFullGC_ ? 1 : 0;
824514f5e3Sopenharmony_ci    for (; spaceIndex < SHARED_SWEEPING_SPACE_NUM; spaceIndex++) {
834514f5e3Sopenharmony_ci        if (remainingTaskNum_[spaceIndex] > 0) {
844514f5e3Sopenharmony_ci            LockHolder holder(mutexs_[spaceIndex]);
854514f5e3Sopenharmony_ci            while (remainingTaskNum_[spaceIndex] > 0) {
864514f5e3Sopenharmony_ci                cvs_[spaceIndex].Wait(&mutexs_[spaceIndex]);
874514f5e3Sopenharmony_ci            }
884514f5e3Sopenharmony_ci        }
894514f5e3Sopenharmony_ci    }
904514f5e3Sopenharmony_ci}
914514f5e3Sopenharmony_ci
924514f5e3Sopenharmony_ci// call in suspendAll thread.
934514f5e3Sopenharmony_civoid SharedConcurrentSweeper::EnsureAllTaskFinished()
944514f5e3Sopenharmony_ci{
954514f5e3Sopenharmony_ci    if (!isSweeping_) {
964514f5e3Sopenharmony_ci        return;
974514f5e3Sopenharmony_ci    }
984514f5e3Sopenharmony_ci    int spaceIndex = isFullGC_ ? 1 : 0;
994514f5e3Sopenharmony_ci    for (; spaceIndex < SHARED_SWEEPING_SPACE_NUM; spaceIndex++) {
1004514f5e3Sopenharmony_ci        int type = spaceIndex + SHARED_SWEEPING_SPACE_BEGIN;
1014514f5e3Sopenharmony_ci        WaitingTaskFinish(static_cast<MemSpaceType>(type));
1024514f5e3Sopenharmony_ci    }
1034514f5e3Sopenharmony_ci    isSweeping_ = false;
1044514f5e3Sopenharmony_ci    if (IsRequestDisabled()) {
1054514f5e3Sopenharmony_ci        enableType_ = EnableConcurrentSweepType::DISABLE;
1064514f5e3Sopenharmony_ci    }
1074514f5e3Sopenharmony_ci}
1084514f5e3Sopenharmony_ci
1094514f5e3Sopenharmony_ci// call in mutator thread
1104514f5e3Sopenharmony_civoid SharedConcurrentSweeper::EnsureTaskFinished(MemSpaceType type)
1114514f5e3Sopenharmony_ci{
1124514f5e3Sopenharmony_ci    if (!isSweeping_) {
1134514f5e3Sopenharmony_ci        return;
1144514f5e3Sopenharmony_ci    }
1154514f5e3Sopenharmony_ci    WaitingTaskFinish(type);
1164514f5e3Sopenharmony_ci}
1174514f5e3Sopenharmony_ci
1184514f5e3Sopenharmony_civoid SharedConcurrentSweeper::WaitingTaskFinish(MemSpaceType type)
1194514f5e3Sopenharmony_ci{
1204514f5e3Sopenharmony_ci    int spaceIndex = type - SHARED_SWEEPING_SPACE_BEGIN;
1214514f5e3Sopenharmony_ci    if (remainingTaskNum_[spaceIndex] > 0) {
1224514f5e3Sopenharmony_ci        {
1234514f5e3Sopenharmony_ci            LockHolder holder(mutexs_[spaceIndex]);
1244514f5e3Sopenharmony_ci            remainingTaskNum_[spaceIndex]++;
1254514f5e3Sopenharmony_ci        }
1264514f5e3Sopenharmony_ci        AsyncSweepSpace(type, true);
1274514f5e3Sopenharmony_ci        LockHolder holder(mutexs_[spaceIndex]);
1284514f5e3Sopenharmony_ci        while (remainingTaskNum_[spaceIndex] > 0) {
1294514f5e3Sopenharmony_ci            cvs_[spaceIndex].Wait(&mutexs_[spaceIndex]);
1304514f5e3Sopenharmony_ci        }
1314514f5e3Sopenharmony_ci    }
1324514f5e3Sopenharmony_ci    SharedSparseSpace *space = sHeap_->GetSpaceWithType(type);
1334514f5e3Sopenharmony_ci    space->FinishFillSweptRegion();
1344514f5e3Sopenharmony_ci}
1354514f5e3Sopenharmony_ci
1364514f5e3Sopenharmony_civoid SharedConcurrentSweeper::TryFillSweptRegion()
1374514f5e3Sopenharmony_ci{
1384514f5e3Sopenharmony_ci    if (!isFullGC_) {
1394514f5e3Sopenharmony_ci        sHeap_->GetOldSpace()->TryFillSweptRegion();
1404514f5e3Sopenharmony_ci    }
1414514f5e3Sopenharmony_ci    sHeap_->GetNonMovableSpace()->TryFillSweptRegion();
1424514f5e3Sopenharmony_ci}
1434514f5e3Sopenharmony_ci
1444514f5e3Sopenharmony_cibool SharedConcurrentSweeper::SweeperTask::Run([[maybe_unused]] uint32_t threadIndex)
1454514f5e3Sopenharmony_ci{
1464514f5e3Sopenharmony_ci    if (type_ == SHARED_NON_MOVABLE) {
1474514f5e3Sopenharmony_ci        sweeper_->AsyncSweepSpace(SHARED_NON_MOVABLE, false);
1484514f5e3Sopenharmony_ci        if (!sweeper_->isFullGC_) {
1494514f5e3Sopenharmony_ci            sweeper_->AsyncSweepSpace(SHARED_OLD_SPACE, false);
1504514f5e3Sopenharmony_ci        }
1514514f5e3Sopenharmony_ci    } else {
1524514f5e3Sopenharmony_ci        ASSERT(type_ == SHARED_OLD_SPACE);
1534514f5e3Sopenharmony_ci        if (!sweeper_->isFullGC_) {
1544514f5e3Sopenharmony_ci            sweeper_->AsyncSweepSpace(SHARED_OLD_SPACE, false);
1554514f5e3Sopenharmony_ci        }
1564514f5e3Sopenharmony_ci        sweeper_->AsyncSweepSpace(SHARED_NON_MOVABLE, false);
1574514f5e3Sopenharmony_ci    }
1584514f5e3Sopenharmony_ci
1594514f5e3Sopenharmony_ci    return true;
1604514f5e3Sopenharmony_ci}
1614514f5e3Sopenharmony_ci
1624514f5e3Sopenharmony_civoid SharedConcurrentSweeper::EnableConcurrentSweep(EnableConcurrentSweepType type)
1634514f5e3Sopenharmony_ci{
1644514f5e3Sopenharmony_ci    if (IsConfigDisabled()) {
1654514f5e3Sopenharmony_ci        return;
1664514f5e3Sopenharmony_ci    }
1674514f5e3Sopenharmony_ci    if (ConcurrentSweepEnabled() && isSweeping_ && type == EnableConcurrentSweepType::DISABLE) {
1684514f5e3Sopenharmony_ci        enableType_ = EnableConcurrentSweepType::REQUEST_DISABLE;
1694514f5e3Sopenharmony_ci    } else {
1704514f5e3Sopenharmony_ci        enableType_ = type;
1714514f5e3Sopenharmony_ci    }
1724514f5e3Sopenharmony_ci}
1734514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
174