1 /*
2 * Copyright (c) 2021 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/concurrent_sweeper.h"
17
18 #include "ecmascript/ecma_macros.h"
19 #include "ecmascript/mem/heap.h"
20 #include "ecmascript/mem/space-inl.h"
21 #include "ecmascript/platform/platform.h"
22 #include "ecmascript/runtime_call_id.h"
23
24 namespace panda::ecmascript {
ConcurrentSweeper(Heap * heap,bool concurrentSweep)25 ConcurrentSweeper::ConcurrentSweeper(Heap *heap, bool concurrentSweep)
26 : heap_(heap), concurrentSweep_(concurrentSweep)
27 {
28 }
29
PostConcurrentSweepTasks(bool fullGC)30 void ConcurrentSweeper::PostConcurrentSweepTasks(bool fullGC)
31 {
32 if (concurrentSweep_) {
33 if (!fullGC) {
34 Platform::GetCurrentPlatform()->PostTask(std::make_unique<SweeperTask>(this, OLD_SPACE));
35 }
36 Platform::GetCurrentPlatform()->PostTask(std::make_unique<SweeperTask>(this, NON_MOVABLE));
37 Platform::GetCurrentPlatform()->PostTask(std::make_unique<SweeperTask>(this, MACHINE_CODE_SPACE));
38 }
39 }
40
SweepPhases(bool fullGC)41 void ConcurrentSweeper::SweepPhases(bool fullGC)
42 {
43 MEM_ALLOCATE_AND_GC_TRACE(heap_->GetEcmaVM(), ConcurrentSweepingInitialize);
44 if (concurrentSweep_) {
45 // Add all region to region list. Ensure all task finish
46 if (!fullGC) {
47 heap_->GetOldSpace()->PrepareSweeping();
48 }
49 heap_->GetNonMovableSpace()->PrepareSweeping();
50 heap_->GetMachineCodeSpace()->PrepareSweeping();
51
52 // Prepare
53 isSweeping_ = true;
54 startSpaceType_ = fullGC ? NON_MOVABLE : OLD_SPACE;
55 for (int type = startSpaceType_; type < FREE_LIST_NUM; type++) {
56 remainderTaskNum_[type] = FREE_LIST_NUM - startSpaceType_;
57 }
58 } else {
59 if (!fullGC) {
60 heap_->GetOldSpace()->Sweeping();
61 }
62 heap_->GetNonMovableSpace()->Sweeping();
63 heap_->GetMachineCodeSpace()->Sweeping();
64 }
65 heap_->GetHugeObjectSpace()->Sweeping();
66 }
67
AsyncSweepSpace(MemSpaceType type,bool isMain)68 void ConcurrentSweeper::AsyncSweepSpace(MemSpaceType type, bool isMain)
69 {
70 auto space = heap_->GetSpaceWithType(type);
71 space->AsyncSweeping(isMain);
72
73 os::memory::LockHolder holder(mutexs_[type]);
74 if (--remainderTaskNum_[type] == 0) {
75 cvs_[type].SignalAll();
76 }
77 }
78
WaitAllTaskFinished()79 void ConcurrentSweeper::WaitAllTaskFinished()
80 {
81 if (!isSweeping_) {
82 return;
83 }
84 for (int i = startSpaceType_; i < FREE_LIST_NUM; i++) {
85 if (remainderTaskNum_[i] > 0) {
86 os::memory::LockHolder holder(mutexs_[i]);
87 while (remainderTaskNum_[i] > 0) {
88 cvs_[i].Wait(&mutexs_[i]);
89 }
90 }
91 }
92 }
93
EnsureAllTaskFinished()94 void ConcurrentSweeper::EnsureAllTaskFinished()
95 {
96 CHECK_JS_THREAD(heap_->GetEcmaVM());
97 if (!isSweeping_) {
98 return;
99 }
100 for (int i = startSpaceType_; i < FREE_LIST_NUM; i++) {
101 WaitingTaskFinish(static_cast<MemSpaceType>(i));
102 }
103 isSweeping_ = false;
104 }
105
EnsureTaskFinished(MemSpaceType type)106 void ConcurrentSweeper::EnsureTaskFinished(MemSpaceType type)
107 {
108 CHECK_JS_THREAD(heap_->GetEcmaVM());
109 if (!isSweeping_) {
110 return;
111 }
112 WaitingTaskFinish(type);
113 }
114
WaitingTaskFinish(MemSpaceType type)115 void ConcurrentSweeper::WaitingTaskFinish(MemSpaceType type)
116 {
117 if (remainderTaskNum_[type] > 0) {
118 {
119 os::memory::LockHolder holder(mutexs_[type]);
120 remainderTaskNum_[type]++;
121 }
122 AsyncSweepSpace(type, true);
123 os::memory::LockHolder holder(mutexs_[type]);
124 while (remainderTaskNum_[type] > 0) {
125 cvs_[type].Wait(&mutexs_[type]);
126 }
127 }
128 FinishSweeping(type);
129 }
130
FinishSweeping(MemSpaceType type)131 void ConcurrentSweeper::FinishSweeping(MemSpaceType type)
132 {
133 SparseSpace *space = heap_->GetSpaceWithType(type);
134 space->FillSweptRegion();
135 }
136
Run(uint32_t threadIndex)137 bool ConcurrentSweeper::SweeperTask::Run(uint32_t threadIndex)
138 {
139 int sweepTypeNum = FREE_LIST_NUM - sweeper_->startSpaceType_;
140 for (size_t i = sweeper_->startSpaceType_; i < FREE_LIST_NUM; i++) {
141 auto type = static_cast<MemSpaceType>(((i + type_) % sweepTypeNum) + sweeper_->startSpaceType_);
142 sweeper_->AsyncSweepSpace(type, false);
143 }
144 return true;
145 }
146 } // namespace panda::ecmascript
147