• 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     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