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