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