1/* 2 * Copyright (c) 2021-2022 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/jspandafile/literal_data_extractor.h" 17 18#include "ecmascript/compiler/aot_file/aot_file_manager.h" 19#include "ecmascript/global_env.h" 20#include "ecmascript/module/js_shared_module_manager.h" 21#include "ecmascript/patch/quick_fix_helper.h" 22 23namespace panda::ecmascript { 24using LiteralTag = panda_file::LiteralTag; 25using StringData = panda_file::StringData; 26using LiteralDataAccessor = panda_file::LiteralDataAccessor; 27using LiteralValue = panda_file::LiteralDataAccessor::LiteralValue; 28 29void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const JSPandaFile *jsPandaFile, size_t index, 30 JSMutableHandle<TaggedArray> elements, 31 JSMutableHandle<TaggedArray> properties, 32 JSHandle<ConstantPool> constpool, 33 const CString &entryPoint) 34{ 35 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 36 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor(); 37 uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half 38 elements.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue()); 39 properties.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue()); 40 uint32_t epos = 0; 41 uint32_t ppos = 0; 42 const uint8_t pairSize = 2; 43 uint32_t methodId = 0; 44 FunctionKind kind; 45 lda.EnumerateLiteralVals( 46 index, [elements, properties, &epos, &ppos, factory, thread, jsPandaFile, 47 &methodId, &kind, &constpool, &entryPoint](const LiteralValue &value, const LiteralTag &tag) { 48 JSTaggedValue jt = JSTaggedValue::Null(); 49 bool flag = false; 50 switch (tag) { 51 case LiteralTag::INTEGER: { 52 jt = JSTaggedValue(std::get<uint32_t>(value)); 53 break; 54 } 55 case LiteralTag::DOUBLE: { 56 jt = JSTaggedValue(std::get<double>(value)); 57 break; 58 } 59 case LiteralTag::BOOL: { 60 jt = JSTaggedValue(std::get<bool>(value)); 61 break; 62 } 63 case LiteralTag::STRING: { 64 StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value))); 65 EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE); 66 jt = JSTaggedValue(str); 67 uint32_t elementIndex = 0; 68 if (JSTaggedValue::ToElementIndex(jt, &elementIndex) && ppos % pairSize == 0) { 69 flag = true; 70 } 71 break; 72 } 73 case LiteralTag::METHOD: { 74 methodId = std::get<uint32_t>(value); 75 kind = FunctionKind::NORMAL_FUNCTION; 76 break; 77 } 78 case LiteralTag::GETTER: { 79 methodId = std::get<uint32_t>(value); 80 kind = FunctionKind::GETTER_FUNCTION; 81 break; 82 } 83 case LiteralTag::SETTER: { 84 methodId = std::get<uint32_t>(value); 85 kind = FunctionKind::SETTER_FUNCTION; 86 break; 87 } 88 case LiteralTag::GENERATORMETHOD: { 89 methodId = std::get<uint32_t>(value); 90 kind = FunctionKind::GENERATOR_FUNCTION; 91 break; 92 } 93 case LiteralTag::ASYNCGENERATORMETHOD: { 94 methodId = std::get<uint32_t>(value); 95 kind = FunctionKind::ASYNC_GENERATOR_FUNCTION; 96 break; 97 } 98 case LiteralTag::METHODAFFILIATE: { 99 uint16_t length = std::get<uint16_t>(value); 100 JSHandle<JSFunction> jsFunc = 101 DefineMethodInLiteral(thread, jsPandaFile, methodId, constpool, kind, length, entryPoint); 102 jt = jsFunc.GetTaggedValue(); 103 break; 104 } 105 case LiteralTag::ACCESSOR: { 106 JSHandle<AccessorData> accessor = factory->NewAccessorData(); 107 jt = accessor.GetTaggedValue(); 108 break; 109 } 110 case LiteralTag::NULLVALUE: { 111 break; 112 } 113 default: { 114 LOG_ECMA(FATAL) << "this branch is unreachable"; 115 UNREACHABLE(); 116 break; 117 } 118 } 119 if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER && 120 tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) { 121 if (epos % pairSize == 0 && !flag) { 122 properties->Set(thread, ppos++, jt); 123 } else { 124 elements->Set(thread, epos++, jt); 125 } 126 } 127 }); 128} 129 130JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreTypeForClass(JSThread *thread, 131 const JSPandaFile *jsPandaFile, size_t index, JSHandle<ConstantPool> constpool, const CString &entryPoint) 132{ 133 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor(); 134 uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half 135 // The num is 1, indicating that the current class has no member variable. 136 if (num == 1) { 137 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 138 return factory->EmptyArray(); 139 } 140 return EnumerateLiteralVals(thread, lda, jsPandaFile, index, constpool, entryPoint); 141} 142 143JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile, 144 size_t index, JSHandle<ConstantPool> constpool, 145 const CString &entryPoint) 146{ 147 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor(); 148 return EnumerateLiteralVals(thread, lda, jsPandaFile, index, constpool, entryPoint); 149} 150 151JSHandle<TaggedArray> LiteralDataExtractor::EnumerateLiteralVals(JSThread *thread, LiteralDataAccessor &lda, 152 const JSPandaFile *jsPandaFile, size_t index, JSHandle<ConstantPool> constpool, const CString &entryPoint) 153{ 154 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 155 uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half 156 JSHandle<TaggedArray> literals = factory->NewOldSpaceTaggedArray(num); 157 uint32_t pos = 0; 158 uint32_t methodId = 0; 159 FunctionKind kind; 160 lda.EnumerateLiteralVals( 161 index, [literals, &pos, factory, thread, jsPandaFile, &methodId, &kind, &constpool, &entryPoint] 162 (const LiteralValue &value, const LiteralTag &tag) { 163 JSTaggedValue jt = JSTaggedValue::Null(); 164 switch (tag) { 165 case LiteralTag::INTEGER: { 166 jt = JSTaggedValue(std::get<uint32_t>(value)); 167 break; 168 } 169 case LiteralTag::DOUBLE: { 170 jt = JSTaggedValue(std::get<double>(value)); 171 break; 172 } 173 case LiteralTag::BOOL: { 174 jt = JSTaggedValue(std::get<bool>(value)); 175 break; 176 } 177 case LiteralTag::STRING: { 178 StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value))); 179 EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE); 180 jt = JSTaggedValue(str); 181 break; 182 } 183 case LiteralTag::METHOD: { 184 methodId = std::get<uint32_t>(value); 185 kind = FunctionKind::NORMAL_FUNCTION; 186 break; 187 } 188 case LiteralTag::GETTER: { 189 methodId = std::get<uint32_t>(value); 190 kind = FunctionKind::GETTER_FUNCTION; 191 break; 192 } 193 case LiteralTag::SETTER: { 194 methodId = std::get<uint32_t>(value); 195 kind = FunctionKind::SETTER_FUNCTION; 196 break; 197 } 198 case LiteralTag::GENERATORMETHOD: { 199 methodId = std::get<uint32_t>(value); 200 kind = FunctionKind::GENERATOR_FUNCTION; 201 break; 202 } 203 case LiteralTag::ASYNCGENERATORMETHOD: { 204 methodId = std::get<uint32_t>(value); 205 kind = FunctionKind::ASYNC_GENERATOR_FUNCTION; 206 break; 207 } 208 case LiteralTag::METHODAFFILIATE: { 209 uint16_t length = std::get<uint16_t>(value); 210 JSHandle<FunctionTemplate> jsFunc = 211 DefineFunctionTemplate(thread, jsPandaFile, methodId, constpool, kind, length, entryPoint); 212 jt = jsFunc.GetTaggedValue(); 213 break; 214 } 215 case LiteralTag::ACCESSOR: { 216 JSHandle<AccessorData> accessor = factory->NewAccessorData(); 217 jt = accessor.GetTaggedValue(); 218 break; 219 } 220 case LiteralTag::NULLVALUE: { 221 break; 222 } 223 default: { 224 LOG_ECMA(FATAL) << "this branch is unreachable"; 225 UNREACHABLE(); 226 break; 227 } 228 } 229 if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER && 230 tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) { 231 literals->Set(thread, pos++, jt); 232 } else { 233 uint32_t oldLength = literals->GetLength(); 234 ASSERT(oldLength > 0); 235 literals->Trim(thread, oldLength - 1); 236 } 237 }); 238 return literals; 239} 240 241JSHandle<FunctionTemplate> LiteralDataExtractor::DefineFunctionTemplate(JSThread *thread, 242 const JSPandaFile *jsPandaFile, 243 uint32_t offset, 244 JSHandle<ConstantPool> constpool, 245 FunctionKind kind, uint16_t length, 246 const CString &entryPoint, 247 bool isLoadedAOT, uint32_t entryIndex, 248 JSHandle<JSTaggedValue> sendableEnv, 249 ClassKind classKind) 250{ 251 EcmaVM *vm = thread->GetEcmaVM(); 252 ObjectFactory *factory = vm->GetFactory(); 253 254 // New Method 255 auto methodLiteral = jsPandaFile->FindMethodLiteral(offset); 256 CHECK_INPUT_NULLPTR(methodLiteral, 257 "DefineFunctionTemplate:methodLiteral is nullptr, offset: " + std::to_string(offset)); 258 FunctionKind literalKind = methodLiteral->GetFunctionKind(); 259 if (literalKind == FunctionKind::NONE_FUNCTION || classKind == ClassKind::SENDABLE) { 260 methodLiteral->SetFunctionKind(kind); 261 } else { 262 kind = literalKind; 263 } 264 JSHandle<Method> method = factory->NewSMethod(jsPandaFile, methodLiteral, constpool, entryIndex, isLoadedAOT); 265 if (classKind == ClassKind::SENDABLE) { 266 method->SetIsSendable(true); 267 } 268 269 // Generate Module 270 JSHandle<JSTaggedValue> module = SharedModuleManager::GetInstance()->GenerateFuncModule(thread, jsPandaFile, 271 entryPoint, classKind); 272 if (module->IsSourceTextModule()) { 273 SourceTextModule::Cast(module->GetTaggedObject())->SetSendableEnv(thread, sendableEnv); 274 } 275 276 // New FunctionTemplate 277 JSHandle<FunctionTemplate> funcTemp; 278 if (classKind == ClassKind::SENDABLE) { 279 funcTemp = factory->NewSFunctionTemplate(method, module, length); 280 } else { 281 funcTemp = factory->NewFunctionTemplate(method, module, length); 282 } 283 return funcTemp; 284} 285 286JSHandle<JSFunction> LiteralDataExtractor::CreateJSFunctionInLiteral(EcmaVM *vm, 287 const JSHandle<Method> &method, 288 FunctionKind kind, 289 ClassKind classKind) 290{ 291 ObjectFactory *factory = vm->GetFactory(); 292 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); 293 JSHandle<JSFunction> jsFunc; 294 JSHandle<JSHClass> functionClass; 295 if (classKind == ClassKind::SENDABLE) { 296 if (kind == FunctionKind::NORMAL_FUNCTION || 297 kind == FunctionKind::GETTER_FUNCTION || 298 kind == FunctionKind::SETTER_FUNCTION) { 299 functionClass = JSHandle<JSHClass>::Cast(env->GetSFunctionClassWithoutProto()); 300 } else if (kind == FunctionKind::ASYNC_FUNCTION) { 301 functionClass = JSHandle<JSHClass>::Cast(env->GetAsyncFunctionClass()); 302 } else { 303 functionClass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass()); 304 } 305 jsFunc = factory->NewSFunctionByHClass(method, functionClass); 306 } else { 307 if (kind == FunctionKind::NORMAL_FUNCTION || 308 kind == FunctionKind::GETTER_FUNCTION || 309 kind == FunctionKind::SETTER_FUNCTION) { 310 functionClass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutProto()); 311 } else if (kind == FunctionKind::ASYNC_FUNCTION) { 312 functionClass = JSHandle<JSHClass>::Cast(env->GetAsyncFunctionClass()); 313 } else { 314 functionClass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass()); 315 } 316 jsFunc = factory->NewJSFunctionByHClass(method, functionClass, MemSpaceType::OLD_SPACE); 317 } 318 return jsFunc; 319} 320 321JSHandle<JSFunction> LiteralDataExtractor::DefineMethodInLiteral(JSThread *thread, const JSPandaFile *jsPandaFile, 322 uint32_t offset, JSHandle<ConstantPool> constpool, 323 FunctionKind kind, uint16_t length, 324 const CString &entryPoint, 325 bool isLoadedAOT, uint32_t entryIndex, 326 JSHandle<JSTaggedValue> sendableEnv, 327 ClassKind classKind) 328{ 329 EcmaVM *vm = thread->GetEcmaVM(); 330 ObjectFactory *factory = vm->GetFactory(); 331 332 auto methodLiteral = jsPandaFile->FindMethodLiteral(offset); 333 CHECK_INPUT_NULLPTR(methodLiteral, 334 "DefineMethodInLiteral:methodLiteral is nullptr, offset: " + std::to_string(offset)); 335 FunctionKind literalKind = methodLiteral->GetFunctionKind(); 336 if (literalKind == FunctionKind::NONE_FUNCTION || classKind == ClassKind::SENDABLE) { 337 methodLiteral->SetFunctionKind(kind); 338 } else { 339 kind = literalKind; 340 } 341 bool canFastCall = false; 342 JSHandle<Method> method = 343 factory->NewSMethod(jsPandaFile, methodLiteral, constpool, entryIndex, isLoadedAOT, &canFastCall); 344 if (classKind == ClassKind::SENDABLE) { 345 method->SetIsSendable(true); 346 } 347 JSHandle<JSHClass> functionClass; 348 JSHandle<JSFunction> jsFunc = CreateJSFunctionInLiteral(vm, method, kind, classKind); 349 JSHandle<JSTaggedValue> module = SharedModuleManager::GetInstance()->GenerateFuncModule(thread, jsPandaFile, 350 entryPoint, classKind); 351 if (module->IsSourceTextModule()) { 352 SourceTextModule::Cast(module->GetTaggedObject())->SetSendableEnv(thread, sendableEnv); 353 } 354 355 jsFunc->SetModule(thread, module.GetTaggedValue()); 356 jsFunc->SetLength(length); 357 return jsFunc; 358} 359 360void LiteralDataExtractor::GetMethodOffsets(const JSPandaFile *jsPandaFile, size_t index, 361 std::vector<uint32_t> &methodOffsets) 362{ 363 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor(); 364 lda.EnumerateLiteralVals(index, [&methodOffsets](const LiteralValue &value, const LiteralTag &tag) { 365 switch (tag) { 366 case LiteralTag::METHOD: 367 case LiteralTag::GETTER: 368 case LiteralTag::SETTER: 369 case LiteralTag::ASYNCGENERATORMETHOD: 370 case LiteralTag::GENERATORMETHOD: { 371 methodOffsets.emplace_back(std::get<uint32_t>(value)); 372 break; 373 } 374 default: { 375 break; 376 } 377 } 378 }); 379} 380 381void LiteralDataExtractor::GetMethodOffsets(const JSPandaFile *jsPandaFile, EntityId id, 382 std::vector<uint32_t> &methodOffsets) 383{ 384 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor(); 385 lda.EnumerateLiteralVals(id, [&methodOffsets](const LiteralValue &value, const LiteralTag &tag) { 386 switch (tag) { 387 case LiteralTag::METHOD: 388 case LiteralTag::GETTER: 389 case LiteralTag::SETTER: 390 case LiteralTag::ASYNCGENERATORMETHOD: 391 case LiteralTag::GENERATORMETHOD: { 392 methodOffsets.emplace_back(std::get<uint32_t>(value)); 393 break; 394 } 395 default: { 396 break; 397 } 398 } 399 }); 400} 401 402void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const JSPandaFile *jsPandaFile, EntityId id, 403 JSMutableHandle<TaggedArray> elements, 404 JSMutableHandle<TaggedArray> properties, 405 JSHandle<ConstantPool> constpool, const CString &entry, 406 bool isLoadedAOT, JSHandle<AOTLiteralInfo> entryIndexes) 407{ 408 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 409 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor(); 410 uint32_t num = lda.GetLiteralValsNum(id) / 2; // 2: half 411 elements.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue()); 412 properties.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue()); 413 uint32_t epos = 0; 414 uint32_t ppos = 0; 415 const uint8_t pairSize = 2; 416 uint32_t methodId = 0; 417 int pos = 0; 418 FunctionKind kind; 419 lda.EnumerateLiteralVals( 420 id, [elements, properties, &entryIndexes, &pos, &epos, &ppos, factory, thread, jsPandaFile, 421 &methodId, &kind, &constpool, &entry, &isLoadedAOT](const LiteralValue &value, const LiteralTag &tag) { 422 JSTaggedValue jt = JSTaggedValue::Null(); 423 bool flag = false; 424 switch (tag) { 425 case LiteralTag::INTEGER: { 426 jt = JSTaggedValue(static_cast<int32_t>(std::get<uint32_t>(value))); 427 break; 428 } 429 case LiteralTag::DOUBLE: { 430 jt = JSTaggedValue(std::get<double>(value)); 431 break; 432 } 433 case LiteralTag::BOOL: { 434 jt = JSTaggedValue(std::get<bool>(value)); 435 break; 436 } 437 case LiteralTag::STRING: { 438 StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value))); 439 EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE); 440 jt = JSTaggedValue(str); 441 uint32_t elementIndex = 0; 442 if (JSTaggedValue::ToElementIndex(jt, &elementIndex) && ppos % pairSize == 0) { 443 flag = true; 444 } 445 break; 446 } 447 case LiteralTag::METHOD: { 448 methodId = std::get<uint32_t>(value); 449 kind = FunctionKind::NORMAL_FUNCTION; 450 break; 451 } 452 case LiteralTag::GETTER: { 453 methodId = std::get<uint32_t>(value); 454 kind = FunctionKind::GETTER_FUNCTION; 455 break; 456 } 457 case LiteralTag::SETTER: { 458 methodId = std::get<uint32_t>(value); 459 kind = FunctionKind::SETTER_FUNCTION; 460 break; 461 } 462 case LiteralTag::GENERATORMETHOD: { 463 methodId = std::get<uint32_t>(value); 464 kind = FunctionKind::GENERATOR_FUNCTION; 465 break; 466 } 467 468 case LiteralTag::ASYNCGENERATORMETHOD: { 469 methodId = std::get<uint32_t>(value); 470 kind = FunctionKind::ASYNC_GENERATOR_FUNCTION; 471 break; 472 } 473 474 case LiteralTag::METHODAFFILIATE: { 475 uint16_t length = std::get<uint16_t>(value); 476 int entryIndex = 0; 477 bool needSetAotFlag = (isLoadedAOT && (epos % pairSize == 0) && !flag); 478 if (needSetAotFlag) { 479 entryIndex = entryIndexes->GetObjectFromCache(pos++).GetInt(); 480 // -1 : this jsfunction is a large function 481 if (entryIndex == -1) { 482 needSetAotFlag = false; 483 } 484 } 485 JSHandle<JSFunction> jsFunc = 486 DefineMethodInLiteral(thread, jsPandaFile, methodId, constpool, kind, 487 length, entry, needSetAotFlag, entryIndex); 488 jt = jsFunc.GetTaggedValue(); 489 break; 490 } 491 case LiteralTag::ACCESSOR: { 492 JSHandle<AccessorData> accessor = factory->NewAccessorData(); 493 jt = accessor.GetTaggedValue(); 494 break; 495 } 496 case LiteralTag::NULLVALUE: { 497 break; 498 } 499 default: { 500 LOG_ECMA(FATAL) << "this branch is unreachable"; 501 UNREACHABLE(); 502 break; 503 } 504 } 505 if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER && 506 tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) { 507 if ((epos % pairSize == 0) && !flag) { 508 properties->Set(thread, ppos++, jt); 509 } else { 510 elements->Set(thread, epos++, jt); 511 } 512 } 513 }); 514} 515 516JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreTypeForClass(JSThread *thread, const JSPandaFile *jsPandaFile, 517 EntityId id, JSHandle<ConstantPool> constpool, 518 const CString &entryPoint, bool isLoadedAOT, 519 JSHandle<AOTLiteralInfo> entryIndexes, 520 ElementsKind *newKind, 521 JSHandle<JSTaggedValue> sendableEnv, 522 ClassKind classKind) 523{ 524 ASSERT(jsPandaFile != nullptr); 525 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor(); 526 uint32_t num = lda.GetLiteralValsNum(id) / 2; // 2: half 527 // The num is 1, indicating that the current class has no member variable. 528 if (num == 1) { 529 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 530 return factory->EmptyArray(); 531 } 532 return GetDatasIgnoreType( 533 thread, jsPandaFile, id, constpool, entryPoint, isLoadedAOT, entryIndexes, newKind, sendableEnv, classKind); 534} 535 536JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile, 537 EntityId id, JSHandle<ConstantPool> constpool, 538 const CString &entryPoint, bool isLoadedAOT, 539 JSHandle<AOTLiteralInfo> entryIndexes, 540 ElementsKind *newKind, 541 JSHandle<JSTaggedValue> sendableEnv, 542 ClassKind classKind) 543{ 544 ASSERT(jsPandaFile != nullptr); 545 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 546 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor(); 547 uint32_t num = lda.GetLiteralValsNum(id) / 2; // 2: half 548 JSHandle<TaggedArray> literals; 549 if (classKind == ClassKind::SENDABLE) { 550 literals = JSHandle<TaggedArray>(factory->NewSCOWTaggedArray(num)); 551 } else { 552 literals = JSHandle<TaggedArray>(factory->NewCOWTaggedArray(num)); 553 } 554 uint32_t pos = 0; 555 uint32_t methodId = 0; 556 FunctionKind kind; 557 int index = 0; 558 lda.EnumerateLiteralVals( 559 id, [literals, &pos, factory, thread, jsPandaFile, &methodId, &kind, &constpool, 560 &entryPoint, &entryIndexes, &index, isLoadedAOT, newKind, classKind, &sendableEnv] 561 (const LiteralValue &value, const LiteralTag &tag) { 562 JSTaggedValue jt = JSTaggedValue::Null(); 563 switch (tag) { 564 case LiteralTag::INTEGER: { 565 jt = JSTaggedValue(std::get<uint32_t>(value)); 566 break; 567 } 568 case LiteralTag::DOUBLE: { 569 jt = JSTaggedValue(std::get<double>(value)); 570 break; 571 } 572 case LiteralTag::BOOL: { 573 jt = JSTaggedValue(std::get<bool>(value)); 574 break; 575 } 576 case LiteralTag::STRING: { 577 StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value))); 578 EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE); 579 jt = JSTaggedValue(str); 580 break; 581 } 582 case LiteralTag::METHOD: { 583 methodId = std::get<uint32_t>(value); 584 kind = FunctionKind::NORMAL_FUNCTION; 585 break; 586 } 587 case LiteralTag::GETTER: { 588 methodId = std::get<uint32_t>(value); 589 kind = FunctionKind::GETTER_FUNCTION; 590 break; 591 } 592 case LiteralTag::SETTER: { 593 methodId = std::get<uint32_t>(value); 594 kind = FunctionKind::SETTER_FUNCTION; 595 break; 596 } 597 case LiteralTag::GENERATORMETHOD: { 598 methodId = std::get<uint32_t>(value); 599 kind = FunctionKind::GENERATOR_FUNCTION; 600 break; 601 } 602 case LiteralTag::ASYNCGENERATORMETHOD: { 603 methodId = std::get<uint32_t>(value); 604 kind = FunctionKind::ASYNC_GENERATOR_FUNCTION; 605 break; 606 } 607 case LiteralTag::METHODAFFILIATE: { 608 uint16_t length = std::get<uint16_t>(value); 609 int entryIndex = 0; 610 bool needSetAotFlag = isLoadedAOT; 611 if (isLoadedAOT) { 612 entryIndex = entryIndexes->GetObjectFromCache(index++).GetInt(); 613 if (entryIndex == -1) { 614 needSetAotFlag = false; 615 } 616 } 617 JSHandle<FunctionTemplate> funcTemp = DefineFunctionTemplate(thread, jsPandaFile, methodId, 618 constpool, kind, length, entryPoint, needSetAotFlag, entryIndex, sendableEnv, classKind); 619 jt = funcTemp.GetTaggedValue(); 620 break; 621 } 622 case LiteralTag::ACCESSOR: { 623 JSHandle<AccessorData> accessor = factory->NewAccessorData(); 624 jt = accessor.GetTaggedValue(); 625 break; 626 } 627 case LiteralTag::LITERALARRAY: { 628 jt = JSTaggedValue(std::get<uint32_t>(value)); 629 break; 630 } 631 case LiteralTag::NULLVALUE: { 632 break; 633 } 634 default: { 635 LOG_ECMA(FATAL) << "this branch is unreachable"; 636 UNREACHABLE(); 637 break; 638 } 639 } 640 if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER && 641 tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) { 642 if (newKind != nullptr) { 643 *newKind = Elements::ToElementsKind(jt, *newKind); 644 } 645 literals->Set(thread, pos++, jt); 646 } else { 647 uint32_t oldLength = literals->GetLength(); 648 ASSERT(oldLength > 0); 649 literals->Trim(thread, oldLength - 1); 650 } 651 }); 652 return literals; 653} 654} // namespace panda::ecmascript 655