14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_MEM_PARALLEL_EVACUATOR_INL_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_MEM_PARALLEL_EVACUATOR_INL_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/mem/parallel_evacuator.h" 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_ci#include "ecmascript/mem/heap.h" 224514f5e3Sopenharmony_ci#include "ecmascript/mem/mark_word.h" 234514f5e3Sopenharmony_ci#include "ecmascript/mem/region-inl.h" 244514f5e3Sopenharmony_ci#include "ecmascript/taskpool/taskpool.h" 254514f5e3Sopenharmony_ci 264514f5e3Sopenharmony_cinamespace panda::ecmascript { 274514f5e3Sopenharmony_ci// Move regions with a survival rate of more than 75% to new space 284514f5e3Sopenharmony_ci// Move regions when young space overshoot size is larger than max capacity. 294514f5e3Sopenharmony_cibool ParallelEvacuator::IsWholeRegionEvacuate(Region *region) 304514f5e3Sopenharmony_ci{ 314514f5e3Sopenharmony_ci if ((static_cast<double>(region->AliveObject()) / region->GetSize()) > MIN_OBJECT_SURVIVAL_RATE && 324514f5e3Sopenharmony_ci !region->HasAgeMark()) { 334514f5e3Sopenharmony_ci return true; 344514f5e3Sopenharmony_ci } 354514f5e3Sopenharmony_ci if (heap_->GetFromSpaceDuringEvacuation()->CommittedSizeIsLarge() && !region->HasAgeMark()) { 364514f5e3Sopenharmony_ci return true; 374514f5e3Sopenharmony_ci } 384514f5e3Sopenharmony_ci return false; 394514f5e3Sopenharmony_ci} 404514f5e3Sopenharmony_ci 414514f5e3Sopenharmony_cibool ParallelEvacuator::WholeRegionEvacuate(Region *region) 424514f5e3Sopenharmony_ci{ 434514f5e3Sopenharmony_ci if (region->IsFreshRegion()) { 444514f5e3Sopenharmony_ci ASSERT(region->InYoungSpace()); 454514f5e3Sopenharmony_ci return heap_->MoveYoungRegionSync(region); 464514f5e3Sopenharmony_ci } 474514f5e3Sopenharmony_ci bool isInYoung = region->InYoungSpace(); 484514f5e3Sopenharmony_ci bool isBelowAgeMark = region->BelowAgeMark(); 494514f5e3Sopenharmony_ci if (isInYoung && !isBelowAgeMark && IsWholeRegionEvacuate(region) && heap_->MoveYoungRegionSync(region)) { 504514f5e3Sopenharmony_ci return true; 514514f5e3Sopenharmony_ci } 524514f5e3Sopenharmony_ci return false; 534514f5e3Sopenharmony_ci} 544514f5e3Sopenharmony_ci 554514f5e3Sopenharmony_citemplate <typename Callback> 564514f5e3Sopenharmony_cibool ParallelEvacuator::VisitBodyInObj( 574514f5e3Sopenharmony_ci TaggedObject *root, ObjectSlot start, ObjectSlot end, Callback callback) 584514f5e3Sopenharmony_ci{ 594514f5e3Sopenharmony_ci auto hclass = root->GetClass(); 604514f5e3Sopenharmony_ci ASSERT(!hclass->IsAllTaggedProp()); 614514f5e3Sopenharmony_ci int index = 0; 624514f5e3Sopenharmony_ci TaggedObject *dst = hclass->GetLayout().GetTaggedObject(); 634514f5e3Sopenharmony_ci auto layout = LayoutInfo::UncheckCast(dst); 644514f5e3Sopenharmony_ci ObjectSlot realEnd = start; 654514f5e3Sopenharmony_ci realEnd += layout->GetPropertiesCapacity(); 664514f5e3Sopenharmony_ci end = end > realEnd ? realEnd : end; 674514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 684514f5e3Sopenharmony_ci auto attr = layout->GetAttr(index++); 694514f5e3Sopenharmony_ci if (attr.IsTaggedRep()) { 704514f5e3Sopenharmony_ci callback(slot); 714514f5e3Sopenharmony_ci } 724514f5e3Sopenharmony_ci } 734514f5e3Sopenharmony_ci return true; 744514f5e3Sopenharmony_ci} 754514f5e3Sopenharmony_ci 764514f5e3Sopenharmony_cibool ParallelEvacuator::UpdateNewToEdenObjectSlot(ObjectSlot &slot) 774514f5e3Sopenharmony_ci{ 784514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 794514f5e3Sopenharmony_ci if (!value.IsHeapObject()) { 804514f5e3Sopenharmony_ci return false; 814514f5e3Sopenharmony_ci } 824514f5e3Sopenharmony_ci TaggedObject *object = value.GetHeapObject(); 834514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(object); 844514f5e3Sopenharmony_ci 854514f5e3Sopenharmony_ci // It is only update edenSpace object when iterate NewToEdenRSet 864514f5e3Sopenharmony_ci if (!valueRegion->InEdenSpace()) { 874514f5e3Sopenharmony_ci return false; 884514f5e3Sopenharmony_ci } 894514f5e3Sopenharmony_ci MarkWord markWord(object); 904514f5e3Sopenharmony_ci if (markWord.IsForwardingAddress()) { 914514f5e3Sopenharmony_ci TaggedObject *dst = markWord.ToForwardingAddress(); 924514f5e3Sopenharmony_ci if (value.IsWeakForHeapObject()) { 934514f5e3Sopenharmony_ci dst = JSTaggedValue(dst).CreateAndGetWeakRef().GetRawTaggedObject(); 944514f5e3Sopenharmony_ci } 954514f5e3Sopenharmony_ci slot.Update(dst); 964514f5e3Sopenharmony_ci } else { 974514f5e3Sopenharmony_ci if (value.IsWeakForHeapObject()) { 984514f5e3Sopenharmony_ci slot.Clear(); 994514f5e3Sopenharmony_ci } 1004514f5e3Sopenharmony_ci } 1014514f5e3Sopenharmony_ci return false; 1024514f5e3Sopenharmony_ci} 1034514f5e3Sopenharmony_ci 1044514f5e3Sopenharmony_cibool ParallelEvacuator::UpdateForwardedOldToNewObjectSlot(TaggedObject *object, ObjectSlot &slot, bool isWeak) 1054514f5e3Sopenharmony_ci{ 1064514f5e3Sopenharmony_ci MarkWord markWord(object); 1074514f5e3Sopenharmony_ci if (markWord.IsForwardingAddress()) { 1084514f5e3Sopenharmony_ci TaggedObject *dst = markWord.ToForwardingAddress(); 1094514f5e3Sopenharmony_ci if (isWeak) { 1104514f5e3Sopenharmony_ci dst = JSTaggedValue(dst).CreateAndGetWeakRef().GetRawTaggedObject(); 1114514f5e3Sopenharmony_ci } 1124514f5e3Sopenharmony_ci slot.Update(dst); 1134514f5e3Sopenharmony_ci Region *dstRegion = Region::ObjectAddressToRange(dst); 1144514f5e3Sopenharmony_ci // Keep oldToNewRSet when object is YoungSpace 1154514f5e3Sopenharmony_ci if (dstRegion->InYoungSpace()) { 1164514f5e3Sopenharmony_ci return true; 1174514f5e3Sopenharmony_ci } 1184514f5e3Sopenharmony_ci } else if (isWeak) { 1194514f5e3Sopenharmony_ci slot.Clear(); 1204514f5e3Sopenharmony_ci } 1214514f5e3Sopenharmony_ci return false; 1224514f5e3Sopenharmony_ci} 1234514f5e3Sopenharmony_ci 1244514f5e3Sopenharmony_citemplate<bool IsEdenGC> 1254514f5e3Sopenharmony_cibool ParallelEvacuator::UpdateOldToNewObjectSlot(ObjectSlot &slot) 1264514f5e3Sopenharmony_ci{ 1274514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 1284514f5e3Sopenharmony_ci if (!value.IsHeapObject()) { 1294514f5e3Sopenharmony_ci return false; 1304514f5e3Sopenharmony_ci } 1314514f5e3Sopenharmony_ci TaggedObject *object = value.GetHeapObject(); 1324514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(object); 1334514f5e3Sopenharmony_ci if constexpr (IsEdenGC) { 1344514f5e3Sopenharmony_ci // only object in EdenSpace will be collect in EdenGC 1354514f5e3Sopenharmony_ci if (valueRegion->InEdenSpace()) { 1364514f5e3Sopenharmony_ci return UpdateForwardedOldToNewObjectSlot(object, slot, value.IsWeakForHeapObject()); 1374514f5e3Sopenharmony_ci } else { 1384514f5e3Sopenharmony_ci // Keep oldToNewRSet when object is YoungSpace 1394514f5e3Sopenharmony_ci return valueRegion->InYoungSpace(); 1404514f5e3Sopenharmony_ci } 1414514f5e3Sopenharmony_ci } else { 1424514f5e3Sopenharmony_ci // It is only update old to new object when iterate OldToNewRSet 1434514f5e3Sopenharmony_ci if (valueRegion->InGeneralNewSpace()) { 1444514f5e3Sopenharmony_ci if (!valueRegion->InNewToNewSet()) { 1454514f5e3Sopenharmony_ci return UpdateForwardedOldToNewObjectSlot(object, slot, value.IsWeakForHeapObject()); 1464514f5e3Sopenharmony_ci } 1474514f5e3Sopenharmony_ci // move region from fromspace to tospace 1484514f5e3Sopenharmony_ci if (valueRegion->Test(object)) { 1494514f5e3Sopenharmony_ci return true; 1504514f5e3Sopenharmony_ci } 1514514f5e3Sopenharmony_ci if (value.IsWeakForHeapObject()) { 1524514f5e3Sopenharmony_ci slot.Clear(); 1534514f5e3Sopenharmony_ci } 1544514f5e3Sopenharmony_ci } 1554514f5e3Sopenharmony_ci } 1564514f5e3Sopenharmony_ci return false; 1574514f5e3Sopenharmony_ci} 1584514f5e3Sopenharmony_ci 1594514f5e3Sopenharmony_civoid ParallelEvacuator::UpdateObjectSlot(ObjectSlot &slot) 1604514f5e3Sopenharmony_ci{ 1614514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 1624514f5e3Sopenharmony_ci if (value.IsHeapObject()) { 1634514f5e3Sopenharmony_ci if (value.IsInSharedHeap()) { 1644514f5e3Sopenharmony_ci return; 1654514f5e3Sopenharmony_ci } 1664514f5e3Sopenharmony_ci if (value.IsWeakForHeapObject()) { 1674514f5e3Sopenharmony_ci return UpdateWeakObjectSlot(value.GetTaggedWeakRef(), slot); 1684514f5e3Sopenharmony_ci } 1694514f5e3Sopenharmony_ci TaggedObject *object = value.GetTaggedObject(); 1704514f5e3Sopenharmony_ci MarkWord markWord(object); 1714514f5e3Sopenharmony_ci if (markWord.IsForwardingAddress()) { 1724514f5e3Sopenharmony_ci TaggedObject *dst = markWord.ToForwardingAddress(); 1734514f5e3Sopenharmony_ci slot.Update(dst); 1744514f5e3Sopenharmony_ci } 1754514f5e3Sopenharmony_ci } 1764514f5e3Sopenharmony_ci} 1774514f5e3Sopenharmony_ci 1784514f5e3Sopenharmony_civoid ParallelEvacuator::UpdateWeakObjectSlot(TaggedObject *value, ObjectSlot &slot) 1794514f5e3Sopenharmony_ci{ 1804514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(value); 1814514f5e3Sopenharmony_ci if (objectRegion->InSharedHeap()) { 1824514f5e3Sopenharmony_ci return; 1834514f5e3Sopenharmony_ci } 1844514f5e3Sopenharmony_ci 1854514f5e3Sopenharmony_ci TaggedObject *dst = UpdateAddressAfterEvacation(value); 1864514f5e3Sopenharmony_ci if (dst == value) { 1874514f5e3Sopenharmony_ci return; 1884514f5e3Sopenharmony_ci } 1894514f5e3Sopenharmony_ci if (dst == nullptr) { 1904514f5e3Sopenharmony_ci slot.Clear(); 1914514f5e3Sopenharmony_ci return; 1924514f5e3Sopenharmony_ci } 1934514f5e3Sopenharmony_ci auto weakRef = JSTaggedValue(dst).CreateAndGetWeakRef().GetRawTaggedObject(); 1944514f5e3Sopenharmony_ci slot.Update(weakRef); 1954514f5e3Sopenharmony_ci} 1964514f5e3Sopenharmony_ci 1974514f5e3Sopenharmony_citemplate<TriggerGCType gcType> 1984514f5e3Sopenharmony_civoid ParallelEvacuator::UpdateObjectSlotOpt(ObjectSlot &slot) 1994514f5e3Sopenharmony_ci{ 2004514f5e3Sopenharmony_ci JSTaggedValue value(slot.GetTaggedType()); 2014514f5e3Sopenharmony_ci if (value.IsHeapObject()) { 2024514f5e3Sopenharmony_ci if (UpdateWeakObjectSlotOpt<gcType>(value, slot)) { 2034514f5e3Sopenharmony_ci return; 2044514f5e3Sopenharmony_ci } 2054514f5e3Sopenharmony_ci MarkWord markWord(value.GetTaggedObject()); 2064514f5e3Sopenharmony_ci if (markWord.IsForwardingAddress()) { 2074514f5e3Sopenharmony_ci auto dst = reinterpret_cast<JSTaggedType>(markWord.ToForwardingAddress()); 2084514f5e3Sopenharmony_ci slot.Update(dst); 2094514f5e3Sopenharmony_ci } 2104514f5e3Sopenharmony_ci } 2114514f5e3Sopenharmony_ci} 2124514f5e3Sopenharmony_ci 2134514f5e3Sopenharmony_citemplate<TriggerGCType gcType> 2144514f5e3Sopenharmony_cibool ParallelEvacuator::UpdateWeakObjectSlotOpt(JSTaggedValue value, ObjectSlot &slot) 2154514f5e3Sopenharmony_ci{ 2164514f5e3Sopenharmony_ci // if need to update slot as non-weak then return FALSE, else return TRUE 2174514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(value.GetRawData()); 2184514f5e3Sopenharmony_ci ASSERT(objectRegion != nullptr); 2194514f5e3Sopenharmony_ci if constexpr (gcType == TriggerGCType::YOUNG_GC) { 2204514f5e3Sopenharmony_ci if (!objectRegion->InGeneralNewSpace()) { 2214514f5e3Sopenharmony_ci return true; 2224514f5e3Sopenharmony_ci } 2234514f5e3Sopenharmony_ci } else if constexpr (gcType == TriggerGCType::OLD_GC) { 2244514f5e3Sopenharmony_ci if (!objectRegion->InGeneralNewSpaceOrCSet()) { 2254514f5e3Sopenharmony_ci if (value.IsWeakForHeapObject() && !objectRegion->InSharedHeap() && 2264514f5e3Sopenharmony_ci (objectRegion->GetMarkGCBitset() == nullptr || !objectRegion->Test(value.GetRawData()))) { 2274514f5e3Sopenharmony_ci slot.Clear(); 2284514f5e3Sopenharmony_ci } 2294514f5e3Sopenharmony_ci return true; 2304514f5e3Sopenharmony_ci } 2314514f5e3Sopenharmony_ci } else { 2324514f5e3Sopenharmony_ci LOG_GC(FATAL) << "UpdateWeakObjectSlotOpt: not support gcType yet"; 2334514f5e3Sopenharmony_ci UNREACHABLE(); 2344514f5e3Sopenharmony_ci } 2354514f5e3Sopenharmony_ci if (objectRegion->InNewToNewSet()) { 2364514f5e3Sopenharmony_ci if (value.IsWeakForHeapObject() && !objectRegion->Test(value.GetRawData())) { 2374514f5e3Sopenharmony_ci slot.Clear(); 2384514f5e3Sopenharmony_ci } 2394514f5e3Sopenharmony_ci return true; 2404514f5e3Sopenharmony_ci } 2414514f5e3Sopenharmony_ci if (value.IsWeakForHeapObject()) { 2424514f5e3Sopenharmony_ci MarkWord markWord(value.GetWeakReferent()); 2434514f5e3Sopenharmony_ci if (markWord.IsForwardingAddress()) { 2444514f5e3Sopenharmony_ci auto dst = static_cast<JSTaggedType>(ToUintPtr(markWord.ToForwardingAddress())); 2454514f5e3Sopenharmony_ci slot.Update(JSTaggedValue(dst).CreateAndGetWeakRef().GetRawData()); 2464514f5e3Sopenharmony_ci } else { 2474514f5e3Sopenharmony_ci slot.Clear(); 2484514f5e3Sopenharmony_ci } 2494514f5e3Sopenharmony_ci return true; 2504514f5e3Sopenharmony_ci } 2514514f5e3Sopenharmony_ci return false; 2524514f5e3Sopenharmony_ci} 2534514f5e3Sopenharmony_ci 2544514f5e3Sopenharmony_civoid ParallelEvacuator::UpdateLocalToShareRSet(TaggedObject *object, JSHClass *cls) 2554514f5e3Sopenharmony_ci{ 2564514f5e3Sopenharmony_ci Region *region = Region::ObjectAddressToRange(object); 2574514f5e3Sopenharmony_ci ASSERT(!region->InSharedHeap()); 2584514f5e3Sopenharmony_ci auto callbackWithCSet = [this, region](TaggedObject *root, ObjectSlot start, ObjectSlot end, VisitObjectArea area) { 2594514f5e3Sopenharmony_ci if (area == VisitObjectArea::IN_OBJECT) { 2604514f5e3Sopenharmony_ci if (VisitBodyInObj(root, start, end, [&](ObjectSlot slot) { SetLocalToShareRSet(slot, region); })) { 2614514f5e3Sopenharmony_ci return; 2624514f5e3Sopenharmony_ci }; 2634514f5e3Sopenharmony_ci } 2644514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 2654514f5e3Sopenharmony_ci SetLocalToShareRSet(slot, region); 2664514f5e3Sopenharmony_ci } 2674514f5e3Sopenharmony_ci }; 2684514f5e3Sopenharmony_ci ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>(object, cls, callbackWithCSet); 2694514f5e3Sopenharmony_ci} 2704514f5e3Sopenharmony_ci 2714514f5e3Sopenharmony_civoid ParallelEvacuator::SetLocalToShareRSet(ObjectSlot slot, Region *region) 2724514f5e3Sopenharmony_ci{ 2734514f5e3Sopenharmony_ci ASSERT(!region->InSharedHeap()); 2744514f5e3Sopenharmony_ci JSTaggedType value = slot.GetTaggedType(); 2754514f5e3Sopenharmony_ci if (!JSTaggedValue(value).IsHeapObject()) { 2764514f5e3Sopenharmony_ci return; 2774514f5e3Sopenharmony_ci } 2784514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value); 2794514f5e3Sopenharmony_ci if (valueRegion->InSharedSweepableSpace()) { 2804514f5e3Sopenharmony_ci region->AtomicInsertLocalToShareRSet(slot.SlotAddress()); 2814514f5e3Sopenharmony_ci } 2824514f5e3Sopenharmony_ci} 2834514f5e3Sopenharmony_ci 2844514f5e3Sopenharmony_citemplate<bool SetEdenObject> 2854514f5e3Sopenharmony_civoid ParallelEvacuator::SetObjectFieldRSet(TaggedObject *object, JSHClass *cls) 2864514f5e3Sopenharmony_ci{ 2874514f5e3Sopenharmony_ci Region *region = Region::ObjectAddressToRange(object); 2884514f5e3Sopenharmony_ci auto callbackWithCSet = [this, region](TaggedObject *root, ObjectSlot start, ObjectSlot end, VisitObjectArea area) { 2894514f5e3Sopenharmony_ci if (area == VisitObjectArea::IN_OBJECT) { 2904514f5e3Sopenharmony_ci if (VisitBodyInObj(root, start, end, 2914514f5e3Sopenharmony_ci [&](ObjectSlot slot) { SetObjectRSet<SetEdenObject>(slot, region); })) { 2924514f5e3Sopenharmony_ci return; 2934514f5e3Sopenharmony_ci }; 2944514f5e3Sopenharmony_ci } 2954514f5e3Sopenharmony_ci for (ObjectSlot slot = start; slot < end; slot++) { 2964514f5e3Sopenharmony_ci SetObjectRSet<SetEdenObject>(slot, region); 2974514f5e3Sopenharmony_ci } 2984514f5e3Sopenharmony_ci }; 2994514f5e3Sopenharmony_ci ObjectXRay::VisitObjectBody<VisitType::OLD_GC_VISIT>(object, cls, callbackWithCSet); 3004514f5e3Sopenharmony_ci} 3014514f5e3Sopenharmony_ci 3024514f5e3Sopenharmony_citemplate<bool SetEdenObject> 3034514f5e3Sopenharmony_civoid ParallelEvacuator::SetObjectRSet(ObjectSlot slot, Region *region) 3044514f5e3Sopenharmony_ci{ 3054514f5e3Sopenharmony_ci JSTaggedType value = slot.GetTaggedType(); 3064514f5e3Sopenharmony_ci if (!JSTaggedValue(value).IsHeapObject()) { 3074514f5e3Sopenharmony_ci return; 3084514f5e3Sopenharmony_ci } 3094514f5e3Sopenharmony_ci Region *valueRegion = Region::ObjectAddressToRange(value); 3104514f5e3Sopenharmony_ci if constexpr (SetEdenObject) { 3114514f5e3Sopenharmony_ci if (region->InYoungSpace() && valueRegion->InEdenSpace()) { 3124514f5e3Sopenharmony_ci region->AtomicInsertNewToEdenRSet(slot.SlotAddress()); 3134514f5e3Sopenharmony_ci } else if (valueRegion->InSharedSweepableSpace()) { 3144514f5e3Sopenharmony_ci region->AtomicInsertLocalToShareRSet(slot.SlotAddress()); 3154514f5e3Sopenharmony_ci } 3164514f5e3Sopenharmony_ci } else { 3174514f5e3Sopenharmony_ci if (valueRegion->InGeneralNewSpace()) { 3184514f5e3Sopenharmony_ci region->InsertOldToNewRSet(slot.SlotAddress()); 3194514f5e3Sopenharmony_ci } else if (valueRegion->InSharedSweepableSpace()) { 3204514f5e3Sopenharmony_ci region->InsertLocalToShareRSet(slot.SlotAddress()); 3214514f5e3Sopenharmony_ci } else if (valueRegion->InCollectSet()) { 3224514f5e3Sopenharmony_ci region->InsertCrossRegionRSet(slot.SlotAddress()); 3234514f5e3Sopenharmony_ci } else if (JSTaggedValue(value).IsWeakForHeapObject()) { 3244514f5e3Sopenharmony_ci if (heap_->IsConcurrentFullMark() && !valueRegion->InSharedHeap() && 3254514f5e3Sopenharmony_ci (valueRegion->GetMarkGCBitset() == nullptr || !valueRegion->Test(value))) { 3264514f5e3Sopenharmony_ci slot.Clear(); 3274514f5e3Sopenharmony_ci } 3284514f5e3Sopenharmony_ci } 3294514f5e3Sopenharmony_ci } 3304514f5e3Sopenharmony_ci} 3314514f5e3Sopenharmony_ci 3324514f5e3Sopenharmony_cibool ParallelEvacuator::AcquireItem::TryAcquire() 3334514f5e3Sopenharmony_ci{ 3344514f5e3Sopenharmony_ci return acquire_.exchange(true, std::memory_order_relaxed) == false; 3354514f5e3Sopenharmony_ci} 3364514f5e3Sopenharmony_ci 3374514f5e3Sopenharmony_civoid ParallelEvacuator::WorkloadSet::Add(std::unique_ptr<Workload> workload) 3384514f5e3Sopenharmony_ci{ 3394514f5e3Sopenharmony_ci workloads_.emplace_back(AcquireItem{}, std::move(workload)); 3404514f5e3Sopenharmony_ci} 3414514f5e3Sopenharmony_ci 3424514f5e3Sopenharmony_cibool ParallelEvacuator::WorkloadSet::HasRemaningWorkload() const 3434514f5e3Sopenharmony_ci{ 3444514f5e3Sopenharmony_ci return remainingWorkloadNum_.load(std::memory_order_relaxed) > 0; 3454514f5e3Sopenharmony_ci} 3464514f5e3Sopenharmony_ci 3474514f5e3Sopenharmony_cibool ParallelEvacuator::WorkloadSet::FetchSubAndCheckWorkloadCount(size_t finishedCount) 3484514f5e3Sopenharmony_ci{ 3494514f5e3Sopenharmony_ci return remainingWorkloadNum_.fetch_sub(finishedCount, std::memory_order_relaxed) == finishedCount; 3504514f5e3Sopenharmony_ci} 3514514f5e3Sopenharmony_ci 3524514f5e3Sopenharmony_ciTaggedObject* ParallelEvacuator::UpdateAddressAfterEvacation(TaggedObject *oldAddress) 3534514f5e3Sopenharmony_ci{ 3544514f5e3Sopenharmony_ci Region *objectRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(oldAddress)); 3554514f5e3Sopenharmony_ci if (!objectRegion) { 3564514f5e3Sopenharmony_ci return nullptr; 3574514f5e3Sopenharmony_ci } 3584514f5e3Sopenharmony_ci if (heap_->IsEdenMark()) { 3594514f5e3Sopenharmony_ci if (!objectRegion->InEdenSpace()) { 3604514f5e3Sopenharmony_ci return oldAddress; 3614514f5e3Sopenharmony_ci } 3624514f5e3Sopenharmony_ci MarkWord markWord(oldAddress); 3634514f5e3Sopenharmony_ci if (markWord.IsForwardingAddress()) { 3644514f5e3Sopenharmony_ci return markWord.ToForwardingAddress(); 3654514f5e3Sopenharmony_ci } 3664514f5e3Sopenharmony_ci return nullptr; 3674514f5e3Sopenharmony_ci } 3684514f5e3Sopenharmony_ci if (objectRegion->InGeneralNewSpaceOrCSet()) { 3694514f5e3Sopenharmony_ci if (objectRegion->InNewToNewSet()) { 3704514f5e3Sopenharmony_ci if (objectRegion->Test(oldAddress)) { 3714514f5e3Sopenharmony_ci return oldAddress; 3724514f5e3Sopenharmony_ci } 3734514f5e3Sopenharmony_ci } else { 3744514f5e3Sopenharmony_ci MarkWord markWord(oldAddress); 3754514f5e3Sopenharmony_ci if (markWord.IsForwardingAddress()) { 3764514f5e3Sopenharmony_ci return markWord.ToForwardingAddress(); 3774514f5e3Sopenharmony_ci } 3784514f5e3Sopenharmony_ci } 3794514f5e3Sopenharmony_ci return nullptr; 3804514f5e3Sopenharmony_ci } 3814514f5e3Sopenharmony_ci if (heap_->IsConcurrentFullMark()) { 3824514f5e3Sopenharmony_ci if (objectRegion->GetMarkGCBitset() == nullptr || !objectRegion->Test(oldAddress)) { 3834514f5e3Sopenharmony_ci return nullptr; 3844514f5e3Sopenharmony_ci } 3854514f5e3Sopenharmony_ci } 3864514f5e3Sopenharmony_ci return oldAddress; 3874514f5e3Sopenharmony_ci} 3884514f5e3Sopenharmony_ci 3894514f5e3Sopenharmony_ciint ParallelEvacuator::CalculateEvacuationThreadNum() 3904514f5e3Sopenharmony_ci{ 3914514f5e3Sopenharmony_ci uint32_t count = evacuateWorkloadSet_.GetWorkloadCount(); 3924514f5e3Sopenharmony_ci uint32_t regionPerThread = 8; 3934514f5e3Sopenharmony_ci uint32_t maxThreadNum = std::min(heap_->GetMaxEvacuateTaskCount(), 3944514f5e3Sopenharmony_ci Taskpool::GetCurrentTaskpool()->GetTotalThreadNum()); 3954514f5e3Sopenharmony_ci return static_cast<int>(std::min(std::max(1U, count / regionPerThread), maxThreadNum)); 3964514f5e3Sopenharmony_ci} 3974514f5e3Sopenharmony_ci 3984514f5e3Sopenharmony_ciint ParallelEvacuator::CalculateUpdateThreadNum() 3994514f5e3Sopenharmony_ci{ 4004514f5e3Sopenharmony_ci uint32_t count = updateWorkloadSet_.GetWorkloadCount(); 4014514f5e3Sopenharmony_ci double regionPerThread = 1.0 / 4; 4024514f5e3Sopenharmony_ci count = std::pow(count, regionPerThread); 4034514f5e3Sopenharmony_ci uint32_t maxThreadNum = std::min(heap_->GetMaxEvacuateTaskCount(), 4044514f5e3Sopenharmony_ci Taskpool::GetCurrentTaskpool()->GetTotalThreadNum()); 4054514f5e3Sopenharmony_ci return static_cast<int>(std::min(std::max(1U, count), maxThreadNum)); 4064514f5e3Sopenharmony_ci} 4074514f5e3Sopenharmony_ci 4084514f5e3Sopenharmony_cisize_t ParallelEvacuator::WorkloadSet::GetWorkloadCount() const 4094514f5e3Sopenharmony_ci{ 4104514f5e3Sopenharmony_ci return workloads_.size(); 4114514f5e3Sopenharmony_ci} 4124514f5e3Sopenharmony_ci 4134514f5e3Sopenharmony_ci} // namespace panda::ecmascript 4144514f5e3Sopenharmony_ci#endif // ECMASCRIPT_MEM_PARALLEL_EVACUATOR_INL_H 415