• 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_COMPILER_JIT_COMPILATION_ENV_H
17 #define ECMASCRIPT_COMPILER_JIT_COMPILATION_ENV_H
18 
19 #include "ecmascript/compiler/bytecode_info_collector.h"
20 #include "ecmascript/compiler/compilation_env.h"
21 #include "ecmascript/dependent_infos.h"
22 #include "ecmascript/ic/profile_type_info.h"
23 #include "ecmascript/jit/jit_thread.h"
24 
25 namespace panda::ecmascript {
26 class JitCompilationEnv final : public CompilationEnv {
27 public:
28     static constexpr uint32_t INVALID_HEAP_CONSTANT_INDEX = std::numeric_limits<uint32_t>::max();
29     enum ConstantType : uint8_t {
30         IN_SHARED_CONSTANTPOOL,
31         IN_UNSHARED_CONSTANTPOOL
32     };
33 
34     struct ConstantPoolHeapConstant {
35         uint32_t constpoolId;
36         uint32_t index;
37         ConstantType constType;
38 
39         bool operator < (const ConstantPoolHeapConstant &heapConstant) const
40         {
41             if (index != heapConstant.index) {
42                 return index < heapConstant.index;
43             }
44             if (constType != heapConstant.constType) {
45                 return constType < heapConstant.constType;
46             }
47             return constpoolId < heapConstant.constpoolId;
48         }
49     };
50 
51     JitCompilationEnv(EcmaVM *vm, EcmaVM *hVm,
52         JSHandle<JSFunction> &jsFunction, kungfu::LazyDeoptAllDependencies *dependencies);
53     ~JitCompilationEnv() = default;
IsJitCompiler()54     bool IsJitCompiler() const override
55     {
56         return true;
57     }
SupportHeapConstant()58     bool SupportHeapConstant() const override
59     {
60         if (g_isEnableCMCGC) {
61             // Disable heapConstant until we enable barrier for heap constant table
62             return false;
63         } else {
64             return hostThread_->GetEcmaVM()->GetJSOptions().IsCompilerEnableLiteCG();
65         }
66     }
67 
SupportIntrinsic()68     bool SupportIntrinsic() const override
69     {
70         return hostThread_->GetEcmaVM()->GetJSOptions().IsCompilerEnableLiteCG();
71     }
72 
SupportNonExistIC()73     bool SupportNonExistIC() const override
74     {
75         return true;
76     }
77 
GetDependencies()78     kungfu::LazyDeoptAllDependencies *GetDependencies() const override
79     {
80         return dependencies_;
81     }
82 
83     JSRuntimeOptions &GetJSOptions() const override;
84     // thread
85     GlobalEnvField GetArrayHClassIndex(ElementsKind kind, bool isProtoType) const override;
86     const BuiltinHClassEntries &GetBuiltinHClassEntries() const override;
87     JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const override;
88     void SetTsManagerCompilationEnv();
89 
90     std::shared_ptr<pgo::PGOProfiler> GetPGOProfiler() const override;
91 
92     // context
93     JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id) const override;
94     JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, int32_t index) const override;
95     JSTaggedValue FindOrCreateUnsharedConstpool(const uint32_t methodOffset) const override;
96     JSTaggedValue FindOrCreateUnsharedConstpool(JSTaggedValue sharedConstpool) const override;
97     JSHandle<ConstantPool> FindOrCreateConstPool(const JSPandaFile *jsPandaFile,
98         panda_file::File::EntityId id) override;
99     JSTaggedValue GetConstantPoolByMethodOffset(const uint32_t methodOffset) const override;
100 
101     // ConstantPool
102     JSTaggedValue GetArrayLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const override;
103     JSTaggedValue GetObjectLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const override;
104     JSTaggedValue GetMethodFromCache(JSTaggedValue constpool, uint32_t index) const override;
105     panda_file::File::EntityId GetIdFromCache(JSTaggedValue constpool, uint32_t index) const override;
106 
107     // GlobalEnv
108     JSHandle<GlobalEnv> GetGlobalEnv() const override;
109 
110     // GlobalConstants
111     const GlobalEnvConstants *GlobalConstants() const override;
112 
113     JSTaggedValue GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx,
114         bool allowAlloc = true) const override;
115 
GetHostThread()116     JSThread *GetHostThread() const override
117     {
118         return hostThread_;
119     }
120 
GetJSPandaFile()121     JSPandaFile *GetJSPandaFile() const override
122     {
123         return jsPandaFile_;
124     }
125 
GetMethodLiteral()126     MethodLiteral *GetMethodLiteral() const override
127     {
128         return methodLiteral_;
129     }
130 
ProcessMethod(MethodLiteral * method,const JSPandaFile * jsPandaFile)131     void ProcessMethod(MethodLiteral *method, const JSPandaFile *jsPandaFile) const override
132     {
133         kungfu::BytecodeInfoCollector::ProcessMethodForJIT(method, jsPandaFile);
134     }
135 
GetMethodPcStart()136     const uint8_t *GetMethodPcStart() const override
137     {
138         return pcStart_;
139     }
140 
GetMethodAbcId()141     pgo::ApEntityId GetMethodAbcId() const override
142     {
143         return abcId_;
144     }
145 
SetProfileTypeInfo(const JSHandle<ProfileTypeInfo> & info)146     void SetProfileTypeInfo(const JSHandle<ProfileTypeInfo> &info)
147     {
148         profileTypeInfo_ = info;
149     }
150 
GetHeapConstantTable()151     const std::vector<JSHandle<JSTaggedValue>> &GetHeapConstantTable() const
152     {
153         return heapConstantInfo_.heapConstantTable;
154     }
155 
UpdateFuncSlotIdMap(uint32_t calleeOffset,uint32_t callerOffset,uint32_t slotId)156     void UpdateFuncSlotIdMap(uint32_t calleeOffset, uint32_t callerOffset, uint32_t slotId)
157     {
158         if (functionSlotIdMap_.find(calleeOffset) != functionSlotIdMap_.end()) {
159             return;
160         }
161         if (callee2CallerMap_.find(calleeOffset) != callee2CallerMap_.end()) {
162             return;
163         }
164         functionSlotIdMap_[calleeOffset] = slotId;
165         callee2CallerMap_[calleeOffset] = callerOffset;
166     }
GetJsFunction()167     JSHandle<JSFunction> GetJsFunction() const
168     {
169         return jsFunction_;
170     }
171 
172     JSFunction *GetJsFunctionByMethodOffset(uint32_t methodOffset) const;
173 
RecordHeapConstant(const JSHandle<JSTaggedValue> & heapObj)174     uint32_t RecordHeapConstant(const JSHandle<JSTaggedValue> &heapObj)
175     {
176         auto it = std::find_if(heapConstantInfo_.heapConstantTable.begin(), heapConstantInfo_.heapConstantTable.end(),
177             [&heapObj](const JSHandle<JSTaggedValue> &value) {
178                 return value.GetTaggedType() == heapObj.GetTaggedType();
179         });
180         if (it != heapConstantInfo_.heapConstantTable.end()) {
181             return std::distance(heapConstantInfo_.heapConstantTable.begin(), it);
182         }
183         heapConstantInfo_.heapConstantTable.push_back(heapObj);
184         ASSERT(heapConstantInfo_.heapConstantTable.size() < INVALID_HEAP_CONSTANT_INDEX);
185         size_t index = heapConstantInfo_.heapConstantTable.size() - 1;
186         return static_cast<uint32_t>(index);
187     }
188 
189     uint32_t RecordHeapConstant(ConstantPoolHeapConstant heapConstant, const JSHandle<JSTaggedValue> &heapObj);
190 
NewJSHandle(JSTaggedValue value)191     JSHandle<JSTaggedValue> NewJSHandle(JSTaggedValue value) const override
192     {
193         ASSERT(thread_->IsJitThread());
194         auto jitThread = static_cast<JitThread*>(thread_);
195         return jitThread->NewHandle(value);
196     }
197 
SetLdExtModuleVarResolved(uint32_t methodOffset,uint32_t pcOffset)198     void SetLdExtModuleVarResolved(uint32_t methodOffset, uint32_t pcOffset)
199     {
200         ldExtModuleVarResolved_[methodOffset][pcOffset] = true;
201     }
202 
IsLdExtModuleVarResolved(uint32_t methodOffset,uint32_t bcOffset)203     bool IsLdExtModuleVarResolved(uint32_t methodOffset, uint32_t bcOffset) const
204     {
205         auto itMethodOffset = ldExtModuleVarResolved_.find(methodOffset);
206         if (itMethodOffset != ldExtModuleVarResolved_.end()) {
207             auto &bcOffsetMap = itMethodOffset->second;
208             auto itBcOffset = bcOffsetMap.find(bcOffset);
209             if (itBcOffset != bcOffsetMap.end()) {
210                 return itBcOffset->second;
211             }
212         }
213         return false;
214     }
215 
216     JSHandle<JSTaggedValue> GetHeapConstantHandle(uint32_t heapConstantIndex) const;
217 
RecordGate2HeapConstantIndex(uint32_t gate,uint32_t heapConstantIndex)218     void RecordGate2HeapConstantIndex(uint32_t gate, uint32_t heapConstantIndex)
219     {
220         heapConstantInfo_.gate2HeapConstantIndex[gate] = heapConstantIndex;
221     }
222 
GetGate2HeapConstantIndex()223     const std::unordered_map<int32_t, uint32_t> &GetGate2HeapConstantIndex() const
224     {
225         return heapConstantInfo_.gate2HeapConstantIndex;
226     }
227 
RecordCallMethodId2HeapConstantIndex(uint32_t callMethodId,uint32_t heapConstantIndex)228     void RecordCallMethodId2HeapConstantIndex(uint32_t callMethodId, uint32_t heapConstantIndex)
229     {
230         heapConstantInfo_.callMethodId2HeapConstantIndex[callMethodId] = heapConstantIndex;
231     }
232 
GetCallMethodId2HeapConstantIndex()233     const std::unordered_map<uint32_t, uint32_t> &GetCallMethodId2HeapConstantIndex() const
234     {
235         return heapConstantInfo_.callMethodId2HeapConstantIndex;
236     }
237 
RecordCtorMethodId2HeapConstantIndex(uint32_t callMethodId,uint32_t heapConstantIndex)238     void RecordCtorMethodId2HeapConstantIndex(uint32_t callMethodId, uint32_t heapConstantIndex)
239     {
240         heapConstantInfo_.ctorMethodId2HeapConstantIndex[callMethodId] = heapConstantIndex;
241     }
242 
GetCtorMethodId2HeapConstantIndex()243     const std::unordered_map<uint32_t, uint32_t> &GetCtorMethodId2HeapConstantIndex() const
244     {
245         return heapConstantInfo_.ctorMethodId2HeapConstantIndex;
246     }
247 
RecordOnlyInlineMethodId2HeapConstantIndex(uint32_t callMethodId,uint32_t heapConstantIndex)248     void RecordOnlyInlineMethodId2HeapConstantIndex(uint32_t callMethodId, uint32_t heapConstantIndex)
249     {
250         heapConstantInfo_.onlyInlineMethodId2HeapConstantIndex[callMethodId] = heapConstantIndex;
251     }
252 
GetOnlyInlineMethodId2HeapConstantIndex()253     const std::unordered_map<uint32_t, uint32_t> &GetOnlyInlineMethodId2HeapConstantIndex() const
254     {
255         return heapConstantInfo_.onlyInlineMethodId2HeapConstantIndex;
256     }
257 
RecordLdGlobalByNameBcOffset2HeapConstantIndex(uint32_t methodOffset,uint32_t bcOffset,uint32_t heapConstantIndex)258     void RecordLdGlobalByNameBcOffset2HeapConstantIndex(uint32_t methodOffset,
259         uint32_t bcOffset, uint32_t heapConstantIndex)
260     {
261         heapConstantInfo_.ldGlobalByNameBcOffset2HeapConstantIndex[methodOffset][bcOffset] = heapConstantIndex;
262     }
263 
GetLdGlobalByNameBcOffset2HeapConstantIndex(uint32_t methodOffset,uint32_t bcOffset)264     uint32_t GetLdGlobalByNameBcOffset2HeapConstantIndex(uint32_t methodOffset, uint32_t bcOffset) const
265     {
266         auto itMethodOffset = heapConstantInfo_.ldGlobalByNameBcOffset2HeapConstantIndex.find(methodOffset);
267         if (itMethodOffset != heapConstantInfo_.ldGlobalByNameBcOffset2HeapConstantIndex.end()) {
268             auto &bcOffsetMap = itMethodOffset->second;
269             auto itBcOffset = bcOffsetMap.find(bcOffset);
270             if (itBcOffset != bcOffsetMap.end()) {
271                 return itBcOffset->second;
272             }
273         }
274         return INVALID_HEAP_CONSTANT_INDEX;
275     }
276 
RecordHolderHClassIndex2HeapConstantIndex(int32_t holderHClassIndex,uint32_t heapConstantIndex)277     void RecordHolderHClassIndex2HeapConstantIndex(int32_t holderHClassIndex, uint32_t heapConstantIndex)
278     {
279         heapConstantInfo_.holderHClassIndex2HeapConstantIndex[holderHClassIndex] = heapConstantIndex;
280     }
281 
GetHolderHClassIndex2HeapConstantIndex()282     const std::unordered_map<int32_t, uint32_t> &GetHolderHClassIndex2HeapConstantIndex() const
283     {
284         return heapConstantInfo_.holderHClassIndex2HeapConstantIndex;
285     }
286 private:
287     JSThread *hostThread_ {nullptr};
288     JSHandle<JSFunction> jsFunction_;
289     JSTaggedValue globalEnv_ {JSTaggedValue::Hole()};
290     JSPandaFile *jsPandaFile_ {nullptr};
291     MethodLiteral *methodLiteral_ {nullptr};
292     const uint8_t* pcStart_ {nullptr};
293     pgo::ApEntityId abcId_ {0};
294     JSHandle<ProfileTypeInfo> profileTypeInfo_;
295     std::unordered_map<uint32_t, std::unordered_map<uint32_t, bool>> ldExtModuleVarResolved_;
296     std::unordered_map<uint32_t, uint32_t> functionSlotIdMap_;
297     std::unordered_map<uint32_t, uint32_t> callee2CallerMap_;
298     struct HeapConstantInfo {
299         std::vector<JSHandle<JSTaggedValue>> heapConstantTable;
300         std::map<ConstantPoolHeapConstant, uint32_t> constPoolHeapConstant2Index;
301         std::unordered_map<int32_t, uint32_t> gate2HeapConstantIndex;
302         std::unordered_map<uint32_t, uint32_t> callMethodId2HeapConstantIndex;
303         std::unordered_map<uint32_t, uint32_t> ctorMethodId2HeapConstantIndex;
304         std::unordered_map<uint32_t, uint32_t> onlyInlineMethodId2HeapConstantIndex;
305         std::unordered_map<uint32_t, std::unordered_map<uint32_t, uint32_t>> ldGlobalByNameBcOffset2HeapConstantIndex;
306         std::unordered_map<int32_t, uint32_t> holderHClassIndex2HeapConstantIndex;
307     } heapConstantInfo_;
308     kungfu::LazyDeoptAllDependencies *dependencies_ {nullptr};
309 };
310 } // namespace panda::ecmascript
311 #endif  // ECMASCRIPT_COMPILER_JIT_COMPILATION_ENV_H
312