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#include "ecmascript/mem/heap-inl.h" 174514f5e3Sopenharmony_ci#include "ecmascript/mem/jit_fort.h" 184514f5e3Sopenharmony_ci#include "ecmascript/jit/jit.h" 194514f5e3Sopenharmony_ci#if defined(JIT_ENABLE_CODE_SIGN) && !defined(JIT_FORT_DISABLE) 204514f5e3Sopenharmony_ci#include <sys/ioctl.h> 214514f5e3Sopenharmony_ci#include <sys/prctl.h> 224514f5e3Sopenharmony_ci 234514f5e3Sopenharmony_ci#define XPM_JITFORT_ENABLE_OPCODE 3 244514f5e3Sopenharmony_ci#define XPM_MAGIC 'x' 254514f5e3Sopenharmony_ci#define XPM_SET_JITFORT_ENABLE _IOW(XPM_MAGIC, XPM_JITFORT_ENABLE_OPCODE, unsigned long) 264514f5e3Sopenharmony_ci#endif 274514f5e3Sopenharmony_ci 284514f5e3Sopenharmony_cinamespace panda::ecmascript { 294514f5e3Sopenharmony_ci 304514f5e3Sopenharmony_citemplate <> 314514f5e3Sopenharmony_ciFreeListAllocator<MemDesc>::FreeListAllocator(BaseHeap *heap, MemDescPool *pool, JitFort *fort) 324514f5e3Sopenharmony_ci : memDescPool_(pool), heap_(heap) 334514f5e3Sopenharmony_ci{ 344514f5e3Sopenharmony_ci freeList_ = std::make_unique<FreeObjectList<MemDesc>>(fort); 354514f5e3Sopenharmony_ci} 364514f5e3Sopenharmony_ci 374514f5e3Sopenharmony_ciJitFort::JitFort() 384514f5e3Sopenharmony_ci{ 394514f5e3Sopenharmony_ci jitFortMem_ = PageMap(JIT_FORT_REG_SPACE_MAX, 404514f5e3Sopenharmony_ci PageProtectProt(Jit::GetInstance()->IsDisableCodeSign() || !IsResourceAvailable()), 414514f5e3Sopenharmony_ci DEFAULT_REGION_SIZE, nullptr, MAP_JITFORT); 424514f5e3Sopenharmony_ci jitFortBegin_ = reinterpret_cast<uintptr_t>(jitFortMem_.GetMem()); 434514f5e3Sopenharmony_ci jitFortSize_ = JIT_FORT_REG_SPACE_MAX; 444514f5e3Sopenharmony_ci memDescPool_ = new MemDescPool(jitFortBegin_, jitFortSize_); 454514f5e3Sopenharmony_ci allocator_ = new FreeListAllocator<MemDesc>(nullptr, memDescPool_, this); 464514f5e3Sopenharmony_ci InitRegions(); 474514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "JitFort Begin " << (void *)JitFortBegin() << " end " << (void *)(JitFortBegin() + JitFortSize()); 484514f5e3Sopenharmony_ci} 494514f5e3Sopenharmony_ci 504514f5e3Sopenharmony_ciJitFort::~JitFort() 514514f5e3Sopenharmony_ci{ 524514f5e3Sopenharmony_ci constexpr size_t numRegions = JIT_FORT_REG_SPACE_MAX / DEFAULT_REGION_SIZE; 534514f5e3Sopenharmony_ci for (size_t i = 0; i < numRegions; i++) { 544514f5e3Sopenharmony_ci regions_[i]->DestroyFreeObjectSets(); 554514f5e3Sopenharmony_ci delete regions_[i]; 564514f5e3Sopenharmony_ci } 574514f5e3Sopenharmony_ci delete allocator_; 584514f5e3Sopenharmony_ci delete memDescPool_; 594514f5e3Sopenharmony_ci PageUnmap(jitFortMem_); 604514f5e3Sopenharmony_ci} 614514f5e3Sopenharmony_ci 624514f5e3Sopenharmony_civoid JitFort::InitRegions() 634514f5e3Sopenharmony_ci{ 644514f5e3Sopenharmony_ci constexpr size_t numRegions = JIT_FORT_REG_SPACE_MAX / DEFAULT_REGION_SIZE; 654514f5e3Sopenharmony_ci for (size_t i = 0; i < numRegions; i++) { 664514f5e3Sopenharmony_ci uintptr_t mem = reinterpret_cast<uintptr_t>(jitFortMem_.GetMem()) + i*DEFAULT_REGION_SIZE; 674514f5e3Sopenharmony_ci uintptr_t end = mem + DEFAULT_REGION_SIZE; 684514f5e3Sopenharmony_ci JitFortRegion *region = new JitFortRegion(nullptr, mem, end, RegionSpaceFlag::IN_MACHINE_CODE_SPACE, 694514f5e3Sopenharmony_ci memDescPool_); 704514f5e3Sopenharmony_ci regions_[i] = region; 714514f5e3Sopenharmony_ci } 724514f5e3Sopenharmony_ci AddRegion(); 734514f5e3Sopenharmony_ci} 744514f5e3Sopenharmony_ci 754514f5e3Sopenharmony_cibool JitFort::AddRegion() 764514f5e3Sopenharmony_ci{ 774514f5e3Sopenharmony_ci if (nextFreeRegionIdx_ < MAX_JIT_FORT_REGIONS) { 784514f5e3Sopenharmony_ci allocator_->AddFree(regions_[nextFreeRegionIdx_]); 794514f5e3Sopenharmony_ci regionList_.AddNode(regions_[nextFreeRegionIdx_]); 804514f5e3Sopenharmony_ci nextFreeRegionIdx_++; 814514f5e3Sopenharmony_ci return true; 824514f5e3Sopenharmony_ci } 834514f5e3Sopenharmony_ci return false; 844514f5e3Sopenharmony_ci} 854514f5e3Sopenharmony_ci 864514f5e3Sopenharmony_ci// Fort buf allocation is in multiples of FORT_BUF_ALIGN 874514f5e3Sopenharmony_cisize_t JitFort::FortAllocSize(size_t instrSize) 884514f5e3Sopenharmony_ci{ 894514f5e3Sopenharmony_ci return(AlignUp(instrSize, FORT_BUF_ALIGN)); 904514f5e3Sopenharmony_ci} 914514f5e3Sopenharmony_ci 924514f5e3Sopenharmony_ciuintptr_t JitFort::Allocate(MachineCodeDesc *desc) 934514f5e3Sopenharmony_ci{ 944514f5e3Sopenharmony_ci LockHolder lock(mutex_); 954514f5e3Sopenharmony_ci 964514f5e3Sopenharmony_ci size_t size = FortAllocSize(desc->instructionsSize); 974514f5e3Sopenharmony_ci auto ret = allocator_->Allocate(size); 984514f5e3Sopenharmony_ci if (ret == ToUintPtr(nullptr)) { 994514f5e3Sopenharmony_ci if (AddRegion()) { 1004514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "JitFort: Allocate - AddRegion"; 1014514f5e3Sopenharmony_ci ret = allocator_->Allocate(size); 1024514f5e3Sopenharmony_ci } 1034514f5e3Sopenharmony_ci } 1044514f5e3Sopenharmony_ci if (ret == ToUintPtr(nullptr)) { 1054514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "JitFort:: Allocate return nullptr for size " << size; 1064514f5e3Sopenharmony_ci return ret; 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci // Record allocation to keep it from being collected by the next 1094514f5e3Sopenharmony_ci // JitFort::UpdateFreeSpace in case corresponding Machine code object is not 1104514f5e3Sopenharmony_ci // marked for sweep yet by then. 1114514f5e3Sopenharmony_ci ASSERT((ret & FORT_BUF_ADDR_MASK) == 0); 1124514f5e3Sopenharmony_ci MarkJitFortMemAwaitInstall(ret, size); 1134514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "JitFort:: Allocate " << (void *)ret << " - " << (void *)(ret+size-1) << 1144514f5e3Sopenharmony_ci " size " << size << " instructionsSize " << desc->instructionsSize; 1154514f5e3Sopenharmony_ci return ret; 1164514f5e3Sopenharmony_ci} 1174514f5e3Sopenharmony_ci 1184514f5e3Sopenharmony_ci// Called by GC thread during Mark to mark Fort buf alive. 1194514f5e3Sopenharmony_ci// Encoding details in GCBitset for marking live Fort buffers: 1204514f5e3Sopenharmony_ci// Begin of a live Fort buf: 1214514f5e3Sopenharmony_ci// - 10: a live Jit Fort buf that has been installed 1224514f5e3Sopenharmony_ci// - 11: a live Jit Fort buf that has not been installed yet 1234514f5e3Sopenharmony_ci// End of a live Fort buf: 1244514f5e3Sopenharmony_ci// - 01 1254514f5e3Sopenharmony_ci// This encoding requires 4 GCBitset bits to mark a live JitFort 1264514f5e3Sopenharmony_ci// buffer, which makes the minimum Fort buffer allocation size 32 bytes. 1274514f5e3Sopenharmony_civoid JitFort::MarkJitFortMemAlive(MachineCode *obj) 1284514f5e3Sopenharmony_ci{ 1294514f5e3Sopenharmony_ci size_t size = FortAllocSize(obj->GetInstructionsSize()); 1304514f5e3Sopenharmony_ci uintptr_t addr = obj->GetText(); 1314514f5e3Sopenharmony_ci uintptr_t endAddr = addr + size - 1; 1324514f5e3Sopenharmony_ci uint32_t regionIdx = AddrToFortRegionIdx(addr); 1334514f5e3Sopenharmony_ci regions_[regionIdx]->AtomicMark(reinterpret_cast<void *>(addr)); 1344514f5e3Sopenharmony_ci regions_[regionIdx]->AtomicMark(reinterpret_cast<void *>(endAddr)); 1354514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "MarkFortMemAlive: addr " << (void *)addr << " size " << size 1364514f5e3Sopenharmony_ci << " regionIdx " << regionIdx << " instructionsSize " << obj->GetInstructionsSize(); 1374514f5e3Sopenharmony_ci} 1384514f5e3Sopenharmony_ci 1394514f5e3Sopenharmony_ci// Called by Jit Compile thread during JitFort Allocate to mark Fort buf 1404514f5e3Sopenharmony_ci// awaiting install. Need mutex (JitGCLockHolder) for region gcBitset access. 1414514f5e3Sopenharmony_ci// See JitFort::MarkJitFortMemAlive comments for mark bit encoding in GC bitset. 1424514f5e3Sopenharmony_civoid JitFort::MarkJitFortMemAwaitInstall(uintptr_t addr, size_t size) 1434514f5e3Sopenharmony_ci{ 1444514f5e3Sopenharmony_ci uintptr_t endAddr = addr + size - 1; 1454514f5e3Sopenharmony_ci uint32_t regionIdx = AddrToFortRegionIdx(addr); 1464514f5e3Sopenharmony_ci regions_[regionIdx]->AtomicMark(reinterpret_cast<void *>(addr)); 1474514f5e3Sopenharmony_ci regions_[regionIdx]->AtomicMark(reinterpret_cast<void *>(addr + sizeof(uint64_t))); // mark next bit 1484514f5e3Sopenharmony_ci regions_[regionIdx]->AtomicMark(reinterpret_cast<void *>(endAddr)); 1494514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "MarkFortMemAwaitInstall: addr " << (void *)addr << " size " << size 1504514f5e3Sopenharmony_ci << " regionIdx " << regionIdx; 1514514f5e3Sopenharmony_ci} 1524514f5e3Sopenharmony_ci 1534514f5e3Sopenharmony_ci// Called by JS/Main thread during SafePoint to clear Fort buf AwaitInstall bit 1544514f5e3Sopenharmony_ci// See JitFort::MarkJitFortMemAlive comments for mark bit encoding in GC bitset. 1554514f5e3Sopenharmony_civoid JitFort::MarkJitFortMemInstalled(MachineCode *obj) 1564514f5e3Sopenharmony_ci{ 1574514f5e3Sopenharmony_ci size_t size = FortAllocSize(obj->GetInstructionsSize()); 1584514f5e3Sopenharmony_ci uintptr_t addr = obj->GetText(); 1594514f5e3Sopenharmony_ci uint32_t regionIdx = AddrToFortRegionIdx(addr); 1604514f5e3Sopenharmony_ci regions_[regionIdx]->GetGCBitset()->ClearMark(addr + sizeof(uint64_t)); // clear next bit 1614514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "MarkFortMemInstalled: addr " << (void *)addr << " size " << size 1624514f5e3Sopenharmony_ci << " regionIdx " << regionIdx << " instructionsSize " << obj->GetInstructionsSize(); 1634514f5e3Sopenharmony_ci} 1644514f5e3Sopenharmony_ci 1654514f5e3Sopenharmony_ciuint32_t JitFort::AddrToFortRegionIdx(uint64_t addr) 1664514f5e3Sopenharmony_ci{ 1674514f5e3Sopenharmony_ci ASSERT(InRange(addr)); 1684514f5e3Sopenharmony_ci uint32_t regionIdx = ((addr - JitFortBegin()) & ~(DEFAULT_REGION_MASK)) >> REGION_SIZE_LOG2; 1694514f5e3Sopenharmony_ci ASSERT(regionIdx < MAX_JIT_FORT_REGIONS); 1704514f5e3Sopenharmony_ci return regionIdx; 1714514f5e3Sopenharmony_ci} 1724514f5e3Sopenharmony_ci 1734514f5e3Sopenharmony_ci/* 1744514f5e3Sopenharmony_ci * Called from GC worker thread duing Old/Full GC Sweep (AsyncSweep). Mutex is needed 1754514f5e3Sopenharmony_ci * to ensure exclusive access to JitFort memory by GC thread when it frees JitFort mem 1764514f5e3Sopenharmony_ci * blocks, and by Jit compiled thread when it allocates Fort mem. 1774514f5e3Sopenharmony_ci */ 1784514f5e3Sopenharmony_civoid JitFort::UpdateFreeSpace() 1794514f5e3Sopenharmony_ci{ 1804514f5e3Sopenharmony_ci if (!Jit::GetInstance()->IsEnableJitFort()) { 1814514f5e3Sopenharmony_ci return; 1824514f5e3Sopenharmony_ci } 1834514f5e3Sopenharmony_ci 1844514f5e3Sopenharmony_ci LockHolder lock(mutex_); 1854514f5e3Sopenharmony_ci 1864514f5e3Sopenharmony_ci if (!regionList_.GetLength()) { // LCOV_EXCL_BR_LINE 1874514f5e3Sopenharmony_ci return; 1884514f5e3Sopenharmony_ci } 1894514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "UpdateFreeSpace enter: " << "Fort space allocated: " 1904514f5e3Sopenharmony_ci << allocator_->GetAllocatedSize() 1914514f5e3Sopenharmony_ci << " available: " << allocator_->GetAvailableSize(); 1924514f5e3Sopenharmony_ci allocator_->RebuildFreeList(); 1934514f5e3Sopenharmony_ci JitFortRegion *region = regionList_.GetFirst(); 1944514f5e3Sopenharmony_ci while (region) { 1954514f5e3Sopenharmony_ci FreeRegion(region); 1964514f5e3Sopenharmony_ci region = region->GetNext(); 1974514f5e3Sopenharmony_ci } 1984514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "UpdateFreeSpace exit: allocator_->GetAvailableSize " 1994514f5e3Sopenharmony_ci << allocator_->GetAvailableSize(); 2004514f5e3Sopenharmony_ci} 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_civoid JitFort::FreeRegion(JitFortRegion *region) 2034514f5e3Sopenharmony_ci{ 2044514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "JitFort FreeRegion " << (void*)(region->GetBegin()); 2054514f5e3Sopenharmony_ci 2064514f5e3Sopenharmony_ci uintptr_t freeStart = region->GetBegin(); 2074514f5e3Sopenharmony_ci region->GetGCBitset()->IterateMarkedBitsConst( 2084514f5e3Sopenharmony_ci region->GetBegin(), region->GetGCBitsetSize(), 2094514f5e3Sopenharmony_ci [this, ®ion, &freeStart](void *mem, size_t size) { 2104514f5e3Sopenharmony_ci ASSERT(region->InRange(ToUintPtr(mem))); 2114514f5e3Sopenharmony_ci (void) region; 2124514f5e3Sopenharmony_ci uintptr_t freeEnd = ToUintPtr(mem); 2134514f5e3Sopenharmony_ci if (freeStart != freeEnd) { 2144514f5e3Sopenharmony_ci allocator_->Free(freeStart, freeEnd - freeStart, true); 2154514f5e3Sopenharmony_ci } 2164514f5e3Sopenharmony_ci freeStart = freeEnd + size; 2174514f5e3Sopenharmony_ci }); 2184514f5e3Sopenharmony_ci uintptr_t freeEnd = region->GetEnd(); 2194514f5e3Sopenharmony_ci if (freeStart != freeEnd) { 2204514f5e3Sopenharmony_ci allocator_->Free(freeStart, freeEnd - freeStart, true); 2214514f5e3Sopenharmony_ci } 2224514f5e3Sopenharmony_ci} 2234514f5e3Sopenharmony_ci 2244514f5e3Sopenharmony_cibool JitFort::InRange(uintptr_t address) const 2254514f5e3Sopenharmony_ci{ 2264514f5e3Sopenharmony_ci return address >= jitFortBegin_ && (jitFortBegin_ + jitFortSize_) > 1 && 2274514f5e3Sopenharmony_ci address <= (jitFortBegin_ + jitFortSize_ - 1); 2284514f5e3Sopenharmony_ci} 2294514f5e3Sopenharmony_ci 2304514f5e3Sopenharmony_civoid JitFort::PrepareSweeping() 2314514f5e3Sopenharmony_ci{ 2324514f5e3Sopenharmony_ci isSweeping_.store(false, std::memory_order_release); 2334514f5e3Sopenharmony_ci} 2344514f5e3Sopenharmony_ci 2354514f5e3Sopenharmony_ci// concurrent sweep - only one of the AsyncSweep task will do JitFort sweep 2364514f5e3Sopenharmony_civoid JitFort::AsyncSweep() 2374514f5e3Sopenharmony_ci{ 2384514f5e3Sopenharmony_ci bool expect = false; 2394514f5e3Sopenharmony_ci if (isSweeping_.compare_exchange_strong(expect, true, std::memory_order_seq_cst)) { 2404514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "JitFort::AsyncSweep"; 2414514f5e3Sopenharmony_ci UpdateFreeSpace(); 2424514f5e3Sopenharmony_ci } 2434514f5e3Sopenharmony_ci} 2444514f5e3Sopenharmony_ci 2454514f5e3Sopenharmony_ci// non-concurrent sweep 2464514f5e3Sopenharmony_civoid JitFort::Sweep() 2474514f5e3Sopenharmony_ci{ 2484514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "JitFort::Sweep"; 2494514f5e3Sopenharmony_ci UpdateFreeSpace(); 2504514f5e3Sopenharmony_ci} 2514514f5e3Sopenharmony_ci 2524514f5e3Sopenharmony_ci// Used by JitFort::UpdateFreeSpace call path to find corresponding 2534514f5e3Sopenharmony_ci// JitFortRegion for a free block in JitFort space, in order to put the blk into 2544514f5e3Sopenharmony_ci// the corresponding free set of the JitFortRegion the free block belongs. 2554514f5e3Sopenharmony_ciJitFortRegion *JitFort::ObjectAddressToRange(uintptr_t addr) 2564514f5e3Sopenharmony_ci{ 2574514f5e3Sopenharmony_ci return regions_[AddrToFortRegionIdx(addr)]; 2584514f5e3Sopenharmony_ci} 2594514f5e3Sopenharmony_ci 2604514f5e3Sopenharmony_civoid JitFortGCBitset::MarkStartAddr(bool awaitInstall, uintptr_t startAddr, uint32_t index, uint32_t &word) 2614514f5e3Sopenharmony_ci{ 2624514f5e3Sopenharmony_ci if (!awaitInstall) { 2634514f5e3Sopenharmony_ci ClearMark(startAddr); 2644514f5e3Sopenharmony_ci word &= ~(1u << index); 2654514f5e3Sopenharmony_ci } else { 2664514f5e3Sopenharmony_ci word &= ~(1u << index); 2674514f5e3Sopenharmony_ci word &= ~(1u << (index+1)); 2684514f5e3Sopenharmony_ci } 2694514f5e3Sopenharmony_ci} 2704514f5e3Sopenharmony_ci 2714514f5e3Sopenharmony_civoid JitFortGCBitset::MarkEndAddr(bool awaitInstall, uintptr_t endAddr, uint32_t index, uint32_t &word) 2724514f5e3Sopenharmony_ci{ 2734514f5e3Sopenharmony_ci if (!awaitInstall) { 2744514f5e3Sopenharmony_ci ClearMark(endAddr - 1); 2754514f5e3Sopenharmony_ci } 2764514f5e3Sopenharmony_ci word &= ~(1u << index); 2774514f5e3Sopenharmony_ci} 2784514f5e3Sopenharmony_ci 2794514f5e3Sopenharmony_ci// See JitFort::MarkJitFortMemAlive comments for mark bit encoding in JitFort GC bitset. 2804514f5e3Sopenharmony_citemplate <typename Visitor> 2814514f5e3Sopenharmony_civoid JitFortGCBitset::IterateMarkedBitsConst(uintptr_t regionAddr, size_t bitsetSize, Visitor visitor) 2824514f5e3Sopenharmony_ci{ 2834514f5e3Sopenharmony_ci bool awaitInstall = false; 2844514f5e3Sopenharmony_ci uintptr_t startAddr = 0; 2854514f5e3Sopenharmony_ci uintptr_t endAddr = 0; 2864514f5e3Sopenharmony_ci 2874514f5e3Sopenharmony_ci auto words = Words(); 2884514f5e3Sopenharmony_ci uint32_t wordCount = WordCount(bitsetSize); 2894514f5e3Sopenharmony_ci uint32_t index = BIT_PER_WORD; 2904514f5e3Sopenharmony_ci for (uint32_t i = 0; i < wordCount; i++) { 2914514f5e3Sopenharmony_ci uint32_t word = words[i]; 2924514f5e3Sopenharmony_ci while (word != 0) { 2934514f5e3Sopenharmony_ci index = static_cast<uint32_t>(__builtin_ctz(word)); 2944514f5e3Sopenharmony_ci ASSERT(index < BIT_PER_WORD); 2954514f5e3Sopenharmony_ci if (!startAddr) { 2964514f5e3Sopenharmony_ci startAddr = regionAddr + (index << TAGGED_TYPE_SIZE_LOG); 2974514f5e3Sopenharmony_ci awaitInstall = Test(regionAddr + ((index+1) << TAGGED_TYPE_SIZE_LOG)); 2984514f5e3Sopenharmony_ci MarkStartAddr(awaitInstall, startAddr, index, word); 2994514f5e3Sopenharmony_ci } else { 3004514f5e3Sopenharmony_ci endAddr = regionAddr + ((index+1) << TAGGED_TYPE_SIZE_LOG); 3014514f5e3Sopenharmony_ci LOG_JIT(DEBUG) << "Live Jit Mem " << (void *)startAddr << " size " << endAddr-startAddr; 3024514f5e3Sopenharmony_ci visitor(reinterpret_cast<void *>(startAddr), endAddr - startAddr); 3034514f5e3Sopenharmony_ci MarkEndAddr(awaitInstall, endAddr, index, word); 3044514f5e3Sopenharmony_ci awaitInstall = false; 3054514f5e3Sopenharmony_ci startAddr = 0; 3064514f5e3Sopenharmony_ci } 3074514f5e3Sopenharmony_ci } 3084514f5e3Sopenharmony_ci regionAddr += TAGGED_TYPE_SIZE * BIT_PER_WORD; 3094514f5e3Sopenharmony_ci } 3104514f5e3Sopenharmony_ci} 3114514f5e3Sopenharmony_ci 3124514f5e3Sopenharmony_cibool JitFort::isResourceAvailable_ = true; 3134514f5e3Sopenharmony_cibool JitFort::IsResourceAvailable() 3144514f5e3Sopenharmony_ci{ 3154514f5e3Sopenharmony_ci return isResourceAvailable_; 3164514f5e3Sopenharmony_ci} 3174514f5e3Sopenharmony_civoid JitFort::InitJitFortResource() 3184514f5e3Sopenharmony_ci{ 3194514f5e3Sopenharmony_ci#if defined(JIT_ENABLE_CODE_SIGN) && !defined(JIT_FORT_DISABLE) 3204514f5e3Sopenharmony_ci ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "JIT::InitJitFortResource"); 3214514f5e3Sopenharmony_ci if (!Jit::GetInstance()->IsAppJit()) { 3224514f5e3Sopenharmony_ci int fd = open("/dev/xpm", O_RDWR); 3234514f5e3Sopenharmony_ci if (fd < 0) { 3244514f5e3Sopenharmony_ci isResourceAvailable_ = false; 3254514f5e3Sopenharmony_ci LOG_JIT(ERROR) << "Failed to init jitfort resource, open xpm failed: " << strerror(errno); 3264514f5e3Sopenharmony_ci return; 3274514f5e3Sopenharmony_ci } 3284514f5e3Sopenharmony_ci int rc = ioctl(fd, XPM_SET_JITFORT_ENABLE, 0); 3294514f5e3Sopenharmony_ci if (rc < 0) { 3304514f5e3Sopenharmony_ci isResourceAvailable_ = false; 3314514f5e3Sopenharmony_ci LOG_JIT(ERROR) << "Failed to init jitfort resource, enable xpm failed: " << strerror(errno); 3324514f5e3Sopenharmony_ci close(fd); 3334514f5e3Sopenharmony_ci return; 3344514f5e3Sopenharmony_ci } 3354514f5e3Sopenharmony_ci close(fd); 3364514f5e3Sopenharmony_ci } 3374514f5e3Sopenharmony_ci constexpr int prSetJitFort = 0x6a6974; 3384514f5e3Sopenharmony_ci constexpr int jitFortInit = 5; 3394514f5e3Sopenharmony_ci int res = prctl(prSetJitFort, jitFortInit, 0); 3404514f5e3Sopenharmony_ci if (res < 0) { 3414514f5e3Sopenharmony_ci isResourceAvailable_ = false; 3424514f5e3Sopenharmony_ci LOG_JIT(ERROR) << "Failed to init jitfort resource: " << strerror(errno); 3434514f5e3Sopenharmony_ci return; 3444514f5e3Sopenharmony_ci } 3454514f5e3Sopenharmony_ci res = prctl(prSetJitFort, jitFortInit, 0); 3464514f5e3Sopenharmony_ci if (res >= 0 || errno != EEXIST) { 3474514f5e3Sopenharmony_ci isResourceAvailable_ = false; 3484514f5e3Sopenharmony_ci LOG_JIT(ERROR) << "jitfort not support"; 3494514f5e3Sopenharmony_ci } 3504514f5e3Sopenharmony_ci#endif 3514514f5e3Sopenharmony_ci} 3524514f5e3Sopenharmony_ci 3534514f5e3Sopenharmony_ciMemDescPool::MemDescPool(uintptr_t fortBegin, size_t fortSize) 3544514f5e3Sopenharmony_ci : fortBegin_(fortBegin), fortSize_(fortSize) 3554514f5e3Sopenharmony_ci{ 3564514f5e3Sopenharmony_ci Expand(); 3574514f5e3Sopenharmony_ci} 3584514f5e3Sopenharmony_ci 3594514f5e3Sopenharmony_ciMemDescPool::~MemDescPool() 3604514f5e3Sopenharmony_ci{ 3614514f5e3Sopenharmony_ci for (const auto& block : memDescBlocks_) { 3624514f5e3Sopenharmony_ci if (block) { 3634514f5e3Sopenharmony_ci free(block); 3644514f5e3Sopenharmony_ci } 3654514f5e3Sopenharmony_ci } 3664514f5e3Sopenharmony_ci} 3674514f5e3Sopenharmony_ci 3684514f5e3Sopenharmony_ciMemDesc *MemDescPool::GetDesc() 3694514f5e3Sopenharmony_ci{ 3704514f5e3Sopenharmony_ci if (IsEmpty(freeList_)) { 3714514f5e3Sopenharmony_ci Expand(); 3724514f5e3Sopenharmony_ci } 3734514f5e3Sopenharmony_ci if (!IsEmpty(freeList_)) { // LCOV_EXCL_BR_LINE 3744514f5e3Sopenharmony_ci MemDesc *res = freeList_; 3754514f5e3Sopenharmony_ci freeList_ = freeList_->GetNext(); 3764514f5e3Sopenharmony_ci allocated_++; 3774514f5e3Sopenharmony_ci if (allocated_-returned_ > highwater_) { 3784514f5e3Sopenharmony_ci highwater_ = allocated_ - returned_; 3794514f5e3Sopenharmony_ci } 3804514f5e3Sopenharmony_ci return res; 3814514f5e3Sopenharmony_ci } 3824514f5e3Sopenharmony_ci return nullptr; 3834514f5e3Sopenharmony_ci} 3844514f5e3Sopenharmony_ci 3854514f5e3Sopenharmony_civoid MemDescPool::Expand() 3864514f5e3Sopenharmony_ci{ 3874514f5e3Sopenharmony_ci void *block = malloc(sizeof(MemDesc) * MEMDESCS_PER_BLOCK); 3884514f5e3Sopenharmony_ci if (block) { 3894514f5e3Sopenharmony_ci memDescBlocks_.push_back(block); 3904514f5e3Sopenharmony_ci for (size_t i = 0; i < MEMDESCS_PER_BLOCK; ++i) { 3914514f5e3Sopenharmony_ci Add(new (ToVoidPtr(reinterpret_cast<uintptr_t>(block) + i*sizeof(MemDesc))) MemDesc()); 3924514f5e3Sopenharmony_ci } 3934514f5e3Sopenharmony_ci } 3944514f5e3Sopenharmony_ci} 3954514f5e3Sopenharmony_ci 3964514f5e3Sopenharmony_civoid MemDescPool::Add(MemDesc *desc) 3974514f5e3Sopenharmony_ci{ 3984514f5e3Sopenharmony_ci desc->SetNext(freeList_); 3994514f5e3Sopenharmony_ci freeList_ = desc; 4004514f5e3Sopenharmony_ci} 4014514f5e3Sopenharmony_ci 4024514f5e3Sopenharmony_ci} // namespace panda::ecmascript 403