• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 #include "common_components/taskpool/taskpool.h"
19 #include "ecmascript/daemon/daemon_thread.h"
20 #include "ecmascript/mem/heap.h"
21 
22 namespace panda::ecmascript {
SharedConcurrentSweeper(SharedHeap * heap,EnableConcurrentSweepType type)23 SharedConcurrentSweeper::SharedConcurrentSweeper(SharedHeap *heap, EnableConcurrentSweepType type)
24     : sHeap_(heap),
25       enableType_(type)
26 {
27 }
28 
PostTask(bool isFullGC)29 void SharedConcurrentSweeper::PostTask(bool isFullGC)
30 {
31     auto tid = DaemonThread::GetInstance()->GetThreadId();
32     if (ConcurrentSweepEnabled()) {
33         if (!isFullGC) {
34             common::Taskpool::GetCurrentTaskpool()->PostTask(
35                 std::make_unique<SweeperTask>(tid, this, SHARED_OLD_SPACE, isFullGC));
36         }
37         common::Taskpool::GetCurrentTaskpool()->PostTask(
38             std::make_unique<SweeperTask>(tid, this, SHARED_NON_MOVABLE, isFullGC));
39     } else {
40         if (!isFullGC_) {
41             sHeap_->GetOldSpace()->Sweep();
42         }
43         sHeap_->GetNonMovableSpace()->Sweep();
44     }
45     sHeap_->GetHugeObjectSpace()->Sweep();
46 }
47 
Sweep(bool isFullGC)48 void SharedConcurrentSweeper::Sweep(bool isFullGC)
49 {
50     isFullGC_ = isFullGC;
51     if (ConcurrentSweepEnabled()) {
52         // Add all region to region list. Ensure all task finish
53         if (!isFullGC_) {
54             sHeap_->GetOldSpace()->PrepareSweeping();
55             for (int spaceIndex = 0; spaceIndex < SHARED_SWEEPING_SPACE_NUM; spaceIndex++) {
56                 remainingTaskNum_[spaceIndex] = SHARED_SWEEPING_SPACE_NUM;
57             }
58         } else {
59             remainingTaskNum_[0] = 0;  // No need sweep shared old space in FullGC.
60             remainingTaskNum_[1] = 1;  // Need sweep nonmovable space in FullGC.
61         }
62         sHeap_->GetNonMovableSpace()->PrepareSweeping();
63         // Prepare
64         isSweeping_ = true;
65     }
66 }
67 
AsyncSweepSpace(MemSpaceType type,bool isMain)68 void SharedConcurrentSweeper::AsyncSweepSpace(MemSpaceType type, bool isMain)
69 {
70     auto space = sHeap_->GetSpaceWithType(type);
71     space->AsyncSweep(isMain);
72     int spaceIndex = type - SHARED_SWEEPING_SPACE_BEGIN;
73     LockHolder holder(mutexs_[spaceIndex]);
74     if (--remainingTaskNum_[spaceIndex] == 0) {
75         cvs_[spaceIndex].SignalAll();
76     }
77 }
78 
WaitAllTaskFinished()79 void SharedConcurrentSweeper::WaitAllTaskFinished()
80 {
81     if (!isSweeping_) {
82         return;
83     }
84     int spaceIndex = isFullGC_ ? 1 : 0;
85     for (; spaceIndex < SHARED_SWEEPING_SPACE_NUM; spaceIndex++) {
86         if (remainingTaskNum_[spaceIndex] > 0) {
87             LockHolder holder(mutexs_[spaceIndex]);
88             while (remainingTaskNum_[spaceIndex] > 0) {
89                 cvs_[spaceIndex].Wait(&mutexs_[spaceIndex]);
90             }
91         }
92     }
93 }
94 
95 // call in suspendAll thread.
EnsureAllTaskFinished()96 void SharedConcurrentSweeper::EnsureAllTaskFinished()
97 {
98     if (!isSweeping_) {
99         return;
100     }
101     int spaceIndex = isFullGC_ ? 1 : 0;
102     for (; spaceIndex < SHARED_SWEEPING_SPACE_NUM; spaceIndex++) {
103         int type = spaceIndex + SHARED_SWEEPING_SPACE_BEGIN;
104         WaitingTaskFinish(static_cast<MemSpaceType>(type));
105     }
106     isSweeping_ = false;
107     if (IsRequestDisabled()) {
108         enableType_ = EnableConcurrentSweepType::DISABLE;
109     }
110 }
111 
112 // call in mutator thread
EnsureTaskFinished(MemSpaceType type)113 void SharedConcurrentSweeper::EnsureTaskFinished(MemSpaceType type)
114 {
115     if (!isSweeping_) {
116         return;
117     }
118     WaitingTaskFinish(type);
119 }
120 
WaitingTaskFinish(MemSpaceType type)121 void SharedConcurrentSweeper::WaitingTaskFinish(MemSpaceType type)
122 {
123     int spaceIndex = type - SHARED_SWEEPING_SPACE_BEGIN;
124     if (remainingTaskNum_[spaceIndex] > 0) {
125         {
126             LockHolder holder(mutexs_[spaceIndex]);
127             remainingTaskNum_[spaceIndex]++;
128         }
129         AsyncSweepSpace(type, true);
130         LockHolder holder(mutexs_[spaceIndex]);
131         while (remainingTaskNum_[spaceIndex] > 0) {
132             cvs_[spaceIndex].Wait(&mutexs_[spaceIndex]);
133         }
134     }
135     SharedSparseSpace *space = sHeap_->GetSpaceWithType(type);
136     space->FinishFillSweptRegion();
137 }
138 
TryFillSweptRegion()139 void SharedConcurrentSweeper::TryFillSweptRegion()
140 {
141     if (!isFullGC_) {
142         sHeap_->GetOldSpace()->TryFillSweptRegion();
143     }
144     sHeap_->GetNonMovableSpace()->TryFillSweptRegion();
145 }
146 
Run(uint32_t threadIndex)147 bool SharedConcurrentSweeper::SweeperTask::Run([[maybe_unused]] uint32_t threadIndex)
148 {
149     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedConcurrentSweeper::Sweep", "");
150     if (type_ == SHARED_NON_MOVABLE) {
151         sweeper_->AsyncSweepSpace(SHARED_NON_MOVABLE, false);
152         if (!isFullGC_) {
153             sweeper_->AsyncSweepSpace(SHARED_OLD_SPACE, false);
154         }
155     } else {
156         ASSERT(type_ == SHARED_OLD_SPACE);
157         if (!isFullGC_) {
158             sweeper_->AsyncSweepSpace(SHARED_OLD_SPACE, false);
159         }
160         sweeper_->AsyncSweepSpace(SHARED_NON_MOVABLE, false);
161     }
162 
163     return true;
164 }
165 
EnableConcurrentSweep(EnableConcurrentSweepType type)166 void SharedConcurrentSweeper::EnableConcurrentSweep(EnableConcurrentSweepType type)
167 {
168     if (IsConfigDisabled()) {
169         return;
170     }
171     if (ConcurrentSweepEnabled() && isSweeping_ && type == EnableConcurrentSweepType::DISABLE) {
172         enableType_ = EnableConcurrentSweepType::REQUEST_DISABLE;
173     } else {
174         enableType_ = type;
175     }
176 }
177 }  // namespace panda::ecmascript
178