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 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 115 enum 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 150 enum 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) 182 struct OptimizedFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 183 base::AlignedPointer, 184 base::AlignedPointer, 185 base::AlignedPointer> { 186 public: 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 ComputeReservedSizeOptimizedFrame200 static size_t ComputeReservedSize(size_t slotSize) 201 { 202 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex); 203 return slotSize * slotOffset; 204 } 205 GetTypeOptimizedFrame206 FrameType GetType() const 207 { 208 return type; 209 } 210 211 private: 212 enum class Index : size_t { 213 TypeIndex = 0, 214 PrevFpIndex, 215 ReturnAddrIndex, 216 NumOfMembers 217 }; 218 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 219 GetFrameFromSpOptimizedFrame220 static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp) 221 { 222 return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp) - 223 MEMBER_OFFSET(OptimizedFrame, prevFp)); 224 } GetPrevFrameFpOptimizedFrame225 inline JSTaggedType* GetPrevFrameFp() 226 { 227 return prevFp; 228 } GetReturnAddrOptimizedFrame229 uintptr_t GetReturnAddr() const 230 { 231 return returnAddr; 232 } 233 234 alignas(EAS) FrameType type {0}; 235 alignas(EAS) JSTaggedType *prevFp {nullptr}; 236 alignas(EAS) uintptr_t returnAddr {0}; 237 friend class FrameIterator; 238 }; 239 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64); 240 241 // * BaselineBuiltinFrame layout as the following: 242 // +--------------------------+ --------- 243 // | . . . . . | ^ 244 // callerSP ---> |--------------------------| | 245 // | returnAddr | | 246 // |--------------------------| BuiltinBuiltinFrame 247 // | callsiteFp | | 248 // fp ---> |--------------------------| | 249 // | frameType | v 250 // +--------------------------+ --------- 251 // | . . . . | 252 // calleeSP ---> +--------------------------+ 253 // 254 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 255 struct BaselineBuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 256 base::AlignedPointer, 257 base::AlignedPointer, 258 base::AlignedPointer> { 259 public: 260 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 261 const RootBaseAndDerivedVisitor &derivedVisitor) const; 262 263 static size_t GetTypeOffset(bool isArch32 = false) 264 { 265 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 266 } 267 268 static size_t GetPrevOffset(bool isArch32 = false) 269 { 270 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 271 } 272 ComputeReservedSizeBaselineBuiltinFrame273 static size_t ComputeReservedSize(size_t slotSize) 274 { 275 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex); 276 return slotSize * slotOffset; 277 } 278 GetTypeBaselineBuiltinFrame279 FrameType GetType() const 280 { 281 return type; 282 } 283 GetReturnAddrBaselineBuiltinFrame284 uintptr_t GetReturnAddr() const 285 { 286 return returnAddr; 287 } 288 289 private: 290 enum class Index : size_t { 291 TypeIndex = 0, 292 PrevFpIndex, 293 ReturnAddrIndex, 294 NumOfMembers 295 }; 296 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 297 GetFrameFromSpBaselineBuiltinFrame298 static BaselineBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 299 { 300 return reinterpret_cast<BaselineBuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) - 301 MEMBER_OFFSET(BaselineBuiltinFrame, prevFp)); 302 } GetPrevFrameFpBaselineBuiltinFrame303 inline JSTaggedType* GetPrevFrameFp() 304 { 305 return prevFp; 306 } 307 308 alignas(EAS) FrameType type {0}; 309 alignas(EAS) JSTaggedType *prevFp {nullptr}; 310 alignas(EAS) uintptr_t returnAddr {0}; 311 friend class FrameIterator; 312 }; 313 STATIC_ASSERT_EQ_ARCH(sizeof(BaselineBuiltinFrame), BaselineBuiltinFrame::SizeArch32, BaselineBuiltinFrame::SizeArch64); 314 315 struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 316 base::AlignedPointer, 317 base::AlignedPointer, 318 base::AlignedPointer> { 319 public: 320 static size_t GetTypeOffset(bool isArch32 = false) 321 { 322 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 323 } 324 325 static size_t GetPrevOffset(bool isArch32 = false) 326 { 327 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 328 } 329 GetCallSiteSpAsmBridgeFrame330 uintptr_t GetCallSiteSp() const 331 { 332 return ToUintPtr(this) + sizeof(AsmBridgeFrame); 333 } 334 GetTypeAsmBridgeFrame335 FrameType GetType() const 336 { 337 return type; 338 } 339 340 private: 341 enum class Index : size_t { 342 TypeIndex = 0, 343 PrevFpIndex, 344 ReturnAddrIndex, 345 NumOfMembers 346 }; 347 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 348 GetFrameFromSpAsmBridgeFrame349 static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 350 { 351 return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 352 MEMBER_OFFSET(AsmBridgeFrame, prevFp)); 353 } GetPrevFrameFpAsmBridgeFrame354 inline JSTaggedType* GetPrevFrameFp() 355 { 356 return prevFp; 357 } GetReturnAddrAsmBridgeFrame358 uintptr_t GetReturnAddr() const 359 { 360 return returnAddr; 361 } 362 alignas(EAS) FrameType type {0}; 363 alignas(EAS) JSTaggedType *prevFp {nullptr}; 364 alignas(EAS) uintptr_t returnAddr {0}; 365 friend class FrameIterator; 366 }; 367 STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64); 368 369 // * OptimizedUnfoldArgVFrame layout description as the following: 370 // callerSP ---> |--------------------------| --------------- 371 // | returnAddr | ^ 372 // |--------------------------| | 373 // | prevFp | | 374 // fp ---> |--------------------------| OptimizedUnfoldArgVFrame 375 // | frameType | | 376 // |--------------------------| | 377 // | currentFp | v 378 // calleESP ---> +--------------------------+ --------------- 379 // 380 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 381 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 382 base::AlignedPointer, 383 base::AlignedPointer, 384 base::AlignedPointer, 385 base::AlignedPointer> { 386 public: 387 static size_t GetTypeOffset(bool isArch32 = false) 388 { 389 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 390 } 391 392 static size_t GetPrevOffset(bool isArch32 = false) 393 { 394 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 395 } 396 GetTypeOptimizedJSFunctionUnfoldArgVFrame397 FrameType GetType() const 398 { 399 return type; 400 } 401 402 private: 403 enum class Index : size_t { 404 CallSiteSpIndex = 0, 405 TypeIndex, 406 PrevFpIndex, 407 ReturnAddrIndex, 408 NumOfMembers 409 }; 410 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 411 GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame412 static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp) 413 { 414 return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp) - 415 MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp)); 416 } GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame417 inline JSTaggedType* GetPrevFrameFp() const 418 { 419 return prevFp; 420 } GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame421 uintptr_t GetReturnAddr() const 422 { 423 return returnAddr; 424 } GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame425 uintptr_t GetPrevFrameSp() const 426 { 427 return callSiteSp; 428 } 429 alignas(EAS) uintptr_t callSiteSp {0}; 430 alignas(EAS) FrameType type {0}; 431 alignas(EAS) JSTaggedType *prevFp {nullptr}; 432 alignas(EAS) uintptr_t returnAddr {0}; 433 friend class FrameIterator; 434 }; 435 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame), 436 OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64); 437 438 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following: 439 // +--------------------------+ 440 // | arg[N-1] | 441 // +--------------------------+ 442 // | . . . . | 443 // +--------------------------+ 444 // | arg[0] | 445 // +--------------------------+ 446 // | argC | 447 // sp ---> +--------------------------+ ----------------- 448 // | | ^ 449 // | prevFP | | 450 // fp ---> |--------------------------| OptimizedJSFunctionArgsConfigFrame 451 // | frameType | | 452 // | | V 453 // +--------------------------+ ----------------- 454 // 455 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 456 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 457 base::AlignedPointer, 458 base::AlignedPointer> { 459 public: 460 static size_t GetTypeOffset(bool isArch32 = false) 461 { 462 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 463 } 464 465 static size_t GetPrevOffset(bool isArch32 = false) 466 { 467 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 468 } 469 GetTypeOptimizedJSFunctionArgConfigFrame470 FrameType GetType() const 471 { 472 return type; 473 } 474 475 private: 476 enum class Index : size_t { 477 TypeIndex = 0, 478 PrevFpIndex, 479 NumOfMembers 480 }; 481 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 482 GetFrameFromSpOptimizedJSFunctionArgConfigFrame483 static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp) 484 { 485 return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp) - 486 MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp)); 487 } GetPrevFrameFpOptimizedJSFunctionArgConfigFrame488 inline JSTaggedType* GetPrevFrameFp() 489 { 490 return prevFp; 491 } 492 493 alignas(EAS) FrameType type {0}; 494 alignas(EAS) JSTaggedType *prevFp {nullptr}; 495 friend class FrameIterator; 496 }; 497 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame), 498 OptimizedJSFunctionArgConfigFrame::SizeArch32, 499 OptimizedJSFunctionArgConfigFrame::SizeArch64); 500 501 // * OptimizedJSFunctionFrame layout description as the following: 502 // +----------------------------------------+ 503 // | arg[N-1] | 504 // +----------------------------------------+ 505 // | ... | 506 // +----------------------------------------+ 507 // | arg[1] | 508 // +----------------------------------------+ 509 // | arg[0] | 510 // +----------------------------------------+ 511 // | this | 512 // +----------------------------------------+ 513 // | new-target [not exist in fastcall] | 514 // +----------------------------------------+ 515 // | call-target | 516 // argv ---> +----------------------------------------+ 517 // | argv [not exist in fastcall] | 518 // |----------------------------------------| 519 // | argc [not exist in fastcall] | 520 // callerSp ---> |----------------------------------------|---------------- 521 // | returnAddr | ^ 522 // |----------------------------------------| | 523 // | callsiteFp | | 524 // fp ---> |----------------------------------------| OptimizedJSFunctionFrame 525 // | frameType | | 526 // |----------------------------------------| | 527 // | call-target | v 528 // calleeSP ---> +----------------------------------------+---------------- 529 // 530 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 531 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 532 JSTaggedValue, 533 base::AlignedPointer, 534 base::AlignedPointer, 535 base::AlignedPointer> { 536 public: 537 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 538 enum class Index : size_t { 539 JSFuncIndex = 0, 540 TypeIndex, 541 PrevFpIndex, 542 ReturnAddrIndex, 543 NumOfMembers 544 }; 545 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 546 GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame547 static constexpr size_t GetFunctionDeltaReturnAddr() 548 { 549 return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex); 550 } 551 GetPrevFrameFpOptimizedJSFunctionFrame552 inline JSTaggedType* GetPrevFrameFp() 553 { 554 return prevFp; 555 } 556 GetArgvOptimizedJSFunctionFrame557 JSTaggedType* GetArgv(uintptr_t *preFrameSp) const 558 { 559 const size_t offset = 2; // 2: skip argc and argv. 560 return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t)); 561 } 562 GetArgcOptimizedJSFunctionFrame563 size_t GetArgc(uintptr_t *preFrameSp) const 564 { 565 return *preFrameSp; 566 } 567 568 JSTaggedType* GetArgv(const FrameIterator &it) const; 569 GetReturnAddrOptimizedJSFunctionFrame570 uintptr_t GetReturnAddr() const 571 { 572 return returnAddr; 573 } 574 575 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 576 const RootBaseAndDerivedVisitor &derivedVisitor, FrameType frameType) const; 577 void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const; 578 GetFunctionOptimizedJSFunctionFrame579 inline JSTaggedValue GetFunction() const 580 { 581 return jsFunc; 582 } 583 ComputeArgsConfigFrameSpOptimizedJSFunctionFrame584 static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp) 585 { 586 const size_t offset = 2; // 2: skip prevFp and return address. 587 return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t); 588 } 589 590 static size_t GetTypeOffset(bool isArch32 = false) 591 { 592 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 593 } 594 595 static size_t GetPrevOffset(bool isArch32 = false) 596 { 597 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 598 } 599 600 static size_t GetFunctionOffset(bool isArch32 = false) 601 { 602 return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32); 603 } 604 605 static size_t GetReturnAddrOffset(bool isArch32 = false) 606 { 607 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 608 } 609 ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame610 static size_t ComputeReservedJSFuncOffset(size_t slotSize) 611 { 612 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex); 613 return slotSize * slotOffset; 614 } 615 GetTypeOptimizedJSFunctionFrame616 FrameType GetType() const 617 { 618 return type; 619 } 620 621 friend class FrameIterator; 622 friend class FrameHandler; 623 void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const; 624 void GetFuncCalleeRegAndOffset( 625 const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const; 626 uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const; 627 628 private: GetFrameFromSpOptimizedJSFunctionFrame629 static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) 630 { 631 return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) - 632 MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp)); 633 } 634 635 // dynamic callee saveregisters for x86-64 636 alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()}; 637 alignas(EAS) FrameType type {0}; 638 alignas(EAS) JSTaggedType *prevFp {nullptr}; 639 alignas(EAS) uintptr_t returnAddr {0}; 640 // dynamic callee saveregisters for arm64 641 }; 642 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame), 643 OptimizedJSFunctionFrame::SizeArch32, 644 OptimizedJSFunctionFrame::SizeArch64); 645 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time. 646 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1); 647 648 // * The JSFunctionEntry Frame's structure is illustrated as the following: 649 // +--------------------------+ 650 // | . . . . . . | 651 // callerSP --> +--------------------------+ ----------------- 652 // | prevFP | ^ 653 // fp --> |--------------------------| | 654 // | frameType | JSFunctionEntryFrame 655 // |--------------------------| | 656 // | preLeaveFrameFp | v 657 // calleeSP --> +--------------------------+ ----------------- 658 659 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 660 base::AlignedPointer, 661 base::AlignedPointer, 662 base::AlignedPointer> { 663 public: 664 enum class CallType : size_t { 665 CALL_FUNC = 0, 666 CALL_NEW, 667 }; 668 669 enum class Index : size_t { 670 PreLeaveFrameFpIndex = 0, 671 TypeIndex, 672 PrevFpIndex, 673 NumOfMembers 674 }; 675 676 static size_t GetTypeOffset(bool isArch32 = false) 677 { 678 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 679 } 680 681 static size_t GetLeaveFrameFpOffset(bool isArch32 = false) 682 { 683 return GetOffset<static_cast<size_t>(Index::PreLeaveFrameFpIndex)>(isArch32); 684 } 685 GetPrevFrameFpOptimizedEntryFrame686 inline JSTaggedType* GetPrevFrameFp() 687 { 688 return preLeaveFrameFp; 689 } 690 ComputeReservedSizeOptimizedEntryFrame691 static size_t ComputeReservedSize(size_t slotSize) 692 { 693 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex); 694 return slotSize * slotOffset; 695 } 696 GetTypeOptimizedEntryFrame697 FrameType GetType() const 698 { 699 return type; 700 } 701 friend class FrameIterator; 702 703 private: GetFrameFromSpOptimizedEntryFrame704 static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 705 { 706 return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) - 707 MEMBER_OFFSET(OptimizedEntryFrame, prevFp)); 708 } 709 GetLeaveFpOptimizedEntryFrame710 JSTaggedType* GetLeaveFp() const 711 { 712 return preLeaveFrameFp; 713 } 714 GetPrevFpOptimizedEntryFrame715 JSTaggedType* GetPrevFp() const 716 { 717 return prevFp; 718 } 719 720 alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr}; 721 alignas(EAS) FrameType type {0}; 722 alignas(EAS) JSTaggedType *prevFp {nullptr}; 723 }; 724 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64); 725 726 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 727 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(), 728 base::AlignedPointer, 729 base::AlignedSize> { 730 enum class Index : size_t { 731 PrevIndex = 0, 732 TypeIndex, 733 NumOfMembers 734 }; 735 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 736 GetPrevFrameFpInterpretedFrameBase737 inline JSTaggedType* GetPrevFrameFp() 738 { 739 return prev; 740 } 741 GetFrameFromSpInterpretedFrameBase742 static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp) 743 { 744 return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1; 745 } 746 747 static size_t GetPrevOffset(bool isArch32 = false) 748 { 749 return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32); 750 } 751 752 static size_t GetTypeOffset(bool isArch32 = false) 753 { 754 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 755 } 756 GetSizeInterpretedFrameBase757 static constexpr size_t GetSize(bool isArch32) 758 { 759 return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64; 760 } 761 762 alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc 763 alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0 764 }; 765 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase), 766 InterpretedFrameBase::SizeArch32, 767 InterpretedFrameBase::SizeArch64); 768 769 // Interpreter Frame Layout as the following: 770 // +----------------------------------+ 771 // | argv[n-1] | 772 // |----------------------------------| 773 // | ...... | 774 // |----------------------------------| 775 // | thisArg [maybe not exist] | 776 // |----------------------------------| 777 // | newTarget [maybe not exist] | 778 // |----------------------------------| 779 // | ...... | 780 // |----------------------------------| 781 // | Vregs [not exist in native] | 782 // +----------------------------------+--------+ 783 // | base.frameType | ^ 784 // |----------------------------------| | 785 // | base.prev(prev stack pointer) | | 786 // |----------------------------------| | 787 // | pc(bytecode addr) | | 788 // |----------------------------------| | 789 // | sp(current stack pointer) | | 790 // |----------------------------------| | 791 // | env | | 792 // |----------------------------------| | 793 // | acc | | 794 // |----------------------------------| InterpretedFrame 795 // | profileTypeInfo | | 796 // |----------------------------------| | 797 // | thisObj | | 798 // |----------------------------------| | 799 // | function | | 800 // |----------------------------------| | 801 // | constpool | v 802 // +----------------------------------+--------+ 803 // 804 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 805 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 806 JSTaggedValue, 807 JSTaggedValue, 808 JSTaggedValue, 809 JSTaggedValue, 810 JSTaggedValue, 811 JSTaggedValue, 812 base::AlignedPointer, 813 InterpretedFrameBase> { 814 public: 815 enum class Index : size_t { 816 ConstPoolIndex = 0, 817 FunctionIndex, 818 ThisObjIndex, 819 ProFileTypeInfoIndex, 820 AccIndex, 821 EnvIndex, 822 PcIndex, 823 BaseIndex, 824 NumOfMembers 825 }; 826 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 827 GetPrevFrameFpInterpretedFrame828 inline JSTaggedType* GetPrevFrameFp() const 829 { 830 return base.prev; 831 } 832 GetFrameFromSpInterpretedFrame833 static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 834 { 835 return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 836 } 837 GetPcInterpretedFrame838 inline const uint8_t *GetPc() const 839 { 840 return pc; 841 } 842 GetEnvInterpretedFrame843 inline JSTaggedValue GetEnv() const 844 { 845 return env; 846 } 847 NumOfMembersInterpretedFrame848 static uint32_t NumOfMembers() 849 { 850 return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 851 } 852 GetPcOffsetInterpretedFrame853 static size_t GetPcOffset(bool isArch32) 854 { 855 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 856 } 857 858 static size_t GetTypeOffset(bool isArch32 = false) 859 { 860 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 861 InterpretedFrameBase::GetTypeOffset(isArch32); 862 } 863 864 static size_t GetPrevOffset(bool isArch32 = false) 865 { 866 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 867 InterpretedFrameBase::GetPrevOffset(isArch32); 868 } 869 870 static size_t GetFunctionOffset(bool isArch32 = false) 871 { 872 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 873 } 874 875 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 876 877 alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()}; 878 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 879 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 880 alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()}; 881 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 882 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 883 alignas(EAS) const uint8_t *pc {nullptr}; 884 alignas(EAS) InterpretedFrameBase base; 885 friend class FrameIterator; 886 }; 887 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64); 888 889 // * InterpretedBuiltinFrame layout description as the following: 890 // |--------------------------| --------------- 891 // | . . . . . | ^ 892 // | InterpretedFrameBase | | 893 // | . . . . . | | 894 // |--------------------------| InterpretedBuiltinFrame 895 // | bytecode-PC | | 896 // |--------------------------| | 897 // | call-target | v 898 // +--------------------------+ --------------- 899 // 900 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 901 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 902 JSTaggedValue, 903 base::AlignedPointer, 904 InterpretedFrameBase> { 905 enum class Index : size_t { 906 FunctionIndex = 0, 907 PcIndex, 908 BaseIndex, 909 NumOfMembers 910 }; 911 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 912 GetPrevFrameFpInterpretedBuiltinFrame913 inline JSTaggedType* GetPrevFrameFp() 914 { 915 return base.prev; 916 } 917 GetFrameFromSpInterpretedBuiltinFrame918 static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 919 { 920 return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 921 } 922 NumOfMembersInterpretedBuiltinFrame923 static uint32_t NumOfMembers() 924 { 925 return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize(); 926 } 927 928 static size_t GetTypeOffset(bool isArch32 = false) 929 { 930 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 931 InterpretedFrameBase::GetTypeOffset(isArch32); 932 } 933 934 static size_t GetPrevOffset(bool isArch32 = false) 935 { 936 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 937 InterpretedFrameBase::GetPrevOffset(isArch32); 938 } 939 940 static size_t GetFunctionOffset(bool isArch32 = false) 941 { 942 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 943 } 944 945 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 946 947 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 948 alignas(EAS) const uint8_t *pc {nullptr}; 949 alignas(EAS) InterpretedFrameBase base; 950 }; 951 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame), 952 InterpretedBuiltinFrame::SizeArch32, 953 InterpretedBuiltinFrame::SizeArch64); 954 955 // AsmInterpretedFrame Layout as the following: 956 // +----------------------------------+ 957 // | argv[n-1] | 958 // |----------------------------------| 959 // | ...... | 960 // |----------------------------------| 961 // | thisArg [maybe not exist] | 962 // |----------------------------------| 963 // | newTarget [maybe not exist] | 964 // |----------------------------------| 965 // | ...... | 966 // |----------------------------------| 967 // | Vregs [not exist in native] | 968 // +----------------------------------+--------+ 969 // | . . . . | ^ 970 // | InterpretedFrameBase | | 971 // | . . . . | | 972 // |----------------------------------| | 973 // | pc(bytecode addr) | | 974 // |----------------------------------| | 975 // | sp(current stack pointer) | | 976 // |----------------------------------| AsmInterpretedFrame 977 // | callSize | | 978 // |----------------------------------| | 979 // | env | | 980 // |----------------------------------| | 981 // | acc | | 982 // |----------------------------------| | 983 // | thisObj | | 984 // |----------------------------------| | 985 // | call-target | v 986 // +----------------------------------+--------+ 987 // 988 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 989 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 990 JSTaggedValue, 991 JSTaggedValue, 992 JSTaggedValue, 993 JSTaggedValue, 994 base::AlignedPointer, 995 base::AlignedPointer, 996 base::AlignedPointer, 997 InterpretedFrameBase> { 998 enum class Index : size_t { 999 FunctionIndex = 0, 1000 ThisObjIndex, 1001 AccIndex, 1002 EnvIndex, 1003 CallSizeIndex, 1004 FpIndex, 1005 PcIndex, 1006 BaseIndex, 1007 NumOfMembers 1008 }; 1009 1010 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1011 GetCurrentFramePointerAsmInterpretedFrame1012 inline JSTaggedType* GetCurrentFramePointer() 1013 { 1014 return fp; 1015 } 1016 GetPrevFrameFpAsmInterpretedFrame1017 inline JSTaggedType* GetPrevFrameFp() 1018 { 1019 return base.prev; 1020 } 1021 GetFrameFromSpAsmInterpretedFrame1022 static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 1023 { 1024 return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1025 } 1026 GetFpOffsetAsmInterpretedFrame1027 static size_t GetFpOffset(bool isArch32) 1028 { 1029 return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32); 1030 } 1031 GetCallSizeOffsetAsmInterpretedFrame1032 static size_t GetCallSizeOffset(bool isArch32) 1033 { 1034 return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32); 1035 } 1036 GetFunctionOffsetAsmInterpretedFrame1037 static size_t GetFunctionOffset(bool isArch32) 1038 { 1039 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 1040 } 1041 GetThisOffsetAsmInterpretedFrame1042 static size_t GetThisOffset(bool isArch32) 1043 { 1044 return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32); 1045 } 1046 GetAccOffsetAsmInterpretedFrame1047 static size_t GetAccOffset(bool isArch32) 1048 { 1049 return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32); 1050 } 1051 GetEnvOffsetAsmInterpretedFrame1052 static size_t GetEnvOffset(bool isArch32) 1053 { 1054 return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32); 1055 } 1056 GetBaseOffsetAsmInterpretedFrame1057 static size_t GetBaseOffset(bool isArch32) 1058 { 1059 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 1060 } 1061 GetPcOffsetAsmInterpretedFrame1062 static size_t GetPcOffset(bool isArch32) 1063 { 1064 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 1065 } 1066 GetSizeAsmInterpretedFrame1067 static constexpr size_t GetSize(bool isArch32) 1068 { 1069 return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64; 1070 } 1071 GetFpOffsetAsIntptrAsmInterpretedFrame1072 static intptr_t GetFpOffsetAsIntptr(bool isArch32) 1073 { 1074 return static_cast<intptr_t>(GetFpOffset(isArch32)); 1075 } 1076 GetFunctionOffsetAsIntptrAsmInterpretedFrame1077 static intptr_t GetFunctionOffsetAsIntptr(bool isArch32) 1078 { 1079 return static_cast<intptr_t>(GetFunctionOffset(isArch32)); 1080 } 1081 GetSizeAsIntptrAsmInterpretedFrame1082 static intptr_t GetSizeAsIntptr(bool isArch32) 1083 { 1084 return static_cast<intptr_t>(GetSize(isArch32)); 1085 } 1086 NumOfMembersAsmInterpretedFrame1087 static uint32_t NumOfMembers() 1088 { 1089 return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 1090 } 1091 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 1092 const RootBaseAndDerivedVisitor &derivedVisitor, bool isBaselineFrame) const; 1093 GetEnvAsmInterpretedFrame1094 JSTaggedValue GetEnv() const 1095 { 1096 return env; 1097 } 1098 GetPcAsmInterpretedFrame1099 const uint8_t *GetPc() const 1100 { 1101 return pc; 1102 } 1103 GetTypeOffsetAsmInterpretedFrame1104 static size_t GetTypeOffset() 1105 { 1106 return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type); 1107 } 1108 GetPrevOffsetAsmInterpretedFrame1109 static size_t GetPrevOffset() 1110 { 1111 return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev); 1112 } 1113 1114 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 1115 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 1116 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 1117 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 1118 alignas(EAS) uintptr_t callSize {0}; 1119 alignas(EAS) JSTaggedType *fp {nullptr}; 1120 alignas(EAS) const uint8_t *pc {nullptr}; 1121 alignas(EAS) InterpretedFrameBase base; 1122 // vregs, not exist in native 1123 // args, may be truncated if not extra 1124 }; 1125 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64); 1126 1127 // InterpretedEntryFrame Layout as the following: 1128 // +----------------------------------+--------------- 1129 // | . . . . | ^ 1130 // | InterpretedFrameBase | | 1131 // | . . . . | InterpretedEntryFrame 1132 // |----------------------------------| | 1133 // | pc(bytecode addr) | v 1134 // |----------------------------------|--------------- 1135 // 1136 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1137 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1138 base::AlignedPointer, 1139 InterpretedFrameBase> { 1140 enum class Index : size_t { 1141 PcIndex = 0, 1142 BaseIndex, 1143 NumOfMembers 1144 }; 1145 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1146 GetPrevFrameFpInterpretedEntryFrame1147 inline JSTaggedType* GetPrevFrameFp() 1148 { 1149 return base.prev; 1150 } 1151 GetFrameFromSpInterpretedEntryFrame1152 static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 1153 { 1154 return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1155 } 1156 NumOfMembersInterpretedEntryFrame1157 static uint32_t NumOfMembers() 1158 { 1159 return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize(); 1160 } 1161 1162 static size_t GetTypeOffset(bool isArch32 = false) 1163 { 1164 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1165 InterpretedFrameBase::GetTypeOffset(isArch32); 1166 } 1167 1168 static size_t GetPrevOffset(bool isArch32 = false) 1169 { 1170 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1171 InterpretedFrameBase::GetPrevOffset(isArch32); 1172 } 1173 1174 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, 1175 const RootRangeVisitor &rangeVisitor) const; 1176 alignas(EAS) const uint8_t *pc {nullptr}; 1177 alignas(EAS) InterpretedFrameBase base; 1178 }; 1179 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame), 1180 InterpretedEntryFrame::SizeArch32, 1181 InterpretedEntryFrame::SizeArch64); 1182 1183 1184 // AsmInterpretedEntryFrame Layout as the following: 1185 // +----------------------------------+--------------- 1186 // | . . . . | ^ 1187 // | InterpretedFrameBase | | 1188 // | . . . . | AsmInterpretedEntryFrame 1189 // |----------------------------------| | 1190 // | pc(bytecode addr) | v 1191 // |----------------------------------|--------------- 1192 // 1193 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1194 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1195 base::AlignedPointer, 1196 InterpretedFrameBase> { 1197 enum class Index : size_t { 1198 PcIndex = 0, 1199 BaseIndex, 1200 NumOfMembers 1201 }; 1202 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1203 GetPrevFrameFpAsmInterpretedEntryFrame1204 inline JSTaggedType* GetPrevFrameFp() 1205 { 1206 return base.prev; 1207 } 1208 GetBaseOffsetAsmInterpretedEntryFrame1209 static size_t GetBaseOffset(bool isArch32) 1210 { 1211 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 1212 } 1213 GetFrameFromSpAsmInterpretedEntryFrame1214 static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 1215 { 1216 return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1217 } 1218 1219 static size_t GetTypeOffset(bool isArch32 = false) 1220 { 1221 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1222 InterpretedFrameBase::GetTypeOffset(isArch32); 1223 } 1224 1225 static size_t GetPrevOffset(bool isArch32 = false) 1226 { 1227 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1228 InterpretedFrameBase::GetPrevOffset(isArch32); 1229 } 1230 1231 alignas(EAS) const uint8_t *pc {nullptr}; 1232 alignas(EAS) InterpretedFrameBase base; 1233 }; 1234 1235 // AsmInterpretedBridgeFrame Layout as the following: 1236 // +----------------------------------+--------------- 1237 // | ret-address | ^ 1238 // |----------------------------------| | 1239 // | . . . . | AsmInterpretedBridgeFrame 1240 // | AsmInterpretedEntryFrame | | 1241 // | . . . . | v 1242 // |----------------------------------|--------------- 1243 // 1244 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1245 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1246 AsmInterpretedEntryFrame, 1247 base::AlignedPointer> { 1248 enum class Index : size_t { 1249 EntryIndex = 0, 1250 ReturnAddrIndex, 1251 NumOfMembers 1252 }; 1253 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1254 GetFrameFromSpAsmInterpretedBridgeFrame1255 static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 1256 { 1257 return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 1258 MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr)); 1259 } GetCallSiteSpAsmInterpretedBridgeFrame1260 uintptr_t GetCallSiteSp() const 1261 { 1262 return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame); 1263 } GetPrevFrameFpAsmInterpretedBridgeFrame1264 inline JSTaggedType* GetPrevFrameFp() 1265 { 1266 return entry.base.prev; 1267 } 1268 GetReturnAddrOffsetAsmInterpretedBridgeFrame1269 static size_t GetReturnAddrOffset(bool isArch32) 1270 { 1271 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 1272 } 1273 GetSizeAsmInterpretedBridgeFrame1274 static constexpr size_t GetSize(bool isArch32) 1275 { 1276 return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64; 1277 } 1278 1279 static size_t GetTypeOffset(bool isArch32 = false) 1280 { 1281 return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) + 1282 AsmInterpretedEntryFrame::GetBaseOffset(isArch32) + 1283 InterpretedFrameBase::GetTypeOffset(isArch32); 1284 } 1285 static size_t GetPrevOffset(bool isArch32 = false) 1286 { 1287 return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) + 1288 AsmInterpretedEntryFrame::GetBaseOffset(isArch32) + 1289 InterpretedFrameBase::GetPrevOffset(isArch32); 1290 } 1291 GetReturnAddrAsmInterpretedBridgeFrame1292 uintptr_t GetReturnAddr() const 1293 { 1294 return returnAddr; 1295 } 1296 1297 AsmInterpretedEntryFrame entry; 1298 alignas(EAS) uintptr_t returnAddr; 1299 }; 1300 1301 // * Optimized-leaved-frame layout as the following: 1302 // +--------------------------+ 1303 // | argv[N-1] | 1304 // |--------------------------| 1305 // | . . . . . | 1306 // |--------------------------| 1307 // | argv[0] | 1308 // +--------------------------+------------- 1309 // | argc | ^ 1310 // |--------------------------| | 1311 // | RuntimeId | | 1312 // callerSP --> |--------------------------| OptimizedLeaveFrame 1313 // | ret-addr | | 1314 // |--------------------------| | 1315 // | prevFp | | 1316 // fp --> |--------------------------| | 1317 // | frameType | v 1318 // calleeSP --> +--------------------------+------------- 1319 // 1320 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1321 struct OptimizedLeaveFrame { 1322 FrameType type; 1323 uintptr_t callsiteFp; // thread sp set here 1324 uintptr_t returnAddr; 1325 uint64_t argRuntimeId; 1326 uint64_t argc; 1327 1328 // argv[0]...argv[argc-1] dynamic according to agc GetFrameFromSpOptimizedLeaveFrame1329 static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1330 { 1331 return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1332 MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp)); 1333 } 1334 GetCallSiteSpOptimizedLeaveFrame1335 uintptr_t GetCallSiteSp() const 1336 { 1337 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId); 1338 } 1339 GetPrevFrameFpOptimizedLeaveFrame1340 inline JSTaggedType* GetPrevFrameFp() const 1341 { 1342 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1343 } 1344 GetReturnAddrOptimizedLeaveFrame1345 uintptr_t GetReturnAddr() const 1346 { 1347 return returnAddr; 1348 } 1349 GetTypeOffsetOptimizedLeaveFrame1350 static size_t GetTypeOffset() 1351 { 1352 return MEMBER_OFFSET(OptimizedLeaveFrame, type); 1353 } 1354 GetPrevOffsetOptimizedLeaveFrame1355 static size_t GetPrevOffset() 1356 { 1357 return MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp); 1358 } 1359 1360 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1361 }; 1362 1363 // * Optimized-leaved-frame-with-argv layout as the following: 1364 // +--------------------------+ 1365 // | argv[] | 1366 // +--------------------------+------------- 1367 // | argc | ^ 1368 // |--------------------------| | 1369 // | RuntimeId | OptimizedWithArgvLeaveFrame 1370 // callerSP --> |--------------------------| | 1371 // | returnAddr | | 1372 // |--------------------------| | 1373 // | callsiteFp | | 1374 // fp --> |--------------------------| | 1375 // | frameType | v 1376 // calleeSP --> +--------------------------+------------- 1377 1378 struct OptimizedWithArgvLeaveFrame { 1379 FrameType type; 1380 uintptr_t callsiteFp; // thread sp set here 1381 uintptr_t returnAddr; 1382 uint64_t argRuntimeId; 1383 uint64_t argc; 1384 GetFrameFromSpOptimizedWithArgvLeaveFrame1385 static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1386 { 1387 return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1388 MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp)); 1389 } 1390 GetCallSiteSpOptimizedWithArgvLeaveFrame1391 uintptr_t GetCallSiteSp() const 1392 { 1393 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId); 1394 } 1395 GetPrevFrameFpOptimizedWithArgvLeaveFrame1396 inline JSTaggedType* GetPrevFrameFp() 1397 { 1398 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1399 } 1400 GetReturnAddrOptimizedWithArgvLeaveFrame1401 uintptr_t GetReturnAddr() const 1402 { 1403 return returnAddr; 1404 } 1405 GetTypeOffsetOptimizedWithArgvLeaveFrame1406 static size_t GetTypeOffset() 1407 { 1408 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type); 1409 } 1410 GetPrevOffsetOptimizedWithArgvLeaveFrame1411 static size_t GetPrevOffset() 1412 { 1413 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp); 1414 } 1415 1416 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1417 }; 1418 1419 // * OptimizedBuiltinLeaveFrame layout as the following: 1420 // +--------------------------+ 1421 // | argv[N-1] | 1422 // |--------------------------| 1423 // | . . . . . | 1424 // |--------------------------| 1425 // | argv[0] | 1426 // +--------------------------+------------- 1427 // | argc | ^ 1428 // |--------------------------| | 1429 // | thread | | 1430 // callerSP --> +--------------------------+ | 1431 // | ret-addr | | 1432 // |--------------------------| OptimizedBuiltinLeaveFrame 1433 // | prevFp | | 1434 // fp --> |--------------------------| | 1435 // | frameType | | 1436 // |--------------------------| | 1437 // | align byte | v 1438 // calleeSP --> +--------------------------+------------- 1439 // 1440 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1441 struct OptimizedBuiltinLeaveFrame { 1442 public: GetFrameFromSpOptimizedBuiltinLeaveFrame1443 static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1444 { 1445 return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1446 MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp)); 1447 } 1448 GetCallSiteSpOptimizedBuiltinLeaveFrame1449 uintptr_t GetCallSiteSp() const 1450 { 1451 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, thread); 1452 } 1453 GetPrevFrameFpOptimizedBuiltinLeaveFrame1454 inline JSTaggedType* GetPrevFrameFp() const 1455 { 1456 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1457 } 1458 GetReturnAddrOptimizedBuiltinLeaveFrame1459 uintptr_t GetReturnAddr() const 1460 { 1461 return returnAddr; 1462 } 1463 1464 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1465 GetTypeOffsetOptimizedBuiltinLeaveFrame1466 static size_t GetTypeOffset() 1467 { 1468 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type); 1469 } 1470 GetPrevOffsetOptimizedBuiltinLeaveFrame1471 static size_t GetPrevOffset() 1472 { 1473 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp); 1474 } 1475 GetFunctionOffsetOptimizedBuiltinLeaveFrame1476 static size_t GetFunctionOffset() 1477 { 1478 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argc) + 1; 1479 } 1480 GetArgvOptimizedBuiltinLeaveFrame1481 const JSTaggedType* GetArgv() const 1482 { 1483 return reinterpret_cast<const JSTaggedType *>(&argc + 1); 1484 } 1485 GetTypeOptimizedBuiltinLeaveFrame1486 FrameType GetType() const 1487 { 1488 return type; 1489 } 1490 1491 private: 1492 FrameType type; 1493 uintptr_t callsiteFp; // thread sp set here 1494 uintptr_t returnAddr; 1495 JSTaggedValue thread; 1496 uint64_t argc; 1497 // argv[0]...argv[argc-1] dynamic according to agc 1498 }; 1499 1500 // * BuiltinFrame layout as the following: 1501 // +--------------------------+ 1502 // | argV[N - 1] | 1503 // |--------------------------| 1504 // | . . . . | 1505 // |--------------------------+ 1506 // | argV[2]=this | 1507 // +--------------------------+ 1508 // | argV[1]=new-target | 1509 // +--------------------------+ 1510 // | argV[0]=call-target | 1511 // +--------------------------+ --------- 1512 // | argc | ^ 1513 // |--------------------------| | 1514 // | thread | | 1515 // callerSP --> |--------------------------| | 1516 // | returnAddr | BuiltinFrame 1517 // |--------------------------| | 1518 // | callsiteFp | | 1519 // fp --> |--------------------------| | 1520 // | frameType | v 1521 // calleeSP --> +--------------------------+ --------- 1522 // 1523 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1524 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1525 base::AlignedSize, 1526 base::AlignedPointer, 1527 base::AlignedPointer, 1528 base::AlignedPointer, 1529 base::AlignedPointer, 1530 base::AlignedPointer> { 1531 enum class Index : size_t { 1532 TypeIndex = 0, 1533 PrevFpIndex, 1534 ReturnAddrIndex, 1535 ThreadIndex, 1536 NumArgsIndex, 1537 StackArgsIndex, 1538 NumOfMembers 1539 }; 1540 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1541 GetFrameFromSpBuiltinFrame1542 static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 1543 { 1544 return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) - 1545 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1546 } 1547 GetPrevFrameFpBuiltinFrame1548 inline JSTaggedType* GetPrevFrameFp() 1549 { 1550 return prevFp; 1551 } 1552 GetCallSiteSpBuiltinFrame1553 uintptr_t GetCallSiteSp() const 1554 { 1555 return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread); 1556 } 1557 GetPreFpOffsetBuiltinFrame1558 static size_t GetPreFpOffset(bool isArch32) 1559 { 1560 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1561 } 1562 GetNumArgsToFpDeltaBuiltinFrame1563 static size_t GetNumArgsToFpDelta(bool isArch32) 1564 { 1565 auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32); 1566 return offset - GetPreFpOffset(isArch32); 1567 } 1568 GetStackArgsToFpDeltaBuiltinFrame1569 static size_t GetStackArgsToFpDelta(bool isArch32) 1570 { 1571 auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 1572 return offset - GetPreFpOffset(isArch32); 1573 } 1574 GetStackArgsAddressBuiltinFrame1575 uintptr_t GetStackArgsAddress() 1576 { 1577 return reinterpret_cast<uintptr_t>(&stackArgs); 1578 } 1579 GetFunctionBuiltinFrame1580 JSTaggedValue GetFunction() 1581 { 1582 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1583 return JSTaggedValue(*functionAddress); 1584 } 1585 GetNumArgsBuiltinFrame1586 uint32_t GetNumArgs() 1587 { 1588 return numArgs; 1589 } 1590 GetReturnAddrBuiltinFrame1591 uintptr_t GetReturnAddr() const 1592 { 1593 return returnAddr; 1594 } 1595 1596 static size_t GetStackArgsOffset(bool isArch32 = false) 1597 { 1598 return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 1599 } 1600 1601 static size_t GetTypeOffset(bool isArch32 = false) 1602 { 1603 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1604 } 1605 1606 static size_t GetPrevOffset(bool isArch32 = false) 1607 { 1608 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1609 } 1610 1611 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1612 1613 alignas(EAS) FrameType type; 1614 alignas(EAS) JSTaggedType *prevFp; 1615 alignas(EAS) uintptr_t returnAddr; 1616 alignas(EAS) uintptr_t thread; 1617 alignas(EAS) uint32_t numArgs; 1618 alignas(EAS) uintptr_t stackArgs; 1619 }; 1620 1621 // * BuiltinWithArgvFrame layout as the following: 1622 // +--------------------------+ --------- 1623 // | . . . . . | ^ 1624 // callerSP --> |--------------------------| | 1625 // | returnAddr | | 1626 // |--------------------------| | 1627 // | callsiteFp | BuiltinWithArgvFrame 1628 // fp --> |--------------------------| | 1629 // | frameType | | 1630 // +--------------------------+ | 1631 // | argc | v 1632 // +--------------------------+ --------- 1633 // | argV[0] | 1634 // +--------------------------+ 1635 // | argV[1] | 1636 // +--------------------------+ 1637 // | . . . . | 1638 // calleeSP --> +--------------------------+ 1639 // 1640 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1641 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1642 base::AlignedSize, 1643 base::AlignedPointer, 1644 base::AlignedPointer> { 1645 enum class Index : int { 1646 StackArgsTopIndex = -1, 1647 NumArgsIndex = -1, 1648 TypeIndex = 0, 1649 PrevFpIndex, 1650 ReturnAddrIndex, 1651 NumOfMembers 1652 }; 1653 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1654 GetFrameFromSpBuiltinWithArgvFrame1655 static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp) 1656 { 1657 return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) - 1658 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1659 } 1660 GetPrevFrameFpBuiltinWithArgvFrame1661 inline JSTaggedType* GetPrevFrameFp() 1662 { 1663 return prevFp; 1664 } 1665 GetCallSiteSpBuiltinWithArgvFrame1666 uintptr_t GetCallSiteSp() const 1667 { 1668 return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame); 1669 } 1670 GetStackArgsAddressBuiltinWithArgvFrame1671 uintptr_t GetStackArgsAddress() 1672 { 1673 auto topAddress = ToUintPtr(this) + 1674 (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t)); 1675 auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS; 1676 return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t); 1677 } 1678 GetFunctionBuiltinWithArgvFrame1679 JSTaggedValue GetFunction() 1680 { 1681 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1682 return JSTaggedValue(*functionAddress); 1683 } 1684 GetNumArgsBuiltinWithArgvFrame1685 int32_t GetNumArgs() 1686 { 1687 auto argcAddress = reinterpret_cast<int32_t *>( 1688 ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t))); 1689 return *argcAddress; 1690 } 1691 GetReturnAddrBuiltinWithArgvFrame1692 uintptr_t GetReturnAddr() const 1693 { 1694 return returnAddr; 1695 } 1696 1697 static size_t GetTypeOffset(bool isArch32 = false) 1698 { 1699 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1700 } 1701 1702 static size_t GetPrevOffset(bool isArch32 = false) 1703 { 1704 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1705 } 1706 1707 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1708 // argv(... this, new.target, function) 1709 // numargs 1710 alignas(EAS) FrameType type; 1711 alignas(EAS) JSTaggedType *prevFp; 1712 alignas(EAS) uintptr_t returnAddr; 1713 }; 1714 1715 // * FASTJITFunctionFrame layout description as the following: 1716 // +--------------------------+ 1717 // | arg[N-1] | 1718 // +--------------------------+ 1719 // | ... | 1720 // +--------------------------+ 1721 // | arg[1] | 1722 // +--------------------------+ 1723 // | arg[0] | 1724 // +--------------------------+ 1725 // | this | 1726 // +--------------------------+ 1727 // | new-target | 1728 // +--------------------------+ 1729 // | call-target | 1730 // |--------------------------| 1731 // | argc | 1732 // callerSp ---> |--------------------------| --------------- 1733 // | returnAddr | ^ 1734 // |--------------------------| | 1735 // | callsiteFp | | 1736 // |--------------------------| | 1737 // | frameType | FASTJITFunctionFrame 1738 // |--------------------------| | 1739 // | call-target | | 1740 // |--------------------------| | 1741 // | pc(bytecode pc) | v 1742 // calleeSP ---> +--------------------------+ --------------- 1743 // 1744 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1745 struct FASTJITFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1746 JSTaggedValue, 1747 JSTaggedValue, 1748 base::AlignedPointer, 1749 base::AlignedPointer, 1750 base::AlignedPointer> { 1751 public: 1752 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 1753 enum class Index : size_t { 1754 PcIndex = 0, 1755 JSFuncIndex, 1756 TypeIndex, 1757 PrevFpIndex, 1758 ReturnAddrIndex, 1759 NumOfMembers 1760 }; 1761 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1762 GetFunctionDeltaReturnAddrFASTJITFunctionFrame1763 static constexpr size_t GetFunctionDeltaReturnAddr() 1764 { 1765 return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex); 1766 } 1767 GetPrevFrameFpFASTJITFunctionFrame1768 inline JSTaggedType* GetPrevFrameFp() 1769 { 1770 return prevFp; 1771 } 1772 GetArgvFASTJITFunctionFrame1773 JSTaggedType* GetArgv(uintptr_t *preFrameSp) const 1774 { 1775 const size_t offset = 2; // 2: skip argc and argv. 1776 return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t)); 1777 } 1778 GetArgcFASTJITFunctionFrame1779 size_t GetArgc(uintptr_t *preFrameSp) const 1780 { 1781 return *preFrameSp; 1782 } 1783 1784 JSTaggedType* GetArgv(const FrameIterator &it) const; 1785 GetReturnAddrFASTJITFunctionFrame1786 uintptr_t GetReturnAddr() const 1787 { 1788 return returnAddr; 1789 } 1790 1791 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 1792 const RootBaseAndDerivedVisitor &derivedVisitor, FrameType frameType) const; 1793 void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const; 1794 GetFunctionFASTJITFunctionFrame1795 inline JSTaggedValue GetFunction() const 1796 { 1797 return jsFunc; 1798 } 1799 ComputeArgsConfigFrameSpFASTJITFunctionFrame1800 static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp) 1801 { 1802 const size_t offset = 2; // 2: skip prevFp and return address. 1803 return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t); 1804 } 1805 1806 static size_t GetTypeOffset(bool isArch32 = false) 1807 { 1808 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1809 } 1810 1811 static size_t GetPcOffset(bool isArch32 = false) 1812 { 1813 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 1814 } 1815 1816 static size_t GetPrevOffset(bool isArch32 = false) 1817 { 1818 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1819 } 1820 1821 static size_t GetFunctionOffset(bool isArch32 = false) 1822 { 1823 return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32); 1824 } 1825 ComputeReservedJSFuncOffsetFASTJITFunctionFrame1826 static size_t ComputeReservedJSFuncOffset(size_t slotSize) 1827 { 1828 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex); 1829 return slotSize * slotOffset; 1830 } 1831 ComputeReservedPcOffsetFASTJITFunctionFrame1832 static size_t ComputeReservedPcOffset(size_t slotSize) 1833 { 1834 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PcIndex); 1835 return slotSize * slotOffset; 1836 } 1837 GetTypeFASTJITFunctionFrame1838 FrameType GetType() const 1839 { 1840 return type; 1841 } 1842 GetPcFASTJITFunctionFrame1843 inline const uint8_t *GetPc() const 1844 { 1845 return pc; 1846 } 1847 1848 friend class FrameIterator; 1849 friend class FrameHandler; 1850 void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const; 1851 void GetFuncCalleeRegAndOffset( 1852 const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const; 1853 uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const; 1854 1855 private: GetFrameFromSpFASTJITFunctionFrame1856 static FASTJITFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) 1857 { 1858 return reinterpret_cast<FASTJITFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) - 1859 MEMBER_OFFSET(FASTJITFunctionFrame, prevFp)); 1860 } 1861 GetFuncAddrFromSpFASTJITFunctionFrame1862 static uintptr_t GetFuncAddrFromSp(const JSTaggedType *sp) 1863 { 1864 return reinterpret_cast<uintptr_t>(sp) - MEMBER_OFFSET(FASTJITFunctionFrame, type); 1865 } 1866 1867 // dynamic callee saveregisters for x86-64 1868 alignas(EAS) const uint8_t *pc {nullptr}; 1869 alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()}; 1870 alignas(EAS) FrameType type {0}; 1871 alignas(EAS) JSTaggedType *prevFp {nullptr}; 1872 alignas(EAS) uintptr_t returnAddr {0}; 1873 // dynamic callee saveregisters for arm64 1874 }; 1875 1876 enum class GCVisitedFlag : uint8_t { 1877 VISITED = 0, 1878 IGNORED, 1879 HYBRID_STACK, 1880 DEOPT, 1881 }; 1882 1883 class FrameIterator { 1884 public: 1885 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 1886 using CallSiteInfo = std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec>; 1887 explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr); GetFrameType()1888 FrameType GetFrameType() const 1889 { 1890 ASSERT(current_ != nullptr); 1891 FrameType *typeAddr = reinterpret_cast<FrameType *>( 1892 reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType)); 1893 return *typeAddr; 1894 } 1895 1896 template<class T> GetFrame()1897 T* GetFrame() 1898 { 1899 return T::GetFrameFromSp(current_); 1900 } 1901 1902 template<class T> GetFrame()1903 const T* GetFrame() const 1904 { 1905 return T::GetFrameFromSp(current_); 1906 } 1907 Done()1908 bool Done() const 1909 { 1910 return current_ == nullptr; 1911 } GetSp()1912 JSTaggedType *GetSp() const 1913 { 1914 return current_; 1915 } GetSp()1916 JSTaggedType *GetSp() 1917 { 1918 return current_; 1919 } GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)1920 void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const 1921 { 1922 ret = calleeRegInfo_; 1923 } 1924 int ComputeDelta(const Method *method = nullptr) const; 1925 template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED> 1926 void Advance(); 1927 std::map<uint32_t, uint32_t> GetInlinedMethodInfo(); 1928 uint32_t GetBytecodeOffset() const; 1929 uintptr_t GetPrevFrameCallSiteSp() const; 1930 uintptr_t GetPrevFrame() const; GetCallSiteSp()1931 uintptr_t GetCallSiteSp() const 1932 { 1933 return optimizedCallSiteSp_; 1934 } GetOptimizedReturnAddr()1935 uintptr_t GetOptimizedReturnAddr() const 1936 { 1937 return optimizedReturnAddr_; 1938 } GetThread()1939 const JSThread *GetThread() const 1940 { 1941 return thread_; 1942 } 1943 bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const; 1944 void CollectPcOffsetInfo(ConstInfo &info) const; 1945 void CollectMethodOffsetInfo(std::map<uint32_t, uint32_t> &info) const; 1946 void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const; 1947 std::pair<CallSiteInfo, bool> CalCallSiteInfo(uintptr_t retAddr, bool isDeopt) const; 1948 CallSiteInfo TryCalCallSiteInfoFromMachineCode(uintptr_t retAddr) const; 1949 1950 Method *CheckAndGetMethod() const; 1951 JSTaggedValue GetFunction() const; 1952 IsLeaveFrame()1953 bool IsLeaveFrame() const 1954 { 1955 FrameType type = GetFrameType(); 1956 return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV); 1957 } 1958 IsOptimizedFrame()1959 bool IsOptimizedFrame() const 1960 { 1961 FrameType type = GetFrameType(); 1962 return (type == FrameType::OPTIMIZED_FRAME); 1963 } 1964 IsInterpretedFrame(FrameType type)1965 bool IsInterpretedFrame(FrameType type) const 1966 { 1967 return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST); 1968 } 1969 IsJSFrame()1970 bool IsJSFrame() const 1971 { 1972 FrameType type = GetFrameType(); 1973 return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type) || IsFastJitFunctionFrame(type); 1974 } 1975 IsOptimizedJSFunctionFrame(FrameType type)1976 bool IsOptimizedJSFunctionFrame(FrameType type) const 1977 { 1978 return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || 1979 type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME; 1980 } 1981 IsOptimizedJSFunctionFrame()1982 bool IsOptimizedJSFunctionFrame() const 1983 { 1984 FrameType type = GetFrameType(); 1985 return IsOptimizedJSFunctionFrame(type); 1986 } 1987 IsFastJitFunctionFrame(FrameType type)1988 bool IsFastJitFunctionFrame(FrameType type) const 1989 { 1990 return type == FrameType::FASTJIT_FUNCTION_FRAME || 1991 type == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME; 1992 } 1993 IsFastJitFunctionFrame()1994 bool IsFastJitFunctionFrame() const 1995 { 1996 FrameType type = GetFrameType(); 1997 return IsFastJitFunctionFrame(type); 1998 } 1999 IsAotOrJitFunctionFrame()2000 bool IsAotOrJitFunctionFrame() const 2001 { 2002 return IsOptimizedJSFunctionFrame() || IsFastJitFunctionFrame(); 2003 } 2004 GetMachineCodeSlot()2005 JSTaggedType *GetMachineCodeSlot() const 2006 { 2007 return const_cast<JSTaggedType*>(&machineCode_); 2008 } 2009 2010 private: 2011 JSTaggedType *current_ {nullptr}; 2012 const JSThread *thread_ {nullptr}; 2013 const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr}; 2014 uintptr_t optimizedCallSiteSp_ {0}; 2015 uintptr_t optimizedReturnAddr_ {0}; 2016 uint8_t *stackMapAddr_ {nullptr}; 2017 kungfu::CalleeRegAndOffsetVec calleeRegInfo_; 2018 2019 // in jit, delta on method is not set, get it from iterator 2020 bool isJITFrame_ {false}; 2021 int fpDeltaPrevFrameSp_ {0}; 2022 2023 // cache current machine code, it's nonmovable 2024 JSTaggedType machineCode_ {JSTaggedValue::VALUE_UNDEFINED}; 2025 }; 2026 } // namespace panda::ecmascript 2027 #endif // ECMASCRIPT_FRAMES_H 2028