• 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/jspandafile/type_literal_extractor.h"
21 #include "ecmascript/module/module_path_helper.h"
22 #include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
23 #include "ecmascript/ts_types/ts_type_parser.h"
24 #include "libpandafile/code_data_accessor.h"
25 
26 namespace panda::ecmascript::kungfu {
27 template<class T, class... Args>
InitializeMemory(T * mem,Args...args)28 static T *InitializeMemory(T *mem, Args... args)
29 {
30     return new (mem) T(std::forward<Args>(args)...);
31 }
32 
BytecodeInfoCollector(EcmaVM * vm,JSPandaFile * jsPandaFile,PGOProfilerDecoder & pfDecoder,size_t maxAotMethodSize,bool enableCollectLiteralInfo)33 BytecodeInfoCollector::BytecodeInfoCollector(EcmaVM *vm, JSPandaFile *jsPandaFile, PGOProfilerDecoder &pfDecoder,
34                                              size_t maxAotMethodSize, bool enableCollectLiteralInfo)
35     : vm_(vm),
36       jsPandaFile_(jsPandaFile),
37       bytecodeInfo_(maxAotMethodSize),
38       pfDecoder_(pfDecoder),
39       enableCollectLiteralInfo_(enableCollectLiteralInfo)
40 {
41     vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->SetBytecodeInfoCollector(this);
42     ProcessClasses();
43     ProcessEnvs();
44 }
45 
~BytecodeInfoCollector()46 BytecodeInfoCollector::~BytecodeInfoCollector()
47 {
48     if (envManager_ != nullptr) {
49         delete envManager_;
50         envManager_ = nullptr;
51     }
52     auto tsManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
53     tsManager->PrintTypeInfo(jsPandaFile_);
54     tsManager->SetBytecodeInfoCollector(nullptr);
55 }
56 
ProcessEnvs()57 void BytecodeInfoCollector::ProcessEnvs()
58 {
59     if (envManager_ == nullptr) {
60         envManager_ = new LexEnvManager(bytecodeInfo_);
61     }
62 }
63 
ProcessClasses()64 void BytecodeInfoCollector::ProcessClasses()
65 {
66     ASSERT(jsPandaFile_ != nullptr && jsPandaFile_->GetMethodLiterals() != nullptr);
67     MethodLiteral *methods = jsPandaFile_->GetMethodLiterals();
68     const panda_file::File *pf = jsPandaFile_->GetPandaFile();
69     size_t methodIdx = 0;
70     std::map<uint32_t, std::pair<size_t, uint32_t>> processedMethod;
71     Span<const uint32_t> classIndexes = jsPandaFile_->GetClasses();
72 
73     auto &recordNames = bytecodeInfo_.GetRecordNames();
74     auto &methodPcInfos = bytecodeInfo_.GetMethodPcInfos();
75     std::vector<panda_file::File::EntityId> methodIndexes;
76     std::vector<panda_file::File::EntityId> classConstructIndexes;
77     for (const uint32_t index : classIndexes) {
78         panda_file::File::EntityId classId(index);
79         if (jsPandaFile_->IsExternal(classId)) {
80             continue;
81         }
82         panda_file::ClassDataAccessor cda(*pf, classId);
83         CString desc = utf::Mutf8AsCString(cda.GetDescriptor());
84         const CString recordName = JSPandaFile::ParseEntryPoint(desc);
85         cda.EnumerateMethods([this, methods, &methodIdx, pf, &processedMethod,
86             &recordNames, &methodPcInfos, &recordName,
87             &methodIndexes, &classConstructIndexes] (panda_file::MethodDataAccessor &mda) {
88             auto methodId = mda.GetMethodId();
89             methodIndexes.emplace_back(methodId);
90             CollectFunctionTypeId(methodId);
91 
92             // Generate all constpool
93             vm_->GetJSThread()->GetCurrentEcmaContext()->FindOrCreateConstPool(jsPandaFile_, methodId);
94 
95             auto methodOffset = methodId.GetOffset();
96             CString name = reinterpret_cast<const char *>(jsPandaFile_->GetStringData(mda.GetNameId()).data);
97             if (JSPandaFile::IsEntryOrPatch(name)) {
98                 jsPandaFile_->UpdateMainMethodIndex(methodOffset, recordName);
99                 recordNames.emplace_back(recordName);
100             }
101 
102             MethodLiteral *methodLiteral = methods + (methodIdx++);
103             InitializeMemory(methodLiteral, methodId);
104             methodLiteral->Initialize(jsPandaFile_);
105 
106             ASSERT(jsPandaFile_->IsNewVersion());
107             panda_file::IndexAccessor indexAccessor(*pf, methodId);
108             panda_file::FunctionKind funcKind = indexAccessor.GetFunctionKind();
109             FunctionKind kind = JSPandaFile::GetFunctionKind(funcKind);
110             methodLiteral->SetFunctionKind(kind);
111 
112             auto codeId = mda.GetCodeId();
113             ASSERT(codeId.has_value());
114             panda_file::CodeDataAccessor codeDataAccessor(*pf, codeId.value());
115             uint32_t codeSize = codeDataAccessor.GetCodeSize();
116             const uint8_t *insns = codeDataAccessor.GetInstructions();
117             auto it = processedMethod.find(methodOffset);
118             if (it == processedMethod.end()) {
119                 std::vector<std::string> classNameVec;
120                 CollectMethodPcsFromBC(codeSize, insns, methodLiteral, classNameVec,
121                     recordName, methodOffset, classConstructIndexes);
122                 processedMethod[methodOffset] = std::make_pair(methodPcInfos.size() - 1, methodOffset);
123                 // collect className and literal offset for type infer
124                 if (EnableCollectLiteralInfo()) {
125                     CollectClassLiteralInfo(methodLiteral, classNameVec);
126                 }
127             }
128 
129             SetMethodPcInfoIndex(methodOffset, processedMethod[methodOffset]);
130             jsPandaFile_->SetMethodLiteralToMap(methodLiteral);
131             pfDecoder_.MatchAndMarkMethod(recordName, name.c_str(), methodId);
132         });
133     }
134     // class Construct need to use new target, can not fastcall
135     for (auto index : classConstructIndexes) {
136         MethodLiteral *method = jsPandaFile_->GetMethodLiteralByIndex(index.GetOffset());
137         if (method != nullptr) {
138             method->SetFunctionKind(FunctionKind::CLASS_CONSTRUCTOR);
139             method->SetIsFastCall(false);
140             bytecodeInfo_.ModifyMethodOffsetToCanFastCall(index.GetOffset(), false);
141         }
142     }
143     // Collect import(infer-needed) and export relationship among all records.
144     CollectRecordReferenceREL();
145     RearrangeInnerMethods();
146     LOG_COMPILER(INFO) << "Total number of methods in file: "
147                        << jsPandaFile_->GetJSPandaFileDesc()
148                        << " is: "
149                        << methodIdx;
150 }
151 
CollectClassLiteralInfo(const MethodLiteral * method,const std::vector<std::string> & classNameVec)152 void BytecodeInfoCollector::CollectClassLiteralInfo(const MethodLiteral *method,
153                                                     const std::vector<std::string> &classNameVec)
154 {
155     std::vector<uint32_t> classOffsetVec;
156     IterateLiteral(method, classOffsetVec);
157 
158     if (classOffsetVec.size() == classNameVec.size()) {
159         for (uint32_t i = 0; i < classOffsetVec.size(); i++) {
160             vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->AddElementToClassNameMap(
161                 jsPandaFile_, classOffsetVec[i], classNameVec[i]);
162         }
163     }
164 }
165 
CollectFunctionTypeId(panda_file::File::EntityId fieldId)166 void BytecodeInfoCollector::CollectFunctionTypeId(panda_file::File::EntityId fieldId)
167 {
168     uint32_t offset = fieldId.GetOffset();
169     TypeAnnotationExtractor annoExtractor(jsPandaFile_, offset);
170     uint32_t typeId = annoExtractor.GetMethodTypeOffset();
171     if (typeId != 0) {
172         bytecodeInfo_.SetFunctionTypeIDAndMethodOffset(typeId, offset);
173     }
174     if (annoExtractor.IsNamespace()) {
175         MarkMethodNamespace(offset);
176     }
177 }
178 
CollectInnerFuncType(const MethodLiteral * method,uint32_t innerMethodId,int32_t bcIndex)179 void BytecodeInfoCollector::CollectInnerFuncType(const MethodLiteral *method, uint32_t innerMethodId, int32_t bcIndex)
180 {
181     auto &methodList = bytecodeInfo_.GetMethodList();
182     auto methodId = method->GetMethodId().GetOffset();
183     auto methodIter = methodList.find(methodId);
184     if (methodIter == methodList.end()) {
185         return;
186     }
187     TypeAnnotationExtractor annoExtractor(jsPandaFile_, innerMethodId);
188     uint32_t innerFuncType = annoExtractor.GetMethodTypeOffset();
189     if (innerFuncType != 0) {
190         methodIter->second.AddBcToTypeId(bcIndex, innerFuncType);
191     }
192 }
193 
IterateLiteral(const MethodLiteral * method,std::vector<uint32_t> & classOffsetVector)194 void BytecodeInfoCollector::IterateLiteral(const MethodLiteral *method,
195                                            std::vector<uint32_t> &classOffsetVector)
196 {
197     panda_file::File::EntityId fieldId = method->GetMethodId();
198     uint32_t defineMethodOffset = fieldId.GetOffset();
199     TypeAnnotationExtractor annoExtractor(jsPandaFile_, defineMethodOffset);
200     std::map<int32_t, uint32_t> offsetTypeMap;
201     annoExtractor.EnumerateInstsAndTypes(
202         [this, &offsetTypeMap, defineMethodOffset](const int32_t bcOffset, const uint32_t typeOffset) {
203             if (classDefBCIndexes_.find(bcOffset) != classDefBCIndexes_.end() ||
204                 classDefBCIndexes_.find(bcOffset - 1) != classDefBCIndexes_.end()) { // for getter setter
205                 bytecodeInfo_.SetClassTypeOffsetAndDefMethod(typeOffset, defineMethodOffset);
206             }
207             if (bcOffset != TypeRecorder::METHOD_ANNOTATION_THIS_TYPE_OFFSET &&
208                 TSTypeParser::IsUserDefinedType(typeOffset)) {
209                 offsetTypeMap.insert(std::make_pair(bcOffset, typeOffset));
210             }
211         });
212 
213     for (auto item : offsetTypeMap) {
214         uint32_t typeOffset = item.second;
215         StoreClassTypeOffset(typeOffset, classOffsetVector);
216     }
217 
218     classDefBCIndexes_.clear();
219 }
220 
StoreClassTypeOffset(const uint32_t typeOffset,std::vector<uint32_t> & classOffsetVector)221 void BytecodeInfoCollector::StoreClassTypeOffset(const uint32_t typeOffset, std::vector<uint32_t> &classOffsetVector)
222 {
223     TypeLiteralExtractor typeLiteralExtractor(jsPandaFile_, typeOffset);
224     if (typeLiteralExtractor.GetTypeKind() != TSTypeKind::CLASS) {
225         return;
226     }
227 
228     if (classOffsetVector.empty() || typeOffset != classOffsetVector.back()) {
229         classOffsetVector.emplace_back(typeOffset);
230     }
231 }
232 
CollectMethodPcsFromBC(const uint32_t insSz,const uint8_t * insArr,MethodLiteral * method,std::vector<std::string> & classNameVec,const CString & recordName,uint32_t methodOffset,std::vector<panda_file::File::EntityId> & classConstructIndexes)233 void BytecodeInfoCollector::CollectMethodPcsFromBC(const uint32_t insSz, const uint8_t *insArr,
234     MethodLiteral *method, std::vector<std::string> &classNameVec, const CString &recordName,
235     uint32_t methodOffset, std::vector<panda_file::File::EntityId> &classConstructIndexes)
236 {
237     auto bcIns = BytecodeInst(insArr);
238     auto bcInsLast = bcIns.JumpTo(insSz);
239     int32_t bcIndex = 0;
240     auto &methodPcInfos = bytecodeInfo_.GetMethodPcInfos();
241     methodPcInfos.emplace_back(MethodPcInfo { {}, insSz });
242     auto &pcOffsets = methodPcInfos.back().pcOffsets;
243     const uint8_t *curPc = bcIns.GetAddress();
244     bool canFastCall = true;
245     bool noGC = true;
246 
247     while (bcIns.GetAddress() != bcInsLast.GetAddress()) {
248         bool fastCallFlag = true;
249         CollectMethodInfoFromBC(bcIns, method, classNameVec, bcIndex, classConstructIndexes, &fastCallFlag);
250         if (!fastCallFlag) {
251             canFastCall = false;
252         }
253         CollectModuleInfoFromBC(bcIns, method, recordName);
254         CollectConstantPoolIndexInfoFromBC(bcIns, method, bcIndex);
255         pgoBCInfo_.Record(bcIns, bcIndex, recordName, method);
256         if (noGC && !bytecodes_.GetBytecodeMetaData(curPc).IsNoGC()) {
257             noGC = false;
258         }
259         curPc = bcIns.GetAddress();
260         auto nextInst = bcIns.GetNext();
261         bcIns = nextInst;
262         pcOffsets.emplace_back(curPc);
263         bcIndex++;
264     }
265     pcOffsets.emplace_back(bcInsLast.GetAddress());
266     bytecodeInfo_.SetMethodOffsetToFastCallInfo(methodOffset, canFastCall, noGC);
267     method->SetIsFastCall(canFastCall);
268     method->SetNoGCBit(noGC);
269 }
270 
SetMethodPcInfoIndex(uint32_t methodOffset,const std::pair<size_t,uint32_t> & processedMethodInfo)271 void BytecodeInfoCollector::SetMethodPcInfoIndex(uint32_t methodOffset,
272                                                  const std::pair<size_t, uint32_t> &processedMethodInfo)
273 {
274     auto processedMethodPcInfoIndex = processedMethodInfo.first;
275     auto processedMethodOffset = processedMethodInfo.second;
276     uint32_t numOfLexVars = 0;
277     LexicalEnvStatus status = LexicalEnvStatus::VIRTUAL_LEXENV;
278     auto &methodList = bytecodeInfo_.GetMethodList();
279     std::set<uint32_t> indexSet{};
280     // Methods with the same instructions in abc files have the same static information. Since
281     // information from bytecodes is collected only once, methods other than the processed method
282     // will obtain static information from the processed method.
283     auto processedIter = methodList.find(processedMethodOffset);
284     if (processedIter != methodList.end()) {
285         const MethodInfo &processedMethod = processedIter->second;
286         numOfLexVars = processedMethod.GetNumOfLexVars();
287         status = processedMethod.GetLexEnvStatus();
288         indexSet = processedMethod.GetImportIndexes();
289     }
290 
291     auto iter = methodList.find(methodOffset);
292     if (iter != methodList.end()) {
293         MethodInfo &methodInfo = iter->second;
294         methodInfo.SetMethodPcInfoIndex(processedMethodPcInfoIndex);
295         methodInfo.SetNumOfLexVars(numOfLexVars);
296         methodInfo.SetLexEnvStatus(status);
297         // if these methods have the same bytecode, their import indexs must be the same.
298         methodInfo.CopyImportIndex(indexSet);
299         return;
300     }
301     MethodInfo info(GetMethodInfoID(), processedMethodPcInfoIndex, LexEnv::DEFAULT_ROOT,
302         MethodInfo::DEFAULT_OUTMETHOD_OFFSET, numOfLexVars, status);
303     info.CopyImportIndex(indexSet);
304     methodList.emplace(methodOffset, info);
305 }
306 
CollectInnerMethods(const MethodLiteral * method,uint32_t innerMethodOffset,bool isConstructor)307 void BytecodeInfoCollector::CollectInnerMethods(const MethodLiteral *method,
308                                                 uint32_t innerMethodOffset,
309                                                 bool isConstructor)
310 {
311     auto methodId = method->GetMethodId().GetOffset();
312     CollectInnerMethods(methodId, innerMethodOffset, isConstructor);
313 }
314 
CollectInnerMethods(uint32_t methodId,uint32_t innerMethodOffset,bool isConstructor)315 void BytecodeInfoCollector::CollectInnerMethods(uint32_t methodId, uint32_t innerMethodOffset, bool isConstructor)
316 {
317     auto &methodList = bytecodeInfo_.GetMethodList();
318     uint32_t methodInfoId = 0;
319     auto methodIter = methodList.find(methodId);
320     if (methodIter != methodList.end()) {
321         MethodInfo &methodInfo = methodIter->second;
322         methodInfoId = methodInfo.GetMethodInfoIndex();
323         methodInfo.AddInnerMethod(innerMethodOffset, isConstructor);
324     } else {
325         methodInfoId = GetMethodInfoID();
326         MethodInfo info(methodInfoId, 0, LexEnv::DEFAULT_ROOT);
327         methodList.emplace(methodId, info);
328         methodList.at(methodId).AddInnerMethod(innerMethodOffset, isConstructor);
329     }
330 
331     auto innerMethodIter = methodList.find(innerMethodOffset);
332     if (innerMethodIter != methodList.end()) {
333         innerMethodIter->second.SetOutMethodId(methodInfoId);
334         innerMethodIter->second.SetOutMethodOffset(methodId);
335         return;
336     }
337     MethodInfo innerInfo(GetMethodInfoID(), 0, methodInfoId, methodId);
338     methodList.emplace(innerMethodOffset, innerInfo);
339 }
340 
MarkMethodNamespace(const uint32_t methodOffset)341 void BytecodeInfoCollector::MarkMethodNamespace(const uint32_t methodOffset)
342 {
343     auto &methodList = bytecodeInfo_.GetMethodList();
344     auto iter = methodList.find(methodOffset);
345     if (iter != methodList.end()) {
346         MethodInfo &methodInfo = iter->second;
347         methodInfo.MarkMethodNamespace();
348         return;
349     }
350     MethodInfo info(GetMethodInfoID(), 0, LexEnv::DEFAULT_ROOT, MethodInfo::DEFAULT_OUTMETHOD_OFFSET,
351         0, LexicalEnvStatus::VIRTUAL_LEXENV, true);
352     methodList.emplace(methodOffset, info);
353 }
354 
CollectInnerMethodsFromLiteral(const MethodLiteral * method,uint64_t index)355 void BytecodeInfoCollector::CollectInnerMethodsFromLiteral(const MethodLiteral *method, uint64_t index)
356 {
357     std::vector<uint32_t> methodOffsets;
358     LiteralDataExtractor::GetMethodOffsets(jsPandaFile_, index, methodOffsets);
359     for (auto methodOffset : methodOffsets) {
360         CollectInnerMethods(method, methodOffset);
361     }
362 }
363 
NewLexEnvWithSize(const MethodLiteral * method,uint64_t numOfLexVars)364 void BytecodeInfoCollector::NewLexEnvWithSize(const MethodLiteral *method, uint64_t numOfLexVars)
365 {
366     auto &methodList = bytecodeInfo_.GetMethodList();
367     auto methodOffset = method->GetMethodId().GetOffset();
368     auto iter = methodList.find(methodOffset);
369     if (iter != methodList.end()) {
370         MethodInfo &methodInfo = iter->second;
371         methodInfo.SetNumOfLexVars(numOfLexVars);
372         methodInfo.SetLexEnvStatus(LexicalEnvStatus::REALITY_LEXENV);
373         return;
374     }
375     MethodInfo info(GetMethodInfoID(), 0, LexEnv::DEFAULT_ROOT, MethodInfo::DEFAULT_OUTMETHOD_OFFSET,
376         numOfLexVars, LexicalEnvStatus::REALITY_LEXENV);
377     methodList.emplace(methodOffset, info);
378 }
379 
CollectInnerMethodsFromNewLiteral(const MethodLiteral * method,panda_file::File::EntityId literalId)380 void BytecodeInfoCollector::CollectInnerMethodsFromNewLiteral(const MethodLiteral *method,
381                                                               panda_file::File::EntityId literalId)
382 {
383     std::vector<uint32_t> methodOffsets;
384     LiteralDataExtractor::GetMethodOffsets(jsPandaFile_, literalId, methodOffsets);
385     for (auto methodOffset : methodOffsets) {
386         CollectInnerMethods(method, methodOffset);
387     }
388 }
389 
CollectMethodInfoFromBC(const BytecodeInstruction & bcIns,const MethodLiteral * method,std::vector<std::string> & classNameVec,int32_t bcIndex,std::vector<panda_file::File::EntityId> & classConstructIndexes,bool * canFastCall)390 void BytecodeInfoCollector::CollectMethodInfoFromBC(const BytecodeInstruction &bcIns,
391     const MethodLiteral *method, std::vector<std::string> &classNameVec, int32_t bcIndex,
392     std::vector<panda_file::File::EntityId> &classConstructIndexes, bool *canFastCall)
393 {
394     if (!(bcIns.HasFlag(BytecodeInstruction::Flags::STRING_ID) &&
395         BytecodeInstruction::HasId(BytecodeInstruction::GetFormat(bcIns.GetOpcode()), 0))) {
396         BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode());
397         switch (opcode) {
398             uint32_t methodId;
399             case BytecodeInstruction::Opcode::DEFINEFUNC_IMM8_ID16_IMM8:
400             case BytecodeInstruction::Opcode::DEFINEFUNC_IMM16_ID16_IMM8: {
401                 methodId = jsPandaFile_->ResolveMethodIndex(method->GetMethodId(),
402                     static_cast<uint16_t>(bcIns.GetId().AsRawValue())).GetOffset();
403                 CollectInnerMethods(method, methodId);
404                 CollectInnerFuncType(method, methodId, bcIndex);
405                 break;
406             }
407             case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM8_ID16_IMM8:
408             case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM16_ID16_IMM8: {
409                 methodId = jsPandaFile_->ResolveMethodIndex(method->GetMethodId(),
410                     static_cast<uint16_t>(bcIns.GetId().AsRawValue())).GetOffset();
411                 CollectInnerMethods(method, methodId);
412                 break;
413             }
414             case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8:{
415                 auto entityId = jsPandaFile_->ResolveMethodIndex(method->GetMethodId(),
416                     (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 0>()).AsRawValue());
417                 classConstructIndexes.emplace_back(entityId);
418                 classNameVec.emplace_back(GetClassName(entityId));
419                 classDefBCIndexes_.insert(bcIndex);
420                 methodId = entityId.GetOffset();
421                 CollectInnerMethods(method, methodId, true);
422                 auto literalId = jsPandaFile_->ResolveMethodIndex(method->GetMethodId(),
423                     (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 1>()).AsRawValue());
424                 CollectInnerMethodsFromNewLiteral(method, literalId);
425                 break;
426             }
427             case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
428                 auto entityId = jsPandaFile_->ResolveMethodIndex(method->GetMethodId(),
429                     (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 0>()).AsRawValue());
430                 classConstructIndexes.emplace_back(entityId);
431                 classNameVec.emplace_back(GetClassName(entityId));
432                 classDefBCIndexes_.insert(bcIndex);
433                 methodId = entityId.GetOffset();
434                 CollectInnerMethods(method, methodId, true);
435                 auto literalId = jsPandaFile_->ResolveMethodIndex(method->GetMethodId(),
436                     (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 1>()).AsRawValue());
437                 CollectInnerMethodsFromNewLiteral(method, literalId);
438                 break;
439             }
440             case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
441             case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM16_ID16: {
442                 auto literalId = jsPandaFile_->ResolveMethodIndex(method->GetMethodId(),
443                     static_cast<uint16_t>(bcIns.GetId().AsRawValue()));
444                 CollectInnerMethodsFromNewLiteral(method, literalId);
445                 break;
446             }
447             case BytecodeInstruction::Opcode::DEPRECATED_CREATEARRAYWITHBUFFER_PREF_IMM16: {
448                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16>();
449                 CollectInnerMethodsFromLiteral(method, imm);
450                 break;
451             }
452             case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
453             case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: {
454                 auto literalId = jsPandaFile_->ResolveMethodIndex(method->GetMethodId(),
455                     static_cast<uint16_t>(bcIns.GetId().AsRawValue()));
456                 CollectInnerMethodsFromNewLiteral(method, literalId);
457                 break;
458             }
459             case BytecodeInstruction::Opcode::DEPRECATED_CREATEOBJECTWITHBUFFER_PREF_IMM16: {
460                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16>();
461                 CollectInnerMethodsFromLiteral(method, imm);
462                 break;
463             }
464             case BytecodeInstruction::Opcode::NEWLEXENV_IMM8: {
465                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::IMM8>();
466                 NewLexEnvWithSize(method, imm);
467                 break;
468             }
469             case BytecodeInstruction::Opcode::NEWLEXENVWITHNAME_IMM8_ID16: {
470                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::IMM8_ID16>();
471                 NewLexEnvWithSize(method, imm);
472                 break;
473             }
474             case BytecodeInstruction::Opcode::WIDE_NEWLEXENV_PREF_IMM16: {
475                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16>();
476                 NewLexEnvWithSize(method, imm);
477                 break;
478             }
479             case BytecodeInstruction::Opcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16: {
480                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16_ID16>();
481                 NewLexEnvWithSize(method, imm);
482                 break;
483             }
484             case EcmaOpcode::RESUMEGENERATOR:
485             case EcmaOpcode::SUSPENDGENERATOR_V8:
486             case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
487             case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
488             case EcmaOpcode::SUPERCALLARROWRANGE_IMM8_IMM8_V8:
489             case EcmaOpcode::WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8:
490             case EcmaOpcode::SUPERCALLSPREAD_IMM8_V8:
491             case EcmaOpcode::GETUNMAPPEDARGS:
492             case EcmaOpcode::COPYRESTARGS_IMM8:
493             case EcmaOpcode::WIDE_COPYRESTARGS_PREF_IMM16: {
494                 *canFastCall = false;
495                 return;
496             }
497             default:
498                 break;
499         }
500     }
501 }
502 
CollectModuleInfoFromBC(const BytecodeInstruction & bcIns,const MethodLiteral * method,const CString & recordName)503 void BytecodeInfoCollector::CollectModuleInfoFromBC(const BytecodeInstruction &bcIns,
504                                                     const MethodLiteral *method,
505                                                     const CString &recordName)
506 {
507     auto methodOffset = method->GetMethodId().GetOffset();
508     // For records without tsType, we don't need to collect its export info.
509     if (jsPandaFile_->HasTSTypes(recordName) && !(bcIns.HasFlag(BytecodeInstruction::Flags::STRING_ID) &&
510         BytecodeInstruction::HasId(BytecodeInstruction::GetFormat(bcIns.GetOpcode()), 0))) {
511         BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode());
512         switch (opcode) {
513             case BytecodeInstruction::Opcode::STMODULEVAR_IMM8: {
514                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::IMM8>();
515                 // The export syntax only exists in main function.
516                 if (jsPandaFile_->GetMainMethodIndex(recordName) == methodOffset) {
517                     CollectExportIndexs(recordName, imm);
518                 }
519                 break;
520             }
521             case BytecodeInstruction::Opcode::WIDE_STMODULEVAR_PREF_IMM16: {
522                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16>();
523                 if (jsPandaFile_->GetMainMethodIndex(recordName) == methodOffset) {
524                     CollectExportIndexs(recordName, imm);
525                 }
526                 break;
527             }
528             case BytecodeInstruction::Opcode::LDEXTERNALMODULEVAR_IMM8:{
529                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::IMM8>();
530                 CollectImportIndexs(methodOffset, imm);
531                 break;
532             }
533             case BytecodeInstruction::Opcode::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16:{
534                 auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16>();
535                 CollectImportIndexs(methodOffset, imm);
536                 break;
537             }
538             default:
539                 break;
540         }
541     }
542 }
543 
CollectImportIndexs(uint32_t methodOffset,uint32_t index)544 void BytecodeInfoCollector::CollectImportIndexs(uint32_t methodOffset, uint32_t index)
545 {
546     auto &methodList = bytecodeInfo_.GetMethodList();
547     auto iter = methodList.find(methodOffset);
548     if (iter != methodList.end()) {
549         MethodInfo &methodInfo = iter->second;
550         // Collect import indexs of each method in its MethodInfo to do accurate Pgo compilation analysis.
551         methodInfo.AddImportIndex(index);
552         return;
553     }
554     MethodInfo info(GetMethodInfoID(), 0, LexEnv::DEFAULT_ROOT);
555     info.AddImportIndex(index);
556     methodList.emplace(methodOffset, info);
557 }
558 
CollectExportIndexs(const CString & recordName,uint32_t index)559 void BytecodeInfoCollector::CollectExportIndexs(const CString &recordName, uint32_t index)
560 {
561     JSThread *thread = vm_->GetJSThread();
562     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
563     CString exportLocalName = "*default*";
564     ObjectFactory *objFactory = vm_->GetFactory();
565     [[maybe_unused]] EcmaHandleScope scope(thread);
566     JSHandle<SourceTextModule> currentModule = moduleManager->HostGetImportedModule(recordName);
567     if (currentModule->GetLocalExportEntries().IsUndefined()) {
568         return;
569     }
570     // localExportEntries contain all local element info exported in this record.
571     JSHandle<TaggedArray> localExportArray(thread, currentModule->GetLocalExportEntries());
572     ASSERT(index < localExportArray->GetLength());
573     JSHandle<LocalExportEntry> currentExportEntry(thread, localExportArray->Get(index));
574     JSHandle<JSTaggedValue> exportName(thread, currentExportEntry->GetExportName());
575     JSHandle<JSTaggedValue> localName(thread, currentExportEntry->GetLocalName());
576 
577     JSHandle<JSTaggedValue> exportLocalNameHandle =
578         JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(exportLocalName));
579     JSHandle<JSTaggedValue> defaultName = thread->GlobalConstants()->GetHandledDefaultString();
580     /* if current exportName is "default", but localName not "*default*" like "export default class A{},
581      * localName is A, exportName is default in exportEntry". this will be recorded as "A:classType" in
582      * exportTable in typeSystem. At this situation, we will use localName to judge whether it has a actual
583      * Type record. Otherwise, we will use exportName.
584      */
585     if (JSTaggedValue::SameValue(exportName, defaultName) &&
586         !JSTaggedValue::SameValue(localName, exportLocalNameHandle)) {
587         exportName = localName;
588     }
589 
590     JSHandle<EcmaString> exportNameStr(thread, EcmaString::Cast(exportName->GetTaggedObject()));
591     // In order to reduce redundant compilation, when a export element satisfies one of the following conditions,
592     // it will be added to the ExportRecordInfo of this record.
593     // 1) its name is not recorded in exportTypeTable, or
594     // 2) its type is classType or any.
595     if (!CheckExportNameAndClassType(recordName, exportNameStr)) {
596         bytecodeInfo_.AddExportIndexToRecord(recordName, index);
597     }
598 }
599 
CheckExportNameAndClassType(const CString & recordName,const JSHandle<EcmaString> & exportStr)600 bool BytecodeInfoCollector::CheckExportNameAndClassType(const CString &recordName,
601                                                         const JSHandle<EcmaString> &exportStr)
602 {
603     auto tsManager = vm_->GetJSThread()->GetCurrentEcmaContext()->GetTSManager();
604     JSHandle<TaggedArray> exportTypeTable = tsManager->GetExportTableFromLiteral(jsPandaFile_, recordName);
605     uint32_t length = exportTypeTable->GetLength();
606     for (uint32_t i = 0; i < length; i = i + 2) { // 2: skip a pair of key and value
607         EcmaString *valueString = EcmaString::Cast(exportTypeTable->Get(i).GetTaggedObject());
608         if (!EcmaStringAccessor::StringsAreEqual(*exportStr, valueString)) {
609             continue;
610         }
611         uint32_t typeId = static_cast<uint32_t>(exportTypeTable->Get(i + 1).GetInt());
612         if (TSTypeParser::IsUserDefinedType(typeId)) {
613             TypeLiteralExtractor typeExtractor(jsPandaFile_, typeId);
614             if (typeExtractor.GetTypeKind() == TSTypeKind::CLASS) {
615                 return false;
616             }
617         }
618         if (typeId != 0) {
619             return true;
620         }
621     }
622     return false;
623 }
624 
CollectRecordReferenceREL()625 void BytecodeInfoCollector::CollectRecordReferenceREL()
626 {
627     auto &recordNames = bytecodeInfo_.GetRecordNames();
628     for (auto &record : recordNames) {
629         JSRecordInfo info = jsPandaFile_->FindRecordInfo(record);
630         if (jsPandaFile_->HasTSTypes(info)|| jsPandaFile_->IsModule(info)) {
631             CollectRecordImportInfo(record);
632             CollectRecordExportInfo(record);
633         }
634     }
635 }
636 
637 /* Each import index is corresponded to a ResolvedIndexBinding in the Environment of its module.
638  * Through ResolvedIndexBinding, we can get the export module and its export index. Only when the
639  * export index is in the non-type-record set which we have collected in CollectExportIndexs function,
640  * this export element can be infer-needed. We will collect the map as (key: import index , value: (exportRecord,
641  * exportIndex)) for using in pgo analysis and type infer.
642  */
CollectRecordImportInfo(const CString & recordName)643 void BytecodeInfoCollector::CollectRecordImportInfo(const CString &recordName)
644 {
645     auto thread = vm_->GetJSThread();
646     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
647     [[maybe_unused]] EcmaHandleScope scope(thread);
648     JSHandle<SourceTextModule> currentModule = moduleManager->HostGetImportedModule(recordName);
649     // Collect Import Info
650     JSTaggedValue moduleEnvironment = currentModule->GetEnvironment();
651     if (moduleEnvironment.IsUndefined()) {
652         return;
653     }
654     ASSERT(moduleEnvironment.IsTaggedArray());
655     JSHandle<TaggedArray> moduleArray(thread, moduleEnvironment);
656     auto length = moduleArray->GetLength();
657     for (size_t index = 0; index < length; index++) {
658         JSTaggedValue resolvedBinding = moduleArray->Get(index);
659         // if resolvedBinding.IsHole(), means that importname is * or it belongs to empty Aot module.
660         if (resolvedBinding.IsHole()) {
661             continue;
662         }
663         ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolvedBinding.GetTaggedObject());
664         CString resolvedRecord = ModuleManager::GetRecordName(binding->GetModule());
665         auto bindingIndex = binding->GetIndex();
666         if (bytecodeInfo_.HasExportIndexToRecord(resolvedRecord, bindingIndex)) {
667             bytecodeInfo_.AddImportRecordInfoToRecord(recordName, resolvedRecord, index, bindingIndex);
668         }
669     }
670 }
671 
672 // For type infer under retranmission (export * from "xxx"), we collect the star export records in this function.
CollectRecordExportInfo(const CString & recordName)673 void BytecodeInfoCollector::CollectRecordExportInfo(const CString &recordName)
674 {
675     auto thread = vm_->GetJSThread();
676     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
677     [[maybe_unused]] EcmaHandleScope scope(thread);
678     JSHandle<SourceTextModule> currentModule = moduleManager->HostGetImportedModule(recordName);
679     // Collect Star Export Info
680     JSTaggedValue starEntries = currentModule->GetStarExportEntries();
681     if (starEntries.IsUndefined()) {
682         return;
683     }
684     ASSERT(starEntries.IsTaggedArray());
685     JSHandle<TaggedArray> starEntriesArray(thread, starEntries);
686     auto starLength = starEntriesArray->GetLength();
687     JSMutableHandle<StarExportEntry> starExportEntry(thread, JSTaggedValue::Undefined());
688     for (size_t index = 0; index < starLength; index++) {
689         starExportEntry.Update(starEntriesArray->Get(index));
690         JSTaggedValue moduleRequest = starExportEntry->GetModuleRequest();
691         CString moduleRequestName = ConvertToString(EcmaString::Cast(moduleRequest.GetTaggedObject()));
692         if (ModulePathHelper::IsNativeModuleRequest(moduleRequestName)) {
693             return;
694         }
695         CString baseFileName = jsPandaFile_->GetJSPandaFileDesc();
696         CString entryPoint = ModulePathHelper::ConcatFileNameWithMerge(thread, jsPandaFile_,
697             baseFileName, recordName, moduleRequestName);
698         if (jsPandaFile_->HasTypeSummaryOffset(entryPoint)) {
699             bytecodeInfo_.AddStarExportToRecord(recordName, entryPoint);
700         }
701     }
702 }
703 
RearrangeInnerMethods()704 void BytecodeInfoCollector::RearrangeInnerMethods()
705 {
706     auto &methodList = bytecodeInfo_.GetMethodList();
707     for (auto &it : methodList) {
708         MethodInfo &methodInfo = it.second;
709         methodInfo.RearrangeInnerMethods();
710     }
711 }
712 
CollectConstantPoolIndexInfoFromBC(const BytecodeInstruction & bcIns,const MethodLiteral * method,uint32_t bcIndex)713 void BytecodeInfoCollector::CollectConstantPoolIndexInfoFromBC(const BytecodeInstruction &bcIns,
714                                                                const MethodLiteral *method, uint32_t bcIndex)
715 {
716     BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode());
717     uint32_t methodOffset = method->GetMethodId().GetOffset();
718     switch (opcode) {
719         case BytecodeInstruction::Opcode::LDA_STR_ID16:
720         case BytecodeInstruction::Opcode::STOWNBYNAME_IMM8_ID16_V8:
721         case BytecodeInstruction::Opcode::STOWNBYNAME_IMM16_ID16_V8:
722         case BytecodeInstruction::Opcode::CREATEREGEXPWITHLITERAL_IMM8_ID16_IMM8:
723         case BytecodeInstruction::Opcode::CREATEREGEXPWITHLITERAL_IMM16_ID16_IMM8:
724         case BytecodeInstruction::Opcode::STCONSTTOGLOBALRECORD_IMM16_ID16:
725         case BytecodeInstruction::Opcode::TRYLDGLOBALBYNAME_IMM8_ID16:
726         case BytecodeInstruction::Opcode::TRYLDGLOBALBYNAME_IMM16_ID16:
727         case BytecodeInstruction::Opcode::TRYSTGLOBALBYNAME_IMM8_ID16:
728         case BytecodeInstruction::Opcode::TRYSTGLOBALBYNAME_IMM16_ID16:
729         case BytecodeInstruction::Opcode::STTOGLOBALRECORD_IMM16_ID16:
730         case BytecodeInstruction::Opcode::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8:
731         case BytecodeInstruction::Opcode::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8:
732         case BytecodeInstruction::Opcode::LDTHISBYNAME_IMM8_ID16:
733         case BytecodeInstruction::Opcode::LDTHISBYNAME_IMM16_ID16:
734         case BytecodeInstruction::Opcode::STTHISBYNAME_IMM8_ID16:
735         case BytecodeInstruction::Opcode::STTHISBYNAME_IMM16_ID16:
736         case BytecodeInstruction::Opcode::LDGLOBALVAR_IMM16_ID16:
737         case BytecodeInstruction::Opcode::LDOBJBYNAME_IMM8_ID16:
738         case BytecodeInstruction::Opcode::LDOBJBYNAME_IMM16_ID16:
739         case BytecodeInstruction::Opcode::STOBJBYNAME_IMM8_ID16_V8:
740         case BytecodeInstruction::Opcode::STOBJBYNAME_IMM16_ID16_V8:
741         case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM8_ID16:
742         case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM16_ID16:
743         case BytecodeInstruction::Opcode::STSUPERBYNAME_IMM8_ID16_V8:
744         case BytecodeInstruction::Opcode::STSUPERBYNAME_IMM16_ID16_V8:
745         case BytecodeInstruction::Opcode::STGLOBALVAR_IMM16_ID16:
746         case BytecodeInstruction::Opcode::LDBIGINT_ID16: {
747             auto index = bcIns.GetId().AsRawValue();
748             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::STRING, index, methodOffset, bcIndex);
749             break;
750         }
751         case BytecodeInstruction::Opcode::DEFINEFUNC_IMM8_ID16_IMM8:
752         case BytecodeInstruction::Opcode::DEFINEFUNC_IMM16_ID16_IMM8:
753         case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM8_ID16_IMM8:
754         case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM16_ID16_IMM8: {
755             auto index = bcIns.GetId().AsRawValue();
756             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, index, methodOffset, bcIndex);
757             break;
758         }
759         case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
760         case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: {
761             auto index = bcIns.GetId().AsRawValue();
762             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::OBJECT_LITERAL, index, methodOffset, bcIndex);
763             break;
764         }
765         case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
766         case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM16_ID16: {
767             auto index = bcIns.GetId().AsRawValue();
768             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::ARRAY_LITERAL, index, methodOffset, bcIndex);
769             break;
770         }
771         case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: {
772             auto methodIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
773             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, methodIndex, methodOffset, bcIndex);
774             auto literalIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
775             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::CLASS_LITERAL, literalIndex,
776                                          methodOffset, bcIndex);
777             break;
778         }
779         case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
780             auto methodIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
781             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::METHOD, methodIndex, methodOffset, bcIndex);
782             auto literalIndex = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
783             AddConstantPoolIndexToBCInfo(ConstantPoolInfo::ItemType::CLASS_LITERAL, literalIndex,
784                                          methodOffset, bcIndex);
785             break;
786         }
787         default:
788             break;
789     }
790 }
791 
LexEnvManager(BCInfo & bcInfo)792 LexEnvManager::LexEnvManager(BCInfo &bcInfo)
793     : lexEnvs_(bcInfo.GetMethodList().size())
794 {
795     const auto &methodList = bcInfo.GetMethodList();
796     for (const auto &it : methodList) {
797         const MethodInfo &methodInfo = it.second;
798         lexEnvs_[methodInfo.GetMethodInfoIndex()].Inilialize(methodInfo.GetOutMethodId(),
799                                                              methodInfo.GetNumOfLexVars(),
800                                                              methodInfo.GetLexEnvStatus());
801     }
802 }
803 
SetLexEnvElementType(uint32_t methodId,uint32_t level,uint32_t slot,const GateType & type)804 void LexEnvManager::SetLexEnvElementType(uint32_t methodId, uint32_t level, uint32_t slot, const GateType &type)
805 {
806     uint32_t offset = GetTargetLexEnv(methodId, level);
807     lexEnvs_[offset].SetLexVarType(slot, type);
808 }
809 
GetLexEnvElementType(uint32_t methodId,uint32_t level,uint32_t slot) const810 GateType LexEnvManager::GetLexEnvElementType(uint32_t methodId, uint32_t level, uint32_t slot) const
811 {
812     uint32_t offset = GetTargetLexEnv(methodId, level);
813     return lexEnvs_[offset].GetLexVarType(slot);
814 }
815 
GetTargetLexEnv(uint32_t methodId,uint32_t level) const816 uint32_t LexEnvManager::GetTargetLexEnv(uint32_t methodId, uint32_t level) const
817 {
818     auto offset = methodId;
819     auto status = GetLexEnvStatus(offset);
820     while (!HasDefaultRoot(offset) && ((level > 0) || (status != LexicalEnvStatus::REALITY_LEXENV))) {
821         offset = GetOutMethodId(offset);
822         if (HasDefaultRoot(offset)) {
823             break;
824         }
825         if (status == LexicalEnvStatus::REALITY_LEXENV && level != 0) {
826             --level;
827         }
828         status = GetLexEnvStatus(offset);
829     }
830     return offset;
831 }
832 
AddIndexToCPItem(ItemType type,uint32_t index,uint32_t methodOffset,uint32_t bcIndex)833 void ConstantPoolInfo::AddIndexToCPItem(ItemType type, uint32_t index, uint32_t methodOffset, uint32_t bcIndex)
834 {
835     Item &item = GetCPItem(type);
836     if (item.find(index) != item.end()) {
837         return;
838     }
839     item.insert({index, ItemData {index, methodOffset, nullptr, bcIndex}});
840 }
841 }  // namespace panda::ecmascript::kungfu
842