• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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