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 #ifndef ECMASCRIPT_MEM_PARALLEL_EVACUATOR_INL_H
17 #define ECMASCRIPT_MEM_PARALLEL_EVACUATOR_INL_H
18
19 #include "ecmascript/mem/parallel_evacuator.h"
20
21 #include "ecmascript/mem/heap.h"
22 #include "ecmascript/mem/mark_word.h"
23 #include "ecmascript/mem/region-inl.h"
24 #include "ecmascript/taskpool/taskpool.h"
25
26 namespace panda::ecmascript {
27 // Move regions with a survival rate of more than 75% to new space
IsWholeRegionEvacuate(Region * region)28 bool ParallelEvacuator::IsWholeRegionEvacuate(Region *region)
29 {
30 return (static_cast<double>(region->AliveObject()) / region->GetSize()) > MIN_OBJECT_SURVIVAL_RATE &&
31 !region->HasAgeMark();
32 }
33
UpdateOldToNewObjectSlot(ObjectSlot & slot)34 bool ParallelEvacuator::UpdateOldToNewObjectSlot(ObjectSlot &slot)
35 {
36 JSTaggedValue value(slot.GetTaggedType());
37 if (value.IsHeapObject()) {
38 TaggedObject *object = value.GetHeapObject();
39 Region *valueRegion = Region::ObjectAddressToRange(object);
40
41 // It is only update old to new object when iterate OldToNewRSet
42 if (valueRegion->InYoungSpace()) {
43 if (!valueRegion->InNewToNewSet()) {
44 MarkWord markWord(object);
45 if (markWord.IsForwardingAddress()) {
46 TaggedObject *dst = markWord.ToForwardingAddress();
47 if (value.IsWeakForHeapObject()) {
48 dst = JSTaggedValue(dst).CreateAndGetWeakRef().GetRawTaggedObject();
49 }
50 slot.Update(dst);
51 Region *dstRegion = Region::ObjectAddressToRange(dst);
52 // Keep oldtonewrset when object move fromspace to tospace
53 if (dstRegion->InYoungSpace()) {
54 return true;
55 }
56 } else {
57 if (value.IsWeakForHeapObject()) {
58 slot.Clear();
59 }
60 }
61 } else {
62 // move region from fromspace to tospace
63 if (valueRegion->Test(object)) {
64 return true;
65 } else {
66 if (value.IsWeakForHeapObject()) {
67 slot.Clear();
68 }
69 }
70 }
71 }
72 }
73 return false;
74 }
75
UpdateObjectSlot(ObjectSlot & slot)76 void ParallelEvacuator::UpdateObjectSlot(ObjectSlot &slot)
77 {
78 JSTaggedValue value(slot.GetTaggedType());
79 if (value.IsHeapObject()) {
80 if (value.IsWeakForHeapObject()) {
81 return UpdateWeakObjectSlot(value.GetTaggedWeakRef(), slot);
82 }
83 TaggedObject *object = value.GetTaggedObject();
84 MarkWord markWord(object);
85 if (markWord.IsForwardingAddress()) {
86 TaggedObject *dst = markWord.ToForwardingAddress();
87 slot.Update(dst);
88 }
89 }
90 }
91
UpdateWeakObjectSlot(TaggedObject * value,ObjectSlot & slot)92 void ParallelEvacuator::UpdateWeakObjectSlot(TaggedObject *value, ObjectSlot &slot)
93 {
94 Region *objectRegion = Region::ObjectAddressToRange(value);
95 if (objectRegion->InYoungSpaceOrCSet()) {
96 if (objectRegion->InNewToNewSet()) {
97 if (!objectRegion->Test(value)) {
98 slot.Clear();
99 }
100 } else {
101 MarkWord markWord(value);
102 if (markWord.IsForwardingAddress()) {
103 TaggedObject *dst = markWord.ToForwardingAddress();
104 auto weakRef = JSTaggedValue(dst).CreateAndGetWeakRef().GetRawTaggedObject();
105 slot.Update(weakRef);
106 return;
107 }
108 slot.Clear();
109 }
110 return;
111 }
112
113 if (heap_->IsFullMark()) {
114 if (!objectRegion->Test(value)) {
115 slot.Clear();
116 }
117 }
118 }
119
SetObjectFieldRSet(TaggedObject * object,JSHClass * cls)120 void ParallelEvacuator::SetObjectFieldRSet(TaggedObject *object, JSHClass *cls)
121 {
122 Region *region = Region::ObjectAddressToRange(object);
123 auto callbackWithCSet = [region]([[maybe_unused]] TaggedObject *root, ObjectSlot start, ObjectSlot end,
124 [[maybe_unused]] bool isNative) {
125 for (ObjectSlot slot = start; slot < end; slot++) {
126 JSTaggedType value = slot.GetTaggedType();
127 if (!JSTaggedValue(value).IsHeapObject()) {
128 continue;
129 }
130 Region *valueRegion = Region::ObjectAddressToRange(value);
131 if (valueRegion->InYoungSpace()) {
132 region->InsertOldToNewRSet(slot.SlotAddress());
133 } else if (valueRegion->InCollectSet() || JSTaggedValue(value).IsWeakForHeapObject()) {
134 region->InsertCrossRegionRSet(slot.SlotAddress());
135 }
136 }
137 };
138 objXRay_.VisitObjectBody<VisitType::OLD_GC_VISIT>(object, cls, callbackWithCSet);
139 }
140
141
GetWorkloadSafe()142 std::unique_ptr<ParallelEvacuator::Workload> ParallelEvacuator::GetWorkloadSafe()
143 {
144 os::memory::LockHolder holder(mutex_);
145 std::unique_ptr<Workload> unit;
146 if (!workloads_.empty()) {
147 unit = std::move(workloads_.back());
148 workloads_.pop_back();
149 }
150 return unit;
151 }
152
AddWorkload(std::unique_ptr<Workload> region)153 void ParallelEvacuator::AddWorkload(std::unique_ptr<Workload> region)
154 {
155 workloads_.emplace_back(std::move(region));
156 }
157
CalculateEvacuationThreadNum()158 int ParallelEvacuator::CalculateEvacuationThreadNum()
159 {
160 uint32_t length = workloads_.size();
161 uint32_t regionPerThread = 8;
162 uint32_t maxThreadNum = std::min(heap_->GetMaxEvacuateTaskCount(),
163 Taskpool::GetCurrentTaskpool()->GetTotalThreadNum());
164 return static_cast<int>(std::min(std::max(1U, length / regionPerThread), maxThreadNum));
165 }
166
CalculateUpdateThreadNum()167 int ParallelEvacuator::CalculateUpdateThreadNum()
168 {
169 uint32_t length = workloads_.size();
170 double regionPerThread = 1.0 / 4;
171 length = std::pow(length, regionPerThread);
172 uint32_t maxThreadNum = std::min(heap_->GetMaxEvacuateTaskCount(),
173 Taskpool::GetCurrentTaskpool()->GetTotalThreadNum());
174 return static_cast<int>(std::min(std::max(1U, length), maxThreadNum));
175 }
176 } // namespace panda::ecmascript
177 #endif // ECMASCRIPT_MEM_PARALLEL_EVACUATOR_INL_H
178