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