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
22namespace panda::ecmascript::kungfu {
23uint64_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
31bool BaseSnapshotInfo::TryGetABCId(ApEntityId &abcId)
32{
33    return pfDecoder_->GetABCIdByJSPandaFile(jsPandaFile_, abcId);
34}
35
36JSHandle<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
50JSHandle<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
57JSHandle<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
64JSHandle<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
119void BaseSnapshotInfo::Record(ItemData &data)
120{
121    ItemKey key = GetItemKey(data.constantPoolId_, data.constantPoolIdx_);
122    info_.emplace(key, data);
123}
124
125void 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
170bool 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
186bool 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
206bool 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
218void 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
234void 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
282void 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
330void 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
366void 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
389JSHandle<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
397void 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
494void 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