1 /* 2 * Copyright (c) 2023 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 #ifndef ECMASCRIPT_FRAMES_H 17 #define ECMASCRIPT_FRAMES_H 18 19 #include "ecmascript/base/aligned_struct.h" 20 #include "ecmascript/js_tagged_value.h" 21 #include "ecmascript/mem/visitor.h" 22 #include "ecmascript/method.h" 23 #include "ecmascript/stackmap/ark_stackmap.h" 24 #include "ecmascript/stackmap/llvm_stackmap_type.h" 25 26 namespace panda::ecmascript { 27 class JSThread; 28 class EcmaVM; 29 class FrameIterator; 30 namespace kungfu { 31 class ArkStackMapParser; 32 }; 33 34 // Here list all scenarios of calling between Runtime/CInterpreter/ASMInterpreter/AOTCompiler/CBuiltin/ASMBuitlin. 35 // Please note that the "[]" means a must frame while "<>" means an optional frame. Each case is from top to down. 36 // 37 // * Runtime (C++) => CInterpreter: 38 // 1) [INTERPRETER_FRAME] 39 // 40 // * Runtime (C++) -> AOTCompiler: 41 // 1) [OPTIMIZED_ENTRY_FRAME] 42 // <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME> 43 // <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME> 44 // [OPTIMIZED_JS_FUNCTION_FRAME] 45 // 46 // * Runtime (C++) => ASMInterpreter: 47 // 1) [INTERPRETER_ENTRY_FRAME][ASM_INTERPRETER_FRAME] 48 // 49 // * Runtime (C++) => CBuiltin: 50 // 1) [not supported] 51 // 52 // * Runtime (C++) => ASMBuiltin: 53 // 1) [not supported] 54 // 55 // * CInterpreter => CInterpreter: 56 // 1) [INTERPRETER_FRAME] 57 // 58 // * CInterpreter => Runtime (C++): 59 // 1) [INTERPRETER_FAST_NEW_FRAME] 60 // 2) [INTERPRETER_CONSTRUCTOR_FRAME] 61 // 62 // * CInterpreter => AOTCompiler: 63 // 1) [not supported] 64 // 65 // * CInterperter => CBuiltin: 66 // 1) [INTERPRETER_BUILTIN_FRAME] 67 // 68 // * CInterpreter => ASMBuiltin: 69 // 1) [not supported] 70 // 71 // * ASMInterpreter => Runtime (C++): 72 // 1) [LEAVE_FRAME] 73 // 2) [LEAVE_FRAME_WITH_ARGV] 74 // 75 // * ASMInterpreter => AOTCompiler: 76 // 1) [OPTIMIZED_ENTRY_FRAME] 77 // <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME> 78 // <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME> 79 // [OPTIMIZED_JS_FUNCTION_FRAME] 80 // 81 // * ASMInterpreter => ASMInterpreter: 82 // 1) [ASM_INTERPRETER_FRAME] 83 // 84 // * ASMInterpreter => AsmBuiltin: 85 // 1) [BUILTIN_ENTRY_FRAME] 86 // [BUILTIN_FRAME] 87 // 2) [BUILTIN_ENTRY_FRAME] 88 // [BUILTIN_FRAME_WITH_ARGV] 89 // 90 // * ASMInterpreter => CBuiltin: 91 // 1) [LEAVE_FRAME] 92 // 2) [LEAVE_FRAME_WITH_ARGV] 93 // 94 // * AOTCompiler => Runtime (C++): 95 // 1) [LEAVE_FRAME] 96 // 2) [LEAVE_FRAME_WITH_ARGV] 97 // 98 // * AOTCompiler => ASMInterpreter: 99 // 1) [ASM_INTERPRETER_BRIDGE_FRAME] 100 // 2) [ASM_INTERPRETER_FRAME] 101 // 102 // * AOTCompiler => CBuiltin: 103 // 1) [LEAVE_FRAME] 104 // 2) [LEAVE_FRAME_WITH_ARGV] 105 // 106 // * AOTCompiler => ASMBuiltin: 107 // 1) [BUILTIN_ENTRY_FRAME] 108 // [BUILTIN_FRAME] 109 // 2) [BUILTIN_ENTRY_FRAME] 110 // [BUILTIN_FRAME_WITH_ARGV] 111 112 113 enum class FrameType: uintptr_t { 114 OPTIMIZED_FRAME = 0, 115 OPTIMIZED_ENTRY_FRAME, 116 OPTIMIZED_JS_FUNCTION_FRAME, 117 OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME, 118 ASM_BRIDGE_FRAME, 119 LEAVE_FRAME, 120 LEAVE_FRAME_WITH_ARGV, 121 BUILTIN_CALL_LEAVE_FRAME, 122 INTERPRETER_FRAME, 123 ASM_INTERPRETER_FRAME, 124 INTERPRETER_CONSTRUCTOR_FRAME, 125 BUILTIN_FRAME, 126 BUILTIN_FRAME_WITH_ARGV, 127 BUILTIN_ENTRY_FRAME, 128 INTERPRETER_BUILTIN_FRAME, 129 INTERPRETER_FAST_NEW_FRAME, 130 INTERPRETER_ENTRY_FRAME, 131 ASM_INTERPRETER_ENTRY_FRAME, 132 ASM_INTERPRETER_BRIDGE_FRAME, 133 OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME, 134 OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, 135 BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME, 136 137 FRAME_TYPE_FIRST = OPTIMIZED_FRAME, 138 FRAME_TYPE_LAST = OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, 139 INTERPRETER_FIRST = INTERPRETER_FRAME, 140 INTERPRETER_LAST = INTERPRETER_FAST_NEW_FRAME, 141 BUILTIN_FIRST = BUILTIN_FRAME, 142 BUILTIN_LAST = BUILTIN_ENTRY_FRAME, 143 }; 144 145 enum class JSCallMode : uintptr_t { 146 CALL_ARG0 = 0, 147 CALL_ARG1, 148 CALL_ARG2, 149 CALL_ARG3, 150 CALL_THIS_ARG0, 151 CALL_THIS_ARG1, 152 CALL_THIS_ARG2, 153 CALL_THIS_ARG3, 154 CALL_WITH_ARGV, 155 CALL_THIS_WITH_ARGV, 156 CALL_CONSTRUCTOR_WITH_ARGV, 157 SUPER_CALL_WITH_ARGV, 158 SUPER_CALL_SPREAD_WITH_ARGV, 159 DEPRECATED_CALL_ARG0, 160 DEPRECATED_CALL_ARG1, 161 DEPRECATED_CALL_ARG2, 162 DEPRECATED_CALL_ARG3, 163 DEPRECATED_CALL_WITH_ARGV, 164 DEPRECATED_CALL_THIS_WITH_ARGV, 165 DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV, 166 CALL_GETTER, 167 CALL_SETTER, 168 CALL_THIS_ARG3_WITH_RETURN, 169 CALL_THIS_ARGV_WITH_RETURN, 170 CALL_ENTRY, 171 CALL_GENERATOR, 172 CALL_FROM_AOT, 173 }; 174 175 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 176 struct OptimizedFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 177 base::AlignedPointer, 178 base::AlignedPointer, 179 base::AlignedPointer> { 180 public: 181 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 182 const RootBaseAndDerivedVisitor &derivedVisitor) const; 183 184 static size_t GetTypeOffset(bool isArch32 = false) 185 { 186 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 187 } 188 189 static size_t GetPrevOffset(bool isArch32 = false) 190 { 191 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 192 } 193 ComputeReservedSizeOptimizedFrame194 static size_t ComputeReservedSize(size_t slotSize) 195 { 196 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex); 197 return slotSize * slotOffset; 198 } 199 GetTypeOptimizedFrame200 FrameType GetType() const 201 { 202 return type; 203 } 204 private: 205 enum class Index : size_t { 206 TypeIndex = 0, 207 PrevFpIndex, 208 ReturnAddrIndex, 209 NumOfMembers 210 }; 211 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 212 GetFrameFromSpOptimizedFrame213 static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp) 214 { 215 return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp) - 216 MEMBER_OFFSET(OptimizedFrame, prevFp)); 217 } GetPrevFrameFpOptimizedFrame218 inline JSTaggedType* GetPrevFrameFp() 219 { 220 return prevFp; 221 } GetReturnAddrOptimizedFrame222 uintptr_t GetReturnAddr() const 223 { 224 return returnAddr; 225 } 226 227 alignas(EAS) FrameType type {0}; 228 alignas(EAS) JSTaggedType *prevFp {nullptr}; 229 alignas(EAS) uintptr_t returnAddr {0}; 230 friend class FrameIterator; 231 }; 232 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64); 233 234 struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 235 base::AlignedPointer, 236 base::AlignedPointer, 237 base::AlignedPointer> { 238 public: 239 static size_t GetTypeOffset(bool isArch32 = false) 240 { 241 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 242 } 243 244 static size_t GetPrevOffset(bool isArch32 = false) 245 { 246 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 247 } 248 GetCallSiteSpAsmBridgeFrame249 uintptr_t GetCallSiteSp() const 250 { 251 return ToUintPtr(this) + sizeof(AsmBridgeFrame); 252 } 253 GetTypeAsmBridgeFrame254 FrameType GetType() const 255 { 256 return type; 257 } 258 259 private: 260 enum class Index : size_t { 261 TypeIndex = 0, 262 PrevFpIndex, 263 ReturnAddrIndex, 264 NumOfMembers 265 }; 266 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 267 GetFrameFromSpAsmBridgeFrame268 static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 269 { 270 return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 271 MEMBER_OFFSET(AsmBridgeFrame, prevFp)); 272 } GetPrevFrameFpAsmBridgeFrame273 inline JSTaggedType* GetPrevFrameFp() 274 { 275 return prevFp; 276 } GetReturnAddrAsmBridgeFrame277 uintptr_t GetReturnAddr() const 278 { 279 return returnAddr; 280 } 281 alignas(EAS) FrameType type {0}; 282 alignas(EAS) JSTaggedType *prevFp {nullptr}; 283 alignas(EAS) uintptr_t returnAddr {0}; 284 friend class FrameIterator; 285 }; 286 STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64); 287 288 // * OptimizedUnfoldArgVFrame layout description as the following: 289 // sp ----> |--------------------------| --------------- 290 // | returnAddr | ^ 291 // currentFp--> |--------------------------| | 292 // | prevFp | | 293 // |--------------------------| OptimizedUnfoldArgVFrame 294 // | frameType | | 295 // |--------------------------| | 296 // | currentFp | v 297 // +--------------------------+ --------------- 298 // 299 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 300 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 301 base::AlignedPointer, 302 base::AlignedPointer, 303 base::AlignedPointer, 304 base::AlignedPointer> { 305 public: 306 static size_t GetTypeOffset(bool isArch32 = false) 307 { 308 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 309 } 310 311 static size_t GetPrevOffset(bool isArch32 = false) 312 { 313 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 314 } 315 GetTypeOptimizedJSFunctionUnfoldArgVFrame316 FrameType GetType() const 317 { 318 return type; 319 } 320 321 private: 322 enum class Index : size_t { 323 CallSiteSpIndex = 0, 324 TypeIndex, 325 PrevFpIndex, 326 ReturnAddrIndex, 327 NumOfMembers 328 }; 329 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 330 GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame331 static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp) 332 { 333 return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp) - 334 MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp)); 335 } GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame336 inline JSTaggedType* GetPrevFrameFp() const 337 { 338 return prevFp; 339 } GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame340 uintptr_t GetReturnAddr() const 341 { 342 return returnAddr; 343 } GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame344 uintptr_t GetPrevFrameSp() const 345 { 346 return callSiteSp; 347 } 348 alignas(EAS) uintptr_t callSiteSp {0}; 349 alignas(EAS) FrameType type {0}; 350 alignas(EAS) JSTaggedType *prevFp {nullptr}; 351 alignas(EAS) uintptr_t returnAddr {0}; 352 friend class FrameIterator; 353 }; 354 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame), 355 OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64); 356 357 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following: 358 // +--------------------------+ 359 // | arg[N-1] | 360 // +--------------------------+ 361 // | . . . . | 362 // +--------------------------+ 363 // | arg[0] | 364 // +--------------------------+ 365 // | argC | 366 // sp ---> +--------------------------+ ----------------- 367 // | | ^ 368 // | prevFP | | 369 // |--------------------------| OptimizedJSFunctionArgsConfigFrame 370 // | frameType | | 371 // | | V 372 // +--------------------------+ ----------------- 373 // 374 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 375 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 376 base::AlignedPointer, 377 base::AlignedPointer> { 378 public: 379 static size_t GetTypeOffset(bool isArch32 = false) 380 { 381 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 382 } 383 384 static size_t GetPrevOffset(bool isArch32 = false) 385 { 386 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 387 } 388 GetTypeOptimizedJSFunctionArgConfigFrame389 FrameType GetType() const 390 { 391 return type; 392 } 393 394 private: 395 enum class Index : size_t { 396 TypeIndex = 0, 397 PrevFpIndex, 398 NumOfMembers 399 }; 400 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 401 GetFrameFromSpOptimizedJSFunctionArgConfigFrame402 static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp) 403 { 404 return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp) - 405 MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp)); 406 } GetPrevFrameFpOptimizedJSFunctionArgConfigFrame407 inline JSTaggedType* GetPrevFrameFp() 408 { 409 return prevFp; 410 } 411 412 alignas(EAS) FrameType type {0}; 413 alignas(EAS) JSTaggedType *prevFp {nullptr}; 414 friend class FrameIterator; 415 }; 416 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame), 417 OptimizedJSFunctionArgConfigFrame::SizeArch32, 418 OptimizedJSFunctionArgConfigFrame::SizeArch64); 419 420 // * OptimizedJSFunctionFrame layout description as the following: 421 // +--------------------------+ 422 // | arg[N-1] | 423 // +--------------------------+ 424 // | ... | 425 // +--------------------------+ 426 // | arg[1] | 427 // +--------------------------+ 428 // | arg[0] | 429 // +--------------------------+ 430 // | this | 431 // +--------------------------+ 432 // | new-target | 433 // +--------------------------+ 434 // | call-target | 435 // |--------------------------| 436 // | argc | 437 // sp ----> |--------------------------| --------------- 438 // | returnAddr | ^ 439 // |--------------------------| | 440 // | callsiteFp | | 441 // |--------------------------| OptimizedJSFunctionFrame 442 // | frameType | | 443 // |--------------------------| | 444 // | call-target | v 445 // +--------------------------+ --------------- 446 // 447 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 448 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 449 JSTaggedValue, 450 base::AlignedPointer, 451 base::AlignedPointer, 452 base::AlignedPointer> { 453 public: 454 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 455 enum class Index : size_t { 456 JSFuncIndex = 0, 457 TypeIndex, 458 PrevFpIndex, 459 ReturnAddrIndex, 460 NumOfMembers 461 }; 462 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 463 GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame464 static constexpr size_t GetFunctionDeltaReturnAddr() 465 { 466 return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex); 467 } 468 GetPrevFrameFpOptimizedJSFunctionFrame469 inline JSTaggedType* GetPrevFrameFp() 470 { 471 return prevFp; 472 } 473 GetArgvOptimizedJSFunctionFrame474 JSTaggedType* GetArgv(uintptr_t *preFrameSp) const 475 { 476 return reinterpret_cast<JSTaggedType *>(preFrameSp + sizeof(uint64_t) / sizeof(uintptr_t)); 477 } 478 GetArgcOptimizedJSFunctionFrame479 size_t GetArgc(uintptr_t *preFrameSp) const 480 { 481 return *preFrameSp; 482 } 483 484 JSTaggedType* GetArgv(const FrameIterator &it) const; 485 GetReturnAddrOptimizedJSFunctionFrame486 uintptr_t GetReturnAddr() const 487 { 488 return returnAddr; 489 } 490 491 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 492 const RootBaseAndDerivedVisitor &derivedVisitor, FrameType frameType) const; 493 void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const; 494 GetFunctionOptimizedJSFunctionFrame495 inline JSTaggedValue GetFunction() const 496 { 497 return jsFunc; 498 } 499 ComputeArgsConfigFrameSpOptimizedJSFunctionFrame500 static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp) 501 { 502 const size_t offset = 2; // 2: skip prevFp and return address. 503 return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t); 504 } 505 506 static size_t GetTypeOffset(bool isArch32 = false) 507 { 508 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 509 } 510 511 static size_t GetPrevOffset(bool isArch32 = false) 512 { 513 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 514 } 515 516 static size_t GetFunctionOffset(bool isArch32 = false) 517 { 518 return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32); 519 } 520 ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame521 static size_t ComputeReservedJSFuncOffset(size_t slotSize) 522 { 523 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex); 524 return slotSize * slotOffset; 525 } 526 GetTypeOptimizedJSFunctionFrame527 FrameType GetType() const 528 { 529 return type; 530 } 531 532 friend class FrameIterator; 533 friend class FrameHandler; 534 void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const; 535 void GetFuncCalleeRegAndOffset( 536 const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const; 537 uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const; 538 539 private: GetFrameFromSpOptimizedJSFunctionFrame540 static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) 541 { 542 return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) - 543 MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp)); 544 } 545 546 // dynamic callee saveregisters for x86-64 547 alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()}; 548 alignas(EAS) FrameType type {0}; 549 alignas(EAS) JSTaggedType *prevFp {nullptr}; 550 alignas(EAS) uintptr_t returnAddr {0}; 551 // dynamic callee saveregisters for arm64 552 }; 553 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame), 554 OptimizedJSFunctionFrame::SizeArch32, 555 OptimizedJSFunctionFrame::SizeArch64); 556 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time. 557 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1); 558 559 // * The JSFunctionEntry Frame's structure is illustrated as the following: 560 // +--------------------------+ 561 // | . . . . . . | 562 // sp ---> +--------------------------+ ----------------- 563 // | prevFP | ^ 564 // |--------------------------| | 565 // | frameType | JSFunctionEntryFrame 566 // |--------------------------| | 567 // | preLeaveFrameFp | v 568 // +--------------------------+ ----------------- 569 570 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 571 base::AlignedPointer, 572 base::AlignedPointer, 573 base::AlignedPointer> { 574 public: 575 enum class CallType : size_t { 576 CALL_FUNC = 0, 577 CALL_NEW, 578 }; 579 580 enum class Index : size_t { 581 PreLeaveFrameFpIndex = 0, 582 TypeIndex, 583 PrevFpIndex, 584 NumOfMembers 585 }; 586 587 static size_t GetTypeOffset(bool isArch32 = false) 588 { 589 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 590 } 591 592 static size_t GetLeaveFrameFpOffset(bool isArch32 = false) 593 { 594 return GetOffset<static_cast<size_t>(Index::PreLeaveFrameFpIndex)>(isArch32); 595 } 596 GetPrevFrameFpOptimizedEntryFrame597 inline JSTaggedType* GetPrevFrameFp() 598 { 599 return preLeaveFrameFp; 600 } 601 ComputeReservedSizeOptimizedEntryFrame602 static size_t ComputeReservedSize(size_t slotSize) 603 { 604 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex); 605 return slotSize * slotOffset; 606 } 607 GetTypeOptimizedEntryFrame608 FrameType GetType() const 609 { 610 return type; 611 } 612 friend class FrameIterator; 613 614 private: GetFrameFromSpOptimizedEntryFrame615 static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 616 { 617 return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) - 618 MEMBER_OFFSET(OptimizedEntryFrame, prevFp)); 619 } 620 GetLeaveFpOptimizedEntryFrame621 JSTaggedType* GetLeaveFp() const 622 { 623 return preLeaveFrameFp; 624 } 625 GetPrevFpOptimizedEntryFrame626 JSTaggedType* GetPrevFp() const 627 { 628 return prevFp; 629 } 630 631 alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr}; 632 alignas(EAS) FrameType type {0}; 633 alignas(EAS) JSTaggedType *prevFp {nullptr}; 634 }; 635 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64); 636 637 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 638 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(), 639 base::AlignedPointer, 640 base::AlignedSize> { 641 enum class Index : size_t { 642 PrevIndex = 0, 643 TypeIndex, 644 NumOfMembers 645 }; 646 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 647 GetPrevFrameFpInterpretedFrameBase648 inline JSTaggedType* GetPrevFrameFp() 649 { 650 return prev; 651 } 652 GetFrameFromSpInterpretedFrameBase653 static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp) 654 { 655 return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1; 656 } 657 658 static size_t GetPrevOffset(bool isArch32 = false) 659 { 660 return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32); 661 } 662 663 static size_t GetTypeOffset(bool isArch32 = false) 664 { 665 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 666 } 667 GetSizeInterpretedFrameBase668 static constexpr size_t GetSize(bool isArch32) 669 { 670 return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64; 671 } 672 673 alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc 674 alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0 675 }; 676 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase), 677 InterpretedFrameBase::SizeArch32, 678 InterpretedFrameBase::SizeArch64); 679 680 // Interpreter Frame Layout as the following: 681 // +----------------------------------+ 682 // | argv[n-1] | 683 // |----------------------------------| 684 // | ...... | 685 // |----------------------------------| 686 // | thisArg [maybe not exist] | 687 // |----------------------------------| 688 // | newTarget [maybe not exist] | 689 // |----------------------------------| 690 // | ...... | 691 // |----------------------------------| 692 // | Vregs [not exist in native] | 693 // +----------------------------------+--------+ 694 // | base.frameType | ^ 695 // |----------------------------------| | 696 // | base.prev(prev stack pointer) | | 697 // |----------------------------------| | 698 // | pc(bytecode addr) | | 699 // |----------------------------------| | 700 // | sp(current stack pointer) | | 701 // |----------------------------------| | 702 // | env | | 703 // |----------------------------------| | 704 // | acc | | 705 // |----------------------------------| InterpretedFrame 706 // | profileTypeInfo | | 707 // |----------------------------------| | 708 // | thisObj | | 709 // |----------------------------------| | 710 // | function | | 711 // |----------------------------------| | 712 // | constpool | v 713 // +----------------------------------+--------+ 714 // 715 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 716 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 717 JSTaggedValue, 718 JSTaggedValue, 719 JSTaggedValue, 720 JSTaggedValue, 721 JSTaggedValue, 722 JSTaggedValue, 723 base::AlignedPointer, 724 InterpretedFrameBase> { 725 public: 726 enum class Index : size_t { 727 ConstPoolIndex = 0, 728 FunctionIndex, 729 ThisObjIndex, 730 ProFileTypeInfoIndex, 731 AccIndex, 732 EnvIndex, 733 PcIndex, 734 BaseIndex, 735 NumOfMembers 736 }; 737 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 738 GetPrevFrameFpInterpretedFrame739 inline JSTaggedType* GetPrevFrameFp() const 740 { 741 return base.prev; 742 } 743 GetFrameFromSpInterpretedFrame744 static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 745 { 746 return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 747 } 748 GetPcInterpretedFrame749 inline const uint8_t *GetPc() const 750 { 751 return pc; 752 } 753 GetEnvInterpretedFrame754 inline JSTaggedValue GetEnv() const 755 { 756 return env; 757 } 758 NumOfMembersInterpretedFrame759 static uint32_t NumOfMembers() 760 { 761 return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 762 } 763 GetPcOffsetInterpretedFrame764 static size_t GetPcOffset(bool isArch32) 765 { 766 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 767 } 768 769 static size_t GetTypeOffset(bool isArch32 = false) 770 { 771 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 772 InterpretedFrameBase::GetTypeOffset(isArch32); 773 } 774 775 static size_t GetPrevOffset(bool isArch32 = false) 776 { 777 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 778 InterpretedFrameBase::GetPrevOffset(isArch32); 779 } 780 781 static size_t GetFunctionOffset(bool isArch32 = false) 782 { 783 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 784 } 785 786 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 787 788 alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()}; 789 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 790 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 791 alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()}; 792 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 793 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 794 alignas(EAS) const uint8_t *pc {nullptr}; 795 alignas(EAS) InterpretedFrameBase base; 796 friend class FrameIterator; 797 }; 798 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64); 799 800 // * InterpretedBuiltinFrame layout description as the following: 801 // |--------------------------| --------------- 802 // | . . . . . | ^ 803 // | InterpretedFrameBase | | 804 // | . . . . . | | 805 // |--------------------------| InterpretedBuiltinFrame 806 // | bytecode-PC | | 807 // |--------------------------| | 808 // | call-target | v 809 // +--------------------------+ --------------- 810 // 811 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 812 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 813 JSTaggedValue, 814 base::AlignedPointer, 815 InterpretedFrameBase> { 816 enum class Index : size_t { 817 FunctionIndex = 0, 818 PcIndex, 819 BaseIndex, 820 NumOfMembers 821 }; 822 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 823 GetPrevFrameFpInterpretedBuiltinFrame824 inline JSTaggedType* GetPrevFrameFp() 825 { 826 return base.prev; 827 } 828 GetFrameFromSpInterpretedBuiltinFrame829 static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 830 { 831 return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 832 } 833 NumOfMembersInterpretedBuiltinFrame834 static uint32_t NumOfMembers() 835 { 836 return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize(); 837 } 838 839 static size_t GetTypeOffset(bool isArch32 = false) 840 { 841 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 842 InterpretedFrameBase::GetTypeOffset(isArch32); 843 } 844 845 static size_t GetPrevOffset(bool isArch32 = false) 846 { 847 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 848 InterpretedFrameBase::GetPrevOffset(isArch32); 849 } 850 851 static size_t GetFunctionOffset(bool isArch32 = false) 852 { 853 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 854 } 855 856 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 857 858 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 859 alignas(EAS) const uint8_t *pc {nullptr}; 860 alignas(EAS) InterpretedFrameBase base; 861 }; 862 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame), 863 InterpretedBuiltinFrame::SizeArch32, 864 InterpretedBuiltinFrame::SizeArch64); 865 866 // AsmInterpretedFrame Layout as the following: 867 // +----------------------------------+ 868 // | argv[n-1] | 869 // |----------------------------------| 870 // | ...... | 871 // |----------------------------------| 872 // | thisArg [maybe not exist] | 873 // |----------------------------------| 874 // | newTarget [maybe not exist] | 875 // |----------------------------------| 876 // | ...... | 877 // |----------------------------------| 878 // | Vregs [not exist in native] | 879 // +----------------------------------+--------+ 880 // | . . . . | ^ 881 // | InterpretedFrameBase | | 882 // | . . . . | | 883 // |----------------------------------| | 884 // | pc(bytecode addr) | | 885 // |----------------------------------| | 886 // | sp(current stack pointer) | | 887 // |----------------------------------| AsmInterpretedFrame 888 // | callSize | | 889 // |----------------------------------| | 890 // | env | | 891 // |----------------------------------| | 892 // | acc | | 893 // |----------------------------------| | 894 // | thisObj | | 895 // |----------------------------------| | 896 // | call-target | v 897 // +----------------------------------+--------+ 898 // 899 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 900 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 901 JSTaggedValue, 902 JSTaggedValue, 903 JSTaggedValue, 904 JSTaggedValue, 905 base::AlignedPointer, 906 base::AlignedPointer, 907 base::AlignedPointer, 908 InterpretedFrameBase> { 909 enum class Index : size_t { 910 FunctionIndex = 0, 911 ThisObjIndex, 912 AccIndex, 913 EnvIndex, 914 CallSizeIndex, 915 FpIndex, 916 PcIndex, 917 BaseIndex, 918 NumOfMembers 919 }; 920 921 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 922 GetCurrentFramePointerAsmInterpretedFrame923 inline JSTaggedType* GetCurrentFramePointer() 924 { 925 return fp; 926 } 927 GetPrevFrameFpAsmInterpretedFrame928 inline JSTaggedType* GetPrevFrameFp() 929 { 930 return base.prev; 931 } 932 GetFrameFromSpAsmInterpretedFrame933 static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 934 { 935 return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 936 } 937 GetFpOffsetAsmInterpretedFrame938 static size_t GetFpOffset(bool isArch32) 939 { 940 return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32); 941 } 942 GetCallSizeOffsetAsmInterpretedFrame943 static size_t GetCallSizeOffset(bool isArch32) 944 { 945 return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32); 946 } 947 GetFunctionOffsetAsmInterpretedFrame948 static size_t GetFunctionOffset(bool isArch32) 949 { 950 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 951 } 952 GetThisOffsetAsmInterpretedFrame953 static size_t GetThisOffset(bool isArch32) 954 { 955 return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32); 956 } 957 GetAccOffsetAsmInterpretedFrame958 static size_t GetAccOffset(bool isArch32) 959 { 960 return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32); 961 } 962 GetEnvOffsetAsmInterpretedFrame963 static size_t GetEnvOffset(bool isArch32) 964 { 965 return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32); 966 } 967 GetBaseOffsetAsmInterpretedFrame968 static size_t GetBaseOffset(bool isArch32) 969 { 970 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 971 } 972 GetPcOffsetAsmInterpretedFrame973 static size_t GetPcOffset(bool isArch32) 974 { 975 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 976 } 977 GetSizeAsmInterpretedFrame978 static constexpr size_t GetSize(bool isArch32) 979 { 980 return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64; 981 } 982 NumOfMembersAsmInterpretedFrame983 static uint32_t NumOfMembers() 984 { 985 return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 986 } 987 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 988 const RootBaseAndDerivedVisitor &derivedVisitor) const; 989 GetEnvAsmInterpretedFrame990 JSTaggedValue GetEnv() const 991 { 992 return env; 993 } 994 GetPcAsmInterpretedFrame995 const uint8_t *GetPc() const 996 { 997 return pc; 998 } 999 GetTypeOffsetAsmInterpretedFrame1000 static size_t GetTypeOffset() 1001 { 1002 return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type); 1003 } 1004 GetPrevOffsetAsmInterpretedFrame1005 static size_t GetPrevOffset() 1006 { 1007 return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev); 1008 } 1009 1010 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 1011 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 1012 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 1013 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 1014 alignas(EAS) uintptr_t callSize {0}; 1015 alignas(EAS) JSTaggedType *fp {nullptr}; 1016 alignas(EAS) const uint8_t *pc {nullptr}; 1017 alignas(EAS) InterpretedFrameBase base; 1018 // vregs, not exist in native 1019 // args, may be truncated if not extra 1020 }; 1021 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64); 1022 1023 // InterpretedEntryFrame Layout as the following: 1024 // +----------------------------------+--------------- 1025 // | . . . . | ^ 1026 // | InterpretedFrameBase | | 1027 // | . . . . | InterpretedEntryFrame 1028 // |----------------------------------| | 1029 // | pc(bytecode addr) | v 1030 // |----------------------------------|--------------- 1031 // 1032 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1033 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1034 base::AlignedPointer, 1035 InterpretedFrameBase> { 1036 enum class Index : size_t { 1037 PcIndex = 0, 1038 BaseIndex, 1039 NumOfMembers 1040 }; 1041 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1042 GetPrevFrameFpInterpretedEntryFrame1043 inline JSTaggedType* GetPrevFrameFp() 1044 { 1045 return base.prev; 1046 } 1047 GetFrameFromSpInterpretedEntryFrame1048 static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 1049 { 1050 return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1051 } 1052 NumOfMembersInterpretedEntryFrame1053 static uint32_t NumOfMembers() 1054 { 1055 return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize(); 1056 } 1057 1058 static size_t GetTypeOffset(bool isArch32 = false) 1059 { 1060 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1061 InterpretedFrameBase::GetTypeOffset(isArch32); 1062 } 1063 1064 static size_t GetPrevOffset(bool isArch32 = false) 1065 { 1066 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1067 InterpretedFrameBase::GetPrevOffset(isArch32); 1068 } 1069 1070 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, 1071 const RootRangeVisitor &rangeVisitor) const; 1072 alignas(EAS) const uint8_t *pc {nullptr}; 1073 alignas(EAS) InterpretedFrameBase base; 1074 }; 1075 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame), 1076 InterpretedEntryFrame::SizeArch32, 1077 InterpretedEntryFrame::SizeArch64); 1078 1079 1080 // AsmInterpretedEntryFrame Layout as the following: 1081 // +----------------------------------+--------------- 1082 // | . . . . | ^ 1083 // | InterpretedFrameBase | | 1084 // | . . . . | AsmInterpretedEntryFrame 1085 // |----------------------------------| | 1086 // | pc(bytecode addr) | v 1087 // |----------------------------------|--------------- 1088 // 1089 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1090 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1091 base::AlignedPointer, 1092 InterpretedFrameBase> { 1093 enum class Index : size_t { 1094 PcIndex = 0, 1095 BaseIndex, 1096 NumOfMembers 1097 }; 1098 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1099 GetPrevFrameFpAsmInterpretedEntryFrame1100 inline JSTaggedType* GetPrevFrameFp() 1101 { 1102 return base.prev; 1103 } 1104 GetBaseOffsetAsmInterpretedEntryFrame1105 static size_t GetBaseOffset(bool isArch32) 1106 { 1107 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 1108 } 1109 GetFrameFromSpAsmInterpretedEntryFrame1110 static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 1111 { 1112 return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1113 } 1114 1115 static size_t GetTypeOffset(bool isArch32 = false) 1116 { 1117 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1118 InterpretedFrameBase::GetTypeOffset(isArch32); 1119 } 1120 1121 static size_t GetPrevOffset(bool isArch32 = false) 1122 { 1123 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1124 InterpretedFrameBase::GetPrevOffset(isArch32); 1125 } 1126 1127 alignas(EAS) const uint8_t *pc {nullptr}; 1128 alignas(EAS) InterpretedFrameBase base; 1129 }; 1130 1131 // AsmInterpretedBridgeFrame Layout as the following: 1132 // +----------------------------------+--------------- 1133 // | ret-address | ^ 1134 // |----------------------------------| | 1135 // | . . . . | AsmInterpretedBridgeFrame 1136 // | AsmInterpretedEntryFrame | | 1137 // | . . . . | v 1138 // |----------------------------------|--------------- 1139 // 1140 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1141 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1142 AsmInterpretedEntryFrame, 1143 base::AlignedPointer> { 1144 enum class Index : size_t { 1145 EntryIndex = 0, 1146 ReturnAddrIndex, 1147 NumOfMembers 1148 }; 1149 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1150 GetFrameFromSpAsmInterpretedBridgeFrame1151 static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 1152 { 1153 return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 1154 MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr)); 1155 } GetCallSiteSpAsmInterpretedBridgeFrame1156 uintptr_t GetCallSiteSp() const 1157 { 1158 return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame); 1159 } GetPrevFrameFpAsmInterpretedBridgeFrame1160 inline JSTaggedType* GetPrevFrameFp() 1161 { 1162 return entry.base.prev; 1163 } 1164 GetReturnAddrOffsetAsmInterpretedBridgeFrame1165 static size_t GetReturnAddrOffset(bool isArch32) 1166 { 1167 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 1168 } 1169 GetSizeAsmInterpretedBridgeFrame1170 static constexpr size_t GetSize(bool isArch32) 1171 { 1172 return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64; 1173 } 1174 1175 static size_t GetTypeOffset(bool isArch32 = false) 1176 { 1177 return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) + 1178 AsmInterpretedEntryFrame::GetBaseOffset(isArch32) + 1179 InterpretedFrameBase::GetTypeOffset(isArch32); 1180 } 1181 static size_t GetPrevOffset(bool isArch32 = false) 1182 { 1183 return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) + 1184 AsmInterpretedEntryFrame::GetBaseOffset(isArch32) + 1185 InterpretedFrameBase::GetPrevOffset(isArch32); 1186 } 1187 GetReturnAddrAsmInterpretedBridgeFrame1188 uintptr_t GetReturnAddr() const 1189 { 1190 return returnAddr; 1191 } 1192 1193 AsmInterpretedEntryFrame entry; 1194 alignas(EAS) uintptr_t returnAddr; 1195 }; 1196 1197 // * Optimized-leaved-frame layout as the following: 1198 // +--------------------------+ 1199 // | argv[N-1] | 1200 // |--------------------------| 1201 // | . . . . . | 1202 // |--------------------------| 1203 // | argv[0] | 1204 // +--------------------------+------------- 1205 // | argc | ^ 1206 // |--------------------------| | 1207 // | RuntimeId | | 1208 // sp --> |--------------------------| OptimizedLeaveFrame 1209 // | ret-addr | | 1210 // |--------------------------| | 1211 // | prevFp | | 1212 // |--------------------------| | 1213 // | frameType | v 1214 // +--------------------------+------------- 1215 // 1216 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1217 struct OptimizedLeaveFrame { 1218 FrameType type; 1219 uintptr_t callsiteFp; // thread sp set here 1220 uintptr_t returnAddr; 1221 uint64_t argRuntimeId; 1222 uint64_t argc; 1223 1224 // argv[0]...argv[argc-1] dynamic according to agc GetFrameFromSpOptimizedLeaveFrame1225 static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1226 { 1227 return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1228 MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp)); 1229 } 1230 GetCallSiteSpOptimizedLeaveFrame1231 uintptr_t GetCallSiteSp() const 1232 { 1233 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId); 1234 } 1235 GetPrevFrameFpOptimizedLeaveFrame1236 inline JSTaggedType* GetPrevFrameFp() const 1237 { 1238 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1239 } 1240 GetReturnAddrOptimizedLeaveFrame1241 uintptr_t GetReturnAddr() const 1242 { 1243 return returnAddr; 1244 } 1245 GetTypeOffsetOptimizedLeaveFrame1246 static size_t GetTypeOffset() 1247 { 1248 return MEMBER_OFFSET(OptimizedLeaveFrame, type); 1249 } 1250 GetPrevOffsetOptimizedLeaveFrame1251 static size_t GetPrevOffset() 1252 { 1253 return MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp); 1254 } 1255 1256 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1257 }; 1258 1259 // * Optimized-leaved-frame-with-argv layout as the following: 1260 // +--------------------------+ 1261 // | argv[] | 1262 // +--------------------------+------------- 1263 // | argc | ^ 1264 // |--------------------------| | 1265 // | RuntimeId | OptimizedWithArgvLeaveFrame 1266 // sp --> |--------------------------| | 1267 // | returnAddr | | 1268 // |--------------------------| | 1269 // | callsiteFp | | 1270 // |--------------------------| | 1271 // | frameType | v 1272 // +--------------------------+------------- 1273 1274 struct OptimizedWithArgvLeaveFrame { 1275 FrameType type; 1276 uintptr_t callsiteFp; // thread sp set here 1277 uintptr_t returnAddr; 1278 uint64_t argRuntimeId; 1279 uint64_t argc; 1280 GetFrameFromSpOptimizedWithArgvLeaveFrame1281 static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1282 { 1283 return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1284 MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp)); 1285 } 1286 GetCallSiteSpOptimizedWithArgvLeaveFrame1287 uintptr_t GetCallSiteSp() const 1288 { 1289 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId); 1290 } 1291 GetPrevFrameFpOptimizedWithArgvLeaveFrame1292 inline JSTaggedType* GetPrevFrameFp() 1293 { 1294 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1295 } 1296 GetReturnAddrOptimizedWithArgvLeaveFrame1297 uintptr_t GetReturnAddr() const 1298 { 1299 return returnAddr; 1300 } 1301 GetTypeOffsetOptimizedWithArgvLeaveFrame1302 static size_t GetTypeOffset() 1303 { 1304 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type); 1305 } 1306 GetPrevOffsetOptimizedWithArgvLeaveFrame1307 static size_t GetPrevOffset() 1308 { 1309 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp); 1310 } 1311 1312 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1313 }; 1314 1315 // * OptimizedBuiltinLeaveFrame layout as the following: 1316 // +--------------------------+ 1317 // | argv[N-1] | 1318 // |--------------------------| 1319 // | . . . . . | 1320 // |--------------------------| 1321 // | argv[0] | 1322 // +--------------------------+------------- 1323 // | argc | ^ 1324 // |--------------------------| | 1325 // | thread | | 1326 // +--------------------------+ | 1327 // | ret-addr | | 1328 // sp --> |--------------------------| OptimizedBuiltinLeaveFrame 1329 // | prevFp | | 1330 // |--------------------------| | 1331 // | frameType | | 1332 // |--------------------------| | 1333 // | align byte | v 1334 // +--------------------------+------------- 1335 // 1336 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1337 struct OptimizedBuiltinLeaveFrame { 1338 public: GetFrameFromSpOptimizedBuiltinLeaveFrame1339 static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1340 { 1341 return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1342 MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp)); 1343 } 1344 GetCallSiteSpOptimizedBuiltinLeaveFrame1345 uintptr_t GetCallSiteSp() const 1346 { 1347 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argc); 1348 } 1349 GetPrevFrameFpOptimizedBuiltinLeaveFrame1350 inline JSTaggedType* GetPrevFrameFp() const 1351 { 1352 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1353 } 1354 GetReturnAddrOptimizedBuiltinLeaveFrame1355 uintptr_t GetReturnAddr() const 1356 { 1357 return returnAddr; 1358 } 1359 1360 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1361 GetTypeOffsetOptimizedBuiltinLeaveFrame1362 static size_t GetTypeOffset() 1363 { 1364 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type); 1365 } 1366 GetPrevOffsetOptimizedBuiltinLeaveFrame1367 static size_t GetPrevOffset() 1368 { 1369 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp); 1370 } 1371 GetFunctionOffsetOptimizedBuiltinLeaveFrame1372 static size_t GetFunctionOffset() 1373 { 1374 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argc) + 1; 1375 } 1376 GetArgvOptimizedBuiltinLeaveFrame1377 const JSTaggedType* GetArgv() const 1378 { 1379 return reinterpret_cast<const JSTaggedType *>(&argc + 1); 1380 } 1381 GetTypeOptimizedBuiltinLeaveFrame1382 FrameType GetType() const 1383 { 1384 return type; 1385 } 1386 1387 private: 1388 FrameType type; 1389 uintptr_t callsiteFp; // thread sp set here 1390 uintptr_t returnAddr; 1391 JSTaggedValue thread; 1392 uint64_t argc; 1393 // argv[0]...argv[argc-1] dynamic according to agc 1394 }; 1395 1396 // * BuiltinFrame layout as the following: 1397 // +--------------------------+ 1398 // | argV[N - 1] | 1399 // |--------------------------| 1400 // | . . . . | 1401 // |--------------------------+ 1402 // | argV[2]=this | 1403 // +--------------------------+ 1404 // | argV[1]=new-target | 1405 // +--------------------------+ 1406 // | argV[0]=call-target | 1407 // +--------------------------+ --------- 1408 // | argc | ^ 1409 // |--------------------------| | 1410 // | thread | | 1411 // |--------------------------| | 1412 // | returnAddr | BuiltinFrame 1413 // |--------------------------| | 1414 // | callsiteFp | | 1415 // |--------------------------| | 1416 // | frameType | v 1417 // +--------------------------+ --------- 1418 // 1419 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1420 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1421 base::AlignedSize, 1422 base::AlignedPointer, 1423 base::AlignedPointer, 1424 base::AlignedPointer, 1425 base::AlignedPointer, 1426 base::AlignedPointer> { 1427 enum class Index : size_t { 1428 TypeIndex = 0, 1429 PrevFpIndex, 1430 ReturnAddrIndex, 1431 ThreadIndex, 1432 NumArgsIndex, 1433 StackArgsIndex, 1434 NumOfMembers 1435 }; 1436 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1437 GetFrameFromSpBuiltinFrame1438 static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 1439 { 1440 return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) - 1441 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1442 } 1443 GetPrevFrameFpBuiltinFrame1444 inline JSTaggedType* GetPrevFrameFp() 1445 { 1446 return prevFp; 1447 } 1448 GetCallSiteSpBuiltinFrame1449 uintptr_t GetCallSiteSp() const 1450 { 1451 return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread); 1452 } 1453 GetPreFpOffsetBuiltinFrame1454 static size_t GetPreFpOffset(bool isArch32) 1455 { 1456 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1457 } 1458 GetNumArgsToFpDeltaBuiltinFrame1459 static size_t GetNumArgsToFpDelta(bool isArch32) 1460 { 1461 auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32); 1462 return offset - GetPreFpOffset(isArch32); 1463 } 1464 GetStackArgsToFpDeltaBuiltinFrame1465 static size_t GetStackArgsToFpDelta(bool isArch32) 1466 { 1467 auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 1468 return offset - GetPreFpOffset(isArch32); 1469 } 1470 GetStackArgsAddressBuiltinFrame1471 uintptr_t GetStackArgsAddress() 1472 { 1473 return reinterpret_cast<uintptr_t>(&stackArgs); 1474 } 1475 GetFunctionBuiltinFrame1476 JSTaggedValue GetFunction() 1477 { 1478 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1479 return JSTaggedValue(*functionAddress); 1480 } 1481 GetNumArgsBuiltinFrame1482 uint32_t GetNumArgs() 1483 { 1484 return numArgs; 1485 } 1486 GetReturnAddrBuiltinFrame1487 uintptr_t GetReturnAddr() const 1488 { 1489 return returnAddr; 1490 } 1491 1492 static size_t GetStackArgsOffset(bool isArch32 = false) 1493 { 1494 return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 1495 } 1496 1497 static size_t GetTypeOffset(bool isArch32 = false) 1498 { 1499 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1500 } 1501 1502 static size_t GetPrevOffset(bool isArch32 = false) 1503 { 1504 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1505 } 1506 1507 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1508 1509 alignas(EAS) FrameType type; 1510 alignas(EAS) JSTaggedType *prevFp; 1511 alignas(EAS) uintptr_t returnAddr; 1512 alignas(EAS) uintptr_t thread; 1513 alignas(EAS) uint32_t numArgs; 1514 alignas(EAS) uintptr_t stackArgs; 1515 }; 1516 1517 // * BuiltinWithArgvFrame layout as the following: 1518 // +--------------------------+ --------- 1519 // | . . . . . | ^ 1520 // |--------------------------| | 1521 // | returnAddr | | 1522 // |--------------------------| | 1523 // | callsiteFp | BuiltinWithArgvFrame 1524 // |--------------------------| | 1525 // | frameType | | 1526 // +--------------------------+ | 1527 // | argc | v 1528 // +--------------------------+ --------- 1529 // | argV[0] | 1530 // +--------------------------+ 1531 // | argV[1] | 1532 // +--------------------------+ 1533 // | . . . . | 1534 // +--------------------------+ 1535 // 1536 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1537 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1538 base::AlignedSize, 1539 base::AlignedPointer, 1540 base::AlignedPointer> { 1541 enum class Index : int { 1542 StackArgsTopIndex = -1, 1543 NumArgsIndex = -1, 1544 TypeIndex = 0, 1545 PrevFpIndex, 1546 ReturnAddrIndex, 1547 NumOfMembers 1548 }; 1549 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1550 GetFrameFromSpBuiltinWithArgvFrame1551 static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp) 1552 { 1553 return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) - 1554 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1555 } 1556 GetPrevFrameFpBuiltinWithArgvFrame1557 inline JSTaggedType* GetPrevFrameFp() 1558 { 1559 return prevFp; 1560 } 1561 GetCallSiteSpBuiltinWithArgvFrame1562 uintptr_t GetCallSiteSp() const 1563 { 1564 return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame); 1565 } 1566 GetStackArgsAddressBuiltinWithArgvFrame1567 uintptr_t GetStackArgsAddress() 1568 { 1569 auto topAddress = ToUintPtr(this) + 1570 (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t)); 1571 auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS; 1572 return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t); 1573 } 1574 GetFunctionBuiltinWithArgvFrame1575 JSTaggedValue GetFunction() 1576 { 1577 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1578 return JSTaggedValue(*functionAddress); 1579 } 1580 GetNumArgsBuiltinWithArgvFrame1581 int32_t GetNumArgs() 1582 { 1583 auto argcAddress = reinterpret_cast<int32_t *>( 1584 ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t))); 1585 return *argcAddress; 1586 } 1587 GetReturnAddrBuiltinWithArgvFrame1588 uintptr_t GetReturnAddr() const 1589 { 1590 return returnAddr; 1591 } 1592 1593 static size_t GetTypeOffset(bool isArch32 = false) 1594 { 1595 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1596 } 1597 1598 static size_t GetPrevOffset(bool isArch32 = false) 1599 { 1600 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1601 } 1602 1603 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1604 // argv(... this, new.target, function) 1605 // numargs 1606 alignas(EAS) FrameType type; 1607 alignas(EAS) JSTaggedType *prevFp; 1608 alignas(EAS) uintptr_t returnAddr; 1609 }; 1610 1611 enum class GCVisitedFlag : bool { 1612 VISITED = true, 1613 IGNORED = false, 1614 HYBRID_STACK = true, 1615 }; 1616 1617 class FrameIterator { 1618 public: 1619 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 1620 explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr); GetFrameType()1621 FrameType GetFrameType() const 1622 { 1623 ASSERT(current_ != nullptr); 1624 FrameType *typeAddr = reinterpret_cast<FrameType *>( 1625 reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType)); 1626 return *typeAddr; 1627 } 1628 1629 template<class T> GetFrame()1630 T* GetFrame() 1631 { 1632 return T::GetFrameFromSp(current_); 1633 } 1634 1635 template<class T> GetFrame()1636 const T* GetFrame() const 1637 { 1638 return T::GetFrameFromSp(current_); 1639 } 1640 Done()1641 bool Done() const 1642 { 1643 return current_ == nullptr; 1644 } GetSp()1645 JSTaggedType *GetSp() const 1646 { 1647 return current_; 1648 } GetSp()1649 JSTaggedType *GetSp() 1650 { 1651 return current_; 1652 } GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)1653 void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const 1654 { 1655 ret = calleeRegInfo_; 1656 } 1657 int ComputeDelta() const; 1658 template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED> 1659 void Advance(); 1660 std::map<uint32_t, uint32_t> GetInlinedMethodInfo(); 1661 uint32_t GetBytecodeOffset() const; 1662 uintptr_t GetPrevFrameCallSiteSp() const; 1663 uintptr_t GetPrevFrame() const; GetCallSiteSp()1664 uintptr_t GetCallSiteSp() const 1665 { 1666 return optimizedCallSiteSp_; 1667 } GetOptimizedReturnAddr()1668 uintptr_t GetOptimizedReturnAddr() const 1669 { 1670 return optimizedReturnAddr_; 1671 } GetThread()1672 const JSThread *GetThread() const 1673 { 1674 return thread_; 1675 } 1676 bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const; 1677 void CollectPcOffsetInfo(ConstInfo &info) const; 1678 void CollectMethodOffsetInfo(std::map<uint32_t, uint32_t> &info) const; 1679 void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const; 1680 std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const; 1681 int GetCallSiteDelta(uintptr_t retAddr) const; 1682 1683 Method *CheckAndGetMethod() const; 1684 JSTaggedValue GetFunction() const; 1685 IsLeaveFrame()1686 bool IsLeaveFrame() const 1687 { 1688 FrameType type = GetFrameType(); 1689 return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV); 1690 } 1691 IsOptimizedFrame()1692 bool IsOptimizedFrame() const 1693 { 1694 FrameType type = GetFrameType(); 1695 return (type == FrameType::OPTIMIZED_FRAME); 1696 } 1697 IsInterpretedFrame(FrameType type)1698 bool IsInterpretedFrame(FrameType type) const 1699 { 1700 return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST); 1701 } 1702 IsJSFrame()1703 bool IsJSFrame() const 1704 { 1705 FrameType type = GetFrameType(); 1706 return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type); 1707 } 1708 IsOptimizedJSFunctionFrame(FrameType type)1709 bool IsOptimizedJSFunctionFrame(FrameType type) const 1710 { 1711 return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || 1712 type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME; 1713 } 1714 IsOptimizedJSFunctionFrame()1715 bool IsOptimizedJSFunctionFrame() const 1716 { 1717 FrameType type = GetFrameType(); 1718 return IsOptimizedJSFunctionFrame(type); 1719 } 1720 1721 private: 1722 JSTaggedType *current_ {nullptr}; 1723 const JSThread *thread_ {nullptr}; 1724 const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr}; 1725 uintptr_t optimizedCallSiteSp_ {0}; 1726 uintptr_t optimizedReturnAddr_ {0}; 1727 uint8_t *stackMapAddr_ {nullptr}; 1728 int fpDeltaPrevFrameSp_ {0}; 1729 kungfu::CalleeRegAndOffsetVec calleeRegInfo_; 1730 }; 1731 } // namespace panda::ecmascript 1732 #endif // ECMASCRIPT_FRAMES_H 1733