• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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