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, &region, &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