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_JIT_FORT_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_MEM_JIT_FORT_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include <array> 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_ci#include "ecmascript/mem/mem_common.h" 224514f5e3Sopenharmony_ci#include "ecmascript/mem/region.h" 234514f5e3Sopenharmony_ci#include "ecmascript/mem/machine_code.h" 244514f5e3Sopenharmony_ci 254514f5e3Sopenharmony_cinamespace panda::ecmascript { 264514f5e3Sopenharmony_ci 274514f5e3Sopenharmony_ciclass JitFortRegion; 284514f5e3Sopenharmony_ciclass JitFortMemDescPool; 294514f5e3Sopenharmony_citemplate <typename T> 304514f5e3Sopenharmony_ciclass FreeListAllocator; 314514f5e3Sopenharmony_ci 324514f5e3Sopenharmony_ciclass JitFort { 334514f5e3Sopenharmony_cipublic: 344514f5e3Sopenharmony_ci JitFort(); 354514f5e3Sopenharmony_ci ~JitFort(); 364514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(JitFort); 374514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(JitFort); 384514f5e3Sopenharmony_ci 394514f5e3Sopenharmony_ci void InitRegions(); 404514f5e3Sopenharmony_ci bool AddRegion(); 414514f5e3Sopenharmony_ci uintptr_t Allocate(MachineCodeDesc *desc); 424514f5e3Sopenharmony_ci 434514f5e3Sopenharmony_ci inline JitFortRegion *GetRegionList() 444514f5e3Sopenharmony_ci { 454514f5e3Sopenharmony_ci return regionList_.GetFirst(); 464514f5e3Sopenharmony_ci } 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_ci inline uintptr_t JitFortBegin() 494514f5e3Sopenharmony_ci { 504514f5e3Sopenharmony_ci return jitFortBegin_; 514514f5e3Sopenharmony_ci } 524514f5e3Sopenharmony_ci 534514f5e3Sopenharmony_ci inline size_t JitFortSize() 544514f5e3Sopenharmony_ci { 554514f5e3Sopenharmony_ci return jitFortSize_; 564514f5e3Sopenharmony_ci } 574514f5e3Sopenharmony_ci 584514f5e3Sopenharmony_ci bool InRange(uintptr_t address) const; 594514f5e3Sopenharmony_ci void CollectFreeRanges(JitFortRegion *region); 604514f5e3Sopenharmony_ci void UpdateFreeSpace(); 614514f5e3Sopenharmony_ci 624514f5e3Sopenharmony_ci JitFortRegion *ObjectAddressToRange(uintptr_t objAddress); 634514f5e3Sopenharmony_ci static void InitJitFortResource(); 644514f5e3Sopenharmony_ci void PrepareSweeping(); 654514f5e3Sopenharmony_ci void AsyncSweep(); 664514f5e3Sopenharmony_ci void Sweep(); 674514f5e3Sopenharmony_ci void MarkJitFortMemAlive(MachineCode *obj); 684514f5e3Sopenharmony_ci void MarkJitFortMemAwaitInstall(uintptr_t addr, size_t size); 694514f5e3Sopenharmony_ci void MarkJitFortMemInstalled(MachineCode *obj); 704514f5e3Sopenharmony_ci void FreeRegion(JitFortRegion *region); 714514f5e3Sopenharmony_ci uint32_t AddrToFortRegionIdx(uint64_t addr); 724514f5e3Sopenharmony_ci size_t FortAllocSize(size_t instrSize); 734514f5e3Sopenharmony_ci PUBLIC_API static bool IsResourceAvailable(); 744514f5e3Sopenharmony_ci 754514f5e3Sopenharmony_ciprivate: 764514f5e3Sopenharmony_ci static bool isResourceAvailable_; 774514f5e3Sopenharmony_ci FreeListAllocator<MemDesc> *allocator_ {nullptr}; 784514f5e3Sopenharmony_ci 794514f5e3Sopenharmony_ci // Fort memory space 804514f5e3Sopenharmony_ci static constexpr int MAP_JITFORT = 0x1000; 814514f5e3Sopenharmony_ci static constexpr size_t JIT_FORT_REG_SPACE_MAX = 4_MB; 824514f5e3Sopenharmony_ci static constexpr size_t JIT_FORT_HUGE_SPACE_MAX = 2_MB; 834514f5e3Sopenharmony_ci static constexpr size_t JIT_FORT_MEM_DESC_MAX = 40_KB; 844514f5e3Sopenharmony_ci MemMap jitFortMem_; 854514f5e3Sopenharmony_ci uintptr_t jitFortBegin_ {0}; 864514f5e3Sopenharmony_ci size_t jitFortSize_ {0}; 874514f5e3Sopenharmony_ci 884514f5e3Sopenharmony_ci // Fort regions 894514f5e3Sopenharmony_ci static constexpr uint32_t FORT_BUF_ALIGN = 32; 904514f5e3Sopenharmony_ci static constexpr uint32_t FORT_BUF_ALIGN_LOG2 = base::MathHelper::GetIntLog2(FORT_BUF_ALIGN); 914514f5e3Sopenharmony_ci static constexpr size_t FORT_BUF_ADDR_MASK = FORT_BUF_ALIGN - 1; 924514f5e3Sopenharmony_ci static constexpr size_t MAX_JIT_FORT_REGIONS = JIT_FORT_REG_SPACE_MAX/DEFAULT_REGION_SIZE; 934514f5e3Sopenharmony_ci std::array<JitFortRegion *, MAX_JIT_FORT_REGIONS>regions_; 944514f5e3Sopenharmony_ci size_t nextFreeRegionIdx_ {0}; 954514f5e3Sopenharmony_ci EcmaList<JitFortRegion> regionList_ {}; // regions in use by Jit Fort allocator 964514f5e3Sopenharmony_ci 974514f5e3Sopenharmony_ci MemDescPool *memDescPool_ {nullptr}; 984514f5e3Sopenharmony_ci 994514f5e3Sopenharmony_ci bool freeListUpdated_ {false}; // use atomic if not mutext protected 1004514f5e3Sopenharmony_ci Mutex mutex_; 1014514f5e3Sopenharmony_ci Mutex liveJitCodeBlksLock_; 1024514f5e3Sopenharmony_ci std::atomic<bool> isSweeping_ {false}; 1034514f5e3Sopenharmony_ci friend class HugeMachineCodeSpace; 1044514f5e3Sopenharmony_ci}; 1054514f5e3Sopenharmony_ci 1064514f5e3Sopenharmony_ciclass JitFortGCBitset : public GCBitset { 1074514f5e3Sopenharmony_cipublic: 1084514f5e3Sopenharmony_ci JitFortGCBitset() = default; 1094514f5e3Sopenharmony_ci ~JitFortGCBitset() = default; 1104514f5e3Sopenharmony_ci 1114514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(JitFortGCBitset); 1124514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(JitFortGCBitset); 1134514f5e3Sopenharmony_ci 1144514f5e3Sopenharmony_ci template <typename Visitor> 1154514f5e3Sopenharmony_ci void IterateMarkedBitsConst(uintptr_t regionAddr, size_t bitsetSize, Visitor visitor); 1164514f5e3Sopenharmony_ci void MarkStartAddr(bool awaitInstall, uintptr_t startAddr, uint32_t index, uint32_t &word); 1174514f5e3Sopenharmony_ci void MarkEndAddr(bool awaitInstall, uintptr_t endAddr, uint32_t index, uint32_t &word); 1184514f5e3Sopenharmony_ci 1194514f5e3Sopenharmony_ci size_t WordCount(size_t size) const 1204514f5e3Sopenharmony_ci { 1214514f5e3Sopenharmony_ci return size >> BYTE_PER_WORD_LOG2; 1224514f5e3Sopenharmony_ci } 1234514f5e3Sopenharmony_ci 1244514f5e3Sopenharmony_ci inline void ClearMark(uintptr_t addr) 1254514f5e3Sopenharmony_ci { 1264514f5e3Sopenharmony_ci ClearBit((addr & DEFAULT_REGION_MASK) >> TAGGED_TYPE_SIZE_LOG); 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci 1294514f5e3Sopenharmony_ci inline bool Test(uintptr_t addr) 1304514f5e3Sopenharmony_ci { 1314514f5e3Sopenharmony_ci return TestBit((addr & DEFAULT_REGION_MASK) >> TAGGED_TYPE_SIZE_LOG); 1324514f5e3Sopenharmony_ci } 1334514f5e3Sopenharmony_ci}; 1344514f5e3Sopenharmony_ci 1354514f5e3Sopenharmony_ciclass JitFortRegion : public Region { 1364514f5e3Sopenharmony_cipublic: 1374514f5e3Sopenharmony_ci JitFortRegion(NativeAreaAllocator *allocator, uintptr_t allocateBase, uintptr_t end, 1384514f5e3Sopenharmony_ci RegionSpaceFlag spaceType, MemDescPool *pool) : Region(allocator, allocateBase, end, spaceType), 1394514f5e3Sopenharmony_ci memDescPool_(pool) 1404514f5e3Sopenharmony_ci { 1414514f5e3Sopenharmony_ci markGCBitset_ = new(reinterpret_cast<void *>(gcBitSet_)) JitFortGCBitset(); 1424514f5e3Sopenharmony_ci markGCBitset_->Clear(bitsetSize_); 1434514f5e3Sopenharmony_ci InitializeFreeObjectSets(); 1444514f5e3Sopenharmony_ci } 1454514f5e3Sopenharmony_ci 1464514f5e3Sopenharmony_ci void InitializeFreeObjectSets() 1474514f5e3Sopenharmony_ci { 1484514f5e3Sopenharmony_ci fortFreeObjectSets_ = Span<FreeObjectSet<MemDesc> *>(new FreeObjectSet<MemDesc> 1494514f5e3Sopenharmony_ci *[FreeObjectList<MemDesc>::NumberOfSets()](), FreeObjectList<MemDesc>::NumberOfSets()); 1504514f5e3Sopenharmony_ci } 1514514f5e3Sopenharmony_ci 1524514f5e3Sopenharmony_ci void DestroyFreeObjectSets() 1534514f5e3Sopenharmony_ci { 1544514f5e3Sopenharmony_ci for (auto set : fortFreeObjectSets_) { 1554514f5e3Sopenharmony_ci delete set; 1564514f5e3Sopenharmony_ci } 1574514f5e3Sopenharmony_ci delete[] fortFreeObjectSets_.data(); 1584514f5e3Sopenharmony_ci } 1594514f5e3Sopenharmony_ci 1604514f5e3Sopenharmony_ci FreeObjectSet<MemDesc> *GetFreeObjectSet(SetType type) 1614514f5e3Sopenharmony_ci { 1624514f5e3Sopenharmony_ci // Thread safe 1634514f5e3Sopenharmony_ci if (fortFreeObjectSets_[type] == nullptr) { 1644514f5e3Sopenharmony_ci fortFreeObjectSets_[type] = new FreeObjectSet<MemDesc>(type, memDescPool_); 1654514f5e3Sopenharmony_ci } 1664514f5e3Sopenharmony_ci return fortFreeObjectSets_[type]; 1674514f5e3Sopenharmony_ci } 1684514f5e3Sopenharmony_ci 1694514f5e3Sopenharmony_ci inline void LinkNext(JitFortRegion *next) 1704514f5e3Sopenharmony_ci { 1714514f5e3Sopenharmony_ci next_ = next; 1724514f5e3Sopenharmony_ci } 1734514f5e3Sopenharmony_ci 1744514f5e3Sopenharmony_ci inline JitFortRegion *GetNext() const 1754514f5e3Sopenharmony_ci { 1764514f5e3Sopenharmony_ci return next_; 1774514f5e3Sopenharmony_ci } 1784514f5e3Sopenharmony_ci 1794514f5e3Sopenharmony_ci inline void LinkPrev(JitFortRegion *prev) 1804514f5e3Sopenharmony_ci { 1814514f5e3Sopenharmony_ci prev_ = prev; 1824514f5e3Sopenharmony_ci } 1834514f5e3Sopenharmony_ci 1844514f5e3Sopenharmony_ci inline JitFortRegion *GetPrev() const 1854514f5e3Sopenharmony_ci { 1864514f5e3Sopenharmony_ci return prev_; 1874514f5e3Sopenharmony_ci } 1884514f5e3Sopenharmony_ci 1894514f5e3Sopenharmony_ci inline JitFortGCBitset *GetGCBitset() 1904514f5e3Sopenharmony_ci { 1914514f5e3Sopenharmony_ci return markGCBitset_; 1924514f5e3Sopenharmony_ci } 1934514f5e3Sopenharmony_ci 1944514f5e3Sopenharmony_ci inline size_t GetGCBitsetSize() 1954514f5e3Sopenharmony_ci { 1964514f5e3Sopenharmony_ci return bitsetSize_; 1974514f5e3Sopenharmony_ci } 1984514f5e3Sopenharmony_ci 1994514f5e3Sopenharmony_ci inline bool AtomicMark(void *address) 2004514f5e3Sopenharmony_ci { 2014514f5e3Sopenharmony_ci auto addrPtr = reinterpret_cast<uintptr_t>(address); 2024514f5e3Sopenharmony_ci ASSERT(InRange(addrPtr)); 2034514f5e3Sopenharmony_ci return markGCBitset_->SetBit<AccessType::ATOMIC>( 2044514f5e3Sopenharmony_ci (addrPtr & DEFAULT_REGION_MASK) >> TAGGED_TYPE_SIZE_LOG); 2054514f5e3Sopenharmony_ci } 2064514f5e3Sopenharmony_ci 2074514f5e3Sopenharmony_ciprivate: 2084514f5e3Sopenharmony_ci Span<FreeObjectSet<MemDesc> *> fortFreeObjectSets_; 2094514f5e3Sopenharmony_ci JitFortRegion *next_ {nullptr}; 2104514f5e3Sopenharmony_ci JitFortRegion *prev_ {nullptr}; 2114514f5e3Sopenharmony_ci MemDescPool *memDescPool_ {nullptr}; 2124514f5e3Sopenharmony_ci 2134514f5e3Sopenharmony_ci static constexpr int FORT_REGION_BITSET_SIZE = 4096; 2144514f5e3Sopenharmony_ci size_t bitsetSize_ {FORT_REGION_BITSET_SIZE}; 2154514f5e3Sopenharmony_ci alignas(uint64_t) uint8_t gcBitSet_[FORT_REGION_BITSET_SIZE]; 2164514f5e3Sopenharmony_ci alignas(uint64_t) JitFortGCBitset *markGCBitset_ {nullptr}; 2174514f5e3Sopenharmony_ci}; 2184514f5e3Sopenharmony_ci 2194514f5e3Sopenharmony_ci} // namespace panda::ecmascript 2204514f5e3Sopenharmony_ci#endif // ECMASCRIPT_MEM_SPARSE_SPACE_H 221