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#include "ecmascript/compiler/jit_compilation_env.h" 164514f5e3Sopenharmony_ci#include "ecmascript/ecma_context.h" 174514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/program_object.h" 184514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_profiler.h" 194514f5e3Sopenharmony_ci#include "ecmascript/ic/profile_type_info.h" 204514f5e3Sopenharmony_ci#include "ecmascript/ic/ic_handler.h" 214514f5e3Sopenharmony_ci 224514f5e3Sopenharmony_cinamespace panda::ecmascript { 234514f5e3Sopenharmony_ci// jit 244514f5e3Sopenharmony_ciJitCompilationEnv::JitCompilationEnv(EcmaVM *jitVm, EcmaVM *jsVm, JSHandle<JSFunction> &jsFunction) 254514f5e3Sopenharmony_ci : CompilationEnv(jitVm), hostThread_(jsVm->GetJSThreadNoCheck()), jsFunction_(jsFunction) 264514f5e3Sopenharmony_ci{ 274514f5e3Sopenharmony_ci ptManager_ = hostThread_->GetCurrentEcmaContext()->GetPTManager(); 284514f5e3Sopenharmony_ci Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject()); 294514f5e3Sopenharmony_ci jsPandaFile_ = const_cast<JSPandaFile*>(method->GetJSPandaFile()); 304514f5e3Sopenharmony_ci methodLiteral_ = method->GetMethodLiteral(); 314514f5e3Sopenharmony_ci pcStart_ = method->GetBytecodeArray(); 324514f5e3Sopenharmony_ci abcId_ = PGOProfiler::GetMethodAbcId(*jsFunction); 334514f5e3Sopenharmony_ci if (method->GetFunctionKind() == FunctionKind::CLASS_CONSTRUCTOR) { 344514f5e3Sopenharmony_ci methodLiteral_->SetFunctionKind(FunctionKind::CLASS_CONSTRUCTOR); 354514f5e3Sopenharmony_ci } 364514f5e3Sopenharmony_ci} 374514f5e3Sopenharmony_ci 384514f5e3Sopenharmony_ciJSRuntimeOptions &JitCompilationEnv::GetJSOptions() 394514f5e3Sopenharmony_ci{ 404514f5e3Sopenharmony_ci return hostThread_->GetEcmaVM()->GetJSOptions(); 414514f5e3Sopenharmony_ci} 424514f5e3Sopenharmony_ci 434514f5e3Sopenharmony_ciconst CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> &JitCompilationEnv::GetArrayHClassIndexMap() const 444514f5e3Sopenharmony_ci{ 454514f5e3Sopenharmony_ci return hostThread_->GetArrayHClassIndexMap(); 464514f5e3Sopenharmony_ci} 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_ciconst BuiltinHClassEntries &JitCompilationEnv::GetBuiltinHClassEntries() const 494514f5e3Sopenharmony_ci{ 504514f5e3Sopenharmony_ci return hostThread_->GetBuiltinHClassEntries(); 514514f5e3Sopenharmony_ci} 524514f5e3Sopenharmony_ci 534514f5e3Sopenharmony_ciJSHClass *JitCompilationEnv::GetBuiltinPrototypeHClass(BuiltinTypeId type) const 544514f5e3Sopenharmony_ci{ 554514f5e3Sopenharmony_ci return hostThread_->GetBuiltinPrototypeHClass(type); 564514f5e3Sopenharmony_ci} 574514f5e3Sopenharmony_ci 584514f5e3Sopenharmony_civoid JitCompilationEnv::SetTsManagerCompilationEnv() 594514f5e3Sopenharmony_ci{ 604514f5e3Sopenharmony_ci auto pt = hostThread_->GetCurrentEcmaContext()->GetPTManager(); 614514f5e3Sopenharmony_ci ptManager_ = pt; 624514f5e3Sopenharmony_ci} 634514f5e3Sopenharmony_ci 644514f5e3Sopenharmony_cistd::shared_ptr<pgo::PGOProfiler> JitCompilationEnv::GetPGOProfiler() const 654514f5e3Sopenharmony_ci{ 664514f5e3Sopenharmony_ci return hostThread_->GetEcmaVM()->GetPGOProfiler(); 674514f5e3Sopenharmony_ci} 684514f5e3Sopenharmony_ci 694514f5e3Sopenharmony_ciJSTaggedValue JitCompilationEnv::FindConstpool([[maybe_unused]] const JSPandaFile *jsPandaFile, 704514f5e3Sopenharmony_ci [[maybe_unused]] panda_file::File::EntityId id) const 714514f5e3Sopenharmony_ci{ 724514f5e3Sopenharmony_ci ASSERT(thread_->IsInRunningState()); 734514f5e3Sopenharmony_ci Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); 744514f5e3Sopenharmony_ci JSTaggedValue constpool = method->GetConstantPool(); 754514f5e3Sopenharmony_ci [[maybe_unused]] const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 764514f5e3Sopenharmony_ci ASSERT(taggedPool->GetJSPandaFile() == jsPandaFile); 774514f5e3Sopenharmony_ci ASSERT(method->GetMethodId() == id); 784514f5e3Sopenharmony_ci return constpool; 794514f5e3Sopenharmony_ci} 804514f5e3Sopenharmony_ci 814514f5e3Sopenharmony_ciJSTaggedValue JitCompilationEnv::FindConstpool([[maybe_unused]] const JSPandaFile *jsPandaFile, 824514f5e3Sopenharmony_ci [[maybe_unused]] int32_t index) const 834514f5e3Sopenharmony_ci{ 844514f5e3Sopenharmony_ci ASSERT(thread_->IsInRunningState()); 854514f5e3Sopenharmony_ci Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); 864514f5e3Sopenharmony_ci JSTaggedValue constpool = method->GetConstantPool(); 874514f5e3Sopenharmony_ci [[maybe_unused]] const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject()); 884514f5e3Sopenharmony_ci ASSERT(taggedPool->GetJSPandaFile() == jsPandaFile); 894514f5e3Sopenharmony_ci ASSERT(taggedPool->GetSharedConstpoolId().GetInt() == index); 904514f5e3Sopenharmony_ci return constpool; 914514f5e3Sopenharmony_ci} 924514f5e3Sopenharmony_ci 934514f5e3Sopenharmony_ciJSTaggedValue JitCompilationEnv::FindOrCreateUnsharedConstpool([[maybe_unused]] const uint32_t methodOffset) const 944514f5e3Sopenharmony_ci{ 954514f5e3Sopenharmony_ci JSTaggedValue constpool = GetConstantPoolByMethodOffset(methodOffset); 964514f5e3Sopenharmony_ci if (constpool.IsUndefined()) { 974514f5e3Sopenharmony_ci return JSTaggedValue::Undefined(); 984514f5e3Sopenharmony_ci } 994514f5e3Sopenharmony_ci ASSERT(!ConstantPool::CheckUnsharedConstpool(constpool)); 1004514f5e3Sopenharmony_ci JSTaggedValue unSharedConstpool = hostThread_->GetCurrentEcmaContext()->FindUnsharedConstpool(constpool); 1014514f5e3Sopenharmony_ci return unSharedConstpool; 1024514f5e3Sopenharmony_ci} 1034514f5e3Sopenharmony_ci 1044514f5e3Sopenharmony_ciJSTaggedValue JitCompilationEnv::FindOrCreateUnsharedConstpool([[maybe_unused]] JSTaggedValue sharedConstpool) const 1054514f5e3Sopenharmony_ci{ 1064514f5e3Sopenharmony_ci Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); 1074514f5e3Sopenharmony_ci [[maybe_unused]] JSTaggedValue constpool = method->GetConstantPool(); 1084514f5e3Sopenharmony_ci ASSERT(constpool == sharedConstpool); 1094514f5e3Sopenharmony_ci uint32_t methodOffset = method->GetMethodId().GetOffset(); 1104514f5e3Sopenharmony_ci return FindOrCreateUnsharedConstpool(methodOffset); 1114514f5e3Sopenharmony_ci} 1124514f5e3Sopenharmony_ci 1134514f5e3Sopenharmony_ciJSHandle<ConstantPool> JitCompilationEnv::FindOrCreateConstPool([[maybe_unused]] const JSPandaFile *jsPandaFile, 1144514f5e3Sopenharmony_ci [[maybe_unused]] panda_file::File::EntityId id) 1154514f5e3Sopenharmony_ci{ 1164514f5e3Sopenharmony_ci ASSERT_PRINT(0, "jit should unreachable"); 1174514f5e3Sopenharmony_ci return JSHandle<ConstantPool>(); 1184514f5e3Sopenharmony_ci} 1194514f5e3Sopenharmony_ci 1204514f5e3Sopenharmony_ciJSTaggedValue JitCompilationEnv::GetConstantPoolByMethodOffset([[maybe_unused]] const uint32_t methodOffset) const 1214514f5e3Sopenharmony_ci{ 1224514f5e3Sopenharmony_ci ASSERT(thread_->IsInRunningState()); 1234514f5e3Sopenharmony_ci JSTaggedValue constpool; 1244514f5e3Sopenharmony_ci Method *currMethod = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); 1254514f5e3Sopenharmony_ci if (methodOffset != currMethod->GetMethodId().GetOffset()) { 1264514f5e3Sopenharmony_ci auto calleeFunc = GetJsFunctionByMethodOffset(methodOffset); 1274514f5e3Sopenharmony_ci if (!calleeFunc) { 1284514f5e3Sopenharmony_ci return JSTaggedValue::Undefined(); 1294514f5e3Sopenharmony_ci } 1304514f5e3Sopenharmony_ci constpool = Method::Cast(calleeFunc->GetMethod())->GetConstantPool(); 1314514f5e3Sopenharmony_ci } else { 1324514f5e3Sopenharmony_ci constpool = currMethod->GetConstantPool(); 1334514f5e3Sopenharmony_ci } 1344514f5e3Sopenharmony_ci return constpool; 1354514f5e3Sopenharmony_ci} 1364514f5e3Sopenharmony_ci 1374514f5e3Sopenharmony_ciJSTaggedValue JitCompilationEnv::GetArrayLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const 1384514f5e3Sopenharmony_ci{ 1394514f5e3Sopenharmony_ci ASSERT(thread_->IsInRunningState()); 1404514f5e3Sopenharmony_ci return ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(constpool, index, entry); 1414514f5e3Sopenharmony_ci} 1424514f5e3Sopenharmony_ci 1434514f5e3Sopenharmony_ciJSTaggedValue JitCompilationEnv::GetObjectLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const 1444514f5e3Sopenharmony_ci{ 1454514f5e3Sopenharmony_ci ASSERT(thread_->IsInRunningState()); 1464514f5e3Sopenharmony_ci return ConstantPool::GetLiteralFromCache<ConstPoolType::OBJECT_LITERAL>(constpool, index, entry); 1474514f5e3Sopenharmony_ci} 1484514f5e3Sopenharmony_ci 1494514f5e3Sopenharmony_ciJSTaggedValue JitCompilationEnv::GetMethodFromCache(JSTaggedValue constpool, uint32_t index) const 1504514f5e3Sopenharmony_ci{ 1514514f5e3Sopenharmony_ci return ConstantPool::GetMethodFromCache(constpool, index); 1524514f5e3Sopenharmony_ci} 1534514f5e3Sopenharmony_ci 1544514f5e3Sopenharmony_cipanda_file::File::EntityId JitCompilationEnv::GetIdFromCache(JSTaggedValue constpool, uint32_t index) const 1554514f5e3Sopenharmony_ci{ 1564514f5e3Sopenharmony_ci ASSERT(thread_->IsInRunningState()); 1574514f5e3Sopenharmony_ci return ConstantPool::GetIdFromCache(constpool, index); 1584514f5e3Sopenharmony_ci} 1594514f5e3Sopenharmony_ci 1604514f5e3Sopenharmony_ciJSHandle<GlobalEnv> JitCompilationEnv::GetGlobalEnv() const 1614514f5e3Sopenharmony_ci{ 1624514f5e3Sopenharmony_ci ASSERT(thread_->IsInRunningState()); 1634514f5e3Sopenharmony_ci return hostThread_->GetEcmaVM()->GetGlobalEnv(); 1644514f5e3Sopenharmony_ci} 1654514f5e3Sopenharmony_ci 1664514f5e3Sopenharmony_ciconst GlobalEnvConstants *JitCompilationEnv::GlobalConstants() const 1674514f5e3Sopenharmony_ci{ 1684514f5e3Sopenharmony_ci ASSERT(thread_->IsInRunningState()); 1694514f5e3Sopenharmony_ci return hostThread_->GlobalConstants(); 1704514f5e3Sopenharmony_ci} 1714514f5e3Sopenharmony_ci 1724514f5e3Sopenharmony_ci// The caller should add assessment for undefined constpool. 1734514f5e3Sopenharmony_ci// When slotValue in profileTypeInfo is changed in main thread, constpool may be undefined. 1744514f5e3Sopenharmony_ciJSTaggedValue JitCompilationEnv::GetStringFromConstantPool([[maybe_unused]] const uint32_t methodOffset, 1754514f5e3Sopenharmony_ci const uint16_t cpIdx, bool allowAlloc) const 1764514f5e3Sopenharmony_ci{ 1774514f5e3Sopenharmony_ci JSTaggedValue constpool = GetConstantPoolByMethodOffset(methodOffset); 1784514f5e3Sopenharmony_ci if (constpool.IsUndefined()) { 1794514f5e3Sopenharmony_ci return JSTaggedValue::Undefined(); 1804514f5e3Sopenharmony_ci } 1814514f5e3Sopenharmony_ci return ConstantPool::GetStringFromCacheForJit(GetJSThread(), constpool, cpIdx, allowAlloc); 1824514f5e3Sopenharmony_ci} 1834514f5e3Sopenharmony_ci 1844514f5e3Sopenharmony_ciJSFunction *JitCompilationEnv::GetJsFunctionByMethodOffset(uint32_t methodOffset) const 1854514f5e3Sopenharmony_ci{ 1864514f5e3Sopenharmony_ci ASSERT(thread_->IsInRunningState()); 1874514f5e3Sopenharmony_ci Method *currMethod = Method::Cast(jsFunction_->GetMethod().GetTaggedObject()); 1884514f5e3Sopenharmony_ci auto currMethodOffset = currMethod->GetMethodId().GetOffset(); 1894514f5e3Sopenharmony_ci if (methodOffset == currMethodOffset) { 1904514f5e3Sopenharmony_ci return *jsFunction_; 1914514f5e3Sopenharmony_ci } 1924514f5e3Sopenharmony_ci std::vector<std::pair<uint32_t, uint32_t>> funcSlotChain; 1934514f5e3Sopenharmony_ci uint32_t calleeOffset = methodOffset; 1944514f5e3Sopenharmony_ci do { 1954514f5e3Sopenharmony_ci if (functionSlotIdMap_.find(calleeOffset) == functionSlotIdMap_.end()) { 1964514f5e3Sopenharmony_ci return nullptr; 1974514f5e3Sopenharmony_ci } 1984514f5e3Sopenharmony_ci funcSlotChain.push_back({functionSlotIdMap_.at(calleeOffset), callee2CallerMap_.at(calleeOffset)}); 1994514f5e3Sopenharmony_ci calleeOffset = callee2CallerMap_.at(calleeOffset); 2004514f5e3Sopenharmony_ci } while (calleeOffset != currMethodOffset); 2014514f5e3Sopenharmony_ci JSFunction *currFunc = *jsFunction_; 2024514f5e3Sopenharmony_ci ProfileTypeInfo *currFuncPTI = *profileTypeInfo_; 2034514f5e3Sopenharmony_ci for (int i = static_cast<int>(funcSlotChain.size()) - 1; i >= 0; --i) { 2044514f5e3Sopenharmony_ci uint32_t slotId = funcSlotChain[i].first; 2054514f5e3Sopenharmony_ci uint32_t callerOffset = funcSlotChain[i].second; 2064514f5e3Sopenharmony_ci if (Method::Cast(currFunc->GetMethod())->GetMethodId().GetOffset() != callerOffset) { 2074514f5e3Sopenharmony_ci return nullptr; 2084514f5e3Sopenharmony_ci } 2094514f5e3Sopenharmony_ci auto slotValue = currFuncPTI->Get(slotId); 2104514f5e3Sopenharmony_ci if (slotValue.IsJSFunction()) { 2114514f5e3Sopenharmony_ci currFunc = JSFunction::Cast(currFuncPTI->Get(slotId).GetTaggedObject()); 2124514f5e3Sopenharmony_ci } else if (slotValue.IsPrototypeHandler()) { 2134514f5e3Sopenharmony_ci auto prototypeHandler = PrototypeHandler::Cast(slotValue.GetTaggedObject()); 2144514f5e3Sopenharmony_ci auto accessorFunction = prototypeHandler->GetAccessorJSFunction(); 2154514f5e3Sopenharmony_ci if (!accessorFunction.IsJSFunction()) { 2164514f5e3Sopenharmony_ci return nullptr; 2174514f5e3Sopenharmony_ci } 2184514f5e3Sopenharmony_ci currFunc = JSFunction::Cast(accessorFunction.GetTaggedObject()); 2194514f5e3Sopenharmony_ci } else { 2204514f5e3Sopenharmony_ci return nullptr; 2214514f5e3Sopenharmony_ci } 2224514f5e3Sopenharmony_ci auto profileTypeInfoVal = currFunc->GetProfileTypeInfo(); 2234514f5e3Sopenharmony_ci if (profileTypeInfoVal.IsUndefined()) { 2244514f5e3Sopenharmony_ci return nullptr; 2254514f5e3Sopenharmony_ci } 2264514f5e3Sopenharmony_ci currFuncPTI = ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject()); 2274514f5e3Sopenharmony_ci } 2284514f5e3Sopenharmony_ci if (Method::Cast(currFunc->GetMethod())->GetMethodId().GetOffset() != methodOffset) { 2294514f5e3Sopenharmony_ci return nullptr; 2304514f5e3Sopenharmony_ci } 2314514f5e3Sopenharmony_ci return currFunc; 2324514f5e3Sopenharmony_ci} 2334514f5e3Sopenharmony_ci} // namespace panda::ecmascript 234