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_MEMDESC_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_MEM_JIT_FORT_MEMDESC_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include <deque> 204514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h" 214514f5e3Sopenharmony_ci#include "ecmascript/base/asan_interface.h" 224514f5e3Sopenharmony_ci#include "ecmascript/platform/mutex.h" 234514f5e3Sopenharmony_ci 244514f5e3Sopenharmony_cinamespace panda::ecmascript { 254514f5e3Sopenharmony_ci 264514f5e3Sopenharmony_ci// Before Jit Fort, FreeList allocator uses FreeObject to link 274514f5e3Sopenharmony_ci// together free memory blocks in heap regions where each 284514f5e3Sopenharmony_ci// free memory block is a FreeObject with size of the block and 294514f5e3Sopenharmony_ci// a pointer to the next free block in the heap region. Its usage 304514f5e3Sopenharmony_ci// requires a mutable heap region and does not work with Jit Fort space 314514f5e3Sopenharmony_ci// which is immutbale execept for access by CodeSigner. 324514f5e3Sopenharmony_ci// 334514f5e3Sopenharmony_ci// When JIT Fort is enabled, FreeObject usage is replaced by MemDesc 344514f5e3Sopenharmony_ci// which serves same purpose as FreeObjects, but is stored outside of 354514f5e3Sopenharmony_ci// JitFort memory space. 364514f5e3Sopenharmony_ci// 374514f5e3Sopenharmony_ci// To reuse FreeList allocator code for JitFort, related classes 384514f5e3Sopenharmony_ci// (allocator/FreeObjectList/FreeObjectSet, etc) had to be changed into 394514f5e3Sopenharmony_ci// template classes to support both FreeObject and MemDesc targets, 404514f5e3Sopenharmony_ci// and MemDesc has to support same methods as FreeObject, and use the 414514f5e3Sopenharmony_ci// same null pointer value forlink pointer that FreeObject uses, i.e. 424514f5e3Sopenharmony_ci// NULL_POINTER with a value of 0x5 instead of 0. 434514f5e3Sopenharmony_ci// 444514f5e3Sopenharmony_ci#define INVALID_OBJPTR ((uintptr_t) JSTaggedValue::NULL_POINTER) 454514f5e3Sopenharmony_ci 464514f5e3Sopenharmony_ciclass MemDesc { 474514f5e3Sopenharmony_cipublic: 484514f5e3Sopenharmony_ci MemDesc() = default; 494514f5e3Sopenharmony_ci ~MemDesc() = default; 504514f5e3Sopenharmony_ci 514514f5e3Sopenharmony_ci static MemDesc *Cast(uintptr_t object) 524514f5e3Sopenharmony_ci { 534514f5e3Sopenharmony_ci return reinterpret_cast<MemDesc *>(object); 544514f5e3Sopenharmony_ci } 554514f5e3Sopenharmony_ci 564514f5e3Sopenharmony_ci inline uintptr_t GetBegin() const 574514f5e3Sopenharmony_ci { 584514f5e3Sopenharmony_ci return mem_; 594514f5e3Sopenharmony_ci } 604514f5e3Sopenharmony_ci 614514f5e3Sopenharmony_ci inline uintptr_t GetEnd() const 624514f5e3Sopenharmony_ci { 634514f5e3Sopenharmony_ci return mem_ + size_; 644514f5e3Sopenharmony_ci } 654514f5e3Sopenharmony_ci 664514f5e3Sopenharmony_ci inline void SetMem(uintptr_t mem) 674514f5e3Sopenharmony_ci { 684514f5e3Sopenharmony_ci mem_ = mem; 694514f5e3Sopenharmony_ci } 704514f5e3Sopenharmony_ci 714514f5e3Sopenharmony_ci inline void SetSize(size_t size) 724514f5e3Sopenharmony_ci { 734514f5e3Sopenharmony_ci size_ = size; 744514f5e3Sopenharmony_ci } 754514f5e3Sopenharmony_ci 764514f5e3Sopenharmony_ci inline void SetNext(MemDesc *desc) 774514f5e3Sopenharmony_ci { 784514f5e3Sopenharmony_ci next_ = desc; 794514f5e3Sopenharmony_ci } 804514f5e3Sopenharmony_ci 814514f5e3Sopenharmony_ci inline MemDesc *GetNext() 824514f5e3Sopenharmony_ci { 834514f5e3Sopenharmony_ci return next_; 844514f5e3Sopenharmony_ci } 854514f5e3Sopenharmony_ci 864514f5e3Sopenharmony_ci inline uint32_t Available() const 874514f5e3Sopenharmony_ci { 884514f5e3Sopenharmony_ci return size_; 894514f5e3Sopenharmony_ci } 904514f5e3Sopenharmony_ci 914514f5e3Sopenharmony_ci inline bool IsFreeObject() const 924514f5e3Sopenharmony_ci { 934514f5e3Sopenharmony_ci return true; // for compatibility with FreeObject 944514f5e3Sopenharmony_ci } 954514f5e3Sopenharmony_ci 964514f5e3Sopenharmony_ci inline void SetAvailable(uint32_t size) 974514f5e3Sopenharmony_ci { 984514f5e3Sopenharmony_ci size_ = size; 994514f5e3Sopenharmony_ci } 1004514f5e3Sopenharmony_ci 1014514f5e3Sopenharmony_ci inline void AsanPoisonFreeObject() const 1024514f5e3Sopenharmony_ci { 1034514f5e3Sopenharmony_ci ASAN_POISON_MEMORY_REGION((const volatile void *)mem_, size_); 1044514f5e3Sopenharmony_ci } 1054514f5e3Sopenharmony_ci 1064514f5e3Sopenharmony_ci inline void AsanUnPoisonFreeObject() const 1074514f5e3Sopenharmony_ci { 1084514f5e3Sopenharmony_ci ASAN_UNPOISON_MEMORY_REGION((const volatile void *)mem_, size_); 1094514f5e3Sopenharmony_ci } 1104514f5e3Sopenharmony_ci 1114514f5e3Sopenharmony_ci inline void SetInstalled(bool installed) 1124514f5e3Sopenharmony_ci { 1134514f5e3Sopenharmony_ci installed_.store(installed, std::memory_order_release); 1144514f5e3Sopenharmony_ci } 1154514f5e3Sopenharmony_ci 1164514f5e3Sopenharmony_ci inline bool IsInstalled() 1174514f5e3Sopenharmony_ci { 1184514f5e3Sopenharmony_ci return installed_.load(std::memory_order_acquire); 1194514f5e3Sopenharmony_ci } 1204514f5e3Sopenharmony_ci 1214514f5e3Sopenharmony_ciprivate: 1224514f5e3Sopenharmony_ci uintptr_t mem_ {0}; 1234514f5e3Sopenharmony_ci size_t size_ {0}; 1244514f5e3Sopenharmony_ci std::atomic<bool> installed_ {false}; 1254514f5e3Sopenharmony_ci MemDesc *next_ {MemDesc::Cast(INVALID_OBJPTR)}; 1264514f5e3Sopenharmony_ci}; 1274514f5e3Sopenharmony_ci 1284514f5e3Sopenharmony_ciclass MemDescPool { 1294514f5e3Sopenharmony_cipublic: 1304514f5e3Sopenharmony_ci MemDescPool(uintptr_t fortBegin, size_t fortSize); 1314514f5e3Sopenharmony_ci ~MemDescPool(); 1324514f5e3Sopenharmony_ci 1334514f5e3Sopenharmony_ci static inline bool IsEmpty(MemDesc* list) 1344514f5e3Sopenharmony_ci { 1354514f5e3Sopenharmony_ci return (list == nullptr || list == MemDesc::Cast(INVALID_OBJPTR)); 1364514f5e3Sopenharmony_ci } 1374514f5e3Sopenharmony_ci 1384514f5e3Sopenharmony_ci inline MemDesc *GetDescFromPool() 1394514f5e3Sopenharmony_ci { 1404514f5e3Sopenharmony_ci LockHolder lock(lock_); 1414514f5e3Sopenharmony_ci return GetDesc(); 1424514f5e3Sopenharmony_ci } 1434514f5e3Sopenharmony_ci 1444514f5e3Sopenharmony_ci inline void ReturnDescToPool(MemDesc *desc) 1454514f5e3Sopenharmony_ci { 1464514f5e3Sopenharmony_ci LockHolder lock(lock_); 1474514f5e3Sopenharmony_ci Add(desc); 1484514f5e3Sopenharmony_ci returned_++; 1494514f5e3Sopenharmony_ci } 1504514f5e3Sopenharmony_ci 1514514f5e3Sopenharmony_ci inline uintptr_t JitFortBegin() 1524514f5e3Sopenharmony_ci { 1534514f5e3Sopenharmony_ci return fortBegin_; 1544514f5e3Sopenharmony_ci } 1554514f5e3Sopenharmony_ci 1564514f5e3Sopenharmony_ci inline size_t JitFortSize() 1574514f5e3Sopenharmony_ci { 1584514f5e3Sopenharmony_ci return fortSize_; 1594514f5e3Sopenharmony_ci } 1604514f5e3Sopenharmony_ci 1614514f5e3Sopenharmony_ciprivate: 1624514f5e3Sopenharmony_ci MemDesc *GetDesc(); 1634514f5e3Sopenharmony_ci void Add(MemDesc *); 1644514f5e3Sopenharmony_ci void Expand(); 1654514f5e3Sopenharmony_ci 1664514f5e3Sopenharmony_ci static constexpr size_t MEMDESCS_PER_BLOCK = 100; 1674514f5e3Sopenharmony_ci MemDesc *freeList_ {nullptr}; 1684514f5e3Sopenharmony_ci std::deque<void *> memDescBlocks_; 1694514f5e3Sopenharmony_ci size_t allocated_ {0}; 1704514f5e3Sopenharmony_ci size_t returned_ {0}; 1714514f5e3Sopenharmony_ci size_t highwater_ {0}; 1724514f5e3Sopenharmony_ci Mutex lock_; 1734514f5e3Sopenharmony_ci 1744514f5e3Sopenharmony_ci uintptr_t fortBegin_; 1754514f5e3Sopenharmony_ci size_t fortSize_; 1764514f5e3Sopenharmony_ci}; 1774514f5e3Sopenharmony_ci 1784514f5e3Sopenharmony_ci} // namespace panda::ecmascript 1794514f5e3Sopenharmony_ci 1804514f5e3Sopenharmony_ci#endif // ECMASCRIPT_MEM_JIT_FORT_MEMDESC_H 181