1 /*
2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/compiler/aot_snapshot/snapshot_constantpool_data.h"
17
18 #include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
19 #include "ecmascript/js_object-inl.h"
20 #include "ecmascript/jspandafile/program_object.h"
21
22 namespace panda::ecmascript::kungfu {
GetItemKey(uint32_t constantPoolId, uint32_t constantPoolIdx)23 uint64_t BaseSnapshotInfo::GetItemKey(uint32_t constantPoolId, uint32_t constantPoolIdx)
24 {
25 uint64_t result = constantPoolId;
26 result = result << CONSTPOOL_MASK;
27 result |= constantPoolIdx;
28 return result;
29 }
30
TryGetABCId(ApEntityId &abcId)31 bool BaseSnapshotInfo::TryGetABCId(ApEntityId &abcId)
32 {
33 return pfDecoder_->GetABCIdByJSPandaFile(jsPandaFile_, abcId);
34 }
35
TryGetIHClass(ProfileType rootType, ProfileType childType, const ItemData &data, const JSHandle<TaggedArray> &properties, const SnapshotGlobalData &globalData) const36 JSHandle<JSTaggedValue> BaseSnapshotInfo::TryGetIHClass(ProfileType rootType, ProfileType childType,
37 const ItemData &data, const JSHandle<TaggedArray> &properties, const SnapshotGlobalData &globalData) const
38 {
39 JSHandle<JSTaggedValue> ihc = TryGetHClass(rootType, childType);
40 if (ihc->IsUndefined()) {
41 PGOTypeLocation loc(jsPandaFile_, data.methodOffset_, data.bcIndex_);
42 ihc = TryGetHClassByPGOTypeLocation(loc);
43 if (ihc->IsUndefined()) {
44 ihc = TryGetHClassFromCached(properties, globalData);
45 }
46 }
47 return ihc;
48 }
49
TryGetHClass(ProfileType rootType, ProfileType childType) const50 JSHandle<JSTaggedValue> BaseSnapshotInfo::TryGetHClass(ProfileType rootType, ProfileType childType) const
51 {
52 PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager();
53 JSTaggedValue hclass = ptManager->QueryHClass(rootType, childType);
54 return JSHandle<JSTaggedValue>(thread_, hclass);
55 }
56
TryGetHClassByPGOTypeLocation(PGOTypeLocation loc) const57 JSHandle<JSTaggedValue> BaseSnapshotInfo::TryGetHClassByPGOTypeLocation(PGOTypeLocation loc) const
58 {
59 PGOTypeManager *ptManager = thread_->GetCurrentEcmaContext()->GetPTManager();
60 ProfileType pt = ptManager->GetRootIdByLocation(loc);
61 return TryGetHClass(pt, pt);
62 }
63
TryGetHClassFromCached(const JSHandle<TaggedArray> &properties, const SnapshotGlobalData &globalData) const64 JSHandle<JSTaggedValue> BaseSnapshotInfo::TryGetHClassFromCached(const JSHandle<TaggedArray> &properties,
65 const SnapshotGlobalData &globalData) const
66 {
67 DISALLOW_GARBAGE_COLLECTION;
68 JSHandle<JSTaggedValue> maybeCache(thread_, globalData.GetObjectLiteralHClassCache());
69 if (maybeCache->IsTaggedArray()) {
70 size_t length = properties->GetLength();
71 uint32_t propsLen = 0;
72 for (size_t i = 0; i < length; i += 2) { // 2: skip a pair of key and value
73 if (properties->Get(i).IsHole()) {
74 break;
75 }
76 propsLen++;
77 }
78
79 if (!ObjectFactory::CanObjectLiteralHClassCache(propsLen)) {
80 return thread_->GlobalConstants()->GetHandledUndefined();
81 }
82
83 JSHandle<TaggedArray> hclassCacheArr = JSHandle<TaggedArray>::Cast(maybeCache);
84 JSTaggedValue maybeHClass = hclassCacheArr->Get(propsLen);
85 if (!maybeHClass.IsJSHClass()) {
86 return thread_->GlobalConstants()->GetHandledUndefined();
87 }
88 JSHClass *newClass = JSHClass::Cast(maybeHClass.GetTaggedObject());
89 JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
90
91 for (size_t fieldOffset = 0; fieldOffset < propsLen; fieldOffset++) {
92 key.Update(properties->Get(fieldOffset * 2)); // 2 : pair of key and value
93 ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
94 PropertyAttributes attributes = PropertyAttributes::Default();
95 auto value = properties->Get(fieldOffset * 2 + 1);
96 if (value.IsAccessor()) { // 2: Meaning to double
97 attributes.SetIsAccessor(true);
98 }
99 attributes.SetIsInlinedProps(true);
100 attributes.SetRepresentation(Representation::TAGGED);
101 attributes.SetOffset(fieldOffset);
102
103 auto metadata = JSTaggedValue(attributes.GetPropertyMetaData());
104 auto rep = PropertyAttributes::TranslateToRep(value);
105 newClass = newClass->FindTransitions(key.GetTaggedValue(), metadata, rep);
106 if (newClass == nullptr) {
107 return thread_->GlobalConstants()->GetHandledUndefined();
108 }
109 }
110
111 auto result = JSHandle<JSHClass>(thread_, newClass);
112 if (JSObject::CheckPropertiesForRep(properties, propsLen, result)) {
113 return JSHandle<JSTaggedValue>(result);
114 }
115 }
116 return thread_->GlobalConstants()->GetHandledUndefined();
117 }
118
Record(ItemData &data)119 void BaseSnapshotInfo::Record(ItemData &data)
120 {
121 ItemKey key = GetItemKey(data.constantPoolId_, data.constantPoolIdx_);
122 info_.emplace(key, data);
123 }
124
CollectLiteralInfo(JSHandle<TaggedArray> array, uint32_t constantPoolIndex, JSHandle<ConstantPool> snapshotConstantPool, const std::set<uint32_t> &skippedMethods, JSHandle<JSTaggedValue> ihc, JSHandle<JSTaggedValue> chc)125 void BaseSnapshotInfo::CollectLiteralInfo(JSHandle<TaggedArray> array, uint32_t constantPoolIndex,
126 JSHandle<ConstantPool> snapshotConstantPool,
127 const std::set<uint32_t> &skippedMethods,
128 JSHandle<JSTaggedValue> ihc, JSHandle<JSTaggedValue> chc)
129 {
130 ObjectFactory *factory = vm_->GetFactory();
131 JSMutableHandle<JSTaggedValue> valueHandle(thread_, JSTaggedValue::Undefined());
132 uint32_t len = array->GetLength();
133 std::vector<int> methodOffsetVec;
134 for (uint32_t i = 0; i < len; i++) {
135 valueHandle.Update(array->Get(i));
136 uint32_t methodOffset = 0;
137 if (valueHandle->IsJSFunction()) {
138 methodOffset = JSHandle<JSFunction>(valueHandle)->GetCallTarget()->GetMethodId().GetOffset();
139 } else if (valueHandle->IsFunctionTemplate()) {
140 auto method = Method::Cast(JSHandle<FunctionTemplate>(valueHandle)->GetMethod());
141 methodOffset = method->GetMethodId().GetOffset();
142 }
143 if (methodOffset != 0) {
144 if (skippedMethods.find(methodOffset) != skippedMethods.end()) {
145 methodOffsetVec.emplace_back(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE);
146 } else {
147 methodOffsetVec.emplace_back(methodOffset);
148 }
149 }
150 }
151
152 uint32_t methodSize = methodOffsetVec.size();
153 JSHandle<AOTLiteralInfo> aotLiteralInfo = factory->NewAOTLiteralInfo(methodSize);
154 for (uint32_t i = 0; i < methodSize; ++i) {
155 auto methodOffset = methodOffsetVec[i];
156 aotLiteralInfo->SetObjectToCache(thread_, i, JSTaggedValue(methodOffset));
157 }
158
159 if (!ihc->IsUndefined()) {
160 aotLiteralInfo->SetIhc(ihc.GetTaggedValue());
161 }
162
163 if (!chc->IsUndefined()) {
164 aotLiteralInfo->SetChc(chc.GetTaggedValue());
165 }
166
167 snapshotConstantPool->SetObjectToCache(thread_, constantPoolIndex, aotLiteralInfo.GetTaggedValue());
168 }
169
CheckAOTPropertiesForRep(const JSHandle<TaggedArray> &properties, const JSHandle<JSHClass> &hclass)170 bool BaseSnapshotInfo::CheckAOTPropertiesForRep(const JSHandle<TaggedArray> &properties,
171 const JSHandle<JSHClass> &hclass)
172 {
173 auto layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject());
174 for (size_t i = 0; i < properties->GetLength(); i++) {
175 auto attr = layout->GetAttr(i);
176 auto value = JSObject::ConvertValueWithRep(attr, properties->Get(i));
177 // If value.first is false, indicating that value cannot be converted to the expected value of
178 // representation. For example, the representation is INT, but the value type is string.
179 if (!value.first) {
180 return false;
181 }
182 }
183 return true;
184 }
185
CheckAOTIhcPropertiesForRep(JSThread *thread, const JSHandle<JSTaggedValue> &ihc, const JSHandle<ClassInfoExtractor> &extractor)186 bool BaseSnapshotInfo::CheckAOTIhcPropertiesForRep(JSThread *thread, const JSHandle<JSTaggedValue> &ihc,
187 const JSHandle<ClassInfoExtractor> &extractor)
188 {
189 if (ihc->IsUndefinedOrNull()) {
190 return false;
191 }
192 JSHandle<JSObject> prototype;
193 if (ihc->IsJSHClass()) {
194 JSHandle<JSHClass> ihclass(ihc);
195 prototype = JSHandle<JSObject>(thread, ihclass->GetProto());
196 } else {
197 prototype = JSHandle<JSObject>(ihc);
198 }
199
200 ASSERT(!prototype->GetJSHClass()->IsDictionaryMode());
201 JSHandle<TaggedArray> nonStaticProperties(thread, extractor->GetNonStaticProperties());
202 JSHandle<JSHClass> protohclass(thread, prototype->GetJSHClass());
203 return CheckAOTPropertiesForRep(nonStaticProperties, protohclass);
204 }
205
CheckAOTChcPropertiesForRep(JSThread *thread, const JSHandle<JSTaggedValue> &chc, const JSHandle<ClassInfoExtractor> &extractor)206 bool BaseSnapshotInfo::CheckAOTChcPropertiesForRep(JSThread *thread, const JSHandle<JSTaggedValue> &chc,
207 const JSHandle<ClassInfoExtractor> &extractor)
208 {
209 if (chc->IsUndefinedOrNull()) {
210 return false;
211 }
212 JSHandle<JSHClass> chclass(thread, JSHClass::Cast(chc->GetTaggedObject()));
213 ASSERT(!chclass->IsDictionaryMode());
214 JSHandle<TaggedArray> staticProperties(thread, extractor->GetStaticProperties());
215 return CheckAOTPropertiesForRep(staticProperties, chclass);
216 }
217
StoreDataToGlobalData(SnapshotGlobalData &globalData, const std::set<uint32_t>&)218 void StringSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData, const std::set<uint32_t>&)
219 {
220 for (auto item : info_) {
221 const ItemData &data = item.second;
222 uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
223 JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
224 JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(snapshotCpArrIdx));
225 // Lazy ConstantPool String Loading
226 snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, JSTaggedValue::Hole());
227 }
228
229 if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
230 vm_->AddAOTSnapShotStats("String", info_.size());
231 }
232 }
233
StoreDataToGlobalData(SnapshotGlobalData &globalData, const std::set<uint32_t> &skippedMethods)234 void MethodSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
235 const std::set<uint32_t> &skippedMethods)
236 {
237 ApEntityId abcId = INVALID_INDEX;
238 bool hasAbcId = TryGetABCId(abcId);
239 ObjectFactory *factory = vm_->GetFactory();
240 for (auto item : info_) {
241 const ItemData &data = item.second;
242 JSHandle<ConstantPool> cp(thread_,
243 thread_->GetCurrentEcmaContext()->FindConstpool(jsPandaFile_, data.constantPoolId_));
244 uint32_t methodOffset = cp->GetEntityId(data.constantPoolIdx_).GetOffset();
245
246 uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
247 JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
248 JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(snapshotCpArrIdx));
249
250 JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
251 if (hasAbcId) {
252 ProfileType pt(abcId, methodOffset, ProfileType::Kind::ClassId, true);
253 ihc = TryGetHClass(pt, pt);
254 }
255 JSHandle<AOTLiteralInfo> aotLiteralInfo = factory->NewAOTLiteralInfo(1); // 1: only one method
256 int initValue = static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE);
257 aotLiteralInfo->SetObjectToCache(thread_, 0, JSTaggedValue(initValue));
258 aotLiteralInfo->SetLiteralType(JSTaggedValue(AOTLiteralInfo::METHOD_LITERAL_TYPE));
259 if (!ihc->IsUndefined()) {
260 aotLiteralInfo->SetIhc(ihc.GetTaggedValue());
261 if (skippedMethods.find(methodOffset) == skippedMethods.end()) {
262 aotLiteralInfo->SetObjectToCache(thread_, 0, JSTaggedValue(methodOffset));
263 globalData.RecordReviseData(
264 ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
265 }
266 snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, aotLiteralInfo.GetTaggedValue());
267 } else if (skippedMethods.find(methodOffset) == skippedMethods.end()) {
268 // For MethodSnaphotInfo which does not have ihc info, we insert JSTaggedValue(methodOffset) as revervation.
269 // For the purpose of reducing ai size.
270 globalData.RecordReviseData(
271 ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
272 snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, JSTaggedValue(methodOffset));
273 } else {
274 snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, JSTaggedValue::Hole());
275 }
276 }
277 if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
278 vm_->AddAOTSnapShotStats("Method", info_.size());
279 }
280 }
281
StoreDataToGlobalData(SnapshotGlobalData &globalData, const std::set<uint32_t> &skippedMethods)282 void ClassLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
283 const std::set<uint32_t> &skippedMethods)
284 {
285 ApEntityId abcId = INVALID_INDEX;
286 bool hasAbcId = TryGetABCId(abcId);
287 for (auto item : info_) {
288 const ItemData &data = item.second;
289 JSHandle<ConstantPool> cp = GetUnsharedConstpool(data);
290 auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, cp, data.constantPoolIdx_, data.recordName_);
291 JSHandle<ClassLiteral> classLiteral(thread_, literalObj);
292 JSHandle<TaggedArray> arrayHandle(thread_, classLiteral->GetArray());
293
294 uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
295 JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
296 JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(snapshotCpArrIdx));
297
298 uint32_t methodId = cp->GetEntityId(data.ctorMethodOffset_).GetOffset();
299 JSHandle<JSTaggedValue> undefinedHandle = thread_->GlobalConstants()->GetHandledUndefined();
300 JSHandle<JSTaggedValue> ihc = undefinedHandle;
301 JSHandle<JSTaggedValue> chc = undefinedHandle;
302 if (hasAbcId) {
303 ProfileType pt(abcId, methodId, ProfileType::Kind::ClassId, true);
304 ProfileType ctorPt(abcId, methodId, ProfileType::Kind::ConstructorId, true);
305 ihc = TryGetHClass(pt, pt);
306 chc = TryGetHClass(ctorPt, ctorPt);
307
308 auto method = ConstantPool::GetMethodFromCache(thread_, cp.GetTaggedValue(), data.ctorMethodOffset_);
309 auto *factory = thread_->GetEcmaVM()->GetFactory();
310 auto extractor = factory->NewClassInfoExtractor(JSHandle<JSTaggedValue>(thread_, method));
311 ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(thread_, extractor, arrayHandle,
312 arrayHandle->GetLength());
313 if (!CheckAOTIhcPropertiesForRep(thread_, ihc, extractor)) {
314 ihc = undefinedHandle;
315 }
316 if (!CheckAOTChcPropertiesForRep(thread_, chc, extractor)) {
317 chc = undefinedHandle;
318 }
319 }
320
321 CollectLiteralInfo(arrayHandle, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc);
322 globalData.RecordReviseData(
323 ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
324 }
325 if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
326 vm_->AddAOTSnapShotStats("ClassLiteral", info_.size());
327 }
328 }
329
StoreDataToGlobalData(SnapshotGlobalData &globalData, const std::set<uint32_t> &skippedMethods)330 void ObjectLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
331 const std::set<uint32_t> &skippedMethods)
332 {
333 ApEntityId abcId = INVALID_INDEX;
334 bool hasAbcId = TryGetABCId(abcId);
335 for (auto item : info_) {
336 const ItemData &data = item.second;
337 JSHandle<ConstantPool> cp = GetUnsharedConstpool(data);
338 panda_file::File::EntityId id = cp->GetEntityId(data.constantPoolIdx_);
339 JSMutableHandle<TaggedArray> elements(thread_, JSTaggedValue::Undefined());
340 JSMutableHandle<TaggedArray> properties(thread_, JSTaggedValue::Undefined());
341 LiteralDataExtractor::ExtractObjectDatas(thread_, jsPandaFile_, id, elements,
342 properties, cp, data.recordName_);
343
344 uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
345 JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
346 JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(snapshotCpArrIdx));
347
348 JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
349 JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
350 if (hasAbcId) {
351 ProfileType pt(abcId, id.GetOffset(), ProfileType::Kind::ObjectLiteralId, true);
352 ProfileType ctorPt(abcId, id.GetOffset(), ProfileType::Kind::ConstructorId, true);
353 chc = TryGetHClass(ctorPt, ctorPt);
354 ihc = TryGetIHClass(pt, pt, data, properties, globalData);
355 }
356
357 CollectLiteralInfo(properties, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc);
358 globalData.RecordReviseData(
359 ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
360 }
361 if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
362 vm_->AddAOTSnapShotStats("ObjectLiteral", info_.size());
363 }
364 }
365
StoreDataToGlobalData(SnapshotGlobalData &globalData, const std::set<uint32_t> &skippedMethods)366 void ArrayLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
367 const std::set<uint32_t> &skippedMethods)
368 {
369 for (auto item : info_) {
370 const ItemData &data = item.second;
371 JSHandle<ConstantPool> cp = GetUnsharedConstpool(data);
372 panda_file::File::EntityId id = cp->GetEntityId(data.constantPoolIdx_);
373 JSHandle<TaggedArray> literal = LiteralDataExtractor::GetDatasIgnoreType(
374 thread_, jsPandaFile_, id, cp, data.recordName_);
375 uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
376 JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
377 JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(snapshotCpArrIdx));
378 JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
379 JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
380 CollectLiteralInfo(literal, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc);
381 globalData.RecordReviseData(
382 ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
383 }
384 if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
385 vm_->AddAOTSnapShotStats("ArrayLiteral", info_.size());
386 }
387 }
388
GetUnsharedConstpool(const ItemData &data)389 JSHandle<ConstantPool> BaseSnapshotInfo::GetUnsharedConstpool(const ItemData &data)
390 {
391 EcmaContext *context = thread_->GetCurrentEcmaContext();
392 JSTaggedValue shareCp = context->FindConstpool(jsPandaFile_, data.constantPoolId_);
393 JSHandle<ConstantPool> cp(thread_, context->FindOrCreateUnsharedConstpool(shareCp));
394 return cp;
395 }
396
Record(const BytecodeInstruction &bcIns, int32_t bcIndex, const CString &recordName, const MethodLiteral *method)397 void SnapshotConstantPoolData::Record(const BytecodeInstruction &bcIns, int32_t bcIndex,
398 const CString &recordName, const MethodLiteral *method)
399 {
400 BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode());
401 uint32_t methodOffset = method->GetMethodId().GetOffset();
402 panda_file::IndexAccessor indexAccessor(*jsPandaFile_->GetPandaFile(),
403 panda_file::File::EntityId(methodOffset));
404 uint32_t constantPoolId = static_cast<uint32_t>(indexAccessor.GetHeaderIndex());
405
406 switch (opcode) {
407 case BytecodeInstruction::Opcode::LDA_STR_ID16:
408 case BytecodeInstruction::Opcode::STOWNBYNAME_IMM8_ID16_V8:
409 case BytecodeInstruction::Opcode::STOWNBYNAME_IMM16_ID16_V8:
410 case BytecodeInstruction::Opcode::CREATEREGEXPWITHLITERAL_IMM8_ID16_IMM8:
411 case BytecodeInstruction::Opcode::CREATEREGEXPWITHLITERAL_IMM16_ID16_IMM8:
412 case BytecodeInstruction::Opcode::STCONSTTOGLOBALRECORD_IMM16_ID16:
413 case BytecodeInstruction::Opcode::TRYLDGLOBALBYNAME_IMM8_ID16:
414 case BytecodeInstruction::Opcode::TRYLDGLOBALBYNAME_IMM16_ID16:
415 case BytecodeInstruction::Opcode::TRYSTGLOBALBYNAME_IMM8_ID16:
416 case BytecodeInstruction::Opcode::TRYSTGLOBALBYNAME_IMM16_ID16:
417 case BytecodeInstruction::Opcode::STTOGLOBALRECORD_IMM16_ID16:
418 case BytecodeInstruction::Opcode::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8:
419 case BytecodeInstruction::Opcode::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8:
420 case BytecodeInstruction::Opcode::LDTHISBYNAME_IMM8_ID16:
421 case BytecodeInstruction::Opcode::LDTHISBYNAME_IMM16_ID16:
422 case BytecodeInstruction::Opcode::STTHISBYNAME_IMM8_ID16:
423 case BytecodeInstruction::Opcode::STTHISBYNAME_IMM16_ID16:
424 case BytecodeInstruction::Opcode::LDGLOBALVAR_IMM16_ID16:
425 case BytecodeInstruction::Opcode::LDOBJBYNAME_IMM8_ID16:
426 case BytecodeInstruction::Opcode::LDOBJBYNAME_IMM16_ID16:
427 case BytecodeInstruction::Opcode::STOBJBYNAME_IMM8_ID16_V8:
428 case BytecodeInstruction::Opcode::STOBJBYNAME_IMM16_ID16_V8:
429 case BytecodeInstruction::Opcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
430 case BytecodeInstruction::Opcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8:
431 case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM8_ID16:
432 case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM16_ID16:
433 case BytecodeInstruction::Opcode::STSUPERBYNAME_IMM8_ID16_V8:
434 case BytecodeInstruction::Opcode::STSUPERBYNAME_IMM16_ID16_V8:
435 case BytecodeInstruction::Opcode::STGLOBALVAR_IMM16_ID16:
436 case BytecodeInstruction::Opcode::LDBIGINT_ID16: {
437 auto constantPoolIdx = bcIns.GetId().AsRawValue();
438 BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
439 RecordInfo(Type::STRING, itemData);
440 break;
441 }
442 case BytecodeInstruction::Opcode::DEFINEFUNC_IMM8_ID16_IMM8:
443 case BytecodeInstruction::Opcode::DEFINEFUNC_IMM16_ID16_IMM8:
444 case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM8_ID16_IMM8:
445 case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM16_ID16_IMM8: {
446 auto constantPoolIdx = bcIns.GetId().AsRawValue();
447 BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
448 RecordInfo(Type::METHOD, itemData);
449 break;
450 }
451 case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
452 case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: {
453 auto constantPoolIdx = bcIns.GetId().AsRawValue();
454 BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
455 RecordInfo(Type::OBJECT_LITERAL, itemData);
456 break;
457 }
458 case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
459 case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM16_ID16: {
460 auto constantPoolIdx = bcIns.GetId().AsRawValue();
461 BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
462 RecordInfo(Type::ARRAY_LITERAL, itemData);
463 break;
464 }
465 case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: {
466 auto methodCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
467 BaseSnapshotInfo::ItemData methodItemData = {recordName, constantPoolId,
468 methodCPIdx, methodOffset, bcIndex};
469 RecordInfo(Type::METHOD, methodItemData);
470
471 auto literalCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
472 BaseSnapshotInfo::ItemData literalItemData = {recordName, constantPoolId,
473 literalCPIdx, methodOffset, bcIndex, methodCPIdx};
474 RecordInfo(Type::CLASS_LITERAL, literalItemData);
475 break;
476 }
477 case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
478 auto methodCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
479 BaseSnapshotInfo::ItemData methodItemData = {recordName, constantPoolId,
480 methodCPIdx, methodOffset, bcIndex};
481 RecordInfo(Type::METHOD, methodItemData);
482
483 auto literalCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
484 BaseSnapshotInfo::ItemData literalItemData = {recordName, constantPoolId,
485 literalCPIdx, methodOffset, bcIndex, methodCPIdx};
486 RecordInfo(Type::CLASS_LITERAL, literalItemData);
487 break;
488 }
489 default:
490 break;
491 }
492 }
493
StoreDataToGlobalData(SnapshotGlobalData &snapshotData, const std::set<uint32_t> &skippedMethods) const494 void SnapshotConstantPoolData::StoreDataToGlobalData(SnapshotGlobalData &snapshotData,
495 const std::set<uint32_t> &skippedMethods) const
496 {
497 for (auto &info : infos_) {
498 info->StoreDataToGlobalData(snapshotData, skippedMethods);
499 }
500 }
501 } // namespace panda::ecmascript
502