* Copyright (c) 2023-2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/compiler/aot_snapshot/snapshot_constantpool_data.h"
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
#include "ecmascript/js_object-inl.h"
#include "ecmascript/jspandafile/program_object.h"
namespace panda::ecmascript::kungfu {
uint64_t BaseSnapshotInfo::GetItemKey(uint32_t constantPoolId, uint32_t constantPoolIdx)
{
uint64_t result = constantPoolId;
result = result << CONSTPOOL_MASK;
result |= constantPoolIdx;
return result;
}
bool BaseSnapshotInfo::TryGetABCId(ApEntityId &abcId)
{
return pfDecoder_->GetABCIdByJSPandaFile(jsPandaFile_, abcId);
}
JSHandle<JSTaggedValue> BaseSnapshotInfo::TryGetIHClass(ProfileType rootType, ProfileType childType,
const ItemData &data, const JSHandle<TaggedArray> &properties, const SnapshotGlobalData &globalData) const
{
JSHandle<JSTaggedValue> ihc = TryGetHClass(rootType, childType);
if (ihc->IsUndefined()) {
PGOTypeLocation loc(jsPandaFile_, data.methodOffset_, data.bcIndex_);
ihc = TryGetHClassByPGOTypeLocation(loc);
if (ihc->IsUndefined()) {
ihc = TryGetHClassFromCached(properties, globalData);
}
}
return ihc;
}
JSHandle<JSTaggedValue> BaseSnapshotInfo::TryGetHClass(ProfileType rootType, ProfileType childType) const
{
PGOTypeManager* ptManager = thread_->GetEcmaVM()->GetPTManager();
JSTaggedValue hclass = ptManager->QueryHClass(rootType, childType);
return JSHandle<JSTaggedValue>(thread_, hclass);
}
JSHandle<JSTaggedValue> BaseSnapshotInfo::TryGetHClassByPGOTypeLocation(PGOTypeLocation loc) const
{
PGOTypeManager* ptManager = thread_->GetEcmaVM()->GetPTManager();
ProfileType pt = ptManager->GetRootIdByLocation(loc);
return TryGetHClass(pt, pt);
}
JSHandle<JSTaggedValue> BaseSnapshotInfo::TryGetHClassFromCached(const JSHandle<TaggedArray> &properties,
const SnapshotGlobalData &globalData) const
{
DISALLOW_GARBAGE_COLLECTION;
JSHandle<JSTaggedValue> maybeCache(thread_, globalData.GetObjectLiteralHClassCache(thread_));
if (maybeCache->IsTaggedArray()) {
size_t length = properties->GetLength();
uint32_t propsLen = 0;
for (size_t i = 0; i < length; i += 2) {
if (properties->Get(thread_, i).IsHole()) {
break;
}
propsLen++;
}
if (!ObjectFactory::CanObjectLiteralHClassCache(propsLen)) {
return thread_->GlobalConstants()->GetHandledUndefined();
}
JSHandle<TaggedArray> hclassCacheArr = JSHandle<TaggedArray>::Cast(maybeCache);
JSTaggedValue maybeHClass = hclassCacheArr->Get(thread_, propsLen);
if (!maybeHClass.IsJSHClass()) {
return thread_->GlobalConstants()->GetHandledUndefined();
}
JSHClass *newClass = JSHClass::Cast(maybeHClass.GetTaggedObject());
JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
for (size_t fieldOffset = 0; fieldOffset < propsLen; fieldOffset++) {
key.Update(properties->Get(thread_, fieldOffset * 2));
ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
PropertyAttributes attributes = PropertyAttributes::Default();
auto value = properties->Get(thread_, fieldOffset * 2 + 1);
if (value.IsAccessor()) {
attributes.SetIsAccessor(true);
}
attributes.SetIsInlinedProps(true);
attributes.SetRepresentation(Representation::TAGGED);
attributes.SetOffset(fieldOffset);
auto metadata = JSTaggedValue(attributes.GetPropertyMetaData());
auto rep = PropertyAttributes::TranslateToRep(value);
newClass = newClass->FindTransitions(thread_, key.GetTaggedValue(), metadata, rep);
if (newClass == nullptr) {
return thread_->GlobalConstants()->GetHandledUndefined();
}
}
auto result = JSHandle<JSHClass>(thread_, newClass);
if (JSObject::CheckPropertiesForRep(thread_, properties, propsLen, result)) {
return JSHandle<JSTaggedValue>(result);
}
}
return thread_->GlobalConstants()->GetHandledUndefined();
}
void BaseSnapshotInfo::Record(ItemData &data)
{
ItemKey key = GetItemKey(data.constantPoolId_, data.constantPoolIdx_);
info_.emplace(key, data);
}
void BaseSnapshotInfo::CollectLiteralInfo(JSHandle<TaggedArray> array, uint32_t constantPoolIndex,
JSHandle<ConstantPool> snapshotConstantPool,
const std::set<uint32_t> &skippedMethods,
JSHandle<JSTaggedValue> ihc, JSHandle<JSTaggedValue> chc)
{
ObjectFactory *factory = vm_->GetFactory();
JSMutableHandle<JSTaggedValue> valueHandle(thread_, JSTaggedValue::Undefined());
uint32_t len = array->GetLength();
std::vector<int> methodOffsetVec;
for (uint32_t i = 0; i < len; i++) {
valueHandle.Update(array->Get(thread_, i));
uint32_t methodOffset = 0;
if (valueHandle->IsJSFunction()) {
methodOffset = JSHandle<JSFunction>(valueHandle)->GetCallTarget(thread_)->GetMethodId().GetOffset();
} else if (valueHandle->IsFunctionTemplate()) {
auto method = Method::Cast(JSHandle<FunctionTemplate>(valueHandle)->GetMethod(thread_));
methodOffset = method->GetMethodId().GetOffset();
}
if (methodOffset != 0) {
if (skippedMethods.find(methodOffset) != skippedMethods.end()) {
methodOffsetVec.emplace_back(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE);
} else {
methodOffsetVec.emplace_back(methodOffset);
}
}
}
uint32_t methodSize = methodOffsetVec.size();
JSHandle<AOTLiteralInfo> aotLiteralInfo = factory->NewAOTLiteralInfo(methodSize);
for (uint32_t i = 0; i < methodSize; ++i) {
auto methodOffset = methodOffsetVec[i];
aotLiteralInfo->SetObjectToCache(thread_, i, JSTaggedValue(methodOffset));
}
if (!ihc->IsUndefined()) {
aotLiteralInfo->SetIhc(thread_, ihc.GetTaggedValue());
}
if (!chc->IsUndefined()) {
aotLiteralInfo->SetChc(thread_, chc.GetTaggedValue());
}
snapshotConstantPool->SetObjectToCache(thread_, constantPoolIndex, aotLiteralInfo.GetTaggedValue());
}
bool BaseSnapshotInfo::CheckAOTPropertiesForRep(const JSThread *thread,
const JSHandle<TaggedArray> &properties,
const JSHandle<JSHClass> &hclass)
{
auto layout = LayoutInfo::Cast(hclass->GetLayout(thread).GetTaggedObject());
for (size_t i = 0; i < properties->GetLength(); i++) {
auto attr = layout->GetAttr(thread, i);
auto value = JSObject::ConvertValueWithRep(attr, properties->Get(thread, i));
if (!value.first) {
return false;
}
}
return true;
}
bool BaseSnapshotInfo::CheckAOTIhcPropertiesForRep(JSThread *thread, const JSHandle<JSTaggedValue> &ihc,
const JSHandle<ClassInfoExtractor> &extractor)
{
if (ihc->IsUndefinedOrNull()) {
return false;
}
JSHandle<JSObject> prototype;
if (ihc->IsJSHClass()) {
JSHandle<JSHClass> ihclass(ihc);
prototype = JSHandle<JSObject>(thread, ihclass->GetProto(thread));
} else {
prototype = JSHandle<JSObject>(ihc);
}
ASSERT(!prototype->GetJSHClass()->IsDictionaryMode());
JSHandle<TaggedArray> nonStaticProperties(thread, extractor->GetNonStaticProperties(thread));
JSHandle<JSHClass> protohclass(thread, prototype->GetJSHClass());
return CheckAOTPropertiesForRep(thread, nonStaticProperties, protohclass);
}
bool BaseSnapshotInfo::CheckAOTChcPropertiesForRep(JSThread *thread, const JSHandle<JSTaggedValue> &chc,
const JSHandle<ClassInfoExtractor> &extractor)
{
if (chc->IsUndefinedOrNull()) {
return false;
}
JSHandle<JSHClass> chclass(thread, JSHClass::Cast(chc->GetTaggedObject()));
ASSERT(!chclass->IsDictionaryMode());
JSHandle<TaggedArray> staticProperties(thread, extractor->GetStaticProperties(thread));
return CheckAOTPropertiesForRep(thread, staticProperties, chclass);
}
void StringSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData, const std::set<uint32_t>&)
{
for (auto item : info_) {
const ItemData &data = item.second;
uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(thread_, snapshotCpArrIdx));
snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, JSTaggedValue::Hole());
}
if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
vm_->AddAOTSnapShotStats("String", info_.size());
}
}
void MethodSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
const std::set<uint32_t> &skippedMethods)
{
ApEntityId abcId = INVALID_INDEX;
bool hasAbcId = TryGetABCId(abcId);
ObjectFactory *factory = vm_->GetFactory();
for (auto item : info_) {
const ItemData &data = item.second;
JSHandle<ConstantPool> cp(thread_,
thread_->GetEcmaVM()->FindConstpool(jsPandaFile_, data.constantPoolId_));
uint32_t methodOffset = cp->GetEntityId(data.constantPoolIdx_).GetOffset();
uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(thread_, snapshotCpArrIdx));
JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
if (hasAbcId) {
ProfileType pt(abcId, methodOffset, ProfileType::Kind::ClassId, true);
ihc = TryGetHClass(pt, pt);
}
JSHandle<AOTLiteralInfo> aotLiteralInfo = factory->NewAOTLiteralInfo(1);
int initValue = static_cast<int>(AOTLiteralInfo::NO_FUNC_ENTRY_VALUE);
aotLiteralInfo->SetObjectToCache(thread_, 0, JSTaggedValue(initValue));
aotLiteralInfo->SetLiteralType(JSTaggedValue(AOTLiteralInfo::METHOD_LITERAL_TYPE));
if (!ihc->IsUndefined()) {
aotLiteralInfo->SetIhc(thread_, ihc.GetTaggedValue());
if (skippedMethods.find(methodOffset) == skippedMethods.end()) {
aotLiteralInfo->SetObjectToCache(thread_, 0, JSTaggedValue(methodOffset));
globalData.RecordReviseData(
ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
}
snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, aotLiteralInfo.GetTaggedValue());
} else if (skippedMethods.find(methodOffset) == skippedMethods.end()) {
globalData.RecordReviseData(
ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, JSTaggedValue(methodOffset));
} else {
snapshotCp->SetObjectToCache(thread_, data.constantPoolIdx_, JSTaggedValue::Hole());
}
}
if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
vm_->AddAOTSnapShotStats("Method", info_.size());
}
}
void ClassLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
const std::set<uint32_t> &skippedMethods)
{
ApEntityId abcId = INVALID_INDEX;
bool hasAbcId = TryGetABCId(abcId);
for (auto item : info_) {
const ItemData &data = item.second;
JSHandle<ConstantPool> cp = GetUnsharedConstpool(data);
auto literalObj = ConstantPool::GetClassLiteralFromCache(thread_, cp, data.constantPoolIdx_, data.recordName_);
JSHandle<ClassLiteral> classLiteral(thread_, literalObj);
JSHandle<TaggedArray> arrayHandle(thread_, classLiteral->GetArray(thread_));
uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(thread_, snapshotCpArrIdx));
uint32_t methodId = cp->GetEntityId(data.ctorMethodOffset_).GetOffset();
JSHandle<JSTaggedValue> undefinedHandle = thread_->GlobalConstants()->GetHandledUndefined();
JSHandle<JSTaggedValue> ihc = undefinedHandle;
JSHandle<JSTaggedValue> chc = undefinedHandle;
if (hasAbcId) {
ProfileType pt(abcId, methodId, ProfileType::Kind::ClassId, true);
ProfileType ctorPt(abcId, methodId, ProfileType::Kind::ConstructorId, true);
ihc = TryGetHClass(pt, pt);
chc = TryGetHClass(ctorPt, ctorPt);
auto method = ConstantPool::GetMethodFromCache(thread_, cp.GetTaggedValue(), data.ctorMethodOffset_);
auto *factory = thread_->GetEcmaVM()->GetFactory();
auto extractor = factory->NewClassInfoExtractor(JSHandle<JSTaggedValue>(thread_, method));
ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(thread_, extractor, arrayHandle,
arrayHandle->GetLength());
if (!CheckAOTIhcPropertiesForRep(thread_, ihc, extractor)) {
ihc = undefinedHandle;
}
if (!CheckAOTChcPropertiesForRep(thread_, chc, extractor)) {
chc = undefinedHandle;
}
}
CollectLiteralInfo(arrayHandle, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc);
globalData.RecordReviseData(
ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
}
if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
vm_->AddAOTSnapShotStats("ClassLiteral", info_.size());
}
}
void ObjectLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
const std::set<uint32_t> &skippedMethods)
{
ApEntityId abcId = INVALID_INDEX;
bool hasAbcId = TryGetABCId(abcId);
for (auto item : info_) {
const ItemData &data = item.second;
JSHandle<ConstantPool> cp = GetUnsharedConstpool(data);
panda_file::File::EntityId id = cp->GetEntityId(data.constantPoolIdx_);
JSMutableHandle<TaggedArray> elements(thread_, JSTaggedValue::Undefined());
JSMutableHandle<TaggedArray> properties(thread_, JSTaggedValue::Undefined());
LiteralDataExtractor::ExtractObjectDatas(thread_, jsPandaFile_, id, elements,
properties, cp, data.recordName_);
uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(thread_, snapshotCpArrIdx));
JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
if (hasAbcId) {
ProfileType pt(abcId, id.GetOffset(), ProfileType::Kind::ObjectLiteralId, true);
ProfileType ctorPt(abcId, id.GetOffset(), ProfileType::Kind::ConstructorId, true);
chc = TryGetHClass(ctorPt, ctorPt);
ihc = TryGetIHClass(pt, pt, data, properties, globalData);
}
CollectLiteralInfo(properties, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc);
globalData.RecordReviseData(
ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
}
if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
vm_->AddAOTSnapShotStats("ObjectLiteral", info_.size());
}
}
void ArrayLiteralSnapshotInfo::StoreDataToGlobalData(SnapshotGlobalData &globalData,
const std::set<uint32_t> &skippedMethods)
{
for (auto item : info_) {
const ItemData &data = item.second;
JSHandle<ConstantPool> cp = GetUnsharedConstpool(data);
panda_file::File::EntityId id = cp->GetEntityId(data.constantPoolIdx_);
JSHandle<TaggedArray> literal = LiteralDataExtractor::GetDatasIgnoreType(
thread_, jsPandaFile_, id, cp, data.recordName_);
uint32_t snapshotCpArrIdx = globalData.GetCpArrIdxByConstanPoolId(data.constantPoolId_);
JSHandle<TaggedArray> snapshotCpArr(thread_, globalData.GetCurSnapshotCpArray());
JSHandle<ConstantPool> snapshotCp(thread_, snapshotCpArr->Get(thread_, snapshotCpArrIdx));
JSHandle<JSTaggedValue> ihc = thread_->GlobalConstants()->GetHandledUndefined();
JSHandle<JSTaggedValue> chc = thread_->GlobalConstants()->GetHandledUndefined();
CollectLiteralInfo(literal, data.constantPoolIdx_, snapshotCp, skippedMethods, ihc, chc);
globalData.RecordReviseData(
ReviseData::ItemData {globalData.GetCurDataIdx(), snapshotCpArrIdx, data.constantPoolIdx_});
}
if (vm_->GetJSOptions().IsEnableCompilerLogSnapshot()) {
vm_->AddAOTSnapShotStats("ArrayLiteral", info_.size());
}
}
JSHandle<ConstantPool> BaseSnapshotInfo::GetUnsharedConstpool(const ItemData &data)
{
EcmaVM *vm = thread_->GetEcmaVM();
JSTaggedValue shareCp = vm->FindConstpool(jsPandaFile_, data.constantPoolId_);
JSHandle<ConstantPool> cp(thread_, vm->FindOrCreateUnsharedConstpool(shareCp));
return cp;
}
void SnapshotConstantPoolData::Record(const BytecodeInstruction &bcIns, int32_t bcIndex,
const CString &recordName, const MethodLiteral *method)
{
BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode());
uint32_t methodOffset = method->GetMethodId().GetOffset();
panda_file::IndexAccessor indexAccessor(*jsPandaFile_->GetPandaFile(),
panda_file::File::EntityId(methodOffset));
uint32_t constantPoolId = static_cast<uint32_t>(indexAccessor.GetHeaderIndex());
switch (opcode) {
case BytecodeInstruction::Opcode::LDA_STR_ID16:
case BytecodeInstruction::Opcode::STOWNBYNAME_IMM8_ID16_V8:
case BytecodeInstruction::Opcode::STOWNBYNAME_IMM16_ID16_V8:
case BytecodeInstruction::Opcode::CREATEREGEXPWITHLITERAL_IMM8_ID16_IMM8:
case BytecodeInstruction::Opcode::CREATEREGEXPWITHLITERAL_IMM16_ID16_IMM8:
case BytecodeInstruction::Opcode::STCONSTTOGLOBALRECORD_IMM16_ID16:
case BytecodeInstruction::Opcode::TRYLDGLOBALBYNAME_IMM8_ID16:
case BytecodeInstruction::Opcode::TRYLDGLOBALBYNAME_IMM16_ID16:
case BytecodeInstruction::Opcode::TRYSTGLOBALBYNAME_IMM8_ID16:
case BytecodeInstruction::Opcode::TRYSTGLOBALBYNAME_IMM16_ID16:
case BytecodeInstruction::Opcode::STTOGLOBALRECORD_IMM16_ID16:
case BytecodeInstruction::Opcode::STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8:
case BytecodeInstruction::Opcode::STOWNBYNAMEWITHNAMESET_IMM16_ID16_V8:
case BytecodeInstruction::Opcode::LDTHISBYNAME_IMM8_ID16:
case BytecodeInstruction::Opcode::LDTHISBYNAME_IMM16_ID16:
case BytecodeInstruction::Opcode::STTHISBYNAME_IMM8_ID16:
case BytecodeInstruction::Opcode::STTHISBYNAME_IMM16_ID16:
case BytecodeInstruction::Opcode::LDGLOBALVAR_IMM16_ID16:
case BytecodeInstruction::Opcode::LDOBJBYNAME_IMM8_ID16:
case BytecodeInstruction::Opcode::LDOBJBYNAME_IMM16_ID16:
case BytecodeInstruction::Opcode::STOBJBYNAME_IMM8_ID16_V8:
case BytecodeInstruction::Opcode::STOBJBYNAME_IMM16_ID16_V8:
case BytecodeInstruction::Opcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
case BytecodeInstruction::Opcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8:
case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM8_ID16:
case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM16_ID16:
case BytecodeInstruction::Opcode::STSUPERBYNAME_IMM8_ID16_V8:
case BytecodeInstruction::Opcode::STSUPERBYNAME_IMM16_ID16_V8:
case BytecodeInstruction::Opcode::STGLOBALVAR_IMM16_ID16:
case BytecodeInstruction::Opcode::LDBIGINT_ID16: {
auto constantPoolIdx = bcIns.GetId().AsRawValue();
BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
RecordInfo(Type::STRING, itemData);
break;
}
case BytecodeInstruction::Opcode::DEFINEFUNC_IMM8_ID16_IMM8:
case BytecodeInstruction::Opcode::DEFINEFUNC_IMM16_ID16_IMM8:
case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM8_ID16_IMM8:
case BytecodeInstruction::Opcode::DEFINEMETHOD_IMM16_ID16_IMM8: {
auto constantPoolIdx = bcIns.GetId().AsRawValue();
BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
RecordInfo(Type::METHOD, itemData);
break;
}
case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
case BytecodeInstruction::Opcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: {
auto constantPoolIdx = bcIns.GetId().AsRawValue();
BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
RecordInfo(Type::OBJECT_LITERAL, itemData);
break;
}
case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
case BytecodeInstruction::Opcode::CREATEARRAYWITHBUFFER_IMM16_ID16: {
auto constantPoolIdx = bcIns.GetId().AsRawValue();
BaseSnapshotInfo::ItemData itemData = {recordName, constantPoolId, constantPoolIdx, methodOffset, bcIndex};
RecordInfo(Type::ARRAY_LITERAL, itemData);
break;
}
case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: {
auto methodCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
BaseSnapshotInfo::ItemData methodItemData = {recordName, constantPoolId,
methodCPIdx, methodOffset, bcIndex};
RecordInfo(Type::METHOD, methodItemData);
auto literalCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM8_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
BaseSnapshotInfo::ItemData literalItemData = {recordName, constantPoolId,
literalCPIdx, methodOffset, bcIndex, methodCPIdx};
RecordInfo(Type::CLASS_LITERAL, literalItemData);
break;
}
case BytecodeInstruction::Opcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
auto methodCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 0>()).AsRawValue();
BaseSnapshotInfo::ItemData methodItemData = {recordName, constantPoolId,
methodCPIdx, methodOffset, bcIndex};
RecordInfo(Type::METHOD, methodItemData);
auto literalCPIdx = (bcIns.GetId <BytecodeInstruction::Format::IMM16_ID16_ID16_IMM16_V8, 1>()).AsRawValue();
BaseSnapshotInfo::ItemData literalItemData = {recordName, constantPoolId,
literalCPIdx, methodOffset, bcIndex, methodCPIdx};
RecordInfo(Type::CLASS_LITERAL, literalItemData);
break;
}
default:
break;
}
}
void SnapshotConstantPoolData::StoreDataToGlobalData(SnapshotGlobalData &snapshotData,
const std::set<uint32_t> &skippedMethods) const
{
for (auto &info : infos_) {
info->StoreDataToGlobalData(snapshotData, skippedMethods);
}
}
}