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