14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2024 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_SHARED_SHARED_SPACE_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_MEM_SHARED_SHARED_SPACE_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/mem/mem_common.h"
204514f5e3Sopenharmony_ci#include "ecmascript/mem/sparse_space.h"
214514f5e3Sopenharmony_ci
224514f5e3Sopenharmony_cinamespace panda::ecmascript {
234514f5e3Sopenharmony_ci#define CHECK_SOBJECT_NOT_NULL()                                                        \
244514f5e3Sopenharmony_ci    if (object != 0) {                                                                  \
254514f5e3Sopenharmony_ci        return object;                                                                  \
264514f5e3Sopenharmony_ci    }
274514f5e3Sopenharmony_ci
284514f5e3Sopenharmony_ciclass SharedHeap;
294514f5e3Sopenharmony_ciclass SharedLocalSpace;
304514f5e3Sopenharmony_ci
314514f5e3Sopenharmony_ciclass SharedSparseSpace : public Space {
324514f5e3Sopenharmony_cipublic:
334514f5e3Sopenharmony_ci    SharedSparseSpace(SharedHeap *heap, MemSpaceType type, size_t initialCapacity, size_t maximumCapacity);
344514f5e3Sopenharmony_ci    ~SharedSparseSpace() override
354514f5e3Sopenharmony_ci    {
364514f5e3Sopenharmony_ci        delete allocator_;
374514f5e3Sopenharmony_ci    }
384514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(SharedSparseSpace);
394514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(SharedSparseSpace);
404514f5e3Sopenharmony_ci
414514f5e3Sopenharmony_ci    void Reset();
424514f5e3Sopenharmony_ci
434514f5e3Sopenharmony_ci    uintptr_t AllocateWithoutGC(JSThread *thread, size_t size);
444514f5e3Sopenharmony_ci
454514f5e3Sopenharmony_ci    uintptr_t Allocate(JSThread *thread, size_t size, bool allowGC = true);
464514f5e3Sopenharmony_ci    uintptr_t TryAllocateAndExpand(JSThread *thread, size_t size, bool expand);
474514f5e3Sopenharmony_ci
484514f5e3Sopenharmony_ci    // For work deserialize
494514f5e3Sopenharmony_ci    void ResetTopPointer(uintptr_t top);
504514f5e3Sopenharmony_ci    uintptr_t AllocateNoGCAndExpand(JSThread *thread, size_t size);
514514f5e3Sopenharmony_ci    Region *AllocateDeserializeRegion(JSThread *thread);
524514f5e3Sopenharmony_ci    void MergeDeserializeAllocateRegions(const std::vector<Region *> &allocateRegions);
534514f5e3Sopenharmony_ci
544514f5e3Sopenharmony_ci    // For sweeping
554514f5e3Sopenharmony_ci    void PrepareSweeping();
564514f5e3Sopenharmony_ci    void AsyncSweep(bool isMain);
574514f5e3Sopenharmony_ci    void Sweep();
584514f5e3Sopenharmony_ci
594514f5e3Sopenharmony_ci    bool TryFillSweptRegion();
604514f5e3Sopenharmony_ci    // Ensure All region finished sweeping
614514f5e3Sopenharmony_ci    bool FinishFillSweptRegion();
624514f5e3Sopenharmony_ci
634514f5e3Sopenharmony_ci    void AddSweepingRegion(Region *region);
644514f5e3Sopenharmony_ci    void SortSweepingRegion();
654514f5e3Sopenharmony_ci    Region *GetSweepingRegionSafe();
664514f5e3Sopenharmony_ci    void AddSweptRegionSafe(Region *region);
674514f5e3Sopenharmony_ci    Region *GetSweptRegionSafe();
684514f5e3Sopenharmony_ci
694514f5e3Sopenharmony_ci    void FreeRegion(Region *current, bool isMain = true);
704514f5e3Sopenharmony_ci    void FreeLiveRange(uintptr_t freeStart, uintptr_t freeEnd, bool isMain);
714514f5e3Sopenharmony_ci
724514f5e3Sopenharmony_ci    void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const;
734514f5e3Sopenharmony_ci
744514f5e3Sopenharmony_ci    size_t GetHeapObjectSize() const;
754514f5e3Sopenharmony_ci
764514f5e3Sopenharmony_ci    void IncreaseAllocatedSize(size_t size);
774514f5e3Sopenharmony_ci
784514f5e3Sopenharmony_ci    void IncreaseLiveObjectSize(size_t size)
794514f5e3Sopenharmony_ci    {
804514f5e3Sopenharmony_ci        liveObjectSize_ += size;
814514f5e3Sopenharmony_ci    }
824514f5e3Sopenharmony_ci
834514f5e3Sopenharmony_ci    void DecreaseLiveObjectSize(size_t size)
844514f5e3Sopenharmony_ci    {
854514f5e3Sopenharmony_ci        liveObjectSize_ -= size;
864514f5e3Sopenharmony_ci    }
874514f5e3Sopenharmony_ci
884514f5e3Sopenharmony_ci    bool CommittedSizeExceed()
894514f5e3Sopenharmony_ci    {
904514f5e3Sopenharmony_ci        return committedSize_ >= maximumCapacity_ + outOfMemoryOvershootSize_;
914514f5e3Sopenharmony_ci    }
924514f5e3Sopenharmony_ci
934514f5e3Sopenharmony_ci    void CheckAndTriggerLocalFullMark();
944514f5e3Sopenharmony_ci
954514f5e3Sopenharmony_ci    size_t GetTotalAllocatedSize() const;
964514f5e3Sopenharmony_ci
974514f5e3Sopenharmony_ci    void InvokeAllocationInspector(Address object, size_t size, size_t alignedSize);
984514f5e3Sopenharmony_ci
994514f5e3Sopenharmony_ci    void DetachFreeObjectSet(Region *region);
1004514f5e3Sopenharmony_ci
1014514f5e3Sopenharmony_ciprotected:
1024514f5e3Sopenharmony_ci    bool Expand(JSThread *thread);
1034514f5e3Sopenharmony_ci    FreeListAllocator<FreeObject> *allocator_;
1044514f5e3Sopenharmony_ci    SweepState sweepState_ = SweepState::NO_SWEEP;
1054514f5e3Sopenharmony_ci    SharedHeap *sHeap_ {nullptr};
1064514f5e3Sopenharmony_ci
1074514f5e3Sopenharmony_ciprivate:
1084514f5e3Sopenharmony_ci    static constexpr double LIVE_OBJECT_SIZE_RATIO = 0.8;
1094514f5e3Sopenharmony_ci
1104514f5e3Sopenharmony_ci    uintptr_t AllocateWithExpand(JSThread *thread, size_t size);
1114514f5e3Sopenharmony_ci    uintptr_t TryAllocate(JSThread *thread, size_t size);
1124514f5e3Sopenharmony_ci    // For sweeping
1134514f5e3Sopenharmony_ci    uintptr_t AllocateAfterSweepingCompleted(JSThread *thread, size_t size);
1144514f5e3Sopenharmony_ci    void IncAllocSObjectSize(uintptr_t object, size_t size);
1154514f5e3Sopenharmony_ci
1164514f5e3Sopenharmony_ci    Mutex lock_;
1174514f5e3Sopenharmony_ci    Mutex allocateLock_;
1184514f5e3Sopenharmony_ci    std::vector<Region *> sweepingList_;
1194514f5e3Sopenharmony_ci    std::vector<Region *> sweptList_;
1204514f5e3Sopenharmony_ci    size_t liveObjectSize_ {0};
1214514f5e3Sopenharmony_ci    size_t triggerLocalFullMarkLimit_ {0};
1224514f5e3Sopenharmony_ci};
1234514f5e3Sopenharmony_ci
1244514f5e3Sopenharmony_ciclass SharedAppSpawnSpace : public SharedSparseSpace {
1254514f5e3Sopenharmony_cipublic:
1264514f5e3Sopenharmony_ci    SharedAppSpawnSpace(SharedHeap *heap, size_t initialCapacity);
1274514f5e3Sopenharmony_ci    ~SharedAppSpawnSpace() override = default;
1284514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(SharedAppSpawnSpace);
1294514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(SharedAppSpawnSpace);
1304514f5e3Sopenharmony_ci
1314514f5e3Sopenharmony_ci    void IterateOverMarkedObjects(const std::function<void(TaggedObject *object)> &visitor) const;
1324514f5e3Sopenharmony_ci};
1334514f5e3Sopenharmony_ci
1344514f5e3Sopenharmony_ciclass SharedNonMovableSpace : public SharedSparseSpace {
1354514f5e3Sopenharmony_cipublic:
1364514f5e3Sopenharmony_ci    SharedNonMovableSpace(SharedHeap *heap, size_t initialCapacity, size_t maximumCapacity);
1374514f5e3Sopenharmony_ci    ~SharedNonMovableSpace() override = default;
1384514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(SharedNonMovableSpace);
1394514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(SharedNonMovableSpace);
1404514f5e3Sopenharmony_ci};
1414514f5e3Sopenharmony_ci
1424514f5e3Sopenharmony_ciclass SharedOldSpace : public SharedSparseSpace {
1434514f5e3Sopenharmony_cipublic:
1444514f5e3Sopenharmony_ci    SharedOldSpace(SharedHeap *heap, size_t initialCapacity, size_t maximumCapacity);
1454514f5e3Sopenharmony_ci    ~SharedOldSpace() override = default;
1464514f5e3Sopenharmony_ci    size_t GetMergeSize() const
1474514f5e3Sopenharmony_ci    {
1484514f5e3Sopenharmony_ci        return mergeSize_;
1494514f5e3Sopenharmony_ci    }
1504514f5e3Sopenharmony_ci
1514514f5e3Sopenharmony_ci    void IncreaseMergeSize(size_t size)
1524514f5e3Sopenharmony_ci    {
1534514f5e3Sopenharmony_ci        mergeSize_ += size;
1544514f5e3Sopenharmony_ci    }
1554514f5e3Sopenharmony_ci
1564514f5e3Sopenharmony_ci    void ResetMergeSize()
1574514f5e3Sopenharmony_ci    {
1584514f5e3Sopenharmony_ci        mergeSize_ = 0;
1594514f5e3Sopenharmony_ci    }
1604514f5e3Sopenharmony_ci
1614514f5e3Sopenharmony_ci    void Merge(SharedLocalSpace *localSpace);
1624514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(SharedOldSpace);
1634514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(SharedOldSpace);
1644514f5e3Sopenharmony_ci    Mutex lock_;
1654514f5e3Sopenharmony_ci    size_t mergeSize_ {0};
1664514f5e3Sopenharmony_ci};
1674514f5e3Sopenharmony_ci
1684514f5e3Sopenharmony_ciclass SharedLocalSpace : public SharedSparseSpace {
1694514f5e3Sopenharmony_cipublic:
1704514f5e3Sopenharmony_ci    SharedLocalSpace() = delete;
1714514f5e3Sopenharmony_ci    SharedLocalSpace(SharedHeap *heap, size_t initialCapacity, size_t maximumCapacity);
1724514f5e3Sopenharmony_ci    ~SharedLocalSpace() override = default;
1734514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(SharedLocalSpace);
1744514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(SharedLocalSpace);
1754514f5e3Sopenharmony_ci
1764514f5e3Sopenharmony_ci    uintptr_t Allocate(size_t size, bool isExpand = true);
1774514f5e3Sopenharmony_ci    bool AddRegionToList(Region *region);
1784514f5e3Sopenharmony_ci    void FreeBumpPoint();
1794514f5e3Sopenharmony_ci    void Stop();
1804514f5e3Sopenharmony_ci};
1814514f5e3Sopenharmony_ci
1824514f5e3Sopenharmony_ciclass SharedReadOnlySpace : public Space {
1834514f5e3Sopenharmony_cipublic:
1844514f5e3Sopenharmony_ci    SharedReadOnlySpace(SharedHeap *heap, size_t initialCapacity, size_t maximumCapacity);
1854514f5e3Sopenharmony_ci    ~SharedReadOnlySpace() override = default;
1864514f5e3Sopenharmony_ci    void SetReadOnly()
1874514f5e3Sopenharmony_ci    {
1884514f5e3Sopenharmony_ci        auto cb = [](Region *region) {
1894514f5e3Sopenharmony_ci            region->SetReadOnlyAndMarked();
1904514f5e3Sopenharmony_ci        };
1914514f5e3Sopenharmony_ci        EnumerateRegions(cb);
1924514f5e3Sopenharmony_ci    }
1934514f5e3Sopenharmony_ci
1944514f5e3Sopenharmony_ci    void IterateOverObjects(const std::function<void(TaggedObject *object)> &visitor) const;
1954514f5e3Sopenharmony_ci
1964514f5e3Sopenharmony_ci    void ClearReadOnly()
1974514f5e3Sopenharmony_ci    {
1984514f5e3Sopenharmony_ci        auto cb = [](Region *region) {
1994514f5e3Sopenharmony_ci            region->ClearReadOnly();
2004514f5e3Sopenharmony_ci        };
2014514f5e3Sopenharmony_ci        EnumerateRegions(cb);
2024514f5e3Sopenharmony_ci    }
2034514f5e3Sopenharmony_ci
2044514f5e3Sopenharmony_ci    bool Expand(JSThread *thread);
2054514f5e3Sopenharmony_ci
2064514f5e3Sopenharmony_ci    uintptr_t Allocate(JSThread *thread, size_t size);
2074514f5e3Sopenharmony_ci
2084514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(SharedReadOnlySpace);
2094514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(SharedReadOnlySpace);
2104514f5e3Sopenharmony_ci
2114514f5e3Sopenharmony_ciprivate:
2124514f5e3Sopenharmony_ci    Mutex allocateLock_;
2134514f5e3Sopenharmony_ci    BumpPointerAllocator allocator_;
2144514f5e3Sopenharmony_ci};
2154514f5e3Sopenharmony_ci
2164514f5e3Sopenharmony_ciclass SharedHugeObjectSpace : public Space {
2174514f5e3Sopenharmony_cipublic:
2184514f5e3Sopenharmony_ci    SharedHugeObjectSpace(BaseHeap *heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity,
2194514f5e3Sopenharmony_ci                    size_t maximumCapacity);
2204514f5e3Sopenharmony_ci    ~SharedHugeObjectSpace() override = default;
2214514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(SharedHugeObjectSpace);
2224514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(SharedHugeObjectSpace);
2234514f5e3Sopenharmony_ci    // Sometimes it is unsafe to checkSafePoint here, e.g. in deserialize, if do checkSafePoint JSThread may be
2244514f5e3Sopenharmony_ci    // suspended and then do SharedGC, which will free some regions in SharedHeap that are allocated at the beginning
2254514f5e3Sopenharmony_ci    // of deserializing for further object allocating, but no object has been allocated on at this moment.
2264514f5e3Sopenharmony_ci    uintptr_t Allocate(JSThread *thread, size_t objectSize, AllocateEventType allocType = AllocateEventType::NORMAL);
2274514f5e3Sopenharmony_ci    void Sweep();
2284514f5e3Sopenharmony_ci    size_t GetHeapObjectSize() const;
2294514f5e3Sopenharmony_ci    void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const;
2304514f5e3Sopenharmony_ci
2314514f5e3Sopenharmony_ci    void ReclaimHugeRegion();
2324514f5e3Sopenharmony_ci
2334514f5e3Sopenharmony_ci    void InvokeAllocationInspector(Address object, size_t objectSize);
2344514f5e3Sopenharmony_ci
2354514f5e3Sopenharmony_ci    bool CommittedSizeExceed(size_t size = 0) const
2364514f5e3Sopenharmony_ci    {
2374514f5e3Sopenharmony_ci        return committedSize_ + size >= maximumCapacity_ + outOfMemoryOvershootSize_;
2384514f5e3Sopenharmony_ci    }
2394514f5e3Sopenharmony_ci
2404514f5e3Sopenharmony_ci    void CheckAndTriggerLocalFullMark(JSThread *thread, size_t size);
2414514f5e3Sopenharmony_ciprivate:
2424514f5e3Sopenharmony_ci    static constexpr size_t HUGE_OBJECT_BITSET_SIZE = 16;
2434514f5e3Sopenharmony_ci    static constexpr double HUGE_OBJECT_SIZE_RATIO = 0.8;
2444514f5e3Sopenharmony_ci
2454514f5e3Sopenharmony_ci    size_t triggerLocalFullMarkLimit_ {0};
2464514f5e3Sopenharmony_ci    EcmaList<Region> hugeNeedFreeList_ {};
2474514f5e3Sopenharmony_ci    Mutex allocateLock_;
2484514f5e3Sopenharmony_ci};
2494514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
2504514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_MEM_SHARED_SHARED_SPACE_H
251