• 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 #include "ecmascript/jit/jit_thread.h"
19 
20 namespace panda::ecmascript {
21 // jit
JitCompilationEnv(EcmaVM * jitVm,EcmaVM * jsVm,JSHandle<JSFunction> & jsFunction,kungfu::LazyDeoptAllDependencies * dependencies)22 JitCompilationEnv::JitCompilationEnv(EcmaVM *jitVm, EcmaVM *jsVm,
23                                      JSHandle<JSFunction> &jsFunction,
24                                      kungfu::LazyDeoptAllDependencies *dependencies)
25     : CompilationEnv(jitVm), hostThread_(jsVm->GetJSThreadNoCheck()),
26     jsFunction_(jsFunction), dependencies_(dependencies)
27 {
28     if (hostThread_ != nullptr && jsVm->GetPTManager() != nullptr) {
29         ptManager_ = jsVm->GetPTManager();
30     }
31     JSTaggedValue funcEnv = jsFunction_->GetLexicalEnv(thread_);
32     globalEnv_ = BaseEnv::Cast(funcEnv.GetTaggedObject())->GetGlobalEnv(thread_);
33     ASSERT(globalEnv_.IsJSGlobalEnv());
34     Method *method = Method::Cast(jsFunction->GetMethod(thread_).GetTaggedObject());
35     jsPandaFile_ = const_cast<JSPandaFile*>(method->GetJSPandaFile(thread_));
36     methodLiteral_ = method->GetMethodLiteral(thread_);
37     pcStart_ = method->GetBytecodeArray();
38     abcId_ = PGOProfiler::GetMethodAbcId(thread_, *jsFunction);
39     if (method->GetFunctionKind() == FunctionKind::CLASS_CONSTRUCTOR) {
40         methodLiteral_->SetFunctionKind(FunctionKind::CLASS_CONSTRUCTOR);
41     }
42 }
43 
GetJSOptions() const44 JSRuntimeOptions &JitCompilationEnv::GetJSOptions() const
45 {
46     return hostThread_->GetEcmaVM()->GetJSOptions();
47 }
48 
GetArrayHClassIndex(ElementsKind kind,bool isProtoType) const49 GlobalEnvField JitCompilationEnv::GetArrayHClassIndex(ElementsKind kind, bool isProtoType) const
50 {
51     return hostThread_->GetArrayInstanceHClassIndex(kind, isProtoType);
52 }
53 
GetBuiltinHClassEntries() const54 const BuiltinHClassEntries &JitCompilationEnv::GetBuiltinHClassEntries() const
55 {
56     return hostThread_->GetBuiltinHClassEntries();
57 }
58 
GetBuiltinPrototypeHClass(BuiltinTypeId type) const59 JSHClass *JitCompilationEnv::GetBuiltinPrototypeHClass(BuiltinTypeId type) const
60 {
61     return hostThread_->GetBuiltinPrototypeHClass(type);
62 }
63 
SetTsManagerCompilationEnv()64 void JitCompilationEnv::SetTsManagerCompilationEnv()
65 {
66     auto pt = hostThread_->GetEcmaVM()->GetPTManager();
67     ptManager_ = pt;
68 }
69 
GetPGOProfiler() const70 std::shared_ptr<pgo::PGOProfiler> JitCompilationEnv::GetPGOProfiler() const
71 {
72     return hostThread_->GetEcmaVM()->GetPGOProfiler();
73 }
74 
FindConstpool(const JSPandaFile * jsPandaFile,panda_file::File::EntityId id) const75 JSTaggedValue JitCompilationEnv::FindConstpool([[maybe_unused]] const JSPandaFile *jsPandaFile,
76     [[maybe_unused]] panda_file::File::EntityId id) const
77 {
78     ASSERT(thread_->IsInRunningState());
79     Method *method = Method::Cast(jsFunction_->GetMethod(thread_).GetTaggedObject());
80     JSTaggedValue constpool = method->GetConstantPool(thread_);
81     [[maybe_unused]] const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
82     ASSERT(taggedPool->GetJSPandaFile() == jsPandaFile);
83     ASSERT(method->GetMethodId() == id);
84     return constpool;
85 }
86 
FindConstpool(const JSPandaFile * jsPandaFile,int32_t index) const87 JSTaggedValue JitCompilationEnv::FindConstpool([[maybe_unused]] const JSPandaFile *jsPandaFile,
88     [[maybe_unused]] int32_t index) const
89 {
90     ASSERT(thread_->IsInRunningState());
91     Method *method = Method::Cast(jsFunction_->GetMethod(thread_).GetTaggedObject());
92     JSTaggedValue constpool = method->GetConstantPool(thread_);
93     [[maybe_unused]] const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
94     ASSERT(taggedPool->GetJSPandaFile() == jsPandaFile);
95     ASSERT(taggedPool->GetSharedConstpoolId().GetInt() == index);
96     return constpool;
97 }
98 
FindOrCreateUnsharedConstpool(const uint32_t methodOffset) const99 JSTaggedValue JitCompilationEnv::FindOrCreateUnsharedConstpool([[maybe_unused]] const uint32_t methodOffset) const
100 {
101     JSTaggedValue constpool = GetConstantPoolByMethodOffset(methodOffset);
102     if (constpool.IsUndefined()) {
103         return JSTaggedValue::Undefined();
104     }
105     ASSERT(!ConstantPool::CheckUnsharedConstpool(constpool));
106     JSTaggedValue unSharedConstpool = hostThread_->GetEcmaVM()->FindUnsharedConstpool(constpool);
107     return unSharedConstpool;
108 }
109 
FindOrCreateUnsharedConstpool(JSTaggedValue sharedConstpool) const110 JSTaggedValue JitCompilationEnv::FindOrCreateUnsharedConstpool([[maybe_unused]] JSTaggedValue sharedConstpool) const
111 {
112     Method *method = Method::Cast(jsFunction_->GetMethod(thread_).GetTaggedObject());
113     [[maybe_unused]] JSTaggedValue constpool = method->GetConstantPool(thread_);
114     ASSERT(constpool == sharedConstpool);
115     uint32_t methodOffset = method->GetMethodId().GetOffset();
116     return FindOrCreateUnsharedConstpool(methodOffset);
117 }
118 
FindOrCreateConstPool(const JSPandaFile * jsPandaFile,panda_file::File::EntityId id)119 JSHandle<ConstantPool> JitCompilationEnv::FindOrCreateConstPool([[maybe_unused]] const JSPandaFile *jsPandaFile,
120     [[maybe_unused]] panda_file::File::EntityId id)
121 {
122     ASSERT_PRINT(0, "jit should unreachable");
123     return JSHandle<ConstantPool>();
124 }
125 
GetConstantPoolByMethodOffset(const uint32_t methodOffset) const126 JSTaggedValue JitCompilationEnv::GetConstantPoolByMethodOffset([[maybe_unused]] const uint32_t methodOffset) const
127 {
128     ASSERT(thread_->IsInRunningState());
129     JSTaggedValue constpool;
130     Method *currMethod = Method::Cast(jsFunction_->GetMethod(thread_).GetTaggedObject());
131     if (methodOffset != currMethod->GetMethodId().GetOffset()) {
132         auto calleeFunc = GetJsFunctionByMethodOffset(methodOffset);
133         if (!calleeFunc) {
134             return JSTaggedValue::Undefined();
135         }
136         constpool = Method::Cast(calleeFunc->GetMethod(thread_))->GetConstantPool(thread_);
137     } else {
138         constpool = currMethod->GetConstantPool(thread_);
139     }
140     return constpool;
141 }
142 
GetArrayLiteralFromCache(JSTaggedValue constpool,uint32_t index,CString entry) const143 JSTaggedValue JitCompilationEnv::GetArrayLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const
144 {
145     ASSERT(thread_->IsInRunningState());
146     return ConstantPool::GetLiteralFromCacheNoScope<ConstPoolType::ARRAY_LITERAL>(thread_, constpool, index, entry);
147 }
148 
GetObjectLiteralFromCache(JSTaggedValue constpool,uint32_t index,CString entry) const149 JSTaggedValue JitCompilationEnv::GetObjectLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const
150 {
151     ASSERT(thread_->IsInRunningState());
152     return ConstantPool::GetLiteralFromCacheNoScope<ConstPoolType::OBJECT_LITERAL>(thread_, constpool, index, entry);
153 }
154 
GetMethodFromCache(JSTaggedValue constpool,uint32_t index) const155 JSTaggedValue JitCompilationEnv::GetMethodFromCache(JSTaggedValue constpool, uint32_t index) const
156 {
157     return ConstantPool::GetMethodFromCache(constpool, index, thread_);
158 }
159 
GetIdFromCache(JSTaggedValue constpool,uint32_t index) const160 panda_file::File::EntityId JitCompilationEnv::GetIdFromCache(JSTaggedValue constpool, uint32_t index) const
161 {
162     ASSERT(thread_->IsInRunningState());
163     return ConstantPool::GetIdFromCache(constpool, index);
164 }
165 
GetGlobalEnv() const166 JSHandle<GlobalEnv> JitCompilationEnv::GetGlobalEnv() const
167 {
168     ASSERT(globalEnv_.IsJSGlobalEnv());
169     return JSHandle<GlobalEnv>(ToUintPtr(&globalEnv_));
170 }
171 
GlobalConstants() const172 const GlobalEnvConstants *JitCompilationEnv::GlobalConstants() const
173 {
174     ASSERT(thread_->IsInRunningState());
175     return hostThread_->GlobalConstants();
176 }
177 
178 // The caller should add assessment for undefined constpool.
179 // When slotValue in profileTypeInfo is changed in main thread, constpool may be undefined.
GetStringFromConstantPool(const uint32_t methodOffset,const uint16_t cpIdx,bool allowAlloc) const180 JSTaggedValue JitCompilationEnv::GetStringFromConstantPool([[maybe_unused]] const uint32_t methodOffset,
181     const uint16_t cpIdx, bool allowAlloc) const
182 {
183     JSTaggedValue constpool = GetConstantPoolByMethodOffset(methodOffset);
184     if (constpool.IsUndefined()) {
185         return JSTaggedValue::Undefined();
186     }
187     return ConstantPool::GetStringFromCacheForJit(GetJSThread(), constpool, cpIdx, allowAlloc);
188 }
189 
GetJsFunctionByMethodOffset(uint32_t methodOffset) const190 JSFunction *JitCompilationEnv::GetJsFunctionByMethodOffset(uint32_t methodOffset) const
191 {
192     ASSERT(thread_->IsInRunningState());
193     Method *currMethod = Method::Cast(jsFunction_->GetMethod(thread_).GetTaggedObject());
194     auto currMethodOffset = currMethod->GetMethodId().GetOffset();
195     if (methodOffset == currMethodOffset) {
196         return *jsFunction_;
197     }
198     std::vector<std::pair<uint32_t, uint32_t>> funcSlotChain;
199     uint32_t calleeOffset = methodOffset;
200     do {
201         if (functionSlotIdMap_.find(calleeOffset) == functionSlotIdMap_.end()) {
202             return nullptr;
203         }
204         funcSlotChain.push_back({functionSlotIdMap_.at(calleeOffset), callee2CallerMap_.at(calleeOffset)});
205         calleeOffset = callee2CallerMap_.at(calleeOffset);
206     } while (calleeOffset != currMethodOffset);
207     JSFunction *currFunc = *jsFunction_;
208     ProfileTypeInfo *currFuncPTI = *profileTypeInfo_;
209     for (int i = static_cast<int>(funcSlotChain.size()) - 1; i >= 0; --i) {
210         uint32_t slotId = funcSlotChain[i].first;
211         uint32_t callerOffset = funcSlotChain[i].second;
212         if (Method::Cast(currFunc->GetMethod(thread_))->GetMethodId().GetOffset() != callerOffset) {
213             return nullptr;
214         }
215         auto slotValue = currFuncPTI->Get(thread_, slotId);
216         if (slotValue.IsJSFunction()) {
217             currFunc = JSFunction::Cast(currFuncPTI->Get(thread_, slotId).GetTaggedObject());
218         } else if (slotValue.IsPrototypeHandler()) {
219             auto prototypeHandler = PrototypeHandler::Cast(slotValue.GetTaggedObject());
220             auto accessorFunction = prototypeHandler->GetAccessorJSFunction(thread_);
221             if (!accessorFunction.IsJSFunction()) {
222                 return nullptr;
223             }
224             currFunc = JSFunction::Cast(accessorFunction.GetTaggedObject());
225         } else {
226             return nullptr;
227         }
228         auto profileTypeInfoVal = currFunc->GetProfileTypeInfo(thread_);
229         if (profileTypeInfoVal.IsUndefined()) {
230             return nullptr;
231         }
232         currFuncPTI = ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject());
233     }
234     if (Method::Cast(currFunc->GetMethod(thread_))->GetMethodId().GetOffset() != methodOffset) {
235         return nullptr;
236     }
237     return currFunc;
238 }
239 
RecordHeapConstant(ConstantPoolHeapConstant heapConstant,const JSHandle<JSTaggedValue> & heapObj)240 uint32_t JitCompilationEnv::RecordHeapConstant(
241     ConstantPoolHeapConstant heapConstant, const JSHandle<JSTaggedValue> &heapObj)
242 {
243     ASSERT(SupportHeapConstant());
244     auto itr = heapConstantInfo_.constPoolHeapConstant2Index.find(heapConstant);
245     if (itr != heapConstantInfo_.constPoolHeapConstant2Index.end()) {
246         return itr->second;
247     }
248     heapConstantInfo_.heapConstantTable.push_back(heapObj);
249     ASSERT(heapConstantInfo_.heapConstantTable.size() < INVALID_HEAP_CONSTANT_INDEX);
250     uint32_t index = static_cast<uint32_t>(heapConstantInfo_.heapConstantTable.size() - 1);
251     heapConstantInfo_.constPoolHeapConstant2Index.insert(
252         std::pair<ConstantPoolHeapConstant, uint32_t>(heapConstant, index));
253     return index;
254 }
255 
GetHeapConstantHandle(uint32_t heapConstantIndex) const256 JSHandle<JSTaggedValue> JitCompilationEnv::GetHeapConstantHandle(uint32_t heapConstantIndex) const
257 {
258     ASSERT(heapConstantIndex < heapConstantInfo_.heapConstantTable.size());
259     return heapConstantInfo_.heapConstantTable[heapConstantIndex];
260 }
261 } // namespace panda::ecmascript
262