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