• 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/parallel_marker-inl.h"
17 #include "ecmascript/mem/visitor.h"
18 
19 namespace panda::ecmascript {
Marker(Heap * heap)20 Marker::Marker(Heap *heap) : heap_(heap), objXRay_(heap->GetEcmaVM()), workManager_(heap->GetWorkManager()) {}
21 
MarkRoots(uint32_t threadId)22 void Marker::MarkRoots(uint32_t threadId)
23 {
24     objXRay_.VisitVMRoots(
25         std::bind(&Marker::HandleRoots, this, threadId, std::placeholders::_1, std::placeholders::_2),
26         std::bind(&Marker::HandleRangeRoots, this, threadId, std::placeholders::_1, std::placeholders::_2,
27                   std::placeholders::_3),
28         std::bind(&Marker::HandleDerivedRoots, this, std::placeholders::_1, std::placeholders::_2,
29                   std::placeholders::_3, std::placeholders::_4));
30     workManager_->PushWorkNodeToGlobal(threadId, false);
31 }
32 
ProcessOldToNew(uint32_t threadId)33 void Marker::ProcessOldToNew(uint32_t threadId)
34 {
35     heap_->EnumerateOldSpaceRegions(std::bind(&Marker::HandleOldToNewRSet, this, threadId, std::placeholders::_1));
36     ProcessMarkStack(threadId);
37 }
38 
ProcessOldToNew(uint32_t threadId,Region * region)39 void Marker::ProcessOldToNew(uint32_t threadId, Region *region)
40 {
41     heap_->EnumerateOldSpaceRegions(std::bind(&Marker::HandleOldToNewRSet, this, threadId, std::placeholders::_1),
42                                     region);
43     ProcessMarkStack(threadId);
44 }
45 
ProcessSnapshotRSet(uint32_t threadId)46 void Marker::ProcessSnapshotRSet(uint32_t threadId)
47 {
48     heap_->EnumerateSnapshotSpaceRegions(std::bind(&Marker::HandleOldToNewRSet, this, threadId, std::placeholders::_1));
49     ProcessMarkStack(threadId);
50 }
51 
ProcessMarkStack(uint32_t threadId)52 void NonMovableMarker::ProcessMarkStack(uint32_t threadId)
53 {
54     bool isFullMark = heap_->IsFullMark();
55     auto visitor = [this, threadId, isFullMark](TaggedObject *root, ObjectSlot start, ObjectSlot end,
56                                                 [[maybe_unused]] bool isNative) {
57         Region *rootRegion = Region::ObjectAddressToRange(root);
58         bool needBarrier = isFullMark && !rootRegion->InYoungSpaceOrCSet();
59         for (ObjectSlot slot = start; slot < end; slot++) {
60             JSTaggedValue value(slot.GetTaggedType());
61             if (value.IsHeapObject()) {
62                 TaggedObject *obj = nullptr;
63                 if (!value.IsWeakForHeapObject()) {
64                     obj = value.GetTaggedObject();
65                     MarkObject(threadId, obj);
66                 } else {
67                     RecordWeakReference(threadId, reinterpret_cast<JSTaggedType *>(slot.SlotAddress()), rootRegion);
68                     obj = value.GetWeakReferentUnChecked();
69                 }
70                 if (needBarrier) {
71                     Region *valueRegion = Region::ObjectAddressToRange(obj);
72                     if (valueRegion->InCollectSet()) {
73                         rootRegion->AtomicInsertCrossRegionRSet(slot.SlotAddress());
74                     }
75                 }
76             }
77         }
78     };
79     TaggedObject *obj = nullptr;
80     while (true) {
81         obj = nullptr;
82         if (!workManager_->Pop(threadId, &obj)) {
83             break;
84         }
85 
86         JSHClass *jsHclass = obj->GetClass();
87         MarkObject(threadId, jsHclass);
88         objXRay_.VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, jsHclass, visitor);
89     }
90 }
91 
Initialize()92 void SemiGCMarker::Initialize()
93 {
94     waterLine_ = heap_->GetNewSpace()->GetWaterLine();
95 }
96 
ProcessMarkStack(uint32_t threadId)97 void SemiGCMarker::ProcessMarkStack(uint32_t threadId)
98 {
99     auto visitor = [this, threadId](TaggedObject *root, ObjectSlot start, ObjectSlot end,
100                                     [[maybe_unused]] bool isNative) {
101         for (ObjectSlot slot = start; slot < end; slot++) {
102             JSTaggedValue value(slot.GetTaggedType());
103             if (value.IsHeapObject()) {
104                 Region *rootRegion = Region::ObjectAddressToRange(root);
105                 if (value.IsWeakForHeapObject()) {
106                     RecordWeakReference(threadId, reinterpret_cast<JSTaggedType *>(slot.SlotAddress()), rootRegion);
107                     continue;
108                 }
109                 auto slotStatus = MarkObject(threadId, value.GetTaggedObject(), slot);
110                 if (!rootRegion->InYoungSpace() && slotStatus == SlotStatus::KEEP_SLOT) {
111                     SlotNeedUpdate waitUpdate(reinterpret_cast<TaggedObject *>(root), slot);
112                     workManager_->PushSlotNeedUpdate(threadId, waitUpdate);
113                 }
114             }
115         }
116     };
117     TaggedObject *obj = nullptr;
118     while (true) {
119         obj = nullptr;
120         if (!workManager_->Pop(threadId, &obj)) {
121             break;
122         }
123 
124         auto jsHclass = obj->GetClass();
125         objXRay_.VisitObjectBody<VisitType::SEMI_GC_VISIT>(obj, jsHclass, visitor);
126     }
127 }
128 
ProcessMarkStack(uint32_t threadId)129 void CompressGCMarker::ProcessMarkStack(uint32_t threadId)
130 {
131     auto visitor = [this, threadId]([[maybe_unused]] TaggedObject *root, ObjectSlot start, ObjectSlot end,
132                                     [[maybe_unused]] bool isNative) {
133         for (ObjectSlot slot = start; slot < end; slot++) {
134             JSTaggedValue value(slot.GetTaggedType());
135             if (value.IsHeapObject()) {
136                 if (value.IsWeakForHeapObject()) {
137                     // It is unnecessary to use region pointer in compressGCMarker.
138                     RecordWeakReference(threadId, reinterpret_cast<JSTaggedType *>(slot.SlotAddress()));
139                     continue;
140                 }
141                 MarkObject(threadId, value.GetTaggedObject(), slot);
142             }
143         }
144     };
145     TaggedObject *obj = nullptr;
146     while (true) {
147         obj = nullptr;
148         if (!workManager_->Pop(threadId, &obj)) {
149             break;
150         }
151 
152         auto jsHClass = obj->GetClass();
153         ObjectSlot objectSlot(ToUintPtr(obj));
154         MarkObject(threadId, jsHClass, objectSlot);
155         objXRay_.VisitObjectBody<VisitType::OLD_GC_VISIT>(obj, jsHClass, visitor);
156     }
157 }
158 
AllocateForwardAddress(uint32_t threadId,size_t size,JSHClass * hclass,TaggedObject * object)159 uintptr_t CompressGCMarker::AllocateForwardAddress(uint32_t threadId, size_t size, JSHClass *hclass,
160                                                    TaggedObject *object)
161 {
162     if (!isAppSpawn_) {
163         bool isPromoted = true;
164         return AllocateDstSpace(threadId, size, isPromoted);
165     }
166     if (Heap::ShouldMoveToRoSpace(hclass, object)) {
167         return AllocateReadOnlySpace(size);
168     } else {
169         return AllocateAppSpawnSpace(size);
170     }
171 }
172 }  // namespace panda::ecmascript
173