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/partial_gc.h"
17
18 #include "ecmascript/ecma_vm.h"
19 #include "ecmascript/mem/barriers-inl.h"
20 #include "ecmascript/mem/clock_scope.h"
21 #include "ecmascript/mem/concurrent_marker.h"
22 #include "ecmascript/mem/heap-inl.h"
23 #include "ecmascript/mem/mark_stack.h"
24 #include "ecmascript/mem/mem.h"
25 #include "ecmascript/mem/parallel_evacuator.h"
26 #include "ecmascript/mem/parallel_marker-inl.h"
27 #include "ecmascript/mem/space-inl.h"
28 #include "ecmascript/mem/visitor.h"
29 #include "ecmascript/mem/gc_stats.h"
30 #include "ecmascript/ecma_string_table.h"
31 #include "ecmascript/runtime_call_id.h"
32
33 namespace panda::ecmascript {
PartialGC(Heap * heap)34 PartialGC::PartialGC(Heap *heap) : heap_(heap), workManager_(heap->GetWorkManager()) {}
35
RunPhases()36 void PartialGC::RunPhases()
37 {
38 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::RunPhases" + std::to_string(heap_->IsFullMark()));
39 MEM_ALLOCATE_AND_GC_TRACE(heap_->GetEcmaVM(), PartialGC_RunPhases);
40 ClockScope clockScope;
41
42 markingInProgress_ = heap_->CheckOngoingConcurrentMarking();
43
44 LOG_GC(DEBUG) << "markingInProgress_" << markingInProgress_;
45 Initialize();
46 Mark();
47 Sweep();
48 Evacuate();
49 Finish();
50 heap_->GetEcmaVM()->GetEcmaGCStats()->StatisticPartialGC(markingInProgress_, clockScope.GetPauseTime(), freeSize_);
51 LOG_GC(DEBUG) << "PartialGC::RunPhases " << clockScope.TotalSpentTime();
52 }
53
Initialize()54 void PartialGC::Initialize()
55 {
56 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::Initialize");
57 if (!markingInProgress_) {
58 LOG_GC(DEBUG) << "No ongoing Concurrent marking. Initializing...";
59 heap_->Prepare();
60 if (heap_->IsFullMark()) {
61 heap_->GetOldSpace()->SelectCSet();
62 heap_->GetAppSpawnSpace()->EnumerateRegions([](Region *current) {
63 current->ClearMarkGCBitset();
64 current->ClearCrossRegionRSet();
65 });
66 heap_->EnumerateNonNewSpaceRegions([](Region *current) {
67 current->ResetAliveObject();
68 });
69 }
70 workManager_->Initialize(TriggerGCType::OLD_GC, ParallelGCTaskPhase::OLD_HANDLE_GLOBAL_POOL_TASK);
71
72 freeSize_ = 0;
73 hugeSpaceFreeSize_ = 0;
74 oldSpaceCommitSize_ = heap_->GetOldSpace()->GetCommittedSize();
75 nonMoveSpaceCommitSize_ = heap_->GetNonMovableSpace()->GetCommittedSize();
76 }
77 }
78
Finish()79 void PartialGC::Finish()
80 {
81 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::Finish");
82 if (markingInProgress_) {
83 auto marker = heap_->GetConcurrentMarker();
84 marker->Reset(false);
85 } else {
86 workManager_->Finish();
87 }
88 if (heap_->IsFullMark()) {
89 heap_->GetSweeper()->TryFillSweptRegion();
90 }
91 }
92
Mark()93 void PartialGC::Mark()
94 {
95 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::Mark");
96 if (markingInProgress_) {
97 heap_->GetConcurrentMarker()->ReMark();
98 return;
99 }
100 heap_->GetNonMovableMarker()->MarkRoots(MAIN_THREAD_INDEX);
101 if (heap_->IsFullMark()) {
102 heap_->GetNonMovableMarker()->ProcessMarkStack(MAIN_THREAD_INDEX);
103 } else {
104 heap_->GetNonMovableMarker()->ProcessOldToNew(MAIN_THREAD_INDEX);
105 heap_->GetNonMovableMarker()->ProcessSnapshotRSet(MAIN_THREAD_INDEX);
106 }
107 heap_->WaitRunningTaskFinished();
108 }
109
Sweep()110 void PartialGC::Sweep()
111 {
112 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::Sweep");
113 ProcessNativeDelete();
114 if (heap_->IsFullMark()) {
115 heap_->GetSweeper()->Sweep();
116 }
117 }
118
ProcessNativeDelete()119 void PartialGC::ProcessNativeDelete()
120 {
121 WeakRootVisitor gcUpdateWeak = [this](TaggedObject *header) {
122 Region *objectRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(header));
123 if (!objectRegion->InYoungSpaceOrCSet() && !heap_->IsFullMark()) {
124 return header;
125 }
126 if (!objectRegion->Test(header)) {
127 return reinterpret_cast<TaggedObject *>(ToUintPtr(nullptr));
128 }
129 return header;
130 };
131 heap_->GetEcmaVM()->ProcessNativeDelete(gcUpdateWeak);
132 }
133
Evacuate()134 void PartialGC::Evacuate()
135 {
136 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::Evacuate");
137 heap_->GetEvacuator()->Evacuate();
138 }
139 } // namespace panda::ecmascript
140