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