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/gc_stats.h"
17 #include "ecmascript/mem/incremental_marker.h"
18 #include "ecmascript/mem/parallel_marker-inl.h"
19 #include "ecmascript/mem/visitor.h"
20
21 namespace panda::ecmascript {
Marker(Heap * heap)22 Marker::Marker(Heap *heap) : heap_(heap), objXRay_(heap->GetEcmaVM()), workManager_(heap->GetWorkManager()) {}
23
MarkRoots(uint32_t threadId)24 void Marker::MarkRoots(uint32_t threadId)
25 {
26 TRACE_GC(GCStats::Scope::ScopeId::MarkRoots, heap_->GetEcmaVM()->GetEcmaGCStats());
27 objXRay_.VisitVMRoots(
28 std::bind(&Marker::HandleRoots, this, threadId, std::placeholders::_1, std::placeholders::_2),
29 std::bind(&Marker::HandleRangeRoots, this, threadId, std::placeholders::_1, std::placeholders::_2,
30 std::placeholders::_3),
31 std::bind(&Marker::HandleDerivedRoots, this, std::placeholders::_1, std::placeholders::_2,
32 std::placeholders::_3, std::placeholders::_4));
33 workManager_->PushWorkNodeToGlobal(threadId, false);
34 }
35
ProcessOldToNew(uint32_t threadId)36 void Marker::ProcessOldToNew(uint32_t threadId)
37 {
38 heap_->EnumerateOldSpaceRegions(std::bind(&Marker::HandleOldToNewRSet, this, threadId, std::placeholders::_1));
39 ProcessMarkStack(threadId);
40 }
41
ProcessOldToNewNoMarkStack(uint32_t threadId)42 void Marker::ProcessOldToNewNoMarkStack(uint32_t threadId)
43 {
44 heap_->EnumerateOldSpaceRegions(std::bind(&Marker::HandleOldToNewRSet, this, threadId, std::placeholders::_1));
45 }
46
ProcessOldToNew(uint32_t threadId,Region * region)47 void Marker::ProcessOldToNew(uint32_t threadId, Region *region)
48 {
49 heap_->EnumerateOldSpaceRegions(std::bind(&Marker::HandleOldToNewRSet, this, threadId, std::placeholders::_1),
50 region);
51 ProcessMarkStack(threadId);
52 }
53
ProcessSnapshotRSet(uint32_t threadId)54 void Marker::ProcessSnapshotRSet(uint32_t threadId)
55 {
56 heap_->EnumerateSnapshotSpaceRegions(std::bind(&Marker::HandleOldToNewRSet, this, threadId, std::placeholders::_1));
57 ProcessMarkStack(threadId);
58 }
59
ProcessSnapshotRSetNoMarkStack(uint32_t threadId)60 void Marker::ProcessSnapshotRSetNoMarkStack(uint32_t threadId)
61 {
62 heap_->EnumerateSnapshotSpaceRegions(std::bind(&Marker::HandleOldToNewRSet, this, threadId, std::placeholders::_1));
63 }
64
ProcessMarkStack(uint32_t threadId)65 void NonMovableMarker::ProcessMarkStack(uint32_t threadId)
66 {
67 TRACE_GC(GCStats::Scope::ScopeId::ProcessMarkStack, heap_->GetEcmaVM()->GetEcmaGCStats());
68 bool isFullMark = heap_->IsFullMark();
69 auto visitor = [this, threadId, isFullMark](TaggedObject *root, ObjectSlot start, ObjectSlot end,
70 VisitObjectArea area) {
71 Region *rootRegion = Region::ObjectAddressToRange(root);
72 bool needBarrier = isFullMark && !rootRegion->InYoungSpaceOrCSet();
73 if (area == VisitObjectArea::IN_OBJECT) {
74 if (VisitBodyInObj(root, start, end,
75 [&](ObjectSlot slot) { MarkValue(threadId, slot, rootRegion, needBarrier); })) {
76 return;
77 }
78 }
79 for (ObjectSlot slot = start; slot < end; slot++) {
80 MarkValue(threadId, slot, rootRegion, needBarrier);
81 }
82 };
83 TaggedObject *obj = nullptr;
84 while (true) {
85 obj = nullptr;
86 if (!workManager_->Pop(threadId, &obj)) {
87 break;
88 }
89
90 JSHClass *jsHclass = obj->SynchronizedGetClass();
91 MarkObject(threadId, jsHclass);
92 objXRay_.VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, jsHclass, visitor);
93 }
94 }
95
ProcessIncrementalMarkStack(uint32_t threadId,uint32_t markStepSize)96 void NonMovableMarker::ProcessIncrementalMarkStack(uint32_t threadId, uint32_t markStepSize)
97 {
98 TRACE_GC(GCStats::Scope::ScopeId::ProcessMarkStack, heap_->GetEcmaVM()->GetEcmaGCStats());
99 bool isFullMark = heap_->IsFullMark();
100 uint32_t visitAddrNum = 0;
101 auto visitor = [this, threadId, isFullMark, &visitAddrNum](TaggedObject *root, ObjectSlot start, ObjectSlot end,
102 VisitObjectArea area) {
103 Region *rootRegion = Region::ObjectAddressToRange(root);
104 visitAddrNum += end.SlotAddress() - start.SlotAddress();
105 bool needBarrier = isFullMark && !rootRegion->InYoungSpaceOrCSet();
106 if (area == VisitObjectArea::IN_OBJECT) {
107 if (VisitBodyInObj(root, start, end,
108 [&](ObjectSlot slot) { MarkValue(threadId, slot, rootRegion, needBarrier); })) {
109 return;
110 }
111 }
112 for (ObjectSlot slot = start; slot < end; slot++) {
113 MarkValue(threadId, slot, rootRegion, needBarrier);
114 }
115 };
116 TaggedObject *obj = nullptr;
117 double startTime = heap_->GetIncrementalMarker()->GetCurrentTimeInMs();
118 double costTime = startTime;
119 while (true) {
120 obj = nullptr;
121 if (!workManager_->Pop(threadId, &obj)) {
122 if (heap_->GetJSThread()->IsMarking() && heap_->GetIncrementalMarker()->IsTriggeredIncrementalMark()) {
123 costTime = heap_->GetIncrementalMarker()->GetCurrentTimeInMs() - startTime;
124 heap_->GetIncrementalMarker()->UpdateMarkingSpeed(visitAddrNum, costTime);
125 heap_->GetIncrementalMarker()->SetMarkingFinished(true);
126 }
127 break;
128 }
129
130 JSHClass *jsHclass = obj->GetClass();
131 MarkObject(threadId, jsHclass);
132 objXRay_.VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, jsHclass, visitor);
133 if (heap_->GetIncrementalMarker()->IsTriggeredIncrementalMark() && visitAddrNum >= markStepSize) {
134 costTime = heap_->GetIncrementalMarker()->GetCurrentTimeInMs() - startTime;
135 heap_->GetIncrementalMarker()->UpdateMarkingSpeed(visitAddrNum, costTime);
136 break;
137 }
138 }
139 }
140
Initialize()141 void SemiGCMarker::Initialize()
142 {
143 waterLine_ = heap_->GetNewSpace()->GetWaterLine();
144 }
145
ProcessMarkStack(uint32_t threadId)146 void SemiGCMarker::ProcessMarkStack(uint32_t threadId)
147 {
148 TRACE_GC(GCStats::Scope::ScopeId::ProcessMarkStack, heap_->GetEcmaVM()->GetEcmaGCStats());
149 auto visitor = [this, threadId](TaggedObject *root, ObjectSlot start, ObjectSlot end,
150 VisitObjectArea area) {
151 if (area == VisitObjectArea::IN_OBJECT) {
152 if (VisitBodyInObj(root, start, end, [&](ObjectSlot slot) { MarkValue(threadId, root, slot); })) {
153 return;
154 }
155 }
156 for (ObjectSlot slot = start; slot < end; slot++) {
157 MarkValue(threadId, root, slot);
158 }
159 };
160 TaggedObject *obj = nullptr;
161 while (true) {
162 obj = nullptr;
163 if (!workManager_->Pop(threadId, &obj)) {
164 break;
165 }
166
167 auto jsHclass = obj->GetClass();
168 objXRay_.VisitObjectBody<VisitType::SEMI_GC_VISIT>(obj, jsHclass, visitor);
169 }
170 }
171
ProcessMarkStack(uint32_t threadId)172 void CompressGCMarker::ProcessMarkStack(uint32_t threadId)
173 {
174 TRACE_GC(GCStats::Scope::ScopeId::ProcessMarkStack, heap_->GetEcmaVM()->GetEcmaGCStats());
175 auto visitor = [this, threadId](TaggedObject *root, ObjectSlot start, ObjectSlot end,
176 VisitObjectArea area) {
177 if (area == VisitObjectArea::IN_OBJECT) {
178 if (VisitBodyInObj(root, start, end, [&](ObjectSlot slot) { MarkValue(threadId, slot); })) {
179 return;
180 }
181 }
182 for (ObjectSlot slot = start; slot < end; slot++) {
183 MarkValue(threadId, slot);
184 }
185 };
186 TaggedObject *obj = nullptr;
187 while (true) {
188 obj = nullptr;
189 if (!workManager_->Pop(threadId, &obj)) {
190 break;
191 }
192
193 auto jsHClass = obj->GetClass();
194 ObjectSlot objectSlot(ToUintPtr(obj));
195 MarkObject(threadId, jsHClass, objectSlot);
196 objXRay_.VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, jsHClass, visitor);
197 }
198 }
199
AllocateForwardAddress(uint32_t threadId,size_t size,JSHClass * hclass,TaggedObject * object)200 uintptr_t CompressGCMarker::AllocateForwardAddress(uint32_t threadId, size_t size, JSHClass *hclass,
201 TaggedObject *object)
202 {
203 if (!isAppSpawn_) {
204 bool isPromoted = true;
205 return AllocateDstSpace(threadId, size, isPromoted);
206 }
207 if (Heap::ShouldMoveToRoSpace(hclass, object)) {
208 return AllocateReadOnlySpace(size);
209 } else {
210 return AllocateAppSpawnSpace(size);
211 }
212 }
213 } // namespace panda::ecmascript
214