• 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 #include "ecmascript/compiler/jit_compilation_env.h"
16 #include "ecmascript/jspandafile/program_object.h"
17 #include "ecmascript/ic/ic_handler.h"
18 
19 namespace panda::ecmascript {
20 // jit
JitCompilationEnv(EcmaVM * jitVm,EcmaVM * jsVm,JSHandle<JSFunction> & jsFunction)21 JitCompilationEnv::JitCompilationEnv(EcmaVM *jitVm, EcmaVM *jsVm, JSHandle<JSFunction> &jsFunction)
22     : CompilationEnv(jitVm), hostThread_(jsVm->GetJSThreadNoCheck()), jsFunction_(jsFunction)
23 {
24     if (hostThread_ != nullptr && hostThread_->GetCurrentEcmaContext() != nullptr &&
25         hostThread_->GetCurrentEcmaContext()->GetPTManager() != nullptr) {
26         ptManager_ = hostThread_->GetCurrentEcmaContext()->GetPTManager();
27     }
28     Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject());
29     jsPandaFile_ = const_cast<JSPandaFile*>(method->GetJSPandaFile());
30     methodLiteral_ = method->GetMethodLiteral();
31     pcStart_ = method->GetBytecodeArray();
32     abcId_ = PGOProfiler::GetMethodAbcId(*jsFunction);
33     if (method->GetFunctionKind() == FunctionKind::CLASS_CONSTRUCTOR) {
34         methodLiteral_->SetFunctionKind(FunctionKind::CLASS_CONSTRUCTOR);
35     }
36 }
37 
GetJSOptions()38 JSRuntimeOptions &JitCompilationEnv::GetJSOptions()
39 {
40     return hostThread_->GetEcmaVM()->GetJSOptions();
41 }
42 
GetArrayHClassIndex(ElementsKind kind,bool isProtoType) const43 ConstantIndex JitCompilationEnv::GetArrayHClassIndex(ElementsKind kind, bool isProtoType) const
44 {
45     return hostThread_->GetArrayInstanceHClassIndex(kind, isProtoType);
46 }
47 
GetBuiltinHClassEntries() const48 const BuiltinHClassEntries &JitCompilationEnv::GetBuiltinHClassEntries() const
49 {
50     return hostThread_->GetBuiltinHClassEntries();
51 }
52 
GetBuiltinPrototypeHClass(BuiltinTypeId type) const53 JSHClass *JitCompilationEnv::GetBuiltinPrototypeHClass(BuiltinTypeId type) const
54 {
55     return hostThread_->GetBuiltinPrototypeHClass(type);
56 }
57 
SetTsManagerCompilationEnv()58 void JitCompilationEnv::SetTsManagerCompilationEnv()
59 {
60     auto pt = hostThread_->GetCurrentEcmaContext()->GetPTManager();
61     ptManager_ = pt;
62 }
63 
GetPGOProfiler() const64 std::shared_ptr<pgo::PGOProfiler> JitCompilationEnv::GetPGOProfiler() const
65 {
66     return hostThread_->GetEcmaVM()->GetPGOProfiler();
67 }
68 
FindConstpool(const JSPandaFile * jsPandaFile,panda_file::File::EntityId id) const69 JSTaggedValue JitCompilationEnv::FindConstpool([[maybe_unused]] const JSPandaFile *jsPandaFile,
70     [[maybe_unused]] panda_file::File::EntityId id) const
71 {
72     ASSERT(thread_->IsInRunningState());
73     Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject());
74     JSTaggedValue constpool = method->GetConstantPool();
75     [[maybe_unused]] const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
76     ASSERT(taggedPool->GetJSPandaFile() == jsPandaFile);
77     ASSERT(method->GetMethodId() == id);
78     return constpool;
79 }
80 
FindConstpool(const JSPandaFile * jsPandaFile,int32_t index) const81 JSTaggedValue JitCompilationEnv::FindConstpool([[maybe_unused]] const JSPandaFile *jsPandaFile,
82     [[maybe_unused]] int32_t index) const
83 {
84     ASSERT(thread_->IsInRunningState());
85     Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject());
86     JSTaggedValue constpool = method->GetConstantPool();
87     [[maybe_unused]] const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
88     ASSERT(taggedPool->GetJSPandaFile() == jsPandaFile);
89     ASSERT(taggedPool->GetSharedConstpoolId().GetInt() == index);
90     return constpool;
91 }
92 
FindOrCreateUnsharedConstpool(const uint32_t methodOffset) const93 JSTaggedValue JitCompilationEnv::FindOrCreateUnsharedConstpool([[maybe_unused]] const uint32_t methodOffset) const
94 {
95     JSTaggedValue constpool = GetConstantPoolByMethodOffset(methodOffset);
96     if (constpool.IsUndefined()) {
97         return JSTaggedValue::Undefined();
98     }
99     ASSERT(!ConstantPool::CheckUnsharedConstpool(constpool));
100     JSTaggedValue unSharedConstpool = hostThread_->GetCurrentEcmaContext()->FindUnsharedConstpool(constpool);
101     return unSharedConstpool;
102 }
103 
FindOrCreateUnsharedConstpool(JSTaggedValue sharedConstpool) const104 JSTaggedValue JitCompilationEnv::FindOrCreateUnsharedConstpool([[maybe_unused]] JSTaggedValue sharedConstpool) const
105 {
106     Method *method = Method::Cast(jsFunction_->GetMethod().GetTaggedObject());
107     [[maybe_unused]] JSTaggedValue constpool = method->GetConstantPool();
108     ASSERT(constpool == sharedConstpool);
109     uint32_t methodOffset = method->GetMethodId().GetOffset();
110     return FindOrCreateUnsharedConstpool(methodOffset);
111 }
112 
FindOrCreateConstPool(const JSPandaFile * jsPandaFile,panda_file::File::EntityId id)113 JSHandle<ConstantPool> JitCompilationEnv::FindOrCreateConstPool([[maybe_unused]] const JSPandaFile *jsPandaFile,
114     [[maybe_unused]] panda_file::File::EntityId id)
115 {
116     ASSERT_PRINT(0, "jit should unreachable");
117     return JSHandle<ConstantPool>();
118 }
119 
GetConstantPoolByMethodOffset(const uint32_t methodOffset) const120 JSTaggedValue JitCompilationEnv::GetConstantPoolByMethodOffset([[maybe_unused]] const uint32_t methodOffset) const
121 {
122     ASSERT(thread_->IsInRunningState());
123     JSTaggedValue constpool;
124     Method *currMethod = Method::Cast(jsFunction_->GetMethod().GetTaggedObject());
125     if (methodOffset != currMethod->GetMethodId().GetOffset()) {
126         auto calleeFunc = GetJsFunctionByMethodOffset(methodOffset);
127         if (!calleeFunc) {
128             return JSTaggedValue::Undefined();
129         }
130         constpool = Method::Cast(calleeFunc->GetMethod())->GetConstantPool();
131     } else {
132         constpool = currMethod->GetConstantPool();
133     }
134     return constpool;
135 }
136 
GetArrayLiteralFromCache(JSTaggedValue constpool,uint32_t index,CString entry) const137 JSTaggedValue JitCompilationEnv::GetArrayLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const
138 {
139     ASSERT(thread_->IsInRunningState());
140     return ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(constpool, index, entry);
141 }
142 
GetObjectLiteralFromCache(JSTaggedValue constpool,uint32_t index,CString entry) const143 JSTaggedValue JitCompilationEnv::GetObjectLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const
144 {
145     ASSERT(thread_->IsInRunningState());
146     return ConstantPool::GetLiteralFromCache<ConstPoolType::OBJECT_LITERAL>(constpool, index, entry);
147 }
148 
GetMethodFromCache(JSTaggedValue constpool,uint32_t index) const149 JSTaggedValue JitCompilationEnv::GetMethodFromCache(JSTaggedValue constpool, uint32_t index) const
150 {
151     return ConstantPool::GetMethodFromCache(constpool, index);
152 }
153 
GetIdFromCache(JSTaggedValue constpool,uint32_t index) const154 panda_file::File::EntityId JitCompilationEnv::GetIdFromCache(JSTaggedValue constpool, uint32_t index) const
155 {
156     ASSERT(thread_->IsInRunningState());
157     return ConstantPool::GetIdFromCache(constpool, index);
158 }
159 
GetGlobalEnv() const160 JSHandle<GlobalEnv> JitCompilationEnv::GetGlobalEnv() const
161 {
162     ASSERT(thread_->IsInRunningState());
163     return hostThread_->GetEcmaVM()->GetGlobalEnv();
164 }
165 
GlobalConstants() const166 const GlobalEnvConstants *JitCompilationEnv::GlobalConstants() const
167 {
168     ASSERT(thread_->IsInRunningState());
169     return hostThread_->GlobalConstants();
170 }
171 
172 // The caller should add assessment for undefined constpool.
173 // When slotValue in profileTypeInfo is changed in main thread, constpool may be undefined.
GetStringFromConstantPool(const uint32_t methodOffset,const uint16_t cpIdx,bool allowAlloc) const174 JSTaggedValue JitCompilationEnv::GetStringFromConstantPool([[maybe_unused]] const uint32_t methodOffset,
175     const uint16_t cpIdx, bool allowAlloc) const
176 {
177     JSTaggedValue constpool = GetConstantPoolByMethodOffset(methodOffset);
178     if (constpool.IsUndefined()) {
179         return JSTaggedValue::Undefined();
180     }
181     return ConstantPool::GetStringFromCacheForJit(GetJSThread(), constpool, cpIdx, allowAlloc);
182 }
183 
GetJsFunctionByMethodOffset(uint32_t methodOffset) const184 JSFunction *JitCompilationEnv::GetJsFunctionByMethodOffset(uint32_t methodOffset) const
185 {
186     ASSERT(thread_->IsInRunningState());
187     Method *currMethod = Method::Cast(jsFunction_->GetMethod().GetTaggedObject());
188     auto currMethodOffset = currMethod->GetMethodId().GetOffset();
189     if (methodOffset == currMethodOffset) {
190         return *jsFunction_;
191     }
192     std::vector<std::pair<uint32_t, uint32_t>> funcSlotChain;
193     uint32_t calleeOffset = methodOffset;
194     do {
195         if (functionSlotIdMap_.find(calleeOffset) == functionSlotIdMap_.end()) {
196             return nullptr;
197         }
198         funcSlotChain.push_back({functionSlotIdMap_.at(calleeOffset), callee2CallerMap_.at(calleeOffset)});
199         calleeOffset = callee2CallerMap_.at(calleeOffset);
200     } while (calleeOffset != currMethodOffset);
201     JSFunction *currFunc = *jsFunction_;
202     ProfileTypeInfo *currFuncPTI = *profileTypeInfo_;
203     for (int i = static_cast<int>(funcSlotChain.size()) - 1; i >= 0; --i) {
204         uint32_t slotId = funcSlotChain[i].first;
205         uint32_t callerOffset = funcSlotChain[i].second;
206         if (Method::Cast(currFunc->GetMethod())->GetMethodId().GetOffset() != callerOffset) {
207             return nullptr;
208         }
209         auto slotValue = currFuncPTI->Get(slotId);
210         if (slotValue.IsJSFunction()) {
211             currFunc = JSFunction::Cast(currFuncPTI->Get(slotId).GetTaggedObject());
212         } else if (slotValue.IsPrototypeHandler()) {
213             auto prototypeHandler = PrototypeHandler::Cast(slotValue.GetTaggedObject());
214             auto accessorFunction = prototypeHandler->GetAccessorJSFunction();
215             if (!accessorFunction.IsJSFunction()) {
216                 return nullptr;
217             }
218             currFunc = JSFunction::Cast(accessorFunction.GetTaggedObject());
219         } else {
220             return nullptr;
221         }
222         auto profileTypeInfoVal = currFunc->GetProfileTypeInfo();
223         if (profileTypeInfoVal.IsUndefined()) {
224             return nullptr;
225         }
226         currFuncPTI = ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject());
227     }
228     if (Method::Cast(currFunc->GetMethod())->GetMethodId().GetOffset() != methodOffset) {
229         return nullptr;
230     }
231     return currFunc;
232 }
233 } // namespace panda::ecmascript
234