1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_MEM_JIT_FORT_H 17 #define ECMASCRIPT_MEM_JIT_FORT_H 18 19 #include <array> 20 21 #include "ecmascript/mem/mem_common.h" 22 #include "ecmascript/mem/region.h" 23 #include "ecmascript/mem/machine_code.h" 24 25 namespace panda::ecmascript { 26 27 class JitFortRegion; 28 class JitFortMemDescPool; 29 template <typename T> 30 class FreeListAllocator; 31 32 class JitFort { 33 public: 34 JitFort(); 35 ~JitFort(); 36 NO_COPY_SEMANTIC(JitFort); 37 NO_MOVE_SEMANTIC(JitFort); 38 39 void InitRegions(); 40 bool AddRegion(); 41 uintptr_t Allocate(MachineCodeDesc *desc); 42 GetRegionList()43 inline JitFortRegion *GetRegionList() 44 { 45 return regionList_.GetFirst(); 46 } 47 JitFortBegin()48 inline uintptr_t JitFortBegin() 49 { 50 return jitFortBegin_; 51 } 52 JitFortSize()53 inline size_t JitFortSize() 54 { 55 return jitFortSize_; 56 } 57 IsMachineCodeGC()58 inline bool IsMachineCodeGC() 59 { 60 return isMachineCodeGC_.load(std::memory_order_acquire); 61 } 62 SetMachineCodeGC(bool flag)63 inline void SetMachineCodeGC(bool flag) 64 { 65 LOG_JIT(DEBUG) << "SetMachineCodeGC " << flag; 66 isMachineCodeGC_.store(flag, std::memory_order_release); 67 } 68 69 bool InRange(uintptr_t address) const; 70 MemDesc *RecordLiveJitCode(uintptr_t addr, size_t size, bool installed = true); 71 MemDesc *RecordLiveJitCodeNoLock(uintptr_t addr, size_t size, bool installed = false); 72 void CollectFreeRanges(JitFortRegion *region); 73 void SortLiveMemDescList(); 74 void UpdateFreeSpace(); 75 JitFortRegion *ObjectAddressToRange(uintptr_t objAddress); 76 static void InitJitFortResource(); 77 PUBLIC_API static bool IsResourceAvailable(); 78 79 private: 80 static bool isResourceAvailable_; 81 FreeListAllocator<MemDesc> *allocator_ {nullptr}; 82 83 // Fort memory space 84 static constexpr int MAP_JITFORT = 0x1000; 85 static constexpr size_t JIT_FORT_REG_SPACE_MAX = 4_MB; 86 static constexpr size_t JIT_FORT_HUGE_SPACE_MAX = 2_MB; 87 static constexpr size_t JIT_FORT_MEM_DESC_MAX = 40_KB; 88 MemMap jitFortMem_; 89 uintptr_t jitFortBegin_ {0}; 90 size_t jitFortSize_ {0}; 91 92 // Fort regions 93 static constexpr size_t MAX_JIT_FORT_REGIONS = JIT_FORT_REG_SPACE_MAX/DEFAULT_REGION_SIZE; 94 std::array<JitFortRegion *, MAX_JIT_FORT_REGIONS>regions_; 95 size_t nextFreeRegionIdx_ {0}; 96 EcmaList<JitFortRegion> regionList_ {}; // regions in use by Jit Fort allocator 97 98 // Jit Fort MemDesc to track live code blocks in Jit Fort space 99 std::vector<MemDesc*>liveJitCodeBlks_; 100 MemDescPool *memDescPool_ {nullptr}; 101 102 bool freeListUpdated_ {false}; // use atomic if not mutext protected 103 Mutex mutex_; 104 Mutex liveJitCodeBlksLock_; 105 std::atomic<bool> isMachineCodeGC_ {false}; 106 friend class HugeMachineCodeSpace; 107 }; 108 109 class JitFortRegion : public Region { 110 public: JitFortRegion(NativeAreaAllocator * allocator,uintptr_t allocateBase,uintptr_t end,RegionSpaceFlag spaceType,MemDescPool * pool)111 JitFortRegion(NativeAreaAllocator *allocator, uintptr_t allocateBase, uintptr_t end, 112 RegionSpaceFlag spaceType, MemDescPool *pool) : Region(allocator, allocateBase, end, spaceType), 113 memDescPool_(pool) {} 114 InitializeFreeObjectSets()115 void InitializeFreeObjectSets() 116 { 117 fortFreeObjectSets_ = Span<FreeObjectSet<MemDesc> *>(new FreeObjectSet<MemDesc> 118 *[FreeObjectList<MemDesc>::NumberOfSets()](), FreeObjectList<MemDesc>::NumberOfSets()); 119 } 120 DestroyFreeObjectSets()121 void DestroyFreeObjectSets() 122 { 123 for (auto set : fortFreeObjectSets_) { 124 delete set; 125 } 126 delete[] fortFreeObjectSets_.data(); 127 } 128 GetFreeObjectSet(SetType type)129 FreeObjectSet<MemDesc> *GetFreeObjectSet(SetType type) 130 { 131 // Thread safe 132 if (fortFreeObjectSets_[type] == nullptr) { 133 fortFreeObjectSets_[type] = new FreeObjectSet<MemDesc>(type, memDescPool_); 134 } 135 return fortFreeObjectSets_[type]; 136 } 137 LinkNext(JitFortRegion * next)138 inline void LinkNext(JitFortRegion *next) 139 { 140 next_ = next; 141 } 142 GetNext()143 inline JitFortRegion *GetNext() const 144 { 145 return next_; 146 } 147 LinkPrev(JitFortRegion * prev)148 inline void LinkPrev(JitFortRegion *prev) 149 { 150 prev_ = prev; 151 } 152 GetPrev()153 inline JitFortRegion *GetPrev() const 154 { 155 return prev_; 156 } 157 158 private: 159 Span<FreeObjectSet<MemDesc> *> fortFreeObjectSets_; 160 JitFortRegion *next_ {nullptr}; 161 JitFortRegion *prev_ {nullptr}; 162 MemDescPool *memDescPool_ {nullptr}; 163 }; 164 165 } // namespace panda::ecmascript 166 #endif // ECMASCRIPT_MEM_SPARSE_SPACE_H 167