14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2022-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_REGION_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_MEM_REGION_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include <type_traits> 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_ci#include "ecmascript/base/aligned_struct.h" 224514f5e3Sopenharmony_ci#include "ecmascript/base/asan_interface.h" 234514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h" 244514f5e3Sopenharmony_ci#include "ecmascript/mem/free_object_list.h" 254514f5e3Sopenharmony_ci#include "ecmascript/mem/gc_bitset.h" 264514f5e3Sopenharmony_ci#include "ecmascript/mem/remembered_set.h" 274514f5e3Sopenharmony_ci#include "ecmascript/mem/mem_common.h" 284514f5e3Sopenharmony_ci#include "ecmascript/platform/map.h" 294514f5e3Sopenharmony_ci 304514f5e3Sopenharmony_ci#include "ecmascript/platform/mutex.h" 314514f5e3Sopenharmony_ci 324514f5e3Sopenharmony_ci#include "securec.h" 334514f5e3Sopenharmony_ci 344514f5e3Sopenharmony_cinamespace panda { 354514f5e3Sopenharmony_cinamespace ecmascript { 364514f5e3Sopenharmony_ciclass JSThread; 374514f5e3Sopenharmony_ci 384514f5e3Sopenharmony_cienum RegionSpaceFlag { 394514f5e3Sopenharmony_ci UNINITIALIZED = 0, 404514f5e3Sopenharmony_ci // We should avoid using the lower 3 bits (bits 0 to 2). 414514f5e3Sopenharmony_ci // If ZAP_MEM is enabled, the value of the lower 3 bits conflicts with the INVALID_VALUE. 424514f5e3Sopenharmony_ci 434514f5e3Sopenharmony_ci // Bits 3 to 7 are reserved to denote the space where the region is located. 444514f5e3Sopenharmony_ci IN_EDEN_SPACE = 0x08, 454514f5e3Sopenharmony_ci IN_YOUNG_SPACE = 0x09, 464514f5e3Sopenharmony_ci IN_SNAPSHOT_SPACE = 0x0A, 474514f5e3Sopenharmony_ci IN_HUGE_OBJECT_SPACE = 0x0B, 484514f5e3Sopenharmony_ci IN_OLD_SPACE = 0x0C, 494514f5e3Sopenharmony_ci IN_NON_MOVABLE_SPACE = 0x0D, 504514f5e3Sopenharmony_ci IN_MACHINE_CODE_SPACE = 0x0E, 514514f5e3Sopenharmony_ci IN_READ_ONLY_SPACE = 0X0F, 524514f5e3Sopenharmony_ci IN_APPSPAWN_SPACE = 0x10, 534514f5e3Sopenharmony_ci IN_HUGE_MACHINE_CODE_SPACE = 0x11, 544514f5e3Sopenharmony_ci IN_SHARED_NON_MOVABLE = 0x12, 554514f5e3Sopenharmony_ci IN_SHARED_OLD_SPACE = 0x13, 564514f5e3Sopenharmony_ci IN_SHARED_APPSPAWN_SPACE = 0X14, 574514f5e3Sopenharmony_ci IN_SHARED_HUGE_OBJECT_SPACE = 0x15, 584514f5e3Sopenharmony_ci IN_SHARED_READ_ONLY_SPACE = 0x16, 594514f5e3Sopenharmony_ci 604514f5e3Sopenharmony_ci VALID_SPACE_MASK = 0xFF, 614514f5e3Sopenharmony_ci 624514f5e3Sopenharmony_ci GENERAL_YOUNG_BEGIN = IN_EDEN_SPACE, 634514f5e3Sopenharmony_ci GENERAL_YOUNG_END = IN_YOUNG_SPACE, 644514f5e3Sopenharmony_ci GENERAL_OLD_BEGIN = IN_SNAPSHOT_SPACE, 654514f5e3Sopenharmony_ci GENERAL_OLD_END = IN_HUGE_MACHINE_CODE_SPACE, 664514f5e3Sopenharmony_ci SHARED_SPACE_BEGIN = IN_SHARED_NON_MOVABLE, 674514f5e3Sopenharmony_ci SHARED_SPACE_END = IN_SHARED_READ_ONLY_SPACE, 684514f5e3Sopenharmony_ci SHARED_SWEEPABLE_SPACE_BEGIN = IN_SHARED_NON_MOVABLE, 694514f5e3Sopenharmony_ci SHARED_SWEEPABLE_SPACE_END = IN_SHARED_HUGE_OBJECT_SPACE, 704514f5e3Sopenharmony_ci 714514f5e3Sopenharmony_ci HEAP_SPACE_BEGIN = IN_EDEN_SPACE, 724514f5e3Sopenharmony_ci HEAP_SPACE_END = IN_SHARED_READ_ONLY_SPACE 734514f5e3Sopenharmony_ci}; 744514f5e3Sopenharmony_ci 754514f5e3Sopenharmony_cienum RegionGCFlags { 764514f5e3Sopenharmony_ci // We should avoid using the lower 3 bits (bits 0 to 2). 774514f5e3Sopenharmony_ci // If ZAP_MEM is enabled, the value of the lower 3 bits conflicts with the INVALID_VALUE. 784514f5e3Sopenharmony_ci 794514f5e3Sopenharmony_ci // Below flags are used for GC, and each flag has a dedicated bit starting from the 3rd bit. 804514f5e3Sopenharmony_ci NEVER_EVACUATE = 1 << 3, 814514f5e3Sopenharmony_ci HAS_AGE_MARK = 1 << 4, 824514f5e3Sopenharmony_ci BELOW_AGE_MARK = 1 << 5, 834514f5e3Sopenharmony_ci IN_COLLECT_SET = 1 << 6, 844514f5e3Sopenharmony_ci IN_NEW_TO_NEW_SET = 1 << 7, 854514f5e3Sopenharmony_ci // Bits 8 to 10 (the lower 3 bits for the next byte) are also excluded for the sake of 864514f5e3Sopenharmony_ci // INVALID_VALUE in ZAP_MEM. 874514f5e3Sopenharmony_ci HAS_BEEN_SWEPT = 1 << 11, 884514f5e3Sopenharmony_ci NEED_RELOCATE = 1 << 12, 894514f5e3Sopenharmony_ci // ONLY used for heap verification. 904514f5e3Sopenharmony_ci IN_INACTIVE_SEMI_SPACE = 1 << 13, 914514f5e3Sopenharmony_ci}; 924514f5e3Sopenharmony_ci 934514f5e3Sopenharmony_ci// Currently only use for region in LinearSpace, to check if the region is allocated during concurrent marking. 944514f5e3Sopenharmony_cienum class RegionTypeFlag : uint8_t { 954514f5e3Sopenharmony_ci DEFAULT = 0, 964514f5e3Sopenharmony_ci // We should avoid using the lower 3 bits (bits 0 to 2). 974514f5e3Sopenharmony_ci // If ZAP_MEM is enabled, the value of the lower 3 bits conflicts with the INVALID_VALUE. 984514f5e3Sopenharmony_ci 994514f5e3Sopenharmony_ci // Region is allocated before concurrent marking, but some new object may be allocated here 1004514f5e3Sopenharmony_ci // during concurrent marking. 1014514f5e3Sopenharmony_ci HALF_FRESH = 0x08, 1024514f5e3Sopenharmony_ci // Region is allocated during concurrent marking. 1034514f5e3Sopenharmony_ci FRESH = 0x09, 1044514f5e3Sopenharmony_ci}; 1054514f5e3Sopenharmony_ci 1064514f5e3Sopenharmony_cienum RSetType { 1074514f5e3Sopenharmony_ci OLD_TO_NEW, 1084514f5e3Sopenharmony_ci LOCAL_TO_SHARE, 1094514f5e3Sopenharmony_ci}; 1104514f5e3Sopenharmony_ci 1114514f5e3Sopenharmony_cistatic inline std::string ToSpaceTypeName(uint8_t space) 1124514f5e3Sopenharmony_ci{ 1134514f5e3Sopenharmony_ci switch (space) { 1144514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_EDEN_SPACE: 1154514f5e3Sopenharmony_ci return "eden space"; 1164514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_YOUNG_SPACE: 1174514f5e3Sopenharmony_ci return "young space"; 1184514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_SNAPSHOT_SPACE: 1194514f5e3Sopenharmony_ci return "snapshot space"; 1204514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_HUGE_OBJECT_SPACE: 1214514f5e3Sopenharmony_ci return "huge object space"; 1224514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_OLD_SPACE: 1234514f5e3Sopenharmony_ci return "old space"; 1244514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_NON_MOVABLE_SPACE: 1254514f5e3Sopenharmony_ci return "non movable space"; 1264514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_MACHINE_CODE_SPACE: 1274514f5e3Sopenharmony_ci return "machine code space"; 1284514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_READ_ONLY_SPACE: 1294514f5e3Sopenharmony_ci return "read only space"; 1304514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_APPSPAWN_SPACE: 1314514f5e3Sopenharmony_ci return "appspawn space"; 1324514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_HUGE_MACHINE_CODE_SPACE: 1334514f5e3Sopenharmony_ci return "huge machine code space"; 1344514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_SHARED_NON_MOVABLE: 1354514f5e3Sopenharmony_ci return "shared non movable space"; 1364514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_SHARED_OLD_SPACE: 1374514f5e3Sopenharmony_ci return "shared old space"; 1384514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_SHARED_READ_ONLY_SPACE: 1394514f5e3Sopenharmony_ci return "shared read only space"; 1404514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_SHARED_HUGE_OBJECT_SPACE: 1414514f5e3Sopenharmony_ci return "shared huge object space"; 1424514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_SHARED_APPSPAWN_SPACE: 1434514f5e3Sopenharmony_ci return "shared appspawn space"; 1444514f5e3Sopenharmony_ci default: 1454514f5e3Sopenharmony_ci return "invalid space"; 1464514f5e3Sopenharmony_ci } 1474514f5e3Sopenharmony_ci} 1484514f5e3Sopenharmony_ci 1494514f5e3Sopenharmony_ci// |---------------------------------------------------------------------------------------| 1504514f5e3Sopenharmony_ci// | Region (256 kb) | 1514514f5e3Sopenharmony_ci// |---------------------------------|--------------------------------|--------------------| 1524514f5e3Sopenharmony_ci// | Head (sizeof(Region)) | Mark bitset (4kb) | Data | 1534514f5e3Sopenharmony_ci// |---------------------------------|--------------------------------|--------------------| 1544514f5e3Sopenharmony_ci 1554514f5e3Sopenharmony_ciclass Region { 1564514f5e3Sopenharmony_cipublic: 1574514f5e3Sopenharmony_ci Region(NativeAreaAllocator *allocator, uintptr_t allocateBase, uintptr_t begin, uintptr_t end, 1584514f5e3Sopenharmony_ci RegionSpaceFlag spaceType, RegionTypeFlag typeFlag) 1594514f5e3Sopenharmony_ci : packedData_(begin, end, spaceType, typeFlag), 1604514f5e3Sopenharmony_ci nativeAreaAllocator_(allocator), 1614514f5e3Sopenharmony_ci allocateBase_(allocateBase), 1624514f5e3Sopenharmony_ci end_(end), 1634514f5e3Sopenharmony_ci highWaterMark_(end), 1644514f5e3Sopenharmony_ci aliveObject_(0), 1654514f5e3Sopenharmony_ci wasted_(0), 1664514f5e3Sopenharmony_ci snapshotData_(0) {} 1674514f5e3Sopenharmony_ci 1684514f5e3Sopenharmony_ci // JitFort space is divided into regions (JitForRegion) to enable 1694514f5e3Sopenharmony_ci // reusing free_object_list and free_object_set operations for 1704514f5e3Sopenharmony_ci // JitFort space, and GC marking actually happens in corresponding 1714514f5e3Sopenharmony_ci // MachineCode objects where JitFort space is allocated to. So no 1724514f5e3Sopenharmony_ci // gc mark bits needed in JitFortRegions. 1734514f5e3Sopenharmony_ci Region(NativeAreaAllocator *allocator, uintptr_t allocateBase, uintptr_t end, 1744514f5e3Sopenharmony_ci RegionSpaceFlag spaceType) 1754514f5e3Sopenharmony_ci : packedData_(allocateBase, spaceType), // no markGCBitset_ for JitFort 1764514f5e3Sopenharmony_ci nativeAreaAllocator_(allocator), 1774514f5e3Sopenharmony_ci allocateBase_(allocateBase), 1784514f5e3Sopenharmony_ci end_(end), 1794514f5e3Sopenharmony_ci highWaterMark_(end), 1804514f5e3Sopenharmony_ci aliveObject_(0), 1814514f5e3Sopenharmony_ci wasted_(0), 1824514f5e3Sopenharmony_ci snapshotData_(0) {} 1834514f5e3Sopenharmony_ci 1844514f5e3Sopenharmony_ci ~Region() = default; 1854514f5e3Sopenharmony_ci 1864514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(Region); 1874514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(Region); 1884514f5e3Sopenharmony_ci 1894514f5e3Sopenharmony_ci enum RegionSpaceKind { InYoung, InGeneralOld, Other }; 1904514f5e3Sopenharmony_ci 1914514f5e3Sopenharmony_ci template <RegionSpaceKind kind> 1924514f5e3Sopenharmony_ci class Updater final { 1934514f5e3Sopenharmony_ci public: 1944514f5e3Sopenharmony_ci Updater(uintptr_t updateAddress, Region& region) 1954514f5e3Sopenharmony_ci : bitsetUpdater_(updateAddress), 1964514f5e3Sopenharmony_ci region_(region) 1974514f5e3Sopenharmony_ci { 1984514f5e3Sopenharmony_ci } 1994514f5e3Sopenharmony_ci 2004514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(Updater); 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_ci ARK_INLINE ~Updater() 2034514f5e3Sopenharmony_ci { 2044514f5e3Sopenharmony_ci Flush(); 2054514f5e3Sopenharmony_ci } 2064514f5e3Sopenharmony_ci 2074514f5e3Sopenharmony_ci ARK_INLINE void UpdateLocalToShare() 2084514f5e3Sopenharmony_ci { 2094514f5e3Sopenharmony_ci bitsetUpdater_.Update(LocalToShareIdx); 2104514f5e3Sopenharmony_ci } 2114514f5e3Sopenharmony_ci 2124514f5e3Sopenharmony_ci template <RegionSpaceKind T = kind, std::enable_if_t<T == InYoung, int> = 0> 2134514f5e3Sopenharmony_ci ARK_INLINE void UpdateNewToEden() 2144514f5e3Sopenharmony_ci { 2154514f5e3Sopenharmony_ci bitsetUpdater_.Update(NewToEdenIdx); 2164514f5e3Sopenharmony_ci } 2174514f5e3Sopenharmony_ci 2184514f5e3Sopenharmony_ci template <RegionSpaceKind T = kind, std::enable_if_t<T == InGeneralOld, int> = 0> 2194514f5e3Sopenharmony_ci ARK_INLINE void UpdateOldToNew() 2204514f5e3Sopenharmony_ci { 2214514f5e3Sopenharmony_ci bitsetUpdater_.Update(OldToNewIdx); 2224514f5e3Sopenharmony_ci } 2234514f5e3Sopenharmony_ci 2244514f5e3Sopenharmony_ci ARK_INLINE void Next() 2254514f5e3Sopenharmony_ci { 2264514f5e3Sopenharmony_ci if (bitsetUpdater_.Next()) { 2274514f5e3Sopenharmony_ci Flush(); 2284514f5e3Sopenharmony_ci } 2294514f5e3Sopenharmony_ci } 2304514f5e3Sopenharmony_ci 2314514f5e3Sopenharmony_ci private: 2324514f5e3Sopenharmony_ci ARK_INLINE void Consume(size_t idx, uintptr_t updateAddress, uint32_t mask); 2334514f5e3Sopenharmony_ci 2344514f5e3Sopenharmony_ci ARK_INLINE void Flush(); 2354514f5e3Sopenharmony_ci 2364514f5e3Sopenharmony_ci static constexpr size_t CalculateBitSetNum() 2374514f5e3Sopenharmony_ci { 2384514f5e3Sopenharmony_ci constexpr size_t InYoungBitSetNum = 2; 2394514f5e3Sopenharmony_ci constexpr size_t InGeneralOldBitSetNum = 2; 2404514f5e3Sopenharmony_ci constexpr size_t OtherBitSetNum = 1; 2414514f5e3Sopenharmony_ci switch (kind) { 2424514f5e3Sopenharmony_ci case InYoung: 2434514f5e3Sopenharmony_ci return InYoungBitSetNum; 2444514f5e3Sopenharmony_ci case InGeneralOld: 2454514f5e3Sopenharmony_ci return InGeneralOldBitSetNum; 2464514f5e3Sopenharmony_ci case Other: 2474514f5e3Sopenharmony_ci return OtherBitSetNum; 2484514f5e3Sopenharmony_ci } 2494514f5e3Sopenharmony_ci return 0; 2504514f5e3Sopenharmony_ci } 2514514f5e3Sopenharmony_ci 2524514f5e3Sopenharmony_ci static constexpr size_t BitSetNum = CalculateBitSetNum(); 2534514f5e3Sopenharmony_ci static constexpr size_t LocalToShareIdx = 0; 2544514f5e3Sopenharmony_ci static constexpr size_t NewToEdenIdx = 1; // NewToEden and OldToNew can't be used at same time. 2554514f5e3Sopenharmony_ci static constexpr size_t OldToNewIdx = 1; 2564514f5e3Sopenharmony_ci GCBitSetUpdater<BitSetNum> bitsetUpdater_; 2574514f5e3Sopenharmony_ci Region& region_; 2584514f5e3Sopenharmony_ci }; 2594514f5e3Sopenharmony_ci 2604514f5e3Sopenharmony_ci void Initialize() 2614514f5e3Sopenharmony_ci { 2624514f5e3Sopenharmony_ci lock_ = new Mutex(); 2634514f5e3Sopenharmony_ci if (InSparseSpace()) { 2644514f5e3Sopenharmony_ci InitializeFreeObjectSets(); 2654514f5e3Sopenharmony_ci } 2664514f5e3Sopenharmony_ci } 2674514f5e3Sopenharmony_ci 2684514f5e3Sopenharmony_ci void LinkNext(Region *next) 2694514f5e3Sopenharmony_ci { 2704514f5e3Sopenharmony_ci next_ = next; 2714514f5e3Sopenharmony_ci } 2724514f5e3Sopenharmony_ci 2734514f5e3Sopenharmony_ci Region *GetNext() const 2744514f5e3Sopenharmony_ci { 2754514f5e3Sopenharmony_ci return next_; 2764514f5e3Sopenharmony_ci } 2774514f5e3Sopenharmony_ci 2784514f5e3Sopenharmony_ci void LinkPrev(Region *prev) 2794514f5e3Sopenharmony_ci { 2804514f5e3Sopenharmony_ci prev_ = prev; 2814514f5e3Sopenharmony_ci } 2824514f5e3Sopenharmony_ci 2834514f5e3Sopenharmony_ci Region *GetPrev() const 2844514f5e3Sopenharmony_ci { 2854514f5e3Sopenharmony_ci return prev_; 2864514f5e3Sopenharmony_ci } 2874514f5e3Sopenharmony_ci 2884514f5e3Sopenharmony_ci uintptr_t GetBegin() const 2894514f5e3Sopenharmony_ci { 2904514f5e3Sopenharmony_ci return packedData_.begin_; 2914514f5e3Sopenharmony_ci } 2924514f5e3Sopenharmony_ci 2934514f5e3Sopenharmony_ci uintptr_t GetEnd() const 2944514f5e3Sopenharmony_ci { 2954514f5e3Sopenharmony_ci return end_; 2964514f5e3Sopenharmony_ci } 2974514f5e3Sopenharmony_ci 2984514f5e3Sopenharmony_ci uintptr_t GetHighWaterMark() const 2994514f5e3Sopenharmony_ci { 3004514f5e3Sopenharmony_ci return highWaterMark_; 3014514f5e3Sopenharmony_ci } 3024514f5e3Sopenharmony_ci 3034514f5e3Sopenharmony_ci size_t GetCapacity() const 3044514f5e3Sopenharmony_ci { 3054514f5e3Sopenharmony_ci return end_ - allocateBase_; 3064514f5e3Sopenharmony_ci } 3074514f5e3Sopenharmony_ci 3084514f5e3Sopenharmony_ci size_t GetSize() const 3094514f5e3Sopenharmony_ci { 3104514f5e3Sopenharmony_ci return end_ - packedData_.begin_; 3114514f5e3Sopenharmony_ci } 3124514f5e3Sopenharmony_ci 3134514f5e3Sopenharmony_ci bool IsGCFlagSet(RegionGCFlags flag) const 3144514f5e3Sopenharmony_ci { 3154514f5e3Sopenharmony_ci return (packedData_.flags_.gcFlags_ & flag) == flag; 3164514f5e3Sopenharmony_ci } 3174514f5e3Sopenharmony_ci 3184514f5e3Sopenharmony_ci void SetGCFlag(RegionGCFlags flag) 3194514f5e3Sopenharmony_ci { 3204514f5e3Sopenharmony_ci packedData_.flags_.gcFlags_ |= flag; 3214514f5e3Sopenharmony_ci } 3224514f5e3Sopenharmony_ci 3234514f5e3Sopenharmony_ci void ClearGCFlag(RegionGCFlags flag) 3244514f5e3Sopenharmony_ci { 3254514f5e3Sopenharmony_ci // NOLINTNEXTLINE(hicpp-signed-bitwise) 3264514f5e3Sopenharmony_ci packedData_.flags_.gcFlags_ &= ~flag; 3274514f5e3Sopenharmony_ci } 3284514f5e3Sopenharmony_ci 3294514f5e3Sopenharmony_ci std::string GetSpaceTypeName() 3304514f5e3Sopenharmony_ci { 3314514f5e3Sopenharmony_ci return ToSpaceTypeName(packedData_.flags_.spaceFlag_); 3324514f5e3Sopenharmony_ci } 3334514f5e3Sopenharmony_ci 3344514f5e3Sopenharmony_ci uint8_t GetSpaceType() const 3354514f5e3Sopenharmony_ci { 3364514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_; 3374514f5e3Sopenharmony_ci } 3384514f5e3Sopenharmony_ci 3394514f5e3Sopenharmony_ci // Mark bitset 3404514f5e3Sopenharmony_ci GCBitset *GetMarkGCBitset() const; 3414514f5e3Sopenharmony_ci bool AtomicMark(void *address); 3424514f5e3Sopenharmony_ci // Objects in fresh region should only mark in JS Thread. 3434514f5e3Sopenharmony_ci bool NonAtomicMark(void *address); 3444514f5e3Sopenharmony_ci void ClearMark(void *address); 3454514f5e3Sopenharmony_ci bool Test(void *addr) const; 3464514f5e3Sopenharmony_ci bool Test(uintptr_t addr) const; 3474514f5e3Sopenharmony_ci // ONLY used for heap verification. 3484514f5e3Sopenharmony_ci bool TestNewToEden(uintptr_t addr); 3494514f5e3Sopenharmony_ci bool TestOldToNew(uintptr_t addr); 3504514f5e3Sopenharmony_ci bool TestLocalToShare(uintptr_t addr); 3514514f5e3Sopenharmony_ci template <typename Visitor> 3524514f5e3Sopenharmony_ci void IterateAllMarkedBits(Visitor visitor) const; 3534514f5e3Sopenharmony_ci void ClearMarkGCBitset(); 3544514f5e3Sopenharmony_ci // local to share remembered set 3554514f5e3Sopenharmony_ci bool HasLocalToShareRememberedSet() const; 3564514f5e3Sopenharmony_ci RememberedSet *ExtractLocalToShareRSet(); 3574514f5e3Sopenharmony_ci void InsertLocalToShareRSet(uintptr_t addr); 3584514f5e3Sopenharmony_ci template<RegionSpaceKind kind> 3594514f5e3Sopenharmony_ci Updater<kind> GetBatchRSetUpdater(uintptr_t addr); 3604514f5e3Sopenharmony_ci void AtomicInsertLocalToShareRSet(uintptr_t addr); 3614514f5e3Sopenharmony_ci void ClearLocalToShareRSetInRange(uintptr_t start, uintptr_t end); 3624514f5e3Sopenharmony_ci void AtomicClearLocalToShareRSetInRange(uintptr_t start, uintptr_t end); 3634514f5e3Sopenharmony_ci void AtomicClearSweepingLocalToShareRSetInRange(uintptr_t start, uintptr_t end); 3644514f5e3Sopenharmony_ci template <typename Visitor> 3654514f5e3Sopenharmony_ci void IterateAllLocalToShareBits(Visitor visitor); 3664514f5e3Sopenharmony_ci void DeleteLocalToShareRSet(); 3674514f5e3Sopenharmony_ci void DeleteSweepingLocalToShareRSet(); 3684514f5e3Sopenharmony_ci // Cross region remembered set 3694514f5e3Sopenharmony_ci void InsertCrossRegionRSet(uintptr_t addr); 3704514f5e3Sopenharmony_ci void AtomicInsertCrossRegionRSet(uintptr_t addr); 3714514f5e3Sopenharmony_ci template <typename Visitor> 3724514f5e3Sopenharmony_ci void IterateAllCrossRegionBits(Visitor visitor) const; 3734514f5e3Sopenharmony_ci void ClearCrossRegionRSet(); 3744514f5e3Sopenharmony_ci void ClearCrossRegionRSetInRange(uintptr_t start, uintptr_t end); 3754514f5e3Sopenharmony_ci void AtomicClearCrossRegionRSetInRange(uintptr_t start, uintptr_t end); 3764514f5e3Sopenharmony_ci void DeleteCrossRegionRSet(); 3774514f5e3Sopenharmony_ci // New to eden remembered set 3784514f5e3Sopenharmony_ci void InsertNewToEdenRSet(uintptr_t addr); 3794514f5e3Sopenharmony_ci void AtomicInsertNewToEdenRSet(uintptr_t addr); 3804514f5e3Sopenharmony_ci void ClearNewToEdenRSet(uintptr_t addr); 3814514f5e3Sopenharmony_ci // Old to new remembered set 3824514f5e3Sopenharmony_ci void InsertOldToNewRSet(uintptr_t addr); 3834514f5e3Sopenharmony_ci void ClearOldToNewRSet(uintptr_t addr); 3844514f5e3Sopenharmony_ci 3854514f5e3Sopenharmony_ci template <typename Visitor> 3864514f5e3Sopenharmony_ci void IterateAllNewToEdenBits(Visitor visitor); 3874514f5e3Sopenharmony_ci template <typename Visitor> 3884514f5e3Sopenharmony_ci void IterateAllOldToNewBits(Visitor visitor); 3894514f5e3Sopenharmony_ci RememberedSet* GetNewToEdenRSet(); 3904514f5e3Sopenharmony_ci void ClearNewToEdenRSet(); 3914514f5e3Sopenharmony_ci void ClearNewToEdenRSetInRange(uintptr_t start, uintptr_t end); 3924514f5e3Sopenharmony_ci void DeleteNewToEdenRSet(); 3934514f5e3Sopenharmony_ci void ClearOldToNewRSet(); 3944514f5e3Sopenharmony_ci void ClearOldToNewRSetInRange(uintptr_t start, uintptr_t end); 3954514f5e3Sopenharmony_ci void DeleteOldToNewRSet(); 3964514f5e3Sopenharmony_ci 3974514f5e3Sopenharmony_ci void AtomicClearSweepingOldToNewRSetInRange(uintptr_t start, uintptr_t end); 3984514f5e3Sopenharmony_ci void ClearSweepingOldToNewRSetInRange(uintptr_t start, uintptr_t end); 3994514f5e3Sopenharmony_ci void DeleteSweepingOldToNewRSet(); 4004514f5e3Sopenharmony_ci template <typename Visitor> 4014514f5e3Sopenharmony_ci void AtomicIterateAllSweepingRSetBits(Visitor visitor); 4024514f5e3Sopenharmony_ci template <typename Visitor> 4034514f5e3Sopenharmony_ci void IterateAllSweepingRSetBits(Visitor visitor); 4044514f5e3Sopenharmony_ci 4054514f5e3Sopenharmony_ci static Region *ObjectAddressToRange(TaggedObject *obj) 4064514f5e3Sopenharmony_ci { 4074514f5e3Sopenharmony_ci return reinterpret_cast<Region *>(ToUintPtr(obj) & ~DEFAULT_REGION_MASK); 4084514f5e3Sopenharmony_ci } 4094514f5e3Sopenharmony_ci 4104514f5e3Sopenharmony_ci static Region *ObjectAddressToRange(uintptr_t objAddress) 4114514f5e3Sopenharmony_ci { 4124514f5e3Sopenharmony_ci return reinterpret_cast<Region *>(objAddress & ~DEFAULT_REGION_MASK); 4134514f5e3Sopenharmony_ci } 4144514f5e3Sopenharmony_ci 4154514f5e3Sopenharmony_ci static size_t GetRegionAvailableSize() 4164514f5e3Sopenharmony_ci { 4174514f5e3Sopenharmony_ci size_t regionHeaderSize = AlignUp(sizeof(Region), static_cast<size_t>(MemAlignment::MEM_ALIGN_REGION)); 4184514f5e3Sopenharmony_ci size_t bitsetSize = GCBitset::SizeOfGCBitset(DEFAULT_REGION_SIZE - regionHeaderSize); 4194514f5e3Sopenharmony_ci return DEFAULT_REGION_SIZE - regionHeaderSize - bitsetSize; 4204514f5e3Sopenharmony_ci } 4214514f5e3Sopenharmony_ci 4224514f5e3Sopenharmony_ci void ClearMembers() 4234514f5e3Sopenharmony_ci { 4244514f5e3Sopenharmony_ci if (lock_ != nullptr) { 4254514f5e3Sopenharmony_ci delete lock_; 4264514f5e3Sopenharmony_ci lock_ = nullptr; 4274514f5e3Sopenharmony_ci } 4284514f5e3Sopenharmony_ci } 4294514f5e3Sopenharmony_ci 4304514f5e3Sopenharmony_ci void Invalidate() 4314514f5e3Sopenharmony_ci { 4324514f5e3Sopenharmony_ci ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast<void *>(GetBegin()), GetSize()); 4334514f5e3Sopenharmony_ci packedData_.flags_.spaceFlag_ = RegionSpaceFlag::UNINITIALIZED; 4344514f5e3Sopenharmony_ci } 4354514f5e3Sopenharmony_ci 4364514f5e3Sopenharmony_ci uint8_t GetRegionSpaceFlag(); 4374514f5e3Sopenharmony_ci 4384514f5e3Sopenharmony_ci void SetRegionSpaceFlag(RegionSpaceFlag flag) 4394514f5e3Sopenharmony_ci { 4404514f5e3Sopenharmony_ci packedData_.flags_.spaceFlag_ = flag; 4414514f5e3Sopenharmony_ci } 4424514f5e3Sopenharmony_ci bool InEdenSpace() const 4434514f5e3Sopenharmony_ci { 4444514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_EDEN_SPACE; 4454514f5e3Sopenharmony_ci } 4464514f5e3Sopenharmony_ci 4474514f5e3Sopenharmony_ci bool InYoungSpace() const 4484514f5e3Sopenharmony_ci { 4494514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_YOUNG_SPACE; 4504514f5e3Sopenharmony_ci } 4514514f5e3Sopenharmony_ci 4524514f5e3Sopenharmony_ci bool InOldSpace() const 4534514f5e3Sopenharmony_ci { 4544514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_OLD_SPACE; 4554514f5e3Sopenharmony_ci } 4564514f5e3Sopenharmony_ci 4574514f5e3Sopenharmony_ci bool InYoungOrOldSpace() const 4584514f5e3Sopenharmony_ci { 4594514f5e3Sopenharmony_ci return InGeneralNewSpace() || InOldSpace(); 4604514f5e3Sopenharmony_ci } 4614514f5e3Sopenharmony_ci 4624514f5e3Sopenharmony_ci bool InGeneralNewSpace() const 4634514f5e3Sopenharmony_ci { 4644514f5e3Sopenharmony_ci auto flag = packedData_.flags_.spaceFlag_; 4654514f5e3Sopenharmony_ci return flag >= RegionSpaceFlag::GENERAL_YOUNG_BEGIN && flag <= RegionSpaceFlag::GENERAL_YOUNG_END; 4664514f5e3Sopenharmony_ci } 4674514f5e3Sopenharmony_ci 4684514f5e3Sopenharmony_ci bool InGeneralOldSpace() const 4694514f5e3Sopenharmony_ci { 4704514f5e3Sopenharmony_ci ASSERT(packedData_.flags_.spaceFlag_ != 0); 4714514f5e3Sopenharmony_ci auto flag = packedData_.flags_.spaceFlag_; 4724514f5e3Sopenharmony_ci return flag >= RegionSpaceFlag::GENERAL_OLD_BEGIN && flag <= RegionSpaceFlag::GENERAL_OLD_END; 4734514f5e3Sopenharmony_ci } 4744514f5e3Sopenharmony_ci 4754514f5e3Sopenharmony_ci bool InHugeObjectSpace() const 4764514f5e3Sopenharmony_ci { 4774514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_HUGE_OBJECT_SPACE; 4784514f5e3Sopenharmony_ci } 4794514f5e3Sopenharmony_ci 4804514f5e3Sopenharmony_ci bool InMachineCodeSpace() const 4814514f5e3Sopenharmony_ci { 4824514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_MACHINE_CODE_SPACE; 4834514f5e3Sopenharmony_ci } 4844514f5e3Sopenharmony_ci 4854514f5e3Sopenharmony_ci bool InHugeMachineCodeSpace() const 4864514f5e3Sopenharmony_ci { 4874514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_HUGE_MACHINE_CODE_SPACE; 4884514f5e3Sopenharmony_ci } 4894514f5e3Sopenharmony_ci 4904514f5e3Sopenharmony_ci bool InNonMovableSpace() const 4914514f5e3Sopenharmony_ci { 4924514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_NON_MOVABLE_SPACE; 4934514f5e3Sopenharmony_ci } 4944514f5e3Sopenharmony_ci 4954514f5e3Sopenharmony_ci bool InSnapshotSpace() const 4964514f5e3Sopenharmony_ci { 4974514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_SNAPSHOT_SPACE; 4984514f5e3Sopenharmony_ci } 4994514f5e3Sopenharmony_ci 5004514f5e3Sopenharmony_ci bool InReadOnlySpace() const 5014514f5e3Sopenharmony_ci { 5024514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_READ_ONLY_SPACE; 5034514f5e3Sopenharmony_ci } 5044514f5e3Sopenharmony_ci 5054514f5e3Sopenharmony_ci bool InSharedOldSpace() const 5064514f5e3Sopenharmony_ci { 5074514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_SHARED_OLD_SPACE; 5084514f5e3Sopenharmony_ci } 5094514f5e3Sopenharmony_ci 5104514f5e3Sopenharmony_ci bool InSharedNonMovableSpace() const 5114514f5e3Sopenharmony_ci { 5124514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_SHARED_NON_MOVABLE; 5134514f5e3Sopenharmony_ci } 5144514f5e3Sopenharmony_ci 5154514f5e3Sopenharmony_ci bool InSharedHugeObjectSpace() const 5164514f5e3Sopenharmony_ci { 5174514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_SHARED_HUGE_OBJECT_SPACE; 5184514f5e3Sopenharmony_ci } 5194514f5e3Sopenharmony_ci 5204514f5e3Sopenharmony_ci bool InSharedReadOnlySpace() const 5214514f5e3Sopenharmony_ci { 5224514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_SHARED_READ_ONLY_SPACE; 5234514f5e3Sopenharmony_ci } 5244514f5e3Sopenharmony_ci 5254514f5e3Sopenharmony_ci bool InSharedAppSpawnSpace() const 5264514f5e3Sopenharmony_ci { 5274514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_SHARED_APPSPAWN_SPACE; 5284514f5e3Sopenharmony_ci } 5294514f5e3Sopenharmony_ci 5304514f5e3Sopenharmony_ci bool InAppSpawnSpace() const 5314514f5e3Sopenharmony_ci { 5324514f5e3Sopenharmony_ci return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_APPSPAWN_SPACE; 5334514f5e3Sopenharmony_ci } 5344514f5e3Sopenharmony_ci 5354514f5e3Sopenharmony_ci // Not including shared read only space. 5364514f5e3Sopenharmony_ci bool InSharedSweepableSpace() const 5374514f5e3Sopenharmony_ci { 5384514f5e3Sopenharmony_ci auto flag = packedData_.flags_.spaceFlag_; 5394514f5e3Sopenharmony_ci return flag >= RegionSpaceFlag::SHARED_SWEEPABLE_SPACE_BEGIN && 5404514f5e3Sopenharmony_ci flag <= RegionSpaceFlag::SHARED_SWEEPABLE_SPACE_END; 5414514f5e3Sopenharmony_ci } 5424514f5e3Sopenharmony_ci 5434514f5e3Sopenharmony_ci bool InSharedHeap() const 5444514f5e3Sopenharmony_ci { 5454514f5e3Sopenharmony_ci auto flag = packedData_.flags_.spaceFlag_; 5464514f5e3Sopenharmony_ci return flag >= RegionSpaceFlag::SHARED_SPACE_BEGIN && flag <= RegionSpaceFlag::SHARED_SPACE_END; 5474514f5e3Sopenharmony_ci } 5484514f5e3Sopenharmony_ci 5494514f5e3Sopenharmony_ci bool InSparseSpace() const 5504514f5e3Sopenharmony_ci { 5514514f5e3Sopenharmony_ci auto flag = packedData_.flags_.spaceFlag_; 5524514f5e3Sopenharmony_ci switch (flag) { 5534514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_OLD_SPACE: 5544514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_NON_MOVABLE_SPACE: 5554514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_MACHINE_CODE_SPACE: 5564514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_APPSPAWN_SPACE: 5574514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_SHARED_NON_MOVABLE: 5584514f5e3Sopenharmony_ci case RegionSpaceFlag::IN_SHARED_OLD_SPACE: 5594514f5e3Sopenharmony_ci return true; 5604514f5e3Sopenharmony_ci default: 5614514f5e3Sopenharmony_ci return false; 5624514f5e3Sopenharmony_ci } 5634514f5e3Sopenharmony_ci } 5644514f5e3Sopenharmony_ci 5654514f5e3Sopenharmony_ci bool InHeapSpace() const 5664514f5e3Sopenharmony_ci { 5674514f5e3Sopenharmony_ci uint8_t space = packedData_.flags_.spaceFlag_; 5684514f5e3Sopenharmony_ci return space >= RegionSpaceFlag::HEAP_SPACE_BEGIN && space <= RegionSpaceFlag::HEAP_SPACE_END; 5694514f5e3Sopenharmony_ci } 5704514f5e3Sopenharmony_ci 5714514f5e3Sopenharmony_ci bool InCollectSet() const 5724514f5e3Sopenharmony_ci { 5734514f5e3Sopenharmony_ci return IsGCFlagSet(RegionGCFlags::IN_COLLECT_SET); 5744514f5e3Sopenharmony_ci } 5754514f5e3Sopenharmony_ci 5764514f5e3Sopenharmony_ci bool InGeneralNewSpaceOrCSet() const 5774514f5e3Sopenharmony_ci { 5784514f5e3Sopenharmony_ci return InGeneralNewSpace() || InCollectSet(); 5794514f5e3Sopenharmony_ci } 5804514f5e3Sopenharmony_ci 5814514f5e3Sopenharmony_ci bool InNewToNewSet() const 5824514f5e3Sopenharmony_ci { 5834514f5e3Sopenharmony_ci return IsGCFlagSet(RegionGCFlags::IN_NEW_TO_NEW_SET); 5844514f5e3Sopenharmony_ci } 5854514f5e3Sopenharmony_ci 5864514f5e3Sopenharmony_ci bool HasAgeMark() const 5874514f5e3Sopenharmony_ci { 5884514f5e3Sopenharmony_ci return IsGCFlagSet(RegionGCFlags::HAS_AGE_MARK); 5894514f5e3Sopenharmony_ci } 5904514f5e3Sopenharmony_ci 5914514f5e3Sopenharmony_ci bool BelowAgeMark() const 5924514f5e3Sopenharmony_ci { 5934514f5e3Sopenharmony_ci return IsGCFlagSet(RegionGCFlags::BELOW_AGE_MARK); 5944514f5e3Sopenharmony_ci } 5954514f5e3Sopenharmony_ci 5964514f5e3Sopenharmony_ci bool NeedRelocate() const 5974514f5e3Sopenharmony_ci { 5984514f5e3Sopenharmony_ci return IsGCFlagSet(RegionGCFlags::NEED_RELOCATE); 5994514f5e3Sopenharmony_ci } 6004514f5e3Sopenharmony_ci 6014514f5e3Sopenharmony_ci // ONLY used for heap verification. 6024514f5e3Sopenharmony_ci bool InInactiveSemiSpace() const 6034514f5e3Sopenharmony_ci { 6044514f5e3Sopenharmony_ci return IsGCFlagSet(RegionGCFlags::IN_INACTIVE_SEMI_SPACE); 6054514f5e3Sopenharmony_ci } 6064514f5e3Sopenharmony_ci 6074514f5e3Sopenharmony_ci // ONLY used for heap verification. 6084514f5e3Sopenharmony_ci bool InActiveSemiSpace() const 6094514f5e3Sopenharmony_ci { 6104514f5e3Sopenharmony_ci return InYoungSpace() && !InInactiveSemiSpace(); 6114514f5e3Sopenharmony_ci } 6124514f5e3Sopenharmony_ci 6134514f5e3Sopenharmony_ci RegionTypeFlag GetRegionTypeFlag() const 6144514f5e3Sopenharmony_ci { 6154514f5e3Sopenharmony_ci return packedData_.typeFlag_; 6164514f5e3Sopenharmony_ci } 6174514f5e3Sopenharmony_ci 6184514f5e3Sopenharmony_ci void SetRegionTypeFlag(RegionTypeFlag typeFlag) 6194514f5e3Sopenharmony_ci { 6204514f5e3Sopenharmony_ci packedData_.typeFlag_ = typeFlag; 6214514f5e3Sopenharmony_ci } 6224514f5e3Sopenharmony_ci 6234514f5e3Sopenharmony_ci void ResetRegionTypeFlag() 6244514f5e3Sopenharmony_ci { 6254514f5e3Sopenharmony_ci SetRegionTypeFlag(RegionTypeFlag::DEFAULT); 6264514f5e3Sopenharmony_ci } 6274514f5e3Sopenharmony_ci 6284514f5e3Sopenharmony_ci bool IsFreshRegion() const 6294514f5e3Sopenharmony_ci { 6304514f5e3Sopenharmony_ci return GetRegionTypeFlag() == RegionTypeFlag::FRESH; 6314514f5e3Sopenharmony_ci } 6324514f5e3Sopenharmony_ci 6334514f5e3Sopenharmony_ci bool IsHalfFreshRegion() const 6344514f5e3Sopenharmony_ci { 6354514f5e3Sopenharmony_ci return GetRegionTypeFlag() == RegionTypeFlag::HALF_FRESH; 6364514f5e3Sopenharmony_ci } 6374514f5e3Sopenharmony_ci 6384514f5e3Sopenharmony_ci // ONLY used for heap verification. 6394514f5e3Sopenharmony_ci void SetInactiveSemiSpace() 6404514f5e3Sopenharmony_ci { 6414514f5e3Sopenharmony_ci SetGCFlag(RegionGCFlags::IN_INACTIVE_SEMI_SPACE); 6424514f5e3Sopenharmony_ci } 6434514f5e3Sopenharmony_ci 6444514f5e3Sopenharmony_ci // ONLY used for heap verification. 6454514f5e3Sopenharmony_ci void ResetInactiveSemiSpace() 6464514f5e3Sopenharmony_ci { 6474514f5e3Sopenharmony_ci ClearGCFlag(RegionGCFlags::IN_INACTIVE_SEMI_SPACE); 6484514f5e3Sopenharmony_ci } 6494514f5e3Sopenharmony_ci 6504514f5e3Sopenharmony_ci void SetSwept() 6514514f5e3Sopenharmony_ci { 6524514f5e3Sopenharmony_ci SetGCFlag(RegionGCFlags::HAS_BEEN_SWEPT); 6534514f5e3Sopenharmony_ci } 6544514f5e3Sopenharmony_ci 6554514f5e3Sopenharmony_ci void ResetSwept() 6564514f5e3Sopenharmony_ci { 6574514f5e3Sopenharmony_ci ClearGCFlag(RegionGCFlags::HAS_BEEN_SWEPT); 6584514f5e3Sopenharmony_ci } 6594514f5e3Sopenharmony_ci 6604514f5e3Sopenharmony_ci bool InRange(uintptr_t address) const 6614514f5e3Sopenharmony_ci { 6624514f5e3Sopenharmony_ci return address >= packedData_.begin_ && address <= end_; 6634514f5e3Sopenharmony_ci } 6644514f5e3Sopenharmony_ci 6654514f5e3Sopenharmony_ci uintptr_t GetAllocateBase() const 6664514f5e3Sopenharmony_ci { 6674514f5e3Sopenharmony_ci return allocateBase_; 6684514f5e3Sopenharmony_ci } 6694514f5e3Sopenharmony_ci 6704514f5e3Sopenharmony_ci size_t GetAllocatedBytes(uintptr_t top = 0) 6714514f5e3Sopenharmony_ci { 6724514f5e3Sopenharmony_ci ASSERT(top == 0 || InRange(top)); 6734514f5e3Sopenharmony_ci return (top == 0) ? (highWaterMark_ - packedData_.begin_) : (top - packedData_.begin_); 6744514f5e3Sopenharmony_ci } 6754514f5e3Sopenharmony_ci 6764514f5e3Sopenharmony_ci void SetHighWaterMark(uintptr_t mark) 6774514f5e3Sopenharmony_ci { 6784514f5e3Sopenharmony_ci ASSERT(InRange(mark)); 6794514f5e3Sopenharmony_ci highWaterMark_ = mark; 6804514f5e3Sopenharmony_ci } 6814514f5e3Sopenharmony_ci 6824514f5e3Sopenharmony_ci void SetReadOnlyAndMarked() 6834514f5e3Sopenharmony_ci { 6844514f5e3Sopenharmony_ci packedData_.markGCBitset_->SetAllBits(packedData_.bitsetSize_); 6854514f5e3Sopenharmony_ci PageProtect(reinterpret_cast<void *>(allocateBase_), GetCapacity(), PAGE_PROT_READ); 6864514f5e3Sopenharmony_ci } 6874514f5e3Sopenharmony_ci 6884514f5e3Sopenharmony_ci void ClearReadOnly() 6894514f5e3Sopenharmony_ci { 6904514f5e3Sopenharmony_ci PageProtect(reinterpret_cast<void *>(allocateBase_), GetCapacity(), PAGE_PROT_READWRITE); 6914514f5e3Sopenharmony_ci } 6924514f5e3Sopenharmony_ci 6934514f5e3Sopenharmony_ci void InitializeFreeObjectSets() 6944514f5e3Sopenharmony_ci { 6954514f5e3Sopenharmony_ci FreeObjectSet<FreeObject> **sets = new FreeObjectSet<FreeObject> *[FreeObjectList<FreeObject>::NumberOfSets()]; 6964514f5e3Sopenharmony_ci for (int i = 0; i < FreeObjectList<FreeObject>::NumberOfSets(); i++) { 6974514f5e3Sopenharmony_ci sets[i] = new FreeObjectSet<FreeObject>(i); 6984514f5e3Sopenharmony_ci } 6994514f5e3Sopenharmony_ci freeObjectSets_ = Span<FreeObjectSet<FreeObject> *>(sets, FreeObjectList<FreeObject>::NumberOfSets()); 7004514f5e3Sopenharmony_ci } 7014514f5e3Sopenharmony_ci 7024514f5e3Sopenharmony_ci void DestroyFreeObjectSets() 7034514f5e3Sopenharmony_ci { 7044514f5e3Sopenharmony_ci for (int i = 0; i < FreeObjectList<FreeObject>::NumberOfSets(); i++) { 7054514f5e3Sopenharmony_ci delete freeObjectSets_[i]; 7064514f5e3Sopenharmony_ci freeObjectSets_[i] = nullptr; 7074514f5e3Sopenharmony_ci } 7084514f5e3Sopenharmony_ci delete[] freeObjectSets_.data(); 7094514f5e3Sopenharmony_ci } 7104514f5e3Sopenharmony_ci 7114514f5e3Sopenharmony_ci FreeObjectSet<FreeObject> *GetFreeObjectSet(SetType type) 7124514f5e3Sopenharmony_ci { 7134514f5e3Sopenharmony_ci // Thread safe 7144514f5e3Sopenharmony_ci if (freeObjectSets_[type] == nullptr) { 7154514f5e3Sopenharmony_ci freeObjectSets_[type] = new FreeObjectSet<FreeObject>(type); 7164514f5e3Sopenharmony_ci } 7174514f5e3Sopenharmony_ci return freeObjectSets_[type]; 7184514f5e3Sopenharmony_ci } 7194514f5e3Sopenharmony_ci 7204514f5e3Sopenharmony_ci template<class Callback> 7214514f5e3Sopenharmony_ci void EnumerateFreeObjectSets(Callback cb) 7224514f5e3Sopenharmony_ci { 7234514f5e3Sopenharmony_ci for (auto set : freeObjectSets_) { 7244514f5e3Sopenharmony_ci cb(set); 7254514f5e3Sopenharmony_ci } 7264514f5e3Sopenharmony_ci } 7274514f5e3Sopenharmony_ci 7284514f5e3Sopenharmony_ci template<class Callback> 7294514f5e3Sopenharmony_ci void REnumerateFreeObjectSets(Callback cb) 7304514f5e3Sopenharmony_ci { 7314514f5e3Sopenharmony_ci auto last = freeObjectSets_.crbegin(); 7324514f5e3Sopenharmony_ci auto first = freeObjectSets_.crend(); 7334514f5e3Sopenharmony_ci for (; last != first; last++) { 7344514f5e3Sopenharmony_ci if (!cb(*last)) { 7354514f5e3Sopenharmony_ci break; 7364514f5e3Sopenharmony_ci } 7374514f5e3Sopenharmony_ci } 7384514f5e3Sopenharmony_ci } 7394514f5e3Sopenharmony_ci 7404514f5e3Sopenharmony_ci void IncreaseAliveObjectSafe(size_t size) 7414514f5e3Sopenharmony_ci { 7424514f5e3Sopenharmony_ci ASSERT(aliveObject_ + size <= GetSize()); 7434514f5e3Sopenharmony_ci aliveObject_ += size; 7444514f5e3Sopenharmony_ci } 7454514f5e3Sopenharmony_ci 7464514f5e3Sopenharmony_ci void IncreaseAliveObject(size_t size) 7474514f5e3Sopenharmony_ci { 7484514f5e3Sopenharmony_ci aliveObject_.fetch_add(size, std::memory_order_relaxed); 7494514f5e3Sopenharmony_ci } 7504514f5e3Sopenharmony_ci 7514514f5e3Sopenharmony_ci void SetRegionAliveSize() 7524514f5e3Sopenharmony_ci { 7534514f5e3Sopenharmony_ci gcAliveSize_ = aliveObject_; 7544514f5e3Sopenharmony_ci } 7554514f5e3Sopenharmony_ci 7564514f5e3Sopenharmony_ci void ResetAliveObject() 7574514f5e3Sopenharmony_ci { 7584514f5e3Sopenharmony_ci aliveObject_ = 0; 7594514f5e3Sopenharmony_ci } 7604514f5e3Sopenharmony_ci 7614514f5e3Sopenharmony_ci size_t AliveObject() const 7624514f5e3Sopenharmony_ci { 7634514f5e3Sopenharmony_ci return aliveObject_.load(std::memory_order_relaxed); 7644514f5e3Sopenharmony_ci } 7654514f5e3Sopenharmony_ci 7664514f5e3Sopenharmony_ci size_t GetGCAliveSize() const 7674514f5e3Sopenharmony_ci { 7684514f5e3Sopenharmony_ci return gcAliveSize_; 7694514f5e3Sopenharmony_ci } 7704514f5e3Sopenharmony_ci 7714514f5e3Sopenharmony_ci bool MostObjectAlive() const 7724514f5e3Sopenharmony_ci { 7734514f5e3Sopenharmony_ci return aliveObject_ > MOST_OBJECT_ALIVE_THRESHOLD_PERCENT * GetSize(); 7744514f5e3Sopenharmony_ci } 7754514f5e3Sopenharmony_ci 7764514f5e3Sopenharmony_ci bool BelowCompressThreasholdAlive() const 7774514f5e3Sopenharmony_ci { 7784514f5e3Sopenharmony_ci return gcAliveSize_ < COMPRESS_THREASHOLD_PERCENT * GetSize(); 7794514f5e3Sopenharmony_ci } 7804514f5e3Sopenharmony_ci 7814514f5e3Sopenharmony_ci void ResetWasted() 7824514f5e3Sopenharmony_ci { 7834514f5e3Sopenharmony_ci wasted_ = 0; 7844514f5e3Sopenharmony_ci } 7854514f5e3Sopenharmony_ci 7864514f5e3Sopenharmony_ci void IncreaseWasted(uint64_t size) 7874514f5e3Sopenharmony_ci { 7884514f5e3Sopenharmony_ci wasted_ += size; 7894514f5e3Sopenharmony_ci } 7904514f5e3Sopenharmony_ci 7914514f5e3Sopenharmony_ci uint64_t GetWastedSize() 7924514f5e3Sopenharmony_ci { 7934514f5e3Sopenharmony_ci return wasted_; 7944514f5e3Sopenharmony_ci } 7954514f5e3Sopenharmony_ci 7964514f5e3Sopenharmony_ci uint64_t GetSnapshotData() 7974514f5e3Sopenharmony_ci { 7984514f5e3Sopenharmony_ci return snapshotData_; 7994514f5e3Sopenharmony_ci } 8004514f5e3Sopenharmony_ci 8014514f5e3Sopenharmony_ci void SetSnapshotData(uint64_t value) 8024514f5e3Sopenharmony_ci { 8034514f5e3Sopenharmony_ci snapshotData_ = value; 8044514f5e3Sopenharmony_ci } 8054514f5e3Sopenharmony_ci 8064514f5e3Sopenharmony_ci void SwapOldToNewRSetForCS() 8074514f5e3Sopenharmony_ci { 8084514f5e3Sopenharmony_ci sweepingOldToNewRSet_ = packedData_.oldToNewSet_; 8094514f5e3Sopenharmony_ci packedData_.oldToNewSet_ = nullptr; 8104514f5e3Sopenharmony_ci } 8114514f5e3Sopenharmony_ci 8124514f5e3Sopenharmony_ci void SwapLocalToShareRSetForCS() 8134514f5e3Sopenharmony_ci { 8144514f5e3Sopenharmony_ci sweepingLocalToShareRSet_ = packedData_.localToShareSet_; 8154514f5e3Sopenharmony_ci packedData_.localToShareSet_ = nullptr; 8164514f5e3Sopenharmony_ci } 8174514f5e3Sopenharmony_ci 8184514f5e3Sopenharmony_ci void SetLocalHeap(uintptr_t localHeap) 8194514f5e3Sopenharmony_ci { 8204514f5e3Sopenharmony_ci ASSERT(localHeap != (uintptr_t)nullptr); 8214514f5e3Sopenharmony_ci localHeap_ = localHeap; 8224514f5e3Sopenharmony_ci } 8234514f5e3Sopenharmony_ci 8244514f5e3Sopenharmony_ci uintptr_t GetLocalHeap(void) 8254514f5e3Sopenharmony_ci { 8264514f5e3Sopenharmony_ci return localHeap_; 8274514f5e3Sopenharmony_ci } 8284514f5e3Sopenharmony_ci 8294514f5e3Sopenharmony_ci // should call in js-thread 8304514f5e3Sopenharmony_ci void MergeOldToNewRSetForCS(); 8314514f5e3Sopenharmony_ci void MergeLocalToShareRSetForCS(); 8324514f5e3Sopenharmony_ci 8334514f5e3Sopenharmony_ci // should call in daemon-thread, or in js-thread in RUNNING state 8344514f5e3Sopenharmony_ci void MergeLocalToShareRSetForCM(RememberedSet *set); 8354514f5e3Sopenharmony_ci 8364514f5e3Sopenharmony_ci struct alignas(JSTaggedValue::TaggedTypeSize()) PackedPtr : public base::AlignedPointer { 8374514f5e3Sopenharmony_ci uint8_t spaceFlag_; 8384514f5e3Sopenharmony_ci uint16_t gcFlags_; 8394514f5e3Sopenharmony_ci }; 8404514f5e3Sopenharmony_ci 8414514f5e3Sopenharmony_ci struct PackedData : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 8424514f5e3Sopenharmony_ci base::AlignedPointer, 8434514f5e3Sopenharmony_ci base::AlignedPointer, 8444514f5e3Sopenharmony_ci base::AlignedPointer, 8454514f5e3Sopenharmony_ci base::AlignedPointer, 8464514f5e3Sopenharmony_ci base::AlignedPointer, 8474514f5e3Sopenharmony_ci base::AlignedPointer, 8484514f5e3Sopenharmony_ci base::AlignedSize> { 8494514f5e3Sopenharmony_ci enum class Index : size_t { 8504514f5e3Sopenharmony_ci FlagsIndex = 0, 8514514f5e3Sopenharmony_ci TypeFlagIndex, 8524514f5e3Sopenharmony_ci MarkGCBitSetIndex, 8534514f5e3Sopenharmony_ci OldToNewSetIndex, 8544514f5e3Sopenharmony_ci LocalToShareSetIndex, 8554514f5e3Sopenharmony_ci BeginIndex, 8564514f5e3Sopenharmony_ci BitSetSizeIndex, 8574514f5e3Sopenharmony_ci NumOfMembers 8584514f5e3Sopenharmony_ci }; 8594514f5e3Sopenharmony_ci 8604514f5e3Sopenharmony_ci static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 8614514f5e3Sopenharmony_ci 8624514f5e3Sopenharmony_ci inline PackedData(uintptr_t begin, uintptr_t end, RegionSpaceFlag spaceType, RegionTypeFlag typeFlag) 8634514f5e3Sopenharmony_ci { 8644514f5e3Sopenharmony_ci flags_.spaceFlag_ = spaceType; 8654514f5e3Sopenharmony_ci flags_.gcFlags_ = 0; 8664514f5e3Sopenharmony_ci typeFlag_ = typeFlag; 8674514f5e3Sopenharmony_ci bitsetSize_ = (spaceType == RegionSpaceFlag::IN_HUGE_OBJECT_SPACE || 8684514f5e3Sopenharmony_ci spaceType == RegionSpaceFlag::IN_HUGE_MACHINE_CODE_SPACE || 8694514f5e3Sopenharmony_ci spaceType == RegionSpaceFlag::IN_SHARED_HUGE_OBJECT_SPACE) ? 8704514f5e3Sopenharmony_ci GCBitset::BYTE_PER_WORD : GCBitset::SizeOfGCBitset(end - begin); 8714514f5e3Sopenharmony_ci markGCBitset_ = new (ToVoidPtr(begin)) GCBitset(); 8724514f5e3Sopenharmony_ci markGCBitset_->Clear(bitsetSize_); 8734514f5e3Sopenharmony_ci begin_ = AlignUp(begin + bitsetSize_, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)); 8744514f5e3Sopenharmony_ci // The object region marked with poison until it is allocated if is_asan is true 8754514f5e3Sopenharmony_ci#ifdef ARK_ASAN_ON 8764514f5e3Sopenharmony_ci ASAN_POISON_MEMORY_REGION(reinterpret_cast<void *>(begin_), (end - begin_)); 8774514f5e3Sopenharmony_ci#endif 8784514f5e3Sopenharmony_ci } 8794514f5e3Sopenharmony_ci 8804514f5e3Sopenharmony_ci inline PackedData(uintptr_t begin, RegionSpaceFlag spaceType) 8814514f5e3Sopenharmony_ci { 8824514f5e3Sopenharmony_ci flags_.spaceFlag_ = spaceType; 8834514f5e3Sopenharmony_ci flags_.gcFlags_ = 0; 8844514f5e3Sopenharmony_ci typeFlag_ = RegionTypeFlag::DEFAULT; 8854514f5e3Sopenharmony_ci // no markGCBitset 8864514f5e3Sopenharmony_ci begin_ = begin; 8874514f5e3Sopenharmony_ci markGCBitset_ = nullptr; 8884514f5e3Sopenharmony_ci } 8894514f5e3Sopenharmony_ci 8904514f5e3Sopenharmony_ci static size_t GetFlagsOffset(bool isArch32) 8914514f5e3Sopenharmony_ci { 8924514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::FlagsIndex)>(isArch32); 8934514f5e3Sopenharmony_ci } 8944514f5e3Sopenharmony_ci 8954514f5e3Sopenharmony_ci static size_t GetTypeFlagOffset(bool isArch32) 8964514f5e3Sopenharmony_ci { 8974514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::TypeFlagIndex)>(isArch32); 8984514f5e3Sopenharmony_ci } 8994514f5e3Sopenharmony_ci 9004514f5e3Sopenharmony_ci static size_t GetGCBitsetOffset(bool isArch32) 9014514f5e3Sopenharmony_ci { 9024514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::MarkGCBitSetIndex)>(isArch32); 9034514f5e3Sopenharmony_ci } 9044514f5e3Sopenharmony_ci 9054514f5e3Sopenharmony_ci static size_t GetNewToEdenSetOffset(bool isArch32) 9064514f5e3Sopenharmony_ci { 9074514f5e3Sopenharmony_ci // NewToEdenRSet is Union with OldToNewRSet 9084514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::OldToNewSetIndex)>(isArch32); 9094514f5e3Sopenharmony_ci } 9104514f5e3Sopenharmony_ci 9114514f5e3Sopenharmony_ci static size_t GetOldToNewSetOffset(bool isArch32) 9124514f5e3Sopenharmony_ci { 9134514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::OldToNewSetIndex)>(isArch32); 9144514f5e3Sopenharmony_ci } 9154514f5e3Sopenharmony_ci 9164514f5e3Sopenharmony_ci static size_t GetLocalToShareSetOffset(bool isArch32) 9174514f5e3Sopenharmony_ci { 9184514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::LocalToShareSetIndex)>(isArch32); 9194514f5e3Sopenharmony_ci } 9204514f5e3Sopenharmony_ci 9214514f5e3Sopenharmony_ci static size_t GetBeginOffset(bool isArch32) 9224514f5e3Sopenharmony_ci { 9234514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::BeginIndex)>(isArch32); 9244514f5e3Sopenharmony_ci } 9254514f5e3Sopenharmony_ci 9264514f5e3Sopenharmony_ci alignas(EAS) PackedPtr flags_; 9274514f5e3Sopenharmony_ci // Use different UIntPtr from flags_ to prevent the potential data race. 9284514f5e3Sopenharmony_ci // Be careful when storing to this value, currently this is only from JS_Thread during ConcurrentMarking, 9294514f5e3Sopenharmony_ci // or from GC_Thread during GC ClearTask. 9304514f5e3Sopenharmony_ci alignas(EAS) RegionTypeFlag typeFlag_; 9314514f5e3Sopenharmony_ci alignas(EAS) GCBitset *markGCBitset_ {nullptr}; 9324514f5e3Sopenharmony_ci // OldToNewRSet only for general OldSpace, NewToEdenRSet only for YoungSpace. Their pointers can union 9334514f5e3Sopenharmony_ci union { 9344514f5e3Sopenharmony_ci alignas(EAS) RememberedSet *oldToNewSet_ {nullptr}; 9354514f5e3Sopenharmony_ci alignas(EAS) RememberedSet *newToEdenSet_; 9364514f5e3Sopenharmony_ci }; 9374514f5e3Sopenharmony_ci alignas(EAS) RememberedSet *localToShareSet_ {nullptr}; 9384514f5e3Sopenharmony_ci alignas(EAS) uintptr_t begin_ {0}; 9394514f5e3Sopenharmony_ci alignas(EAS) size_t bitsetSize_ {0}; 9404514f5e3Sopenharmony_ci }; 9414514f5e3Sopenharmony_ci STATIC_ASSERT_EQ_ARCH(sizeof(PackedData), PackedData::SizeArch32, PackedData::SizeArch64); 9424514f5e3Sopenharmony_ci 9434514f5e3Sopenharmony_ci static constexpr double MOST_OBJECT_ALIVE_THRESHOLD_PERCENT = 0.8; 9444514f5e3Sopenharmony_ci static constexpr double AVERAGE_REGION_EVACUATE_SIZE = MOST_OBJECT_ALIVE_THRESHOLD_PERCENT * 9454514f5e3Sopenharmony_ci DEFAULT_REGION_SIZE / 2; // 2 means half 9464514f5e3Sopenharmony_ciprivate: 9474514f5e3Sopenharmony_ci static constexpr double COMPRESS_THREASHOLD_PERCENT = 0.1; 9484514f5e3Sopenharmony_ci 9494514f5e3Sopenharmony_ci RememberedSet *CreateRememberedSet(); 9504514f5e3Sopenharmony_ci RememberedSet *GetOrCreateCrossRegionRememberedSet(); 9514514f5e3Sopenharmony_ci RememberedSet *GetOrCreateNewToEdenRememberedSet(); 9524514f5e3Sopenharmony_ci RememberedSet *GetOrCreateOldToNewRememberedSet(); 9534514f5e3Sopenharmony_ci RememberedSet *GetOrCreateLocalToShareRememberedSet(); 9544514f5e3Sopenharmony_ci 9554514f5e3Sopenharmony_ci inline RememberedSet *CreateNewToEdenRememberedSet(); 9564514f5e3Sopenharmony_ci inline RememberedSet *CreateOldToNewRememberedSet(); 9574514f5e3Sopenharmony_ci inline RememberedSet *CreateLocalToShareRememberedSet(); 9584514f5e3Sopenharmony_ci 9594514f5e3Sopenharmony_ci PackedData packedData_; 9604514f5e3Sopenharmony_ci NativeAreaAllocator *nativeAreaAllocator_; 9614514f5e3Sopenharmony_ci 9624514f5e3Sopenharmony_ci uintptr_t allocateBase_; 9634514f5e3Sopenharmony_ci uintptr_t end_; 9644514f5e3Sopenharmony_ci uintptr_t highWaterMark_; 9654514f5e3Sopenharmony_ci std::atomic_size_t aliveObject_ {0}; 9664514f5e3Sopenharmony_ci size_t gcAliveSize_ {0}; 9674514f5e3Sopenharmony_ci Region *next_ {nullptr}; 9684514f5e3Sopenharmony_ci Region *prev_ {nullptr}; 9694514f5e3Sopenharmony_ci 9704514f5e3Sopenharmony_ci RememberedSet *crossRegionSet_ {nullptr}; 9714514f5e3Sopenharmony_ci RememberedSet *sweepingOldToNewRSet_ {nullptr}; 9724514f5e3Sopenharmony_ci RememberedSet *sweepingLocalToShareRSet_ {nullptr}; 9734514f5e3Sopenharmony_ci Span<FreeObjectSet<FreeObject> *> freeObjectSets_; 9744514f5e3Sopenharmony_ci Mutex *lock_ {nullptr}; 9754514f5e3Sopenharmony_ci uint64_t wasted_; 9764514f5e3Sopenharmony_ci // snapshotdata_ is used to encode the region for snapshot. Its upper 32 bits are used to store the size of 9774514f5e3Sopenharmony_ci // the huge object, and the lower 32 bits are used to store the region index 9784514f5e3Sopenharmony_ci uint64_t snapshotData_; 9794514f5e3Sopenharmony_ci uintptr_t localHeap_ {0}; 9804514f5e3Sopenharmony_ci 9814514f5e3Sopenharmony_ci friend class Snapshot; 9824514f5e3Sopenharmony_ci friend class SnapshotProcessor; 9834514f5e3Sopenharmony_ci}; 9844514f5e3Sopenharmony_ci} // namespace ecmascript 9854514f5e3Sopenharmony_ci} // namespace panda 9864514f5e3Sopenharmony_ci#endif // ECMASCRIPT_MEM_REGION_H 987