1/* 2 * Copyright (c) 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 <cstdio> 17 18#include "assembler/assembly-emitter.h" 19#include "assembler/assembly-parser.h" 20#include "libpandafile/class_data_accessor-inl.h" 21#include "libziparchive/zip_archive.h" 22#include "ecmascript/dfx/stackinfo/js_stackinfo.h" 23#include "ecmascript/tests/test_helper.h" 24 25using namespace panda::ecmascript; 26 27namespace panda::test { 28class JsStackInfoTest : public testing::Test { 29public: 30 static void SetUpTestCase() 31 { 32 GTEST_LOG_(INFO) << "SetUpTestCase"; 33 } 34 35 static void TearDownTestCase() 36 { 37 GTEST_LOG_(INFO) << "TearDownCase"; 38 } 39 40 void SetUp() override 41 { 42 TestHelper::CreateEcmaVMWithScope(instance, thread, scope); 43 instance->SetEnableForceGC(false); 44 } 45 46 void TearDown() override 47 { 48 TestHelper::DestroyEcmaVMWithScope(instance, scope); 49 } 50 51 EcmaVM *instance {nullptr}; 52 EcmaHandleScope *scope {nullptr}; 53 JSThread *thread {nullptr}; 54}; 55 56uintptr_t ToUintPtr(FrameType frame) 57{ 58 return static_cast<uintptr_t>(frame); 59} 60 61bool ReadMemFunc([[maybe_unused]] void *ctx, uintptr_t addr, uintptr_t *value) 62{ 63 *value = *(reinterpret_cast<uintptr_t *>(addr)); 64 return true; 65} 66 67/** 68 * @tc.name: ArkFrameCheck 69 * @tc.desc: Check whether the result returned through "ArkFrameCheck" function is within expectations. 70 * @tc.type: FUNC 71 * @tc.require: 72 */ 73HWTEST_F_L0(JsStackInfoTest, TestArkFrameCheck) 74{ 75 for (uintptr_t i = 0; i < 25; i++) { 76 bool ret = ArkFrameCheck(i); 77 if (i == ToUintPtr(FrameType::OPTIMIZED_ENTRY_FRAME) || 78 i == ToUintPtr(FrameType::ASM_INTERPRETER_ENTRY_FRAME)) { 79 EXPECT_TRUE(ret == true); 80 } else { 81 EXPECT_TRUE(ret == false); 82 } 83 } 84} 85 86/** 87 * @tc.name: IsJsFunctionFrame 88 * @tc.desc: Check whether the result returned through "IsJsFunctionFrame" function is within expectations. 89 * @tc.type: FUNC 90 * @tc.require: 91 */ 92HWTEST_F_L0(JsStackInfoTest, TestIsJsFunctionFrame) 93{ 94 for (uintptr_t i = 0; i < 25; i++) { 95 bool ret = IsJsFunctionFrame(i); 96 if (i == ToUintPtr(FrameType::ASM_INTERPRETER_FRAME) || 97 i == ToUintPtr(FrameType::INTERPRETER_CONSTRUCTOR_FRAME) || 98 i == ToUintPtr(FrameType::INTERPRETER_FRAME) || 99 i == ToUintPtr(FrameType::INTERPRETER_FAST_NEW_FRAME)) { 100 EXPECT_TRUE(ret == true); 101 } else { 102 EXPECT_TRUE(ret == false); 103 } 104 } 105} 106 107/** 108 * @tc.name: IsFastJitFunctionFrame 109 * @tc.desc: Check whether the result returned through "IsFastJitFunctionFrame" function is within expectations. 110 * @tc.type: FUNC 111 * @tc.require: 112 */ 113HWTEST_F_L0(JsStackInfoTest, TestIsFastJitFunctionFrame) 114{ 115 for (uintptr_t i = 0; i < 25; i++) { 116 bool ret = IsFastJitFunctionFrame(i); 117 if (i == ToUintPtr(FrameType::FASTJIT_FUNCTION_FRAME) || 118 i == ToUintPtr(FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME)) { 119 EXPECT_TRUE(ret == true); 120 } else { 121 EXPECT_TRUE(ret == false); 122 } 123 } 124} 125 126/** 127 * @tc.name: IsNativeFunctionFrame 128 * @tc.desc: Check whether the result returned through "IsNativeFunctionFrame" function is within expectations. 129 * @tc.type: FUNC 130 * @tc.require: 131 */ 132HWTEST_F_L0(JsStackInfoTest, TestIsNativeFunctionFrame) 133{ 134 for (uintptr_t i = 0; i < 25; i++) { 135 bool ret = IsNativeFunctionFrame(i); 136 if (i == ToUintPtr(FrameType::OPTIMIZED_FRAME) || 137 i == ToUintPtr(FrameType::BASELINE_BUILTIN_FRAME) || 138 i == ToUintPtr(FrameType::ASM_BRIDGE_FRAME) || 139 i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME) || 140 i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME) || 141 i == ToUintPtr(FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME) || 142 i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_FRAME) || 143 i == ToUintPtr(FrameType::LEAVE_FRAME) || 144 i == ToUintPtr(FrameType::LEAVE_FRAME_WITH_ARGV) || 145 i == ToUintPtr(FrameType::BUILTIN_CALL_LEAVE_FRAME) || 146 i == ToUintPtr(FrameType::BUILTIN_FRAME) || 147 i == ToUintPtr(FrameType::BUILTIN_ENTRY_FRAME) || 148 i == ToUintPtr(FrameType::BUILTIN_FRAME_WITH_ARGV) || 149 i == ToUintPtr(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME) || 150 i == ToUintPtr(FrameType::ASM_INTERPRETER_BRIDGE_FRAME)) { 151 EXPECT_TRUE(ret == true); 152 } else { 153 EXPECT_TRUE(ret == false); 154 } 155 } 156} 157 158/** 159 * @tc.name: IsAotFunctionFrame 160 * @tc.desc: Check whether the result returned through "IsAotFunctionFrame" function is within expectations. 161 * @tc.type: FUNC 162 * @tc.require: 163 */ 164HWTEST_F_L0(JsStackInfoTest, TestIsAotFunctionFrame) 165{ 166 for (uintptr_t i = 0; i < 25; i++) { 167 bool ret = IsAotFunctionFrame(i); 168 if (i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_FRAME) || 169 i == ToUintPtr(FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME)) { 170 EXPECT_TRUE(ret == true); 171 } else { 172 EXPECT_TRUE(ret == false); 173 } 174 } 175} 176 177/** 178 * @tc.name: ReadMethodInfo 179 * @tc.desc: Check whether the result returned through "ReadMethodInfo" function is within expectations. 180 * @tc.type: FUNC 181 * @tc.require: 182 */ 183HWTEST_F_L0(JsStackInfoTest, TestReadMethodInfo) 184{ 185 const char *filename = "__JSPandaFileManagerTest1.pa"; 186 const char *data = R"( 187 .function void foo() { 188 return 189 } 190 )"; 191 pandasm::Parser parser; 192 auto res = parser.Parse(data); 193 auto file = pandasm::AsmEmitter::Emit(res.Value()); 194 auto jsPandaFile = std::make_shared<JSPandaFile>(file.release(), CString(filename)); 195 EXPECT_TRUE(jsPandaFile != nullptr); 196 CVector<MethodInfo> result; 197 const panda_file::File *pf = jsPandaFile->GetPandaFile(); 198 Span<const uint32_t> classIndexes = jsPandaFile->GetClasses(); 199 for (const uint32_t index : classIndexes) { 200 panda_file::File::EntityId classId(index); 201 if (jsPandaFile->IsExternal(classId)) { 202 continue; 203 } 204 panda_file::ClassDataAccessor cda(*pf, classId); 205 cda.EnumerateMethods([&result, jsPandaFile](panda_file::MethodDataAccessor &mda) { 206 auto info = JSStackTrace::ReadMethodInfo(mda); 207 if (!info) { 208 return; 209 } 210 result.push_back(info.value()); 211 }); 212 } 213 EXPECT_TRUE(result.size() > 0); 214} 215 216/** 217 * @tc.name: ReadAllMethodInfos 218 * @tc.desc: Check whether the result returned through "ReadAllMethodInfos" function is within expectations. 219 * @tc.type: FUNC 220 * @tc.require: 221 */ 222HWTEST_F_L0(JsStackInfoTest, TestReadAllMethodInfos) 223{ 224 const char *filename = "__JsStackInfoTest.pa"; 225 const char *data = R"( 226 .function void foo() { 227 return 228 } 229 )"; 230 pandasm::Parser parser; 231 auto res = parser.Parse(data); 232 auto file = pandasm::AsmEmitter::Emit(res.Value()); 233 auto pf = std::make_shared<JSPandaFile>(file.release(), CString(filename)); 234 EXPECT_TRUE(pf != nullptr); 235 auto methods = JSStackTrace::ReadAllMethodInfos(pf); 236 EXPECT_TRUE(methods.size() > 0); 237 pf = nullptr; 238 methods = JSStackTrace::ReadAllMethodInfos(pf); 239 EXPECT_TRUE(methods.size() == 0); 240} 241 242/** 243 * @tc.name: TranslateByteCodePc 244 * @tc.desc: Check whether the result returned through "TranslateByteCodePc" function is within expectations. 245 * @tc.type: FUNC 246 * @tc.require: 247 */ 248HWTEST_F_L0(JsStackInfoTest, TestTranslateByteCodePc) 249{ 250 CVector<MethodInfo> vec = { 251 {0, 0, 24}, 252 {1, 24, 30}, 253 {2, 54, 56}, 254 {3, 110, 60} 255 }; 256 uintptr_t realPc = 115; 257 258 auto ret = JSStackTrace::TranslateByteCodePc(realPc, vec); 259 EXPECT_TRUE(ret != std::nullopt); 260 261 vec.clear(); 262 ret = JSStackTrace::TranslateByteCodePc(realPc, vec); 263 EXPECT_TRUE(ret == std::nullopt); 264 265 vec.push_back({2, 54, 56}); 266 ret = JSStackTrace::TranslateByteCodePc(realPc, vec); 267 EXPECT_TRUE(ret == std::nullopt); 268} 269 270/** 271 * @tc.name: ParseJsFrameInfo 272 * @tc.desc: Check whether the result returned through "ParseJsFrameInfo" function is within expectations. 273 * @tc.type: FUNC 274 * @tc.require: 275 */ 276HWTEST_F_L0(JsStackInfoTest, TestParseJsFrameInfo) 277{ 278 const char *filename = "__JsStackInfoTest.pa"; 279 const char *data = R"( 280 .function void foo() { 281 return 282 } 283 )"; 284 pandasm::Parser parser; 285 auto res = parser.Parse(data); 286 auto file = pandasm::AsmEmitter::Emit(res.Value()); 287 auto jsPandaFile = std::make_shared<JSPandaFile>(file.release(), CString(filename)); 288 EXPECT_TRUE(jsPandaFile != nullptr); 289 auto debugExtractor = std::make_unique<DebugInfoExtractor>(jsPandaFile.get()); 290 auto methods = JSStackTrace::ReadAllMethodInfos(jsPandaFile); 291 uintptr_t offset = 0; 292 JsFunction jsFunction; 293 ParseJsFrameInfo(jsPandaFile.get(), debugExtractor.get(), EntityId(methods[0].methodId), offset, jsFunction); 294 EXPECT_TRUE(std::string(jsFunction.functionName) == "foo"); 295} 296 297/** 298 * @tc.name: ArkParseJsFrameInfo 299 * @tc.desc: Check whether the result returned through "ArkCreateJSSymbolExtractor" function is within expectations; 300 * Check whether the result returned through "ArkParseJsFrameInfo" function is within expectations; 301 * Check whether the result returned through "ArkDestoryJSSymbolExtractor" function is within expectations. 302 * @tc.type: FUNC 303 * @tc.require: 304 */ 305HWTEST_F_L0(JsStackInfoTest, TestArkParseJsFrameInfo) 306{ 307 const char *filename1 = "__JsStackInfoTest1.pa"; 308 const char *filename2 = "__JsStackInfoTest2.pa"; 309 const char *pfdata1 = R"( 310 .function void foo() { 311 return 312 } 313 )"; 314 const char *pfdata2 = R"( 315 .language ECMAScript 316 .function any func_main_0(any a0, any a1, any a2) { 317 ldai 1 318 return 319 } 320 )"; 321 pandasm::Parser parser1; 322 pandasm::Parser parser2; 323 auto res1 = parser1.Parse(pfdata1); 324 auto res2 = parser2.Parse(pfdata2); 325 auto file1 = pandasm::AsmEmitter::Emit(res1.Value()); 326 auto file2 = pandasm::AsmEmitter::Emit(res2.Value()); 327 auto jsPandaFile1 = std::make_shared<JSPandaFile>(file1.release(), CString(filename1)); 328 auto jsPandaFile2 = std::make_shared<JSPandaFile>(file2.release(), CString(filename2)); 329 EXPECT_TRUE(jsPandaFile1 != nullptr); 330 EXPECT_TRUE(jsPandaFile2 != nullptr); 331 auto debugExtractor1 = std::make_unique<DebugInfoExtractor>(jsPandaFile1.get()); 332 auto debugExtractor2 = std::make_unique<DebugInfoExtractor>(jsPandaFile2.get()); 333 auto methods1 = JSStackTrace::ReadAllMethodInfos(jsPandaFile1); 334 auto methods2 = JSStackTrace::ReadAllMethodInfos(jsPandaFile2); 335 336 uintptr_t byteCodePc1 = methods1[0].codeBegin; 337 uintptr_t byteCodePc2 = methods2[0].codeBegin; 338 uintptr_t methodId1 = methods1[0].methodId; 339 uintptr_t methodId2 = methods2[0].methodId; 340 uintptr_t mapBase1 = reinterpret_cast<uintptr_t>(jsPandaFile1->GetHeader()); 341 uintptr_t mapBase2 = reinterpret_cast<uintptr_t>(jsPandaFile2->GetHeader()); 342 uintptr_t loadOffset1 = 0; 343 uintptr_t loadOffset2 = 0; 344 const uint8_t* data1 = jsPandaFile1->GetPandaFile()->GetBase(); 345 const uint8_t* data2 = jsPandaFile2->GetPandaFile()->GetBase(); 346 uint64_t dataSize1 = jsPandaFile1->GetFileSize(); 347 uint64_t dataSize2 = jsPandaFile2->GetFileSize(); 348 uintptr_t extractorptr1 = 0; 349 uintptr_t extractorptr2 = 0; 350 JsFunction jsFunction1; 351 JsFunction jsFunction2; 352 353 auto ret = ark_create_js_symbol_extractor(&extractorptr1); 354 EXPECT_TRUE(ret == 1); 355 EXPECT_TRUE(extractorptr1 != 0); 356 ret = ark_create_js_symbol_extractor(&extractorptr2); 357 EXPECT_TRUE(ret == 1); 358 EXPECT_TRUE(extractorptr2 != 0); 359 360 ret = ark_parse_js_frame_info(byteCodePc1, methodId1, mapBase1, loadOffset1, 361 reinterpret_cast<uint8_t *>(const_cast<char*>(pfdata1)), 362 strlen(pfdata1) + 1, extractorptr1, &jsFunction1); 363 EXPECT_TRUE(ret == -1); 364 365 ret = ark_parse_js_frame_info(byteCodePc1, methodId1, mapBase1, loadOffset1, 366 const_cast<uint8_t*>(data1), dataSize1, extractorptr1, &jsFunction1); 367 EXPECT_TRUE(ret == 1); 368 EXPECT_TRUE(std::string(jsFunction1.functionName) == "foo"); 369 370 ret = ark_parse_js_frame_info(byteCodePc1, methodId1, mapBase1, loadOffset1, 371 const_cast<uint8_t*>(data1), dataSize1 + 1, 0, &jsFunction1); 372 EXPECT_TRUE(ret == -1); 373 374 ret = ark_parse_js_frame_info(byteCodePc1, methodId1, mapBase1, loadOffset1, 375 nullptr, 0, extractorptr1, &jsFunction1); 376 EXPECT_TRUE(ret == -1); 377 378 ret = ark_parse_js_frame_info(byteCodePc1, methodId1, mapBase1, loadOffset1, 379 const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1); 380 EXPECT_TRUE(ret == -1); 381 382 ret = ark_parse_js_frame_info(byteCodePc2, methodId1, mapBase1, loadOffset1, 383 const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1); 384 EXPECT_TRUE(ret == -1); 385 386 ret = ark_parse_js_frame_info(byteCodePc2, methodId2, mapBase1, loadOffset1, 387 const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1); 388 EXPECT_TRUE(ret == -1); 389 390 ret = ark_parse_js_frame_info(byteCodePc2, methodId2, mapBase2, loadOffset2, 391 const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction2); 392 EXPECT_TRUE(ret == 1); 393 EXPECT_TRUE(std::string(jsFunction2.functionName) == "func_main_0"); 394 395 ret = ark_destory_js_symbol_extractor(extractorptr1); 396 EXPECT_TRUE(ret == 1); 397 398 ret = ark_destory_js_symbol_extractor(extractorptr2); 399 EXPECT_TRUE(ret == 1); 400} 401 402/** 403 * @tc.name: BuildJsStackInfo 404 * @tc.desc: Check whether the result returned through "BuildJsStackInfo" function is within expectations; 405 * @tc.type: FUNC 406 * @tc.require: 407 */ 408HWTEST_F_L0(JsStackInfoTest, TestBuildJsStackInfo) 409{ 410 auto jsFrame = JsStackInfo::BuildJsStackInfo(thread); 411 EXPECT_TRUE(jsFrame.empty()); 412} 413 414/** 415 * @tc.name: ark_destory_local 416 * @tc.desc: Check whether the result returned through "ark_destory_local" function is within expectations; 417 * @tc.type: FUNC 418 * @tc.require: 419 */ 420HWTEST_F_L0(JsStackInfoTest, TestArkDestoryLocal) 421{ 422 auto ret = ark_destory_local(); // Direct destruct without creating Pointers 423 EXPECT_TRUE(ret); 424 auto trace = JSStackTrace::GetInstance(); 425 EXPECT_TRUE(trace != nullptr); 426 ret = ark_destory_local(); // destory 427 EXPECT_TRUE(ret); 428 ret = ark_destory_local(); // multiple destory 429 EXPECT_TRUE(ret); 430 431 // Create and destruct multiple times within the process 432 trace = JSStackTrace::GetInstance(); 433 EXPECT_TRUE(trace != nullptr); 434 ret = ark_destory_local(); 435 EXPECT_TRUE(ret); 436} 437 438HWTEST_F_L0(JsStackInfoTest, TestStepArk__001) 439{ 440 void *ctx = nullptr; 441 uintptr_t sp = 0; 442 uintptr_t pc = 0; 443 bool isJsFrame = true; 444 uintptr_t frame[10][3]; 445 uintptr_t fp[10]; 446 for (int i = 0; i < 10; i++) { 447 frame[i][0] = 0; 448 frame[i][1] = 0; 449 } 450 fp[0] = reinterpret_cast<uintptr_t>(&frame[0][2]) + 8; 451 for (int i = 1; i < 10; i++) { 452 fp[i] = fp[i-1] + 24; 453 } 454 frame[0][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_CONSTRUCTOR_FRAME); 455 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[0], &sp, &pc, nullptr, &isJsFrame)); 456 frame[1][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_FAST_NEW_FRAME); 457 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[1], &sp, &pc, nullptr, &isJsFrame)); 458 frame[2][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME); 459 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[2], &sp, &pc, nullptr, &isJsFrame)); 460 frame[3][2] = static_cast<uintptr_t>(FrameType::ASM_INTERPRETER_ENTRY_FRAME); 461 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[3], &sp, &pc, nullptr, &isJsFrame)); 462 frame[4][2] = static_cast<uintptr_t>(FrameType::BUILTIN_ENTRY_FRAME); 463 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[4], &sp, &pc, nullptr, &isJsFrame)); 464 frame[5][2] = static_cast<uintptr_t>(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME); 465 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[5], &sp, &pc, nullptr, &isJsFrame)); 466 frame[6][2] = static_cast<uintptr_t>(FrameType::BASELINE_BUILTIN_FRAME); 467 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[6], &sp, &pc, nullptr, &isJsFrame)); 468 frame[7][2] = static_cast<uintptr_t>(FrameType::ASM_BRIDGE_FRAME); 469 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[7], &sp, &pc, nullptr, &isJsFrame)); 470 frame[8][2] = static_cast<uintptr_t>(FrameType::LEAVE_FRAME); 471 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[8], &sp, &pc, nullptr, &isJsFrame)); 472 frame[9][2] = static_cast<uintptr_t>(FrameType::LEAVE_FRAME_WITH_ARGV); 473 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[9], &sp, &pc, nullptr, &isJsFrame)); 474} 475 476HWTEST_F_L0(JsStackInfoTest, TestStepArk__002) 477{ 478 void *ctx = nullptr; 479 uintptr_t sp = 0; 480 uintptr_t pc = 0; 481 bool isJsFrame = true; 482 uintptr_t frame[30][3]; 483 uintptr_t fp[30]; 484 for (int i = 0; i < 30; i++) { 485 frame[i][0] = 0; 486 frame[i][1] = 0; 487 } 488 fp[0] = reinterpret_cast<uintptr_t>(&frame[0][2]) + 8; 489 for (int i = 1; i < 30; i++) { 490 fp[i] = fp[i-1] + 24; 491 } 492 frame[0][2] = static_cast<uintptr_t>(FrameType::BUILTIN_CALL_LEAVE_FRAME); 493 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[0], &sp, &pc, nullptr, &isJsFrame)); 494 frame[1][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_FRAME); 495 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[1], &sp, &pc, nullptr, &isJsFrame)); 496 frame[2][2] = static_cast<uintptr_t>(FrameType::ASM_INTERPRETER_BRIDGE_FRAME); 497 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[2], &sp, &pc, nullptr, &isJsFrame)); 498 frame[3][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME); 499 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[3], &sp, &pc, nullptr, &isJsFrame)); 500 frame[4][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_CONSTRUCTOR_FRAME); 501 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[4], &sp, &pc, nullptr, &isJsFrame)); 502 frame[5][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_ENTRY_FRAME); 503 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[5], &sp, &pc, nullptr, &isJsFrame)); 504 frame[6][2] = static_cast<uintptr_t>(FrameType::ASM_BRIDGE_FRAME); 505 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[6], &sp, &pc, nullptr, &isJsFrame)); 506 frame[7][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME); 507 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[7], &sp, &pc, nullptr, &isJsFrame)); 508 frame[8][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_FRAME); 509 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[8], &sp, &pc, nullptr, &isJsFrame)); 510 frame[9][2] = 100; 511 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &fp[9], &sp, &pc, nullptr, &isJsFrame)); 512} 513} // namespace panda::test