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