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