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/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 static constexpr int64_t BASELINEJIT_PC_FLAG = static_cast<int64_t>(std::numeric_limits<uint64_t>::max()); 35 // Here list all scenarios of calling between Runtime/CInterpreter/ASMInterpreter/AOTCompiler/CBuiltin/ASMBuitlin. 36 // Please note that the "[]" means a must frame while "<>" means an optional frame. Each case is from top to down. 37 // 38 // * Runtime (C++) => CInterpreter: 39 // 1) [INTERPRETER_FRAME] 40 // 41 // * Runtime (C++) -> AOTCompiler: 42 // 1) [OPTIMIZED_ENTRY_FRAME] 43 // <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME> 44 // <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME> 45 // [OPTIMIZED_JS_FUNCTION_FRAME] 46 // 47 // * Runtime (C++) => ASMInterpreter: 48 // 1) [INTERPRETER_ENTRY_FRAME][ASM_INTERPRETER_FRAME] 49 // 50 // * Runtime (C++) => CBuiltin: 51 // 1) [not supported] 52 // 53 // * Runtime (C++) => ASMBuiltin: 54 // 1) [not supported] 55 // 56 // * CInterpreter => CInterpreter: 57 // 1) [INTERPRETER_FRAME] 58 // 59 // * CInterpreter => Runtime (C++): 60 // 1) [INTERPRETER_FAST_NEW_FRAME] 61 // 2) [INTERPRETER_CONSTRUCTOR_FRAME] 62 // 63 // * CInterpreter => AOTCompiler: 64 // 1) [not supported] 65 // 66 // * CInterperter => CBuiltin: 67 // 1) [INTERPRETER_BUILTIN_FRAME] 68 // 69 // * CInterpreter => ASMBuiltin: 70 // 1) [not supported] 71 // 72 // * ASMInterpreter => Runtime (C++): 73 // 1) [LEAVE_FRAME] 74 // 2) [LEAVE_FRAME_WITH_ARGV] 75 // 76 // * ASMInterpreter => AOTCompiler: 77 // 1) [OPTIMIZED_ENTRY_FRAME] 78 // <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME> 79 // <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME> 80 // [OPTIMIZED_JS_FUNCTION_FRAME] 81 // 82 // * ASMInterpreter => ASMInterpreter: 83 // 1) [ASM_INTERPRETER_FRAME] 84 // 85 // * ASMInterpreter => AsmBuiltin: 86 // 1) [BUILTIN_ENTRY_FRAME] 87 // [BUILTIN_FRAME] 88 // 2) [BUILTIN_ENTRY_FRAME] 89 // [BUILTIN_FRAME_WITH_ARGV] 90 // 91 // * ASMInterpreter => CBuiltin: 92 // 1) [LEAVE_FRAME] 93 // 2) [LEAVE_FRAME_WITH_ARGV] 94 // 95 // * AOTCompiler => Runtime (C++): 96 // 1) [LEAVE_FRAME] 97 // 2) [LEAVE_FRAME_WITH_ARGV] 98 // 99 // * AOTCompiler => ASMInterpreter: 100 // 1) [ASM_INTERPRETER_BRIDGE_FRAME] 101 // 2) [ASM_INTERPRETER_FRAME] 102 // 103 // * AOTCompiler => CBuiltin: 104 // 1) [LEAVE_FRAME] 105 // 2) [LEAVE_FRAME_WITH_ARGV] 106 // 107 // * AOTCompiler => ASMBuiltin: 108 // 1) [BUILTIN_ENTRY_FRAME] 109 // [BUILTIN_FRAME] 110 // 2) [BUILTIN_ENTRY_FRAME] 111 // [BUILTIN_FRAME_WITH_ARGV] 112 113 114 enum class FrameType: uintptr_t { 115 OPTIMIZED_FRAME = 0, 116 OPTIMIZED_ENTRY_FRAME, 117 OPTIMIZED_JS_FUNCTION_FRAME, 118 OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME, 119 FASTJIT_FUNCTION_FRAME, 120 FASTJIT_FAST_CALL_FUNCTION_FRAME, 121 ASM_BRIDGE_FRAME, 122 LEAVE_FRAME, 123 LEAVE_FRAME_WITH_ARGV, 124 BUILTIN_CALL_LEAVE_FRAME, 125 INTERPRETER_FRAME, 126 ASM_INTERPRETER_FRAME, 127 INTERPRETER_CONSTRUCTOR_FRAME, 128 BUILTIN_FRAME, 129 BUILTIN_FRAME_WITH_ARGV, 130 BUILTIN_ENTRY_FRAME, 131 INTERPRETER_BUILTIN_FRAME, 132 INTERPRETER_FAST_NEW_FRAME, 133 INTERPRETER_ENTRY_FRAME, 134 ASM_INTERPRETER_ENTRY_FRAME, 135 ASM_INTERPRETER_BRIDGE_FRAME, 136 OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME, 137 OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, 138 BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME, 139 BASELINE_BUILTIN_FRAME, 140 141 FRAME_TYPE_FIRST = OPTIMIZED_FRAME, 142 FRAME_TYPE_LAST = OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, 143 INTERPRETER_FIRST = INTERPRETER_FRAME, 144 INTERPRETER_LAST = INTERPRETER_FAST_NEW_FRAME, 145 BUILTIN_FIRST = BUILTIN_FRAME, 146 BUILTIN_LAST = BUILTIN_ENTRY_FRAME, 147 }; 148 149 enum class JSCallMode : uintptr_t { 150 CALL_ARG0 = 0, 151 CALL_ARG1, 152 CALL_ARG2, 153 CALL_ARG3, 154 CALL_THIS_ARG0, 155 CALL_THIS_ARG1, 156 CALL_THIS_ARG2, 157 CALL_THIS_ARG3, 158 CALL_WITH_ARGV, 159 CALL_THIS_WITH_ARGV, 160 CALL_CONSTRUCTOR_WITH_ARGV, 161 SUPER_CALL_WITH_ARGV, 162 SUPER_CALL_SPREAD_WITH_ARGV, 163 DEPRECATED_CALL_ARG0, 164 DEPRECATED_CALL_ARG1, 165 DEPRECATED_CALL_ARG2, 166 DEPRECATED_CALL_ARG3, 167 DEPRECATED_CALL_WITH_ARGV, 168 DEPRECATED_CALL_THIS_WITH_ARGV, 169 DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV, 170 CALL_GETTER, 171 CALL_SETTER, 172 CALL_THIS_ARG2_WITH_RETURN, 173 CALL_THIS_ARG3_WITH_RETURN, 174 CALL_THIS_ARGV_WITH_RETURN, 175 CALL_ENTRY, 176 CALL_GENERATOR, 177 CALL_FROM_AOT, 178 }; 179 180 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 181 struct OptimizedFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 182 base::AlignedPointer, 183 base::AlignedPointer, 184 base::AlignedPointer> { 185 public: 186 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 187 188 static size_t GetTypeOffset(bool isArch32 = false) 189 { 190 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 191 } 192 193 static size_t GetPrevOffset(bool isArch32 = false) 194 { 195 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 196 } 197 198 static size_t GetReturnAddrOffset(bool isArch32 = false) 199 { 200 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 201 } 202 ComputeReservedSizeOptimizedFrame203 static size_t ComputeReservedSize(size_t slotSize) 204 { 205 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex); 206 return slotSize * slotOffset; 207 } 208 GetTypeOptimizedFrame209 FrameType GetType() const 210 { 211 return type; 212 } 213 214 private: 215 enum class Index : size_t { 216 TypeIndex = 0, 217 PrevFpIndex, 218 ReturnAddrIndex, 219 NumOfMembers 220 }; 221 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 222 GetFrameFromSpOptimizedFrame223 static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp) 224 { 225 return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp) - 226 MEMBER_OFFSET(OptimizedFrame, prevFp)); 227 } GetPrevFrameFpOptimizedFrame228 inline JSTaggedType* GetPrevFrameFp() 229 { 230 return prevFp; 231 } GetReturnAddrOptimizedFrame232 uintptr_t GetReturnAddr() const 233 { 234 return returnAddr; 235 } 236 GetReturnAddrAddressOptimizedFrame237 const uintptr_t *GetReturnAddrAddress() const 238 { 239 return &returnAddr; 240 } 241 242 alignas(EAS) FrameType type {0}; 243 alignas(EAS) JSTaggedType *prevFp {nullptr}; 244 alignas(EAS) uintptr_t returnAddr {0}; 245 friend class FrameIterator; 246 }; 247 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64); 248 249 // * BaselineBuiltinFrame layout as the following: 250 // +--------------------------+ --------- 251 // | . . . . . | ^ 252 // callerSP ---> |--------------------------| | 253 // | returnAddr | | 254 // |--------------------------| BuiltinBuiltinFrame 255 // | callsiteFp | | 256 // fp ---> |--------------------------| | 257 // | frameType | v 258 // +--------------------------+ --------- 259 // | . . . . | 260 // calleeSP ---> +--------------------------+ 261 // 262 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 263 struct BaselineBuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 264 base::AlignedPointer, 265 base::AlignedPointer, 266 base::AlignedPointer> { 267 public: 268 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 269 270 static size_t GetTypeOffset(bool isArch32 = false) 271 { 272 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 273 } 274 275 static size_t GetPrevOffset(bool isArch32 = false) 276 { 277 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 278 } 279 280 static size_t GetReturnAddrOffset(bool isArch32 = false) 281 { 282 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 283 } 284 ComputeReservedSizeBaselineBuiltinFrame285 static size_t ComputeReservedSize(size_t slotSize) 286 { 287 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex); 288 return slotSize * slotOffset; 289 } 290 GetTypeBaselineBuiltinFrame291 FrameType GetType() const 292 { 293 return type; 294 } 295 GetReturnAddrBaselineBuiltinFrame296 uintptr_t GetReturnAddr() const 297 { 298 return returnAddr; 299 } 300 GetReturnAddrAddressBaselineBuiltinFrame301 const uintptr_t *GetReturnAddrAddress() const 302 { 303 return &returnAddr; 304 } 305 private: 306 enum class Index : size_t { 307 TypeIndex = 0, 308 PrevFpIndex, 309 ReturnAddrIndex, 310 NumOfMembers 311 }; 312 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 313 GetFrameFromSpBaselineBuiltinFrame314 static BaselineBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 315 { 316 return reinterpret_cast<BaselineBuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) - 317 MEMBER_OFFSET(BaselineBuiltinFrame, prevFp)); 318 } GetPrevFrameFpBaselineBuiltinFrame319 inline JSTaggedType* GetPrevFrameFp() 320 { 321 return prevFp; 322 } 323 324 alignas(EAS) FrameType type {0}; 325 alignas(EAS) JSTaggedType *prevFp {nullptr}; 326 alignas(EAS) uintptr_t returnAddr {0}; 327 friend class FrameIterator; 328 }; 329 STATIC_ASSERT_EQ_ARCH(sizeof(BaselineBuiltinFrame), BaselineBuiltinFrame::SizeArch32, BaselineBuiltinFrame::SizeArch64); 330 331 struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 332 base::AlignedPointer, 333 base::AlignedPointer, 334 base::AlignedPointer> { 335 public: 336 static size_t GetTypeOffset(bool isArch32 = false) 337 { 338 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 339 } 340 341 static size_t GetPrevOffset(bool isArch32 = false) 342 { 343 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 344 } 345 346 static size_t GetReturnAddrOffset(bool isArch32 = false) 347 { 348 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 349 } 350 GetCallSiteSpAsmBridgeFrame351 uintptr_t GetCallSiteSp() const 352 { 353 return ToUintPtr(this) + sizeof(AsmBridgeFrame); 354 } 355 GetTypeAsmBridgeFrame356 FrameType GetType() const 357 { 358 return type; 359 } 360 361 private: 362 enum class Index : size_t { 363 TypeIndex = 0, 364 PrevFpIndex, 365 ReturnAddrIndex, 366 NumOfMembers 367 }; 368 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 369 GetFrameFromSpAsmBridgeFrame370 static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 371 { 372 return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 373 MEMBER_OFFSET(AsmBridgeFrame, prevFp)); 374 } GetPrevFrameFpAsmBridgeFrame375 inline JSTaggedType* GetPrevFrameFp() 376 { 377 return prevFp; 378 } 379 GetReturnAddrAsmBridgeFrame380 uintptr_t GetReturnAddr() const 381 { 382 return returnAddr; 383 } 384 GetReturnAddrAddressAsmBridgeFrame385 const uintptr_t *GetReturnAddrAddress() const 386 { 387 return &returnAddr; 388 } 389 390 alignas(EAS) FrameType type {0}; 391 alignas(EAS) JSTaggedType *prevFp {nullptr}; 392 alignas(EAS) uintptr_t returnAddr {0}; 393 friend class FrameIterator; 394 }; 395 STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64); 396 397 // * OptimizedUnfoldArgVFrame layout description as the following: 398 // callerSP ---> |--------------------------| --------------- 399 // | returnAddr | ^ 400 // |--------------------------| | 401 // | prevFp | | 402 // fp ---> |--------------------------| OptimizedUnfoldArgVFrame 403 // | frameType | | 404 // |--------------------------| | 405 // | currentFp | v 406 // calleESP ---> +--------------------------+ --------------- 407 // 408 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 409 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 410 base::AlignedPointer, 411 base::AlignedPointer, 412 base::AlignedPointer, 413 base::AlignedPointer> { 414 public: 415 static size_t GetTypeOffset(bool isArch32 = false) 416 { 417 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 418 } 419 420 static size_t GetPrevOffset(bool isArch32 = false) 421 { 422 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 423 } 424 425 static size_t GetReturnAddrOffset(bool isArch32 = false) 426 { 427 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 428 } 429 GetTypeOptimizedJSFunctionUnfoldArgVFrame430 FrameType GetType() const 431 { 432 return type; 433 } 434 435 private: 436 enum class Index : size_t { 437 CallSiteSpIndex = 0, 438 TypeIndex, 439 PrevFpIndex, 440 ReturnAddrIndex, 441 NumOfMembers 442 }; 443 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 444 GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame445 static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp) 446 { 447 return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp) - 448 MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp)); 449 } GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame450 inline JSTaggedType* GetPrevFrameFp() const 451 { 452 return prevFp; 453 } 454 GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame455 uintptr_t GetReturnAddr() const 456 { 457 return returnAddr; 458 } 459 GetReturnAddrAddressOptimizedJSFunctionUnfoldArgVFrame460 const uintptr_t *GetReturnAddrAddress() const 461 { 462 return &returnAddr; 463 } 464 GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame465 uintptr_t GetPrevFrameSp() const 466 { 467 return callSiteSp; 468 } 469 470 alignas(EAS) uintptr_t callSiteSp {0}; 471 alignas(EAS) FrameType type {0}; 472 alignas(EAS) JSTaggedType *prevFp {nullptr}; 473 alignas(EAS) uintptr_t returnAddr {0}; 474 friend class FrameIterator; 475 }; 476 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame), 477 OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64); 478 479 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following: 480 // +--------------------------+ 481 // | arg[N-1] | 482 // +--------------------------+ 483 // | . . . . | 484 // +--------------------------+ 485 // | arg[0] | 486 // +--------------------------+ 487 // | argC | 488 // sp ---> +--------------------------+ ----------------- 489 // | | ^ 490 // | prevFP | | 491 // fp ---> |--------------------------| OptimizedJSFunctionArgsConfigFrame 492 // | frameType | | 493 // | | V 494 // +--------------------------+ ----------------- 495 // 496 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 497 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 498 base::AlignedPointer, 499 base::AlignedPointer> { 500 public: 501 static size_t GetTypeOffset(bool isArch32 = false) 502 { 503 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 504 } 505 506 static size_t GetPrevOffset(bool isArch32 = false) 507 { 508 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 509 } 510 GetTypeOptimizedJSFunctionArgConfigFrame511 FrameType GetType() const 512 { 513 return type; 514 } 515 516 private: 517 enum class Index : size_t { 518 TypeIndex = 0, 519 PrevFpIndex, 520 NumOfMembers 521 }; 522 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 523 GetFrameFromSpOptimizedJSFunctionArgConfigFrame524 static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp) 525 { 526 return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp) - 527 MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp)); 528 } GetPrevFrameFpOptimizedJSFunctionArgConfigFrame529 inline JSTaggedType* GetPrevFrameFp() 530 { 531 return prevFp; 532 } 533 534 alignas(EAS) FrameType type {0}; 535 alignas(EAS) JSTaggedType *prevFp {nullptr}; 536 friend class FrameIterator; 537 }; 538 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame), 539 OptimizedJSFunctionArgConfigFrame::SizeArch32, 540 OptimizedJSFunctionArgConfigFrame::SizeArch64); 541 542 // * OptimizedJSFunctionFrame layout description as the following: 543 // +----------------------------------------+ 544 // | arg[N-1] | 545 // +----------------------------------------+ 546 // | ... | 547 // +----------------------------------------+ 548 // | arg[1] | 549 // +----------------------------------------+ 550 // | arg[0] | 551 // +----------------------------------------+ 552 // | this | 553 // +----------------------------------------+ 554 // | new-target [not exist in fastcall] | 555 // +----------------------------------------+ 556 // | call-target | 557 // argv ---> +----------------------------------------+ 558 // | argv [not exist in fastcall] | 559 // |----------------------------------------| 560 // | argc [not exist in fastcall] | 561 // callerSp ---> |----------------------------------------|---------------- 562 // | returnAddr | ^ 563 // |----------------------------------------| | 564 // | callsiteFp | | 565 // fp ---> |----------------------------------------| OptimizedJSFunctionFrame 566 // | frameType | | 567 // |----------------------------------------| | 568 // | call-target | v 569 // calleeSP ---> +----------------------------------------+---------------- 570 // 571 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 572 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 573 JSTaggedValue, 574 base::AlignedPointer, 575 base::AlignedPointer, 576 base::AlignedPointer> { 577 public: 578 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 579 enum class Index : size_t { 580 JSFuncIndex = 0, 581 TypeIndex, 582 PrevFpIndex, 583 ReturnAddrIndex, 584 NumOfMembers 585 }; 586 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 587 GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame588 static constexpr size_t GetFunctionDeltaReturnAddr() 589 { 590 return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex); 591 } 592 GetPrevFrameFpOptimizedJSFunctionFrame593 inline JSTaggedType* GetPrevFrameFp() 594 { 595 return prevFp; 596 } 597 GetArgvOptimizedJSFunctionFrame598 JSTaggedType* GetArgv(uintptr_t *preFrameSp) const 599 { 600 const size_t offset = 2; // 2: skip argc and argv. 601 return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t)); 602 } 603 GetArgcOptimizedJSFunctionFrame604 size_t GetArgc(uintptr_t *preFrameSp) const 605 { 606 return *preFrameSp; 607 } 608 609 JSTaggedType* GetArgv(const FrameIterator &it) const; 610 GetReturnAddrOptimizedJSFunctionFrame611 uintptr_t GetReturnAddr() const 612 { 613 return returnAddr; 614 } 615 GetReturnAddrAddressOptimizedJSFunctionFrame616 const uintptr_t *GetReturnAddrAddress() const 617 { 618 return &returnAddr; 619 } 620 621 void GCIterate(const FrameIterator &it, RootVisitor &visitor, FrameType frameType) const; 622 GetFunctionOptimizedJSFunctionFrame623 inline JSTaggedValue GetFunction() const 624 { 625 return jsFunc; 626 } 627 ComputeArgsConfigFrameSpOptimizedJSFunctionFrame628 static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp) 629 { 630 const size_t offset = 2; // 2: skip prevFp and return address. 631 return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t); 632 } 633 634 static size_t GetTypeOffset(bool isArch32 = false) 635 { 636 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 637 } 638 639 static size_t GetPrevOffset(bool isArch32 = false) 640 { 641 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 642 } 643 644 static size_t GetFunctionOffset(bool isArch32 = false) 645 { 646 return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32); 647 } 648 649 static size_t GetReturnAddrOffset(bool isArch32 = false) 650 { 651 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 652 } 653 ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame654 static size_t ComputeReservedJSFuncOffset(size_t slotSize) 655 { 656 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex); 657 return slotSize * slotOffset; 658 } 659 GetFrmaeTypeToFpDeltaOptimizedJSFunctionFrame660 static int GetFrmaeTypeToFpDelta() 661 { 662 return -(int)sizeof(uintptr_t); 663 } 664 GetFunctionToFpDeltaOptimizedJSFunctionFrame665 static int GetFunctionToFpDelta() 666 { 667 int slotOffset = static_cast<int>(Index::JSFuncIndex) - static_cast<int>(Index::TypeIndex); 668 return slotOffset * static_cast<int>(JSTaggedValue::TaggedTypeSize()) + GetFrmaeTypeToFpDelta(); 669 } 670 GetTypeOptimizedJSFunctionFrame671 FrameType GetType() const 672 { 673 return type; 674 } 675 676 friend class FrameIterator; 677 friend class FrameHandler; 678 void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const; 679 void GetFuncCalleeRegAndOffset( 680 const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const; 681 uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const; 682 683 private: GetFrameFromSpOptimizedJSFunctionFrame684 static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) 685 { 686 return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) - 687 MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp)); 688 } 689 690 // dynamic callee saveregisters for x86-64 691 alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()}; 692 alignas(EAS) FrameType type {0}; 693 alignas(EAS) JSTaggedType *prevFp {nullptr}; 694 alignas(EAS) uintptr_t returnAddr {0}; 695 // dynamic callee saveregisters for arm64 696 }; 697 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame), 698 OptimizedJSFunctionFrame::SizeArch32, 699 OptimizedJSFunctionFrame::SizeArch64); 700 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time. 701 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1); 702 703 // * The JSFunctionEntry Frame's structure is illustrated as the following: 704 // +--------------------------+ 705 // | . . . . . . | 706 // callerSP --> +--------------------------+ ----------------- 707 // | prevFP | ^ 708 // fp --> |--------------------------| | 709 // | frameType | JSFunctionEntryFrame 710 // |--------------------------| | 711 // | preLeaveFrameFp | v 712 // calleeSP --> +--------------------------+ ----------------- 713 714 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 715 base::AlignedPointer, 716 base::AlignedPointer, 717 base::AlignedPointer> { 718 public: 719 enum class CallType : size_t { 720 CALL_FUNC = 0, 721 CALL_NEW, 722 }; 723 724 enum class Index : size_t { 725 PreLeaveFrameFpIndex = 0, 726 TypeIndex, 727 PrevFpIndex, 728 NumOfMembers 729 }; 730 731 static size_t GetTypeOffset(bool isArch32 = false) 732 { 733 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 734 } 735 736 static size_t GetLeaveFrameFpOffset(bool isArch32 = false) 737 { 738 return GetOffset<static_cast<size_t>(Index::PreLeaveFrameFpIndex)>(isArch32); 739 } 740 GetPrevFrameFpOptimizedEntryFrame741 inline JSTaggedType* GetPrevFrameFp() 742 { 743 return preLeaveFrameFp; 744 } 745 ComputeReservedSizeOptimizedEntryFrame746 static size_t ComputeReservedSize(size_t slotSize) 747 { 748 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex); 749 return slotSize * slotOffset; 750 } 751 GetTypeOptimizedEntryFrame752 FrameType GetType() const 753 { 754 return type; 755 } 756 friend class FrameIterator; 757 758 private: GetFrameFromSpOptimizedEntryFrame759 static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 760 { 761 return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) - 762 MEMBER_OFFSET(OptimizedEntryFrame, prevFp)); 763 } 764 GetLeaveFpOptimizedEntryFrame765 JSTaggedType* GetLeaveFp() const 766 { 767 return preLeaveFrameFp; 768 } 769 GetPrevFpOptimizedEntryFrame770 JSTaggedType* GetPrevFp() const 771 { 772 return prevFp; 773 } 774 775 alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr}; 776 alignas(EAS) FrameType type {0}; 777 alignas(EAS) JSTaggedType *prevFp {nullptr}; 778 }; 779 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64); 780 781 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 782 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(), 783 base::AlignedPointer, 784 base::AlignedSize> { 785 enum class Index : size_t { 786 PrevIndex = 0, 787 TypeIndex, 788 NumOfMembers 789 }; 790 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 791 GetPrevFrameFpInterpretedFrameBase792 inline JSTaggedType* GetPrevFrameFp() 793 { 794 return prev; 795 } 796 GetFrameFromSpInterpretedFrameBase797 static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp) 798 { 799 return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1; 800 } 801 802 static size_t GetPrevOffset(bool isArch32 = false) 803 { 804 return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32); 805 } 806 807 static size_t GetTypeOffset(bool isArch32 = false) 808 { 809 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 810 } 811 GetSizeInterpretedFrameBase812 static constexpr size_t GetSize(bool isArch32) 813 { 814 return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64; 815 } 816 817 alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc 818 alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0 819 }; 820 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase), 821 InterpretedFrameBase::SizeArch32, 822 InterpretedFrameBase::SizeArch64); 823 824 // Interpreter Frame Layout as the following: 825 // +----------------------------------+ 826 // | argv[n-1] | 827 // |----------------------------------| 828 // | ...... | 829 // |----------------------------------| 830 // | thisArg [maybe not exist] | 831 // |----------------------------------| 832 // | newTarget [maybe not exist] | 833 // |----------------------------------| 834 // | ...... | 835 // |----------------------------------| 836 // | Vregs [not exist in native] | 837 // +----------------------------------+--------+ 838 // | base.frameType | ^ 839 // |----------------------------------| | 840 // | base.prev(prev stack pointer) | | 841 // |----------------------------------| | 842 // | pc(bytecode addr) | | 843 // |----------------------------------| | 844 // | sp(current stack pointer) | | 845 // |----------------------------------| | 846 // | env | | 847 // |----------------------------------| | 848 // | acc | | 849 // |----------------------------------| InterpretedFrame 850 // | profileTypeInfo | | 851 // |----------------------------------| | 852 // | thisObj | | 853 // |----------------------------------| | 854 // | function | | 855 // |----------------------------------| | 856 // | constpool | v 857 // +----------------------------------+--------+ 858 // 859 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 860 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 861 JSTaggedValue, 862 JSTaggedValue, 863 JSTaggedValue, 864 JSTaggedValue, 865 JSTaggedValue, 866 JSTaggedValue, 867 base::AlignedPointer, 868 InterpretedFrameBase> { 869 public: 870 enum class Index : size_t { 871 ConstPoolIndex = 0, 872 FunctionIndex, 873 ThisObjIndex, 874 ProFileTypeInfoIndex, 875 AccIndex, 876 EnvIndex, 877 PcIndex, 878 BaseIndex, 879 NumOfMembers 880 }; 881 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 882 GetPrevFrameFpInterpretedFrame883 inline JSTaggedType* GetPrevFrameFp() const 884 { 885 return base.prev; 886 } 887 GetFrameFromSpInterpretedFrame888 static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 889 { 890 return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 891 } 892 GetPcInterpretedFrame893 inline const uint8_t *GetPc() const 894 { 895 return pc; 896 } 897 GetEnvInterpretedFrame898 inline JSTaggedValue GetEnv() const 899 { 900 return env; 901 } 902 NumOfMembersInterpretedFrame903 static uint32_t NumOfMembers() 904 { 905 return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 906 } 907 GetPcOffsetInterpretedFrame908 static size_t GetPcOffset(bool isArch32) 909 { 910 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 911 } 912 913 static size_t GetTypeOffset(bool isArch32 = false) 914 { 915 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 916 InterpretedFrameBase::GetTypeOffset(isArch32); 917 } 918 919 static size_t GetPrevOffset(bool isArch32 = false) 920 { 921 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 922 InterpretedFrameBase::GetPrevOffset(isArch32); 923 } 924 925 static size_t GetFunctionOffset(bool isArch32 = false) 926 { 927 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 928 } 929 930 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 931 932 alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()}; 933 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 934 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 935 alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()}; 936 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 937 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 938 alignas(EAS) const uint8_t *pc {nullptr}; 939 alignas(EAS) InterpretedFrameBase base; 940 friend class FrameIterator; 941 }; 942 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64); 943 944 // * InterpretedBuiltinFrame layout description as the following: 945 // |--------------------------| --------------- 946 // | . . . . . | ^ 947 // | InterpretedFrameBase | | 948 // | . . . . . | | 949 // |--------------------------| InterpretedBuiltinFrame 950 // | bytecode-PC | | 951 // |--------------------------| | 952 // | call-target | v 953 // +--------------------------+ --------------- 954 // 955 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 956 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 957 JSTaggedValue, 958 base::AlignedPointer, 959 InterpretedFrameBase> { 960 enum class Index : size_t { 961 FunctionIndex = 0, 962 PcIndex, 963 BaseIndex, 964 NumOfMembers 965 }; 966 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 967 GetPrevFrameFpInterpretedBuiltinFrame968 inline JSTaggedType* GetPrevFrameFp() 969 { 970 return base.prev; 971 } 972 GetFrameFromSpInterpretedBuiltinFrame973 static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 974 { 975 return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 976 } 977 NumOfMembersInterpretedBuiltinFrame978 static uint32_t NumOfMembers() 979 { 980 return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize(); 981 } 982 983 static size_t GetTypeOffset(bool isArch32 = false) 984 { 985 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 986 InterpretedFrameBase::GetTypeOffset(isArch32); 987 } 988 989 static size_t GetPrevOffset(bool isArch32 = false) 990 { 991 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 992 InterpretedFrameBase::GetPrevOffset(isArch32); 993 } 994 995 static size_t GetFunctionOffset(bool isArch32 = false) 996 { 997 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 998 } 999 1000 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1001 1002 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 1003 alignas(EAS) const uint8_t *pc {nullptr}; 1004 alignas(EAS) InterpretedFrameBase base; 1005 }; 1006 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame), 1007 InterpretedBuiltinFrame::SizeArch32, 1008 InterpretedBuiltinFrame::SizeArch64); 1009 1010 // AsmInterpretedFrame Layout as the following: 1011 // +----------------------------------+ 1012 // | argv[n-1] | 1013 // |----------------------------------| 1014 // | ...... | 1015 // |----------------------------------| 1016 // | thisArg [maybe not exist] | 1017 // |----------------------------------| 1018 // | newTarget [maybe not exist] | 1019 // |----------------------------------| 1020 // | ...... | 1021 // |----------------------------------| 1022 // | Vregs [not exist in native] | 1023 // +----------------------------------+--------+ 1024 // | . . . . | ^ 1025 // | InterpretedFrameBase | | 1026 // | . . . . | | 1027 // |----------------------------------| | 1028 // | pc(bytecode addr) | | 1029 // |----------------------------------| | 1030 // | sp(current stack pointer) | | 1031 // |----------------------------------| AsmInterpretedFrame 1032 // | callSize | | 1033 // |----------------------------------| | 1034 // | env | | 1035 // |----------------------------------| | 1036 // | acc | | 1037 // |----------------------------------| | 1038 // | thisObj | | 1039 // |----------------------------------| | 1040 // | call-target | v 1041 // +----------------------------------+--------+ 1042 // 1043 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1044 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1045 JSTaggedValue, 1046 JSTaggedValue, 1047 JSTaggedValue, 1048 JSTaggedValue, 1049 base::AlignedPointer, 1050 base::AlignedPointer, 1051 base::AlignedPointer, 1052 InterpretedFrameBase> { 1053 enum class Index : size_t { 1054 FunctionIndex = 0, 1055 ThisObjIndex, 1056 AccIndex, 1057 EnvIndex, 1058 CallSizeIndex, 1059 FpIndex, 1060 PcIndex, 1061 BaseIndex, 1062 NumOfMembers 1063 }; 1064 1065 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1066 GetCurrentFramePointerAsmInterpretedFrame1067 inline JSTaggedType* GetCurrentFramePointer() 1068 { 1069 return fp; 1070 } 1071 GetPrevFrameFpAsmInterpretedFrame1072 inline JSTaggedType* GetPrevFrameFp() 1073 { 1074 return base.prev; 1075 } 1076 GetFrameFromSpAsmInterpretedFrame1077 static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 1078 { 1079 return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1080 } 1081 GetFpOffsetAsmInterpretedFrame1082 static size_t GetFpOffset(bool isArch32) 1083 { 1084 return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32); 1085 } 1086 GetCallSizeOffsetAsmInterpretedFrame1087 static size_t GetCallSizeOffset(bool isArch32) 1088 { 1089 return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32); 1090 } 1091 GetFunctionOffsetAsmInterpretedFrame1092 static size_t GetFunctionOffset(bool isArch32) 1093 { 1094 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 1095 } 1096 GetThisOffsetAsmInterpretedFrame1097 static size_t GetThisOffset(bool isArch32) 1098 { 1099 return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32); 1100 } 1101 GetAccOffsetAsmInterpretedFrame1102 static size_t GetAccOffset(bool isArch32) 1103 { 1104 return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32); 1105 } 1106 GetEnvOffsetAsmInterpretedFrame1107 static size_t GetEnvOffset(bool isArch32) 1108 { 1109 return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32); 1110 } 1111 GetBaseOffsetAsmInterpretedFrame1112 static size_t GetBaseOffset(bool isArch32) 1113 { 1114 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 1115 } 1116 GetPcOffsetAsmInterpretedFrame1117 static size_t GetPcOffset(bool isArch32) 1118 { 1119 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 1120 } 1121 GetSizeAsmInterpretedFrame1122 static constexpr size_t GetSize(bool isArch32) 1123 { 1124 return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64; 1125 } 1126 GetFpOffsetAsIntptrAsmInterpretedFrame1127 static intptr_t GetFpOffsetAsIntptr(bool isArch32) 1128 { 1129 return static_cast<intptr_t>(GetFpOffset(isArch32)); 1130 } 1131 GetFunctionOffsetAsIntptrAsmInterpretedFrame1132 static intptr_t GetFunctionOffsetAsIntptr(bool isArch32) 1133 { 1134 return static_cast<intptr_t>(GetFunctionOffset(isArch32)); 1135 } 1136 GetSizeAsIntptrAsmInterpretedFrame1137 static intptr_t GetSizeAsIntptr(bool isArch32) 1138 { 1139 return static_cast<intptr_t>(GetSize(isArch32)); 1140 } 1141 NumOfMembersAsmInterpretedFrame1142 static uint32_t NumOfMembers() 1143 { 1144 return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 1145 } 1146 void GCIterate(const FrameIterator &it, RootVisitor &visitor, bool isBaselineFrame) const; 1147 GetEnvAsmInterpretedFrame1148 JSTaggedValue GetEnv() const 1149 { 1150 return env; 1151 } 1152 GetPcAsmInterpretedFrame1153 const uint8_t *GetPc() const 1154 { 1155 return pc; 1156 } 1157 GetTypeOffsetAsmInterpretedFrame1158 static size_t GetTypeOffset() 1159 { 1160 return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type); 1161 } 1162 GetPrevOffsetAsmInterpretedFrame1163 static size_t GetPrevOffset() 1164 { 1165 return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev); 1166 } 1167 1168 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 1169 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 1170 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 1171 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 1172 alignas(EAS) uintptr_t callSize {0}; 1173 alignas(EAS) JSTaggedType *fp {nullptr}; 1174 alignas(EAS) const uint8_t *pc {nullptr}; 1175 alignas(EAS) InterpretedFrameBase base; 1176 // vregs, not exist in native 1177 // args, may be truncated if not extra 1178 }; 1179 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64); 1180 1181 // InterpretedEntryFrame Layout as the following: 1182 // +----------------------------------+--------------- 1183 // | . . . . | ^ 1184 // | InterpretedFrameBase | | 1185 // | . . . . | InterpretedEntryFrame 1186 // |----------------------------------| | 1187 // | pc(bytecode addr) | v 1188 // |----------------------------------|--------------- 1189 // 1190 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1191 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1192 base::AlignedPointer, 1193 InterpretedFrameBase> { 1194 enum class Index : size_t { 1195 PcIndex = 0, 1196 BaseIndex, 1197 NumOfMembers 1198 }; 1199 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1200 GetPrevFrameFpInterpretedEntryFrame1201 inline JSTaggedType* GetPrevFrameFp() 1202 { 1203 return base.prev; 1204 } 1205 GetFrameFromSpInterpretedEntryFrame1206 static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 1207 { 1208 return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1209 } 1210 NumOfMembersInterpretedEntryFrame1211 static uint32_t NumOfMembers() 1212 { 1213 return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize(); 1214 } 1215 1216 static size_t GetTypeOffset(bool isArch32 = false) 1217 { 1218 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1219 InterpretedFrameBase::GetTypeOffset(isArch32); 1220 } 1221 1222 static size_t GetPrevOffset(bool isArch32 = false) 1223 { 1224 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1225 InterpretedFrameBase::GetPrevOffset(isArch32); 1226 } 1227 1228 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1229 alignas(EAS) const uint8_t *pc {nullptr}; 1230 alignas(EAS) InterpretedFrameBase base; 1231 }; 1232 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame), 1233 InterpretedEntryFrame::SizeArch32, 1234 InterpretedEntryFrame::SizeArch64); 1235 1236 1237 // AsmInterpretedEntryFrame Layout as the following: 1238 // +----------------------------------+--------------- 1239 // | . . . . | ^ 1240 // | InterpretedFrameBase | | 1241 // | . . . . | AsmInterpretedEntryFrame 1242 // |----------------------------------| | 1243 // | pc(bytecode addr) | v 1244 // |----------------------------------|--------------- 1245 // 1246 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1247 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1248 base::AlignedPointer, 1249 InterpretedFrameBase> { 1250 enum class Index : size_t { 1251 PcIndex = 0, 1252 BaseIndex, 1253 NumOfMembers 1254 }; 1255 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1256 GetPrevFrameFpAsmInterpretedEntryFrame1257 inline JSTaggedType* GetPrevFrameFp() 1258 { 1259 return base.prev; 1260 } 1261 GetBaseOffsetAsmInterpretedEntryFrame1262 static size_t GetBaseOffset(bool isArch32) 1263 { 1264 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 1265 } 1266 GetFrameFromSpAsmInterpretedEntryFrame1267 static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 1268 { 1269 return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1270 } 1271 1272 static size_t GetTypeOffset(bool isArch32 = false) 1273 { 1274 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1275 InterpretedFrameBase::GetTypeOffset(isArch32); 1276 } 1277 1278 static size_t GetPrevOffset(bool isArch32 = false) 1279 { 1280 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1281 InterpretedFrameBase::GetPrevOffset(isArch32); 1282 } 1283 1284 alignas(EAS) const uint8_t *pc {nullptr}; 1285 alignas(EAS) InterpretedFrameBase base; 1286 }; 1287 1288 // AsmInterpretedBridgeFrame Layout as the following: 1289 // +----------------------------------+--------------- 1290 // | ret-address | ^ 1291 // |----------------------------------| | 1292 // | . . . . | AsmInterpretedBridgeFrame 1293 // | AsmInterpretedEntryFrame | | 1294 // | . . . . | v 1295 // |----------------------------------|--------------- 1296 // 1297 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1298 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1299 AsmInterpretedEntryFrame, 1300 base::AlignedPointer> { 1301 enum class Index : size_t { 1302 EntryIndex = 0, 1303 ReturnAddrIndex, 1304 NumOfMembers 1305 }; 1306 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1307 GetFrameFromSpAsmInterpretedBridgeFrame1308 static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 1309 { 1310 return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 1311 MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr)); 1312 } GetCallSiteSpAsmInterpretedBridgeFrame1313 uintptr_t GetCallSiteSp() const 1314 { 1315 return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame); 1316 } GetPrevFrameFpAsmInterpretedBridgeFrame1317 inline JSTaggedType* GetPrevFrameFp() 1318 { 1319 return entry.base.prev; 1320 } 1321 GetReturnAddrOffsetAsmInterpretedBridgeFrame1322 static size_t GetReturnAddrOffset(bool isArch32) 1323 { 1324 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 1325 } 1326 GetSizeAsmInterpretedBridgeFrame1327 static constexpr size_t GetSize(bool isArch32) 1328 { 1329 return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64; 1330 } 1331 1332 static size_t GetTypeOffset(bool isArch32 = false) 1333 { 1334 return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) + 1335 AsmInterpretedEntryFrame::GetBaseOffset(isArch32) + 1336 InterpretedFrameBase::GetTypeOffset(isArch32); 1337 } 1338 static size_t GetPrevOffset(bool isArch32 = false) 1339 { 1340 return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) + 1341 AsmInterpretedEntryFrame::GetBaseOffset(isArch32) + 1342 InterpretedFrameBase::GetPrevOffset(isArch32); 1343 } 1344 GetReturnAddrAsmInterpretedBridgeFrame1345 uintptr_t GetReturnAddr() const 1346 { 1347 return returnAddr; 1348 } 1349 GetReturnAddrAddressAsmInterpretedBridgeFrame1350 const uintptr_t *GetReturnAddrAddress() const 1351 { 1352 return &returnAddr; 1353 } 1354 1355 AsmInterpretedEntryFrame entry; 1356 alignas(EAS) uintptr_t returnAddr {0}; 1357 }; 1358 1359 // * Optimized-leaved-frame layout as the following: 1360 // +--------------------------+ 1361 // | argv[N-1] | 1362 // |--------------------------| 1363 // | . . . . . | 1364 // |--------------------------| 1365 // | argv[0] | 1366 // +--------------------------+------------- 1367 // | argc | ^ 1368 // |--------------------------| | 1369 // | RuntimeId | | 1370 // callerSP --> |--------------------------| OptimizedLeaveFrame 1371 // | ret-addr | | 1372 // |--------------------------| | 1373 // | prevFp | | 1374 // fp --> |--------------------------| | 1375 // | frameType | v 1376 // calleeSP --> +--------------------------+------------- 1377 // 1378 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1379 struct OptimizedLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1380 base::AlignedPointer, 1381 base::AlignedPointer, 1382 base::AlignedPointer, 1383 base::AlignedUint64, 1384 base::AlignedUint64> { 1385 // argv[0]...argv[argc-1] dynamic according to agc GetFrameFromSpOptimizedLeaveFrame1386 static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1387 { 1388 return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1389 MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp)); 1390 } 1391 GetCallSiteSpOptimizedLeaveFrame1392 uintptr_t GetCallSiteSp() const 1393 { 1394 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId); 1395 } 1396 GetPrevFrameFpOptimizedLeaveFrame1397 inline JSTaggedType* GetPrevFrameFp() const 1398 { 1399 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1400 } 1401 GetReturnAddrOptimizedLeaveFrame1402 uintptr_t GetReturnAddr() const 1403 { 1404 return returnAddr; 1405 } 1406 GetReturnAddrAddressOptimizedLeaveFrame1407 const uintptr_t *GetReturnAddrAddress() const 1408 { 1409 return &returnAddr; 1410 } 1411 GetTypeOffsetOptimizedLeaveFrame1412 static size_t GetTypeOffset() 1413 { 1414 return MEMBER_OFFSET(OptimizedLeaveFrame, type); 1415 } 1416 GetPrevOffsetOptimizedLeaveFrame1417 static size_t GetPrevOffset() 1418 { 1419 return MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp); 1420 } 1421 GetReturnAddrOffsetOptimizedLeaveFrame1422 static size_t GetReturnAddrOffset() 1423 { 1424 return MEMBER_OFFSET(OptimizedLeaveFrame, returnAddr); 1425 } 1426 1427 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1428 1429 alignas(EAS) FrameType type {0}; 1430 alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here 1431 alignas(EAS) uintptr_t returnAddr {0}; 1432 alignas(EAS) uint64_t argRuntimeId {0}; 1433 alignas(EAS) uint64_t argc {0}; 1434 }; 1435 1436 // * Optimized-leaved-frame-with-argv layout as the following: 1437 // +--------------------------+ 1438 // | argv[] | 1439 // +--------------------------+------------- 1440 // | argc | ^ 1441 // |--------------------------| | 1442 // | RuntimeId | OptimizedWithArgvLeaveFrame 1443 // callerSP --> |--------------------------| | 1444 // | returnAddr | | 1445 // |--------------------------| | 1446 // | callsiteFp | | 1447 // fp --> |--------------------------| | 1448 // | frameType | v 1449 // calleeSP --> +--------------------------+------------- 1450 1451 struct OptimizedWithArgvLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1452 base::AlignedPointer, 1453 base::AlignedPointer, 1454 base::AlignedPointer, 1455 base::AlignedUint64, 1456 base::AlignedUint64> { GetFrameFromSpOptimizedWithArgvLeaveFrame1457 static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1458 { 1459 return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1460 MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp)); 1461 } 1462 GetCallSiteSpOptimizedWithArgvLeaveFrame1463 uintptr_t GetCallSiteSp() const 1464 { 1465 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId); 1466 } 1467 GetPrevFrameFpOptimizedWithArgvLeaveFrame1468 inline JSTaggedType* GetPrevFrameFp() 1469 { 1470 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1471 } 1472 GetReturnAddrOptimizedWithArgvLeaveFrame1473 uintptr_t GetReturnAddr() const 1474 { 1475 return returnAddr; 1476 } 1477 GetReturnAddrAddressOptimizedWithArgvLeaveFrame1478 const uintptr_t *GetReturnAddrAddress() const 1479 { 1480 return &returnAddr; 1481 } 1482 GetTypeOffsetOptimizedWithArgvLeaveFrame1483 static size_t GetTypeOffset() 1484 { 1485 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type); 1486 } 1487 GetPrevOffsetOptimizedWithArgvLeaveFrame1488 static size_t GetPrevOffset() 1489 { 1490 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp); 1491 } 1492 GetReturnAddrOffsetOptimizedWithArgvLeaveFrame1493 static size_t GetReturnAddrOffset() 1494 { 1495 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, returnAddr); 1496 } 1497 1498 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1499 1500 alignas(EAS) FrameType type {0}; 1501 alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here 1502 alignas(EAS) uintptr_t returnAddr {0}; 1503 alignas(EAS) uint64_t argRuntimeId {0}; 1504 alignas(EAS) uint64_t argc {0}; 1505 }; 1506 1507 // * Optimized-builtin-leave-frame layout as the following: 1508 // +--------------------------+ 1509 // | argv[N-1] | 1510 // |--------------------------| 1511 // | . . . . . | 1512 // |--------------------------| 1513 // | argv[0] | 1514 // +--------------------------+------------- 1515 // | argc | ^ 1516 // |--------------------------| | 1517 // | thread | | 1518 // callerSP --> +--------------------------+ | 1519 // | ret-addr | | 1520 // |--------------------------| OptimizedBuiltinLeaveFrame 1521 // | prevFp | | 1522 // fp --> |--------------------------| | 1523 // | frameType | | 1524 // |--------------------------| | 1525 // | align byte | v 1526 // calleeSP --> +--------------------------+------------- 1527 // 1528 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1529 struct OptimizedBuiltinLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1530 base::AlignedPointer, 1531 base::AlignedPointer, 1532 base::AlignedPointer, 1533 JSTaggedValue, 1534 base::AlignedUint64> { 1535 public: GetFrameFromSpOptimizedBuiltinLeaveFrame1536 static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1537 { 1538 return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1539 MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp)); 1540 } 1541 GetCallSiteSpOptimizedBuiltinLeaveFrame1542 uintptr_t GetCallSiteSp() const 1543 { 1544 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, thread); 1545 } 1546 GetPrevFrameFpOptimizedBuiltinLeaveFrame1547 inline JSTaggedType* GetPrevFrameFp() const 1548 { 1549 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1550 } 1551 GetReturnAddrOptimizedBuiltinLeaveFrame1552 uintptr_t GetReturnAddr() const 1553 { 1554 return returnAddr; 1555 } 1556 GetReturnAddrAddressOptimizedBuiltinLeaveFrame1557 const uintptr_t *GetReturnAddrAddress() const 1558 { 1559 return &returnAddr; 1560 } 1561 1562 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1563 GetTypeOffsetOptimizedBuiltinLeaveFrame1564 static size_t GetTypeOffset() 1565 { 1566 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type); 1567 } 1568 GetPrevOffsetOptimizedBuiltinLeaveFrame1569 static size_t GetPrevOffset() 1570 { 1571 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp); 1572 } 1573 GetReturnAddrOffsetOptimizedBuiltinLeaveFrame1574 static size_t GetReturnAddrOffset() 1575 { 1576 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, returnAddr); 1577 } 1578 GetFunctionOffsetOptimizedBuiltinLeaveFrame1579 static size_t GetFunctionOffset() 1580 { 1581 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argc) + 1; 1582 } 1583 GetArgvOptimizedBuiltinLeaveFrame1584 const JSTaggedType* GetArgv() const 1585 { 1586 return reinterpret_cast<const JSTaggedType *>(&argc + 1); 1587 } 1588 GetTypeOptimizedBuiltinLeaveFrame1589 FrameType GetType() const 1590 { 1591 return type; 1592 } 1593 1594 private: 1595 alignas(EAS) FrameType type {0}; 1596 alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here 1597 alignas(EAS) uintptr_t returnAddr {0}; 1598 alignas(EAS) JSTaggedValue thread {JSTaggedValue::Hole()}; 1599 alignas(EAS) uint64_t argc {0}; 1600 // argv[0]...argv[argc-1] dynamic according to agc 1601 }; 1602 1603 // * BuiltinFrame layout as the following: 1604 // +--------------------------+ 1605 // | argV[N - 1] | 1606 // |--------------------------| 1607 // | . . . . | 1608 // |--------------------------+ 1609 // | argV[2]=this | 1610 // +--------------------------+ 1611 // | argV[1]=new-target | 1612 // +--------------------------+ 1613 // | argV[0]=call-target | 1614 // +--------------------------+ --------- 1615 // | argc | ^ 1616 // |--------------------------| | 1617 // | thread | | 1618 // callerSP --> |--------------------------| | 1619 // | returnAddr | BuiltinFrame 1620 // |--------------------------| | 1621 // | callsiteFp | | 1622 // fp --> |--------------------------| | 1623 // | frameType | v 1624 // calleeSP --> +--------------------------+ --------- 1625 // 1626 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1627 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1628 base::AlignedSize, 1629 base::AlignedPointer, 1630 base::AlignedPointer, 1631 base::AlignedPointer, 1632 base::AlignedUint32, 1633 base::AlignedPointer> { 1634 enum class Index : size_t { 1635 TypeIndex = 0, 1636 PrevFpIndex, 1637 ReturnAddrIndex, 1638 ThreadIndex, 1639 NumArgsIndex, 1640 StackArgsIndex, 1641 NumOfMembers 1642 }; 1643 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1644 GetFrameFromSpBuiltinFrame1645 static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 1646 { 1647 return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) - 1648 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1649 } 1650 GetPrevFrameFpBuiltinFrame1651 inline JSTaggedType* GetPrevFrameFp() 1652 { 1653 return prevFp; 1654 } 1655 GetCallSiteSpBuiltinFrame1656 uintptr_t GetCallSiteSp() const 1657 { 1658 return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread); 1659 } 1660 GetPreFpOffsetBuiltinFrame1661 static size_t GetPreFpOffset(bool isArch32) 1662 { 1663 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1664 } 1665 GetNumArgsToFpDeltaBuiltinFrame1666 static size_t GetNumArgsToFpDelta(bool isArch32) 1667 { 1668 auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32); 1669 return offset - GetPreFpOffset(isArch32); 1670 } 1671 GetStackArgsToFpDeltaBuiltinFrame1672 static size_t GetStackArgsToFpDelta(bool isArch32) 1673 { 1674 auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 1675 return offset - GetPreFpOffset(isArch32); 1676 } 1677 GetStackArgsAddressBuiltinFrame1678 uintptr_t GetStackArgsAddress() 1679 { 1680 return reinterpret_cast<uintptr_t>(&stackArgs); 1681 } 1682 GetFunctionBuiltinFrame1683 JSTaggedValue GetFunction() 1684 { 1685 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1686 return JSTaggedValue(*functionAddress); 1687 } 1688 GetNumArgsBuiltinFrame1689 uint32_t GetNumArgs() 1690 { 1691 return numArgs; 1692 } 1693 GetReturnAddrBuiltinFrame1694 uintptr_t GetReturnAddr() const 1695 { 1696 return returnAddr; 1697 } 1698 GetReturnAddrAddressBuiltinFrame1699 const uintptr_t *GetReturnAddrAddress() const 1700 { 1701 return &returnAddr; 1702 } 1703 1704 static size_t GetStackArgsOffset(bool isArch32 = false) 1705 { 1706 return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 1707 } 1708 1709 static size_t GetTypeOffset(bool isArch32 = false) 1710 { 1711 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1712 } 1713 1714 static size_t GetPrevOffset(bool isArch32 = false) 1715 { 1716 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1717 } 1718 1719 static size_t GetReturnAddrOffset(bool isArch32 = false) 1720 { 1721 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 1722 } 1723 1724 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1725 1726 alignas(EAS) FrameType type {0}; 1727 alignas(EAS) JSTaggedType *prevFp {nullptr}; 1728 alignas(EAS) uintptr_t returnAddr {0}; 1729 alignas(EAS) uintptr_t thread {0}; 1730 alignas(EAS) uint32_t numArgs {0}; 1731 alignas(EAS) uintptr_t stackArgs {0}; 1732 }; 1733 1734 // * BuiltinWithArgvFrame layout as the following: 1735 // +--------------------------+ --------- 1736 // | . . . . . | ^ 1737 // callerSP --> |--------------------------| | 1738 // | returnAddr | | 1739 // |--------------------------| | 1740 // | callsiteFp | BuiltinWithArgvFrame 1741 // fp --> |--------------------------| | 1742 // | frameType | | 1743 // +--------------------------+ | 1744 // | argc | v 1745 // +--------------------------+ --------- 1746 // | argV[0] | 1747 // +--------------------------+ 1748 // | argV[1] | 1749 // +--------------------------+ 1750 // | . . . . | 1751 // calleeSP --> +--------------------------+ 1752 // 1753 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1754 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1755 base::AlignedSize, 1756 base::AlignedPointer, 1757 base::AlignedPointer> { 1758 enum class Index : int { 1759 StackArgsTopIndex = -1, 1760 NumArgsIndex = -1, 1761 TypeIndex = 0, 1762 PrevFpIndex, 1763 ReturnAddrIndex, 1764 NumOfMembers 1765 }; 1766 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1767 GetFrameFromSpBuiltinWithArgvFrame1768 static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp) 1769 { 1770 return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) - 1771 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1772 } 1773 GetPrevFrameFpBuiltinWithArgvFrame1774 inline JSTaggedType* GetPrevFrameFp() 1775 { 1776 return prevFp; 1777 } 1778 GetCallSiteSpBuiltinWithArgvFrame1779 uintptr_t GetCallSiteSp() const 1780 { 1781 return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame); 1782 } 1783 GetStackArgsAddressBuiltinWithArgvFrame1784 uintptr_t GetStackArgsAddress() 1785 { 1786 auto topAddress = ToUintPtr(this) + 1787 (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t)); 1788 auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS; 1789 return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t); 1790 } 1791 GetFunctionBuiltinWithArgvFrame1792 JSTaggedValue GetFunction() 1793 { 1794 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1795 return JSTaggedValue(*functionAddress); 1796 } 1797 GetNumArgsBuiltinWithArgvFrame1798 int32_t GetNumArgs() 1799 { 1800 auto argcAddress = reinterpret_cast<int32_t *>( 1801 ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t))); 1802 return *argcAddress; 1803 } 1804 GetReturnAddrBuiltinWithArgvFrame1805 uintptr_t GetReturnAddr() const 1806 { 1807 return returnAddr; 1808 } 1809 GetReturnAddrAddressBuiltinWithArgvFrame1810 const uintptr_t *GetReturnAddrAddress() const 1811 { 1812 return &returnAddr; 1813 } 1814 1815 static size_t GetTypeOffset(bool isArch32 = false) 1816 { 1817 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1818 } 1819 1820 static size_t GetPrevOffset(bool isArch32 = false) 1821 { 1822 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1823 } 1824 1825 static size_t GetReturnAddrOffset(bool isArch32 = false) 1826 { 1827 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 1828 } 1829 1830 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1831 // argv(... this, new.target, function) 1832 // numargs 1833 alignas(EAS) FrameType type {0}; 1834 alignas(EAS) JSTaggedType *prevFp {nullptr}; 1835 alignas(EAS) uintptr_t returnAddr {0}; 1836 }; 1837 1838 // * FASTJITFunctionFrame layout description as the following: 1839 // +--------------------------+ 1840 // | arg[N-1] | 1841 // +--------------------------+ 1842 // | ... | 1843 // +--------------------------+ 1844 // | arg[1] | 1845 // +--------------------------+ 1846 // | arg[0] | 1847 // +--------------------------+ 1848 // | this | 1849 // +--------------------------+ 1850 // | new-target | 1851 // +--------------------------+ 1852 // | call-target | 1853 // |--------------------------| 1854 // | argc | 1855 // callerSp ---> |--------------------------| --------------- 1856 // | returnAddr | ^ 1857 // |--------------------------| | 1858 // | callsiteFp | | 1859 // |--------------------------| | 1860 // | frameType | FASTJITFunctionFrame 1861 // |--------------------------| | 1862 // | call-target | | 1863 // |--------------------------| | 1864 // | pc(bytecode pc) | v 1865 // calleeSP ---> +--------------------------+ --------------- 1866 // 1867 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1868 struct FASTJITFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1869 JSTaggedValue, 1870 JSTaggedValue, 1871 base::AlignedPointer, 1872 base::AlignedPointer, 1873 base::AlignedPointer> { 1874 public: 1875 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 1876 enum class Index : size_t { 1877 PcIndex = 0, 1878 JSFuncIndex, 1879 TypeIndex, 1880 PrevFpIndex, 1881 ReturnAddrIndex, 1882 NumOfMembers 1883 }; 1884 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1885 GetFunctionDeltaReturnAddrFASTJITFunctionFrame1886 static constexpr size_t GetFunctionDeltaReturnAddr() 1887 { 1888 return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex); 1889 } 1890 GetPrevFrameFpFASTJITFunctionFrame1891 inline JSTaggedType* GetPrevFrameFp() 1892 { 1893 return prevFp; 1894 } 1895 GetArgvFASTJITFunctionFrame1896 JSTaggedType* GetArgv(uintptr_t *preFrameSp) const 1897 { 1898 const size_t offset = 2; // 2: skip argc and argv. 1899 return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t)); 1900 } 1901 GetArgcFASTJITFunctionFrame1902 size_t GetArgc(uintptr_t *preFrameSp) const 1903 { 1904 return *preFrameSp; 1905 } 1906 1907 JSTaggedType* GetArgv(const FrameIterator &it) const; 1908 GetReturnAddrFASTJITFunctionFrame1909 uintptr_t GetReturnAddr() const 1910 { 1911 return returnAddr; 1912 } 1913 GetReturnAddrAddressFASTJITFunctionFrame1914 const uintptr_t *GetReturnAddrAddress() const 1915 { 1916 return &returnAddr; 1917 } 1918 1919 void GCIterate(const FrameIterator &it, RootVisitor &visitor, FrameType frameType) const; 1920 GetFunctionFASTJITFunctionFrame1921 inline JSTaggedValue GetFunction() const 1922 { 1923 return jsFunc; 1924 } 1925 ComputeArgsConfigFrameSpFASTJITFunctionFrame1926 static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp) 1927 { 1928 const size_t offset = 2; // 2: skip prevFp and return address. 1929 return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t); 1930 } 1931 1932 static size_t GetTypeOffset(bool isArch32 = false) 1933 { 1934 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1935 } 1936 1937 static size_t GetPcOffset(bool isArch32 = false) 1938 { 1939 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 1940 } 1941 1942 static size_t GetPrevOffset(bool isArch32 = false) 1943 { 1944 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1945 } 1946 1947 static size_t GetFunctionOffset(bool isArch32 = false) 1948 { 1949 return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32); 1950 } 1951 ComputeReservedJSFuncOffsetFASTJITFunctionFrame1952 static size_t ComputeReservedJSFuncOffset(size_t slotSize) 1953 { 1954 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex); 1955 return slotSize * slotOffset; 1956 } 1957 ComputeReservedPcOffsetFASTJITFunctionFrame1958 static size_t ComputeReservedPcOffset(size_t slotSize) 1959 { 1960 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PcIndex); 1961 return slotSize * slotOffset; 1962 } 1963 GetFrmaeTypeToFpDeltaFASTJITFunctionFrame1964 static int GetFrmaeTypeToFpDelta() 1965 { 1966 return -(int)sizeof(uintptr_t); 1967 } 1968 GetFunctionToFpDeltaFASTJITFunctionFrame1969 static int GetFunctionToFpDelta() 1970 { 1971 int slotOffset = static_cast<int>(Index::JSFuncIndex) - static_cast<int>(Index::TypeIndex); 1972 return slotOffset * static_cast<int>(JSTaggedValue::TaggedTypeSize()) + GetFrmaeTypeToFpDelta(); 1973 } 1974 GetTypeFASTJITFunctionFrame1975 FrameType GetType() const 1976 { 1977 return type; 1978 } 1979 GetPcFASTJITFunctionFrame1980 inline const uint8_t *GetPc() const 1981 { 1982 return pc; 1983 } 1984 1985 friend class FrameIterator; 1986 friend class FrameHandler; 1987 void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const; 1988 void GetFuncCalleeRegAndOffset( 1989 const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const; 1990 uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const; 1991 1992 private: GetFrameFromSpFASTJITFunctionFrame1993 static FASTJITFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) 1994 { 1995 return reinterpret_cast<FASTJITFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) - 1996 MEMBER_OFFSET(FASTJITFunctionFrame, prevFp)); 1997 } 1998 GetFuncAddrFromSpFASTJITFunctionFrame1999 static uintptr_t GetFuncAddrFromSp(const JSTaggedType *sp) 2000 { 2001 return reinterpret_cast<uintptr_t>(sp) - MEMBER_OFFSET(FASTJITFunctionFrame, type); 2002 } 2003 2004 // dynamic callee saveregisters for x86-64 2005 alignas(EAS) const uint8_t *pc {nullptr}; 2006 alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()}; 2007 alignas(EAS) FrameType type {0}; 2008 alignas(EAS) JSTaggedType *prevFp {nullptr}; 2009 alignas(EAS) uintptr_t returnAddr {0}; 2010 // dynamic callee saveregisters for arm64 2011 }; 2012 2013 enum class GCVisitedFlag : uint8_t { 2014 VISITED = 0, 2015 IGNORED, 2016 HYBRID_STACK, 2017 DEOPT, 2018 }; 2019 2020 class FrameIterator { 2021 public: 2022 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 2023 using CallSiteInfo = std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec>; 2024 explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr); 2025 2026 static constexpr uint32_t LAZY_DEOPT_FLAG_BIT = 30; 2027 static constexpr uintptr_t CLEARD_LAZY_DEOPT_FLAG = 2028 static_cast<uintptr_t>(~0ULL & ~(1ULL << LAZY_DEOPT_FLAG_BIT)); 2029 TryRemoveLazyDeoptFlag(uintptr_t & type)2030 inline static void TryRemoveLazyDeoptFlag(uintptr_t& type) 2031 { 2032 type &= CLEARD_LAZY_DEOPT_FLAG; 2033 } 2034 GetFrameType()2035 FrameType GetFrameType() const 2036 { 2037 ASSERT(current_ != nullptr); 2038 uintptr_t *typeAddr = reinterpret_cast<uintptr_t *>( 2039 reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType)); 2040 return static_cast<FrameType>((*typeAddr) & CLEARD_LAZY_DEOPT_FLAG); 2041 } 2042 GetRawFrameType()2043 FrameType GetRawFrameType() const 2044 { 2045 ASSERT(current_ != nullptr); 2046 FrameType *typeAddr = reinterpret_cast<FrameType *>( 2047 reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType)); 2048 return *typeAddr; 2049 } 2050 GetFrameTypeAddress()2051 FrameType *GetFrameTypeAddress() const 2052 { 2053 ASSERT(current_ != nullptr); 2054 FrameType *typeAddr = reinterpret_cast<FrameType *>( 2055 reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType)); 2056 return typeAddr; 2057 } 2058 IsLazyDeoptFrameType()2059 bool IsLazyDeoptFrameType() const 2060 { 2061 return IsLazyDeoptFrameType(GetRawFrameType()); 2062 } 2063 IsLazyDeoptFrameType(FrameType type)2064 static bool IsLazyDeoptFrameType(FrameType type) 2065 { 2066 return static_cast<uint64_t>(type) >= (1ULL << LAZY_DEOPT_FLAG_BIT); 2067 } 2068 DecodeAsLazyDeoptFrameType(FrameType * type)2069 static void DecodeAsLazyDeoptFrameType(FrameType* type) 2070 { 2071 *type = static_cast<FrameType>( 2072 static_cast<uintptr_t>(*type) | (1ULL << LAZY_DEOPT_FLAG_BIT)); 2073 } 2074 2075 uintptr_t *GetReturnAddrAddress() const; 2076 2077 template<class T> GetFrame()2078 T* GetFrame() 2079 { 2080 return T::GetFrameFromSp(current_); 2081 } 2082 2083 template<class T> GetFrame()2084 const T* GetFrame() const 2085 { 2086 return T::GetFrameFromSp(current_); 2087 } 2088 Done()2089 bool Done() const 2090 { 2091 return current_ == nullptr; 2092 } GetSp()2093 JSTaggedType *GetSp() const 2094 { 2095 return current_; 2096 } GetSp()2097 JSTaggedType *GetSp() 2098 { 2099 return current_; 2100 } GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)2101 void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const 2102 { 2103 ret = calleeRegInfo_; 2104 } 2105 int ComputeDelta(const Method *method = nullptr) const; 2106 template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED> 2107 void Advance(); 2108 uint32_t GetBytecodeOffset() const; 2109 void GetStackTraceInfos(std::vector<std::pair<JSTaggedType, uint32_t>> &stackTraceInfos, 2110 bool needBaselineSpecialHandling, uint32_t pcOffset) const; 2111 void CollectStackTraceInfos(std::vector<std::pair<JSTaggedType, uint32_t>> &info) const; 2112 size_t GetInlineDepth() const; 2113 uintptr_t GetPrevFrameCallSiteSp() const; 2114 uintptr_t GetPrevFrame() const; GetCallSiteSp()2115 uintptr_t GetCallSiteSp() const 2116 { 2117 return optimizedCallSiteSp_; 2118 } GetOptimizedReturnAddr()2119 uintptr_t GetOptimizedReturnAddr() const 2120 { 2121 return optimizedReturnAddr_; 2122 } GetThread()2123 const JSThread *GetThread() const 2124 { 2125 return thread_; 2126 } 2127 bool IteratorStackMapAndDeopt(RootVisitor &visitor) const; 2128 void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const; 2129 std::pair<CallSiteInfo, bool> CalCallSiteInfo(uintptr_t retAddr, bool isDeopt) const; 2130 CallSiteInfo TryCalCallSiteInfoFromMachineCode(uintptr_t retAddr) const; 2131 2132 Method *CheckAndGetMethod() const; 2133 JSTaggedValue GetFunction() const; 2134 IsLeaveFrame()2135 bool IsLeaveFrame() const 2136 { 2137 FrameType type = GetFrameType(); 2138 return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV); 2139 } 2140 IsOptimizedFrame()2141 bool IsOptimizedFrame() const 2142 { 2143 FrameType type = GetFrameType(); 2144 return (type == FrameType::OPTIMIZED_FRAME); 2145 } 2146 IsInterpretedFrame(FrameType type)2147 bool IsInterpretedFrame(FrameType type) const 2148 { 2149 return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST); 2150 } 2151 IsJSFrame()2152 bool IsJSFrame() const 2153 { 2154 FrameType type = GetFrameType(); 2155 return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type) || IsFastJitFunctionFrame(type); 2156 } 2157 IsOptimizedJSFunctionFrame(FrameType type)2158 bool IsOptimizedJSFunctionFrame(FrameType type) const 2159 { 2160 return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || 2161 type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME; 2162 } 2163 IsOptimizedJSFunctionFrame()2164 bool IsOptimizedJSFunctionFrame() const 2165 { 2166 FrameType type = GetFrameType(); 2167 return IsOptimizedJSFunctionFrame(type); 2168 } 2169 IsFastJitFunctionFrame(FrameType type)2170 bool IsFastJitFunctionFrame(FrameType type) const 2171 { 2172 return type == FrameType::FASTJIT_FUNCTION_FRAME || 2173 type == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME; 2174 } 2175 IsFastJitFunctionFrame()2176 bool IsFastJitFunctionFrame() const 2177 { 2178 FrameType type = GetFrameType(); 2179 return IsFastJitFunctionFrame(type); 2180 } 2181 IsAotOrJitFunctionFrame()2182 bool IsAotOrJitFunctionFrame() const 2183 { 2184 return IsOptimizedJSFunctionFrame() || IsFastJitFunctionFrame(); 2185 } 2186 GetMachineCodeSlot()2187 JSTaggedType *GetMachineCodeSlot() const 2188 { 2189 return const_cast<JSTaggedType*>(&machineCode_); 2190 } 2191 2192 private: 2193 JSTaggedType *current_ {nullptr}; 2194 const JSThread *thread_ {nullptr}; 2195 const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr}; 2196 uintptr_t optimizedCallSiteSp_ {0}; 2197 uintptr_t optimizedReturnAddr_ {0}; 2198 uint8_t *stackMapAddr_ {nullptr}; 2199 kungfu::CalleeRegAndOffsetVec calleeRegInfo_; 2200 2201 // in jit, delta on method is not set, get it from iterator 2202 bool isJITFrame_ {false}; 2203 int fpDeltaPrevFrameSp_ {0}; 2204 2205 // cache current machine code, it's nonmovable 2206 JSTaggedType machineCode_ {JSTaggedValue::VALUE_UNDEFINED}; 2207 }; 2208 } // namespace panda::ecmascript 2209 #endif // ECMASCRIPT_FRAMES_H 2210