• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include "ecmascript/compiler/bytecode_info_collector.h"
17 
18 #include "ecmascript/compiler/type_recorder.h"
19 #include "ecmascript/interpreter/interpreter-inl.h"
20 #include "ecmascript/ts_types/ts_type_parser.h"
21 #include "libpandafile/code_data_accessor.h"
22 
23 namespace panda::ecmascript::kungfu {
24 template<class T, class... Args>
InitializeMemory(T * mem,Args...args)25 static T *InitializeMemory(T *mem, Args... args)
26 {
27     return new (mem) T(std::forward<Args>(args)...);
28 }
29 
ProcessClasses()30 void BytecodeInfoCollector::ProcessClasses()
31 {
32     ASSERT(jsPandaFile_ != nullptr && jsPandaFile_->GetMethodLiterals() != nullptr);
33     MethodLiteral *methods = jsPandaFile_->GetMethodLiterals();
34     const panda_file::File *pf = jsPandaFile_->GetPandaFile();
35     size_t methodIdx = 0;
36     std::map<const uint8_t *, std::pair<size_t, uint32_t>> processedInsns;
37     Span<const uint32_t> classIndexes = jsPandaFile_->GetClasses();
38 
39     auto &mainMethodIndexes = bytecodeInfo_.GetMainMethodIndexes();
40     auto &recordNames = bytecodeInfo_.GetRecordNames();
41     auto &methodPcInfos = bytecodeInfo_.GetMethodPcInfos();
42 
43     for (const uint32_t index : classIndexes) {
44         panda_file::File::EntityId classId(index);
45         if (pf->IsExternal(classId)) {
46             continue;
47         }
48         panda_file::ClassDataAccessor cda(*pf, classId);
49         CString desc = utf::Mutf8AsCString(cda.GetDescriptor());
50         cda.EnumerateMethods([this, methods, &methodIdx, pf, &processedInsns, &desc,
51             &mainMethodIndexes, &recordNames, &methodPcInfos] (panda_file::MethodDataAccessor &mda) {
52             auto codeId = mda.GetCodeId();
53             auto methodId = mda.GetMethodId();
54             ASSERT(codeId.has_value());
55 
56             // Generate all constpool
57             vm_->FindOrCreateConstPool(jsPandaFile_, methodId);
58 
59             MethodLiteral *methodLiteral = methods + (methodIdx++);
60             panda_file::CodeDataAccessor codeDataAccessor(*pf, codeId.value());
61             uint32_t codeSize = codeDataAccessor.GetCodeSize();
62             auto methodOffset = methodId.GetOffset();
63             CString name = reinterpret_cast<const char *>(pf->GetStringData(mda.GetNameId()).data);
64             if (JSPandaFile::IsEntryOrPatch(name)) {
65                 const CString recordName = jsPandaFile_->ParseEntryPoint(desc);
66                 jsPandaFile_->UpdateMainMethodIndex(methodOffset, recordName);
67                 mainMethodIndexes.emplace_back(methodOffset);
68                 recordNames.emplace_back(recordName);
69             }
70 
71             InitializeMemory(methodLiteral, jsPandaFile_, methodId);
72             methodLiteral->SetHotnessCounter(EcmaInterpreter::GetHotnessCounter(codeSize));
73             methodLiteral->Initialize(
74                 jsPandaFile_, codeDataAccessor.GetNumVregs(), codeDataAccessor.GetNumArgs());
75             const uint8_t *insns = codeDataAccessor.GetInstructions();
76             ASSERT(jsPandaFile_->IsNewVersion());
77             panda_file::IndexAccessor indexAccessor(*pf, methodId);
78             panda_file::FunctionKind funcKind = indexAccessor.GetFunctionKind();
79             FunctionKind kind = JSPandaFile::GetFunctionKind(funcKind);
80             methodLiteral->SetFunctionKind(kind);
81             auto it = processedInsns.find(insns);
82             if (it == processedInsns.end()) {
83                 std::vector<std::string> classNameVec;
84                 CollectMethodPcsFromBC(codeSize, insns, methodLiteral, classNameVec);
85                 processedInsns[insns] = std::make_pair(methodPcInfos.size() - 1, methodOffset);
86                 // collect className and literal offset for type infer
87                 if (EnableCollectLiteralInfo()) {
88                     CollectClassLiteralInfo(methodLiteral, classNameVec);
89                 }
90             }
91 
92             SetMethodPcInfoIndex(methodOffset, processedInsns[insns]);
93             jsPandaFile_->SetMethodLiteralToMap(methodLiteral);
94         });
95     }
96     LOG_COMPILER(INFO) << "Total number of methods in file: "
97                        << jsPandaFile_->GetJSPandaFileDesc()
98                        << " is: "
99                        << methodIdx;
100 }
101 
CollectClassLiteralInfo(const MethodLiteral * method,const std::vector<std::string> & classNameVec)102 void BytecodeInfoCollector::CollectClassLiteralInfo(const MethodLiteral *method,
103                                                     const std::vector<std::string> &classNameVec)
104 {
105     std::vector<uint32_t> classOffsetVec;
106     IterateLiteral(method, classOffsetVec);
107 
108     if (classOffsetVec.size() == classNameVec.size()) {
109         for (uint32_t i = 0; i < classOffsetVec.size(); i++) {
110             vm_->GetTSManager()->AddElementToClassNameMap(jsPandaFile_, classOffsetVec[i], classNameVec[i]);
111         }
112     }
113 }
114 
IterateLiteral(const MethodLiteral * method,std::vector<uint32_t> & classOffsetVector)115 void BytecodeInfoCollector::IterateLiteral(const MethodLiteral *method,
116                                            std::vector<uint32_t> &classOffsetVector)
117 {
118     const panda_file::File *pf = jsPandaFile_->GetPandaFile();
119     panda_file::File::EntityId fieldId = method->GetMethodId();
120     uint32_t defineMethodOffset = fieldId.GetOffset();
121     panda_file::MethodDataAccessor methodDataAccessor(*pf, fieldId);
122 
123     methodDataAccessor.EnumerateAnnotations([&](panda_file::File::EntityId annotation_id) {
124         panda_file::AnnotationDataAccessor ada(*pf, annotation_id);
125         std::string annotationName = std::string(utf::Mutf8AsCString(pf->GetStringData(ada.GetClassId()).data));
126         if (annotationName.compare("L_ESTypeAnnotation;") != 0) {
127             return;
128         }
129         uint32_t length = ada.GetCount();
130         for (uint32_t i = 0; i < length; i++) {
131             panda_file::AnnotationDataAccessor::Elem adae = ada.GetElement(i);
132             std::string elemName = std::string(utf::Mutf8AsCString(pf->GetStringData(adae.GetNameId()).data));
133             if (elemName.compare("_TypeOfInstruction") != 0) {
134                 continue;
135             }
136 
137             panda_file::ScalarValue sv = adae.GetScalarValue();
138             panda_file::File::EntityId literalOffset(sv.GetValue());
139             JSHandle<TaggedArray> typeOfInstruction =
140                 LiteralDataExtractor::GetTypeLiteral(vm_->GetJSThread(), jsPandaFile_, literalOffset);
141             std::map<int32_t, uint32_t> offsetTypeMap;
142             for (uint32_t j = 0; j < typeOfInstruction->GetLength(); j = j + 2) {
143                 int32_t bcOffset = typeOfInstruction->Get(j).GetInt();
144                 uint32_t typeOffset = static_cast<uint32_t>(typeOfInstruction->Get(j + 1).GetInt());
145                 if (classDefBCIndexes_.find(bcOffset) != classDefBCIndexes_.end() ||
146                     classDefBCIndexes_.find(bcOffset - 1) != classDefBCIndexes_.end()) { // for getter setter
147                     bytecodeInfo_.SetClassTypeOffsetAndDefMethod(typeOffset, defineMethodOffset);
148                 }
149                 if (bcOffset != TypeRecorder::METHOD_ANNOTATION_THIS_TYPE_OFFSET &&
150                     typeOffset > TSTypeParser::USER_DEFINED_TYPE_OFFSET) {
151                     offsetTypeMap.insert(std::make_pair(bcOffset, typeOffset));
152                 }
153             }
154 
155             for (auto item : offsetTypeMap) {
156                 panda_file::File::EntityId offset(item.second);
157                 JSHandle<TaggedArray> literal =
158                     LiteralDataExtractor::GetTypeLiteral(vm_->GetJSThread(), jsPandaFile_, offset);
159                 int typeKind = literal->Get(0).GetInt();
160                 if (typeKind == static_cast<int>(TSTypeKind::CLASS)) {
161                     classOffsetVector.push_back(item.second);
162                 }
163             }
164         }
165     });
166     classDefBCIndexes_.clear();
167 }
168 
CollectMethodPcsFromBC(const uint32_t insSz,const uint8_t * insArr,const MethodLiteral * method,std::vector<std::string> & classNameVec)169 void BytecodeInfoCollector::CollectMethodPcsFromBC(const uint32_t insSz, const uint8_t *insArr,
170                                                    const MethodLiteral *method, std::vector<std::string> &classNameVec)
171 {
172     auto bcIns = BytecodeInst(insArr);
173     auto bcInsLast = bcIns.JumpTo(insSz);
174     int32_t bcIndex = 0;
175     auto &methodPcInfos = bytecodeInfo_.GetMethodPcInfos();
176     methodPcInfos.emplace_back(MethodPcInfo { {}, insSz });
177     auto &pcOffsets = methodPcInfos.back().pcOffsets;
178     const uint8_t *curPc = bcIns.GetAddress();
179 
180     while (bcIns.GetAddress() != bcInsLast.GetAddress()) {
181         CollectMethodInfoFromBC(bcIns, method, classNameVec, bcIndex);
182         CollectConstantPoolIndexInfoFromBC(bcIns, method);
183         curPc = bcIns.GetAddress();
184         auto nextInst = bcIns.GetNext();
185         bcIns = nextInst;
186         pcOffsets.emplace_back(curPc);
187         bcIndex++;
188     }
189 }
190 
SetMethodPcInfoIndex(uint32_t methodOffset,const std::pair<size_t,uint32_t> & processedMethodInfo)191 void BytecodeInfoCollector::SetMethodPcInfoIndex(uint32_t methodOffset,
192                                                  const std::pair<size_t, uint32_t> &processedMethodInfo)
193 {
194     auto processedMethodPcInfoIndex = processedMethodInfo.first;
195     auto processedMethodOffset = processedMethodInfo.second;
196     uint32_t numOfLexVars = 0;
197     LexicalEnvStatus status = LexicalEnvStatus::VIRTUAL_LEXENV;
198     auto &methodList = bytecodeInfo_.GetMethodList();
199     // Methods with the same instructions in abc files have the same static information. Since
200     // information from bytecodes is collected only once, methods other than the processed method
201     // will obtain static information from the processed method.
202     auto processedIter = methodList.find(processedMethodOffset);
203     if (processedIter != methodList.end()) {
204         const MethodInfo &processedMethod = processedIter->second;
205         numOfLexVars = processedMethod.GetNumOfLexVars();
206         status = processedMethod.GetLexEnvStatus();
207     }
208 
209     auto iter = methodList.find(methodOffset);
210     if (iter != methodList.end()) {
211         MethodInfo &methodInfo = iter->second;
212         methodInfo.SetMethodPcInfoIndex(processedMethodPcInfoIndex);
213         methodInfo.SetNumOfLexVars(numOfLexVars);
214         methodInfo.SetLexEnvStatus(status);
215         return;
216     }
217     MethodInfo info(GetMethodInfoID(), processedMethodPcInfoIndex, LexEnv::DEFAULT_ROOT,
218         MethodInfo::DEFAULT_OUTMETHOD_OFFSET, numOfLexVars, status);
219     methodList.emplace(methodOffset, info);
220 }
221 
CollectInnerMethods(const MethodLiteral * method,uint32_t innerMethodOffset)222 void BytecodeInfoCollector::CollectInnerMethods(const MethodLiteral *method, uint32_t innerMethodOffset)
223 {
224     auto methodId = method->GetMethodId().GetOffset();
225     CollectInnerMethods(methodId, innerMethodOffset);
226 }
227 
CollectInnerMethods(uint32_t methodId,uint32_t innerMethodOffset)228 void BytecodeInfoCollector::CollectInnerMethods(uint32_t methodId, uint32_t innerMethodOffset)
229 {
230     auto &methodList = bytecodeInfo_.GetMethodList();
231     uint32_t methodInfoId = 0;
232     auto methodIter = methodList.find(methodId);
233     if (methodIter != methodList.end()) {
234         MethodInfo &methodInfo = methodIter->second;
235         methodInfoId = methodInfo.GetMethodInfoIndex();
236         methodInfo.AddInnerMethod(innerMethodOffset);
237     } else {
238         methodInfoId = GetMethodInfoID();
239         MethodInfo info(methodInfoId, 0, LexEnv::DEFAULT_ROOT);
240         methodList.emplace(methodId, info);
241         methodList.at(methodId).AddInnerMethod(innerMethodOffset);
242     }
243 
244     auto innerMethodIter = methodList.find(innerMethodOffset);
245     if (innerMethodIter != methodList.end()) {
246         innerMethodIter->second.SetOutMethodId(methodInfoId);
247         innerMethodIter->second.SetOutMethodOffset(methodId);
248         return;
249     }
250     MethodInfo innerInfo(GetMethodInfoID(), 0, methodInfoId, methodId);
251     methodList.emplace(innerMethodOffset, innerInfo);
252 }
253 
CollectInnerMethodsFromLiteral(const MethodLiteral * method,uint64_t index)254 void BytecodeInfoCollector::CollectInnerMethodsFromLiteral(const MethodLiteral *method, uint64_t index)
255 {
256     std::vector<uint32_t> methodOffsets;
257     LiteralDataExtractor::GetMethodOffsets(jsPandaFile_, index, methodOffsets);
258     for (auto methodOffset : methodOffsets) {
259         CollectInnerMethods(method, methodOffset);
260     }
261 }
262 
NewLexEnvWithSize(const MethodLiteral * method,uint64_t numOfLexVars)263 void BytecodeInfoCollector::NewLexEnvWithSize(const MethodLiteral *method, uint64_t numOfLexVars)
264 {
265     auto &methodList = bytecodeInfo_.GetMethodList();
266     auto methodOffset = method->GetMethodId().GetOffset();
267     auto iter = methodList.find(methodOffset);
268     if (iter != methodList.end()) {
269         MethodInfo &methodInfo = iter->second;
270         methodInfo.SetNumOfLexVars(numOfLexVars);
271         methodInfo.SetLexEnvStatus(LexicalEnvStatus::REALITY_LEXENV);
272         return;
273     }
274     MethodInfo info(GetMethodInfoID(), 0, LexEnv::DEFAULT_ROOT, MethodInfo::DEFAULT_OUTMETHOD_OFFSET,
275         numOfLexVars, LexicalEnvStatus::REALITY_LEXENV);
276     methodList.emplace(methodOffset, info);
277 }
278 
CollectInnerMethodsFromNewLiteral(const MethodLiteral * method,panda_file::File::EntityId literalId)279 void BytecodeInfoCollector::CollectInnerMethodsFromNewLiteral(const MethodLiteral *method,
280                                                               panda_file::File::EntityId literalId)
281 {
282     std::vector<uint32_t> methodOffsets;
283     LiteralDataExtractor::GetMethodOffsets(jsPandaFile_, literalId, methodOffsets);
284     for (auto methodOffset : methodOffsets) {
285         CollectInnerMethods(method, methodOffset);
286     }
287 }
288 
CollectMethodInfoFromBC(const BytecodeInstruction & bcIns,const MethodLiteral * method,std::vector<std::string> & classNameVec,int32_t bcIndex)289 void BytecodeInfoCollector::CollectMethodInfoFromBC(const BytecodeInstruction &bcIns,
290                                                     const MethodLiteral *method, std::vector<std::string> &classNameVec,
291                                                     int32_t bcIndex)
292 {
293     const panda_file::File *pf = jsPandaFile_->GetPandaFile();
294     if (!(bcIns.HasFlag(BytecodeInstruction::Flags::STRING_ID) &&
295         BytecodeInstruction::HasId(BytecodeInstruction::GetFormat(bcIns.GetOpcode()), 0))) {
296         BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode());
297         switch (opcode) {
298             uint32_t methodId;
299             case BytecodeInstruction::Opcode::DEFINEFUNC_IMM8_ID16_IMM8:
300             case BytecodeInstruction::Opcode::DEFINEFUNC_IMM16_ID16_IMM8: {
301                 methodId = pf->ResolveMethodIndex(method->GetMethodId(),
302                                                   static_cast<uint16_t>(bcIns.GetId().AsRawValue())).GetOffset();
303                 CollectInnerMethods(method, methodId);
304                 break;
305             }
306             case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM8_ID16_IMM8:
307             case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM16_ID16_IMM8: {
308                 methodId = pf->ResolveMethodIndex(method->GetMethodId(),
309                                                   static_cast<uint16_t>(bcIns.GetId().AsRawValue())).GetOffset();
310                 CollectInnerMethods(method, methodId);
311                 break;
312             }
313             case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:{
314                 auto entityId = pf->ResolveMethodIndex(method->GetMethodId(),
315                     (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 0>()).AsRawValue());
316                 classNameVec.emplace_back(GetClassName(entityId));
317                 classDefBCIndexes_.insert(bcIndex);
318                 methodId = entityId.GetOffset();
319                 CollectInnerMethods(method, methodId);
320                 auto literalId = pf->ResolveMethodIndex(method->GetMethodId(),
321                     (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 1>()).AsRawValue());
322                 CollectInnerMethodsFromNewLiteral(method, literalId);
323                 break;
324             }
325             case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
326                 auto entityId = pf->ResolveMethodIndex(method->GetMethodId(),
327                     (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 0>()).AsRawValue());
328                 classNameVec.emplace_back(GetClassName(entityId));
329                 classDefBCIndexes_.insert(bcIndex);
330                 methodId = entityId.GetOffset();
331                 CollectInnerMethods(method, methodId);
332                 auto literalId = pf->ResolveMethodIndex(method->GetMethodId(),
333                     (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 1>()).AsRawValue());
334                 CollectInnerMethodsFromNewLiteral(method, literalId);
335                 break;
336             }
337             case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
338             case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM16_ID16: {
339                 auto literalId = pf->ResolveMethodIndex(method->GetMethodId(),
340                                                         static_cast<uint16_t>(bcIns.GetId().AsRawValue()));
341                 CollectInnerMethodsFromNewLiteral(method, literalId);
342                 break;
343             }
344             case BytecodeInstruction::Opcode::DEPRECATED_CREATEARRAYWITHBUFFER_PREF_IMM16: {
345                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16>();
346                 CollectInnerMethodsFromLiteral(method, imm);
347                 break;
348             }
349             case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
350             case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: {
351                 auto literalId = pf->ResolveMethodIndex(method->GetMethodId(),
352                                                         static_cast<uint16_t>(bcIns.GetId().AsRawValue()));
353                 CollectInnerMethodsFromNewLiteral(method, literalId);
354                 break;
355             }
356             case BytecodeInstruction::Opcode::DEPRECATED_CREATEOBJECTWITHBUFFER_PREF_IMM16: {
357                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16>();
358                 CollectInnerMethodsFromLiteral(method, imm);
359                 break;
360             }
361             case BytecodeInstruction::Opcode::NEWLEXENV_IMM8: {
362                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::IMM8>();
363                 NewLexEnvWithSize(method, imm);
364                 break;
365             }
366             case BytecodeInstruction::Opcode::NEWLEXENVWITHNAME_IMM8_ID16: {
367                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::IMM8_ID16>();
368                 NewLexEnvWithSize(method, imm);
369                 break;
370             }
371             case BytecodeInstruction::Opcode::WIDE_NEWLEXENV_PREF_IMM16: {
372                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16>();
373                 NewLexEnvWithSize(method, imm);
374                 break;
375             }
376             case BytecodeInstruction::Opcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16: {
377                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16_ID16>();
378                 NewLexEnvWithSize(method, imm);
379                 break;
380             }
381             default:
382                 break;
383         }
384     }
385 }
386 
CollectConstantPoolIndexInfoFromBC(const BytecodeInstruction & bcIns,const MethodLiteral * methodliteral)387 void BytecodeInfoCollector::CollectConstantPoolIndexInfoFromBC(const BytecodeInstruction &bcIns,
388                                                                const MethodLiteral *methodliteral)
389 {
390     BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode());
391     uint32_t methodOffset = methodliteral->GetMethodId().GetOffset();
392     switch (opcode) {
393         case BytecodeInstruction::Opcode::LDA_STR_ID16:
394         case BytecodeInstruction::Opcode::STOWNBYNAME_IMM8_ID16_V8:
395         case BytecodeInstruction::Opcode::STOWNBYNAME_IMM16_ID16_V8:
396         case BytecodeInstruction::Opcode::CREATEREGEXPWITHLITERAL_IMM8_ID16_IMM8:
397         case BytecodeInstruction::Opcode::CREATEREGEXPWITHLITERAL_IMM16_ID16_IMM8:
398         case BytecodeInstruction::Opcode::STCONSTTOGLOBALRECORD_IMM16_ID16:
399         case BytecodeInstruction::Opcode::TRYLDGLOBALBYNAME_IMM8_ID16:
400         case BytecodeInstruction::Opcode::TRYLDGLOBALBYNAME_IMM16_ID16:
401         case BytecodeInstruction::Opcode::TRYSTGLOBALBYNAME_IMM8_ID16:
402         case BytecodeInstruction::Opcode::TRYSTGLOBALBYNAME_IMM16_ID16:
403         case BytecodeInstruction::Opcode::STTOGLOBALRECORD_IMM16_ID16:
404         case BytecodeInstruction::Opcode::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8:
405         case BytecodeInstruction::Opcode::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8:
406         case BytecodeInstruction::Opcode::LDTHISBYNAME_IMM8_ID16:
407         case BytecodeInstruction::Opcode::LDTHISBYNAME_IMM16_ID16:
408         case BytecodeInstruction::Opcode::STTHISBYNAME_IMM8_ID16:
409         case BytecodeInstruction::Opcode::STTHISBYNAME_IMM16_ID16:
410         case BytecodeInstruction::Opcode::LDGLOBALVAR_IMM16_ID16:
411         case BytecodeInstruction::Opcode::LDOBJBYNAME_IMM8_ID16:
412         case BytecodeInstruction::Opcode::LDOBJBYNAME_IMM16_ID16:
413         case BytecodeInstruction::Opcode::STOBJBYNAME_IMM8_ID16_V8:
414         case BytecodeInstruction::Opcode::STOBJBYNAME_IMM16_ID16_V8:
415         case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM8_ID16:
416         case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM16_ID16:
417         case BytecodeInstruction::Opcode::STSUPERBYNAME_IMM8_ID16_V8:
418         case BytecodeInstruction::Opcode::STSUPERBYNAME_IMM16_ID16_V8:
419         case BytecodeInstruction::Opcode::STGLOBALVAR_IMM16_ID16:
420         case BytecodeInstruction::Opcode::LDBIGINT_ID16: {
421             auto index = bcIns.GetId().AsRawValue();
422             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::STRING, index, methodOffset);
423             break;
424         }
425         case BytecodeInstruction::Opcode::DEFINEFUNC_IMM8_ID16_IMM8:
426         case BytecodeInstruction::Opcode::DEFINEFUNC_IMM16_ID16_IMM8:
427         case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM8_ID16_IMM8:
428         case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM16_ID16_IMM8: {
429             auto index = bcIns.GetId().AsRawValue();
430             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, index, methodOffset);
431             break;
432         }
433         case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
434         case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: {
435             auto index = bcIns.GetId().AsRawValue();
436             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::OBJECT_LITERAL, index, methodOffset);
437             break;
438         }
439         case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
440         case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM16_ID16: {
441             auto index = bcIns.GetId().AsRawValue();
442             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::ARRAY_LITERAL, index, methodOffset);
443             break;
444         }
445         case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: {
446             auto methodIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
447             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, methodIndex, methodOffset);
448             auto literalIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
449             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::CLASS_LITERAL, literalIndex, methodOffset);
450             break;
451         }
452         case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
453             auto methodIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
454             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, methodIndex, methodOffset);
455             auto literalIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
456             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::CLASS_LITERAL, literalIndex, methodOffset);
457             break;
458         }
459         default:
460             break;
461     }
462 }
463 
LexEnvManager(BCInfo & bcInfo)464 LexEnvManager::LexEnvManager(BCInfo &bcInfo)
465     : lexEnvs_(bcInfo.GetMethodList().size())
466 {
467     const auto &methodList = bcInfo.GetMethodList();
468     for (const auto &it : methodList) {
469         const MethodInfo &methodInfo = it.second;
470         lexEnvs_[methodInfo.GetMethodInfoIndex()].Inilialize(methodInfo.GetOutMethodId(),
471                                                              methodInfo.GetNumOfLexVars(),
472                                                              methodInfo.GetLexEnvStatus());
473     }
474 }
475 
SetLexEnvElementType(uint32_t methodId,uint32_t level,uint32_t slot,const GateType & type)476 void LexEnvManager::SetLexEnvElementType(uint32_t methodId, uint32_t level, uint32_t slot, const GateType &type)
477 {
478     uint32_t offset = GetTargetLexEnv(methodId, level);
479     lexEnvs_[offset].SetLexVarType(slot, type);
480 }
481 
GetLexEnvElementType(uint32_t methodId,uint32_t level,uint32_t slot) const482 GateType LexEnvManager::GetLexEnvElementType(uint32_t methodId, uint32_t level, uint32_t slot) const
483 {
484     uint32_t offset = GetTargetLexEnv(methodId, level);
485     return lexEnvs_[offset].GetLexVarType(slot);
486 }
487 
GetTargetLexEnv(uint32_t methodId,uint32_t level) const488 uint32_t LexEnvManager::GetTargetLexEnv(uint32_t methodId, uint32_t level) const
489 {
490     auto offset = methodId;
491     auto status = GetLexEnvStatus(offset);
492     while (!HasDefaultRoot(offset) && ((level > 0) || (status != LexicalEnvStatus::REALITY_LEXENV))) {
493         offset = GetOutMethodId(offset);
494         if (HasDefaultRoot(offset)) {
495             break;
496         }
497         if (status == LexicalEnvStatus::REALITY_LEXENV && level != 0) {
498             --level;
499         }
500         status = GetLexEnvStatus(offset);
501     }
502     return offset;
503 }
504 
AddIndexToCPItem(ItemType type,uint32_t index,uint32_t methodOffset)505 void ConstantPoolInfo::AddIndexToCPItem(ItemType type, uint32_t index, uint32_t methodOffset)
506 {
507     Item &item = GetCPItem(type);
508     if (item.find(index) != item.end()) {
509         return;
510     }
511     item.insert({index, ItemData {index, methodOffset, nullptr}});
512 }
513 }  // namespace panda::ecmascript::kungfu
514