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, RootVisitor &visitor) const; 188 189 static size_t GetTypeOffset(bool isArch32 = false) 190 { 191 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 192 } 193 194 static size_t GetPrevOffset(bool isArch32 = false) 195 { 196 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 197 } 198 199 static size_t GetReturnAddrOffset(bool isArch32 = false) 200 { 201 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 202 } 203 ComputeReservedSizeOptimizedFrame204 static size_t ComputeReservedSize(size_t slotSize) 205 { 206 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex); 207 return slotSize * slotOffset; 208 } 209 GetTypeOptimizedFrame210 FrameType GetType() const 211 { 212 return type; 213 } 214 215 private: 216 enum class Index : size_t { 217 TypeIndex = 0, 218 PrevFpIndex, 219 ReturnAddrIndex, 220 NumOfMembers 221 }; 222 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 223 GetFrameFromSpOptimizedFrame224 static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp) 225 { 226 return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp) - 227 MEMBER_OFFSET(OptimizedFrame, prevFp)); 228 } GetPrevFrameFpOptimizedFrame229 inline JSTaggedType* GetPrevFrameFp() 230 { 231 return prevFp; 232 } GetReturnAddrOptimizedFrame233 uintptr_t GetReturnAddr() const 234 { 235 return returnAddr; 236 } 237 238 alignas(EAS) FrameType type {0}; 239 alignas(EAS) JSTaggedType *prevFp {nullptr}; 240 alignas(EAS) uintptr_t returnAddr {0}; 241 friend class FrameIterator; 242 }; 243 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64); 244 245 // * BaselineBuiltinFrame layout as the following: 246 // +--------------------------+ --------- 247 // | . . . . . | ^ 248 // callerSP ---> |--------------------------| | 249 // | returnAddr | | 250 // |--------------------------| BuiltinBuiltinFrame 251 // | callsiteFp | | 252 // fp ---> |--------------------------| | 253 // | frameType | v 254 // +--------------------------+ --------- 255 // | . . . . | 256 // calleeSP ---> +--------------------------+ 257 // 258 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 259 struct BaselineBuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 260 base::AlignedPointer, 261 base::AlignedPointer, 262 base::AlignedPointer> { 263 public: 264 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 265 266 static size_t GetTypeOffset(bool isArch32 = false) 267 { 268 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 269 } 270 271 static size_t GetPrevOffset(bool isArch32 = false) 272 { 273 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 274 } 275 276 static size_t GetReturnAddrOffset(bool isArch32 = false) 277 { 278 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 279 } 280 ComputeReservedSizeBaselineBuiltinFrame281 static size_t ComputeReservedSize(size_t slotSize) 282 { 283 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex); 284 return slotSize * slotOffset; 285 } 286 GetTypeBaselineBuiltinFrame287 FrameType GetType() const 288 { 289 return type; 290 } 291 GetReturnAddrBaselineBuiltinFrame292 uintptr_t GetReturnAddr() const 293 { 294 return returnAddr; 295 } 296 297 private: 298 enum class Index : size_t { 299 TypeIndex = 0, 300 PrevFpIndex, 301 ReturnAddrIndex, 302 NumOfMembers 303 }; 304 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 305 GetFrameFromSpBaselineBuiltinFrame306 static BaselineBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 307 { 308 return reinterpret_cast<BaselineBuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) - 309 MEMBER_OFFSET(BaselineBuiltinFrame, prevFp)); 310 } GetPrevFrameFpBaselineBuiltinFrame311 inline JSTaggedType* GetPrevFrameFp() 312 { 313 return prevFp; 314 } 315 316 alignas(EAS) FrameType type {0}; 317 alignas(EAS) JSTaggedType *prevFp {nullptr}; 318 alignas(EAS) uintptr_t returnAddr {0}; 319 friend class FrameIterator; 320 }; 321 STATIC_ASSERT_EQ_ARCH(sizeof(BaselineBuiltinFrame), BaselineBuiltinFrame::SizeArch32, BaselineBuiltinFrame::SizeArch64); 322 323 struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 324 base::AlignedPointer, 325 base::AlignedPointer, 326 base::AlignedPointer> { 327 public: 328 static size_t GetTypeOffset(bool isArch32 = false) 329 { 330 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 331 } 332 333 static size_t GetPrevOffset(bool isArch32 = false) 334 { 335 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 336 } 337 338 static size_t GetReturnAddrOffset(bool isArch32 = false) 339 { 340 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 341 } 342 GetCallSiteSpAsmBridgeFrame343 uintptr_t GetCallSiteSp() const 344 { 345 return ToUintPtr(this) + sizeof(AsmBridgeFrame); 346 } 347 GetTypeAsmBridgeFrame348 FrameType GetType() const 349 { 350 return type; 351 } 352 353 private: 354 enum class Index : size_t { 355 TypeIndex = 0, 356 PrevFpIndex, 357 ReturnAddrIndex, 358 NumOfMembers 359 }; 360 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 361 GetFrameFromSpAsmBridgeFrame362 static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 363 { 364 return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 365 MEMBER_OFFSET(AsmBridgeFrame, prevFp)); 366 } GetPrevFrameFpAsmBridgeFrame367 inline JSTaggedType* GetPrevFrameFp() 368 { 369 return prevFp; 370 } GetReturnAddrAsmBridgeFrame371 uintptr_t GetReturnAddr() const 372 { 373 return returnAddr; 374 } 375 alignas(EAS) FrameType type {0}; 376 alignas(EAS) JSTaggedType *prevFp {nullptr}; 377 alignas(EAS) uintptr_t returnAddr {0}; 378 friend class FrameIterator; 379 }; 380 STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64); 381 382 // * OptimizedUnfoldArgVFrame layout description as the following: 383 // callerSP ---> |--------------------------| --------------- 384 // | returnAddr | ^ 385 // |--------------------------| | 386 // | prevFp | | 387 // fp ---> |--------------------------| OptimizedUnfoldArgVFrame 388 // | frameType | | 389 // |--------------------------| | 390 // | currentFp | v 391 // calleESP ---> +--------------------------+ --------------- 392 // 393 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 394 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 395 base::AlignedPointer, 396 base::AlignedPointer, 397 base::AlignedPointer, 398 base::AlignedPointer> { 399 public: 400 static size_t GetTypeOffset(bool isArch32 = false) 401 { 402 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 403 } 404 405 static size_t GetPrevOffset(bool isArch32 = false) 406 { 407 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 408 } 409 410 static size_t GetReturnAddrOffset(bool isArch32 = false) 411 { 412 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 413 } 414 GetTypeOptimizedJSFunctionUnfoldArgVFrame415 FrameType GetType() const 416 { 417 return type; 418 } 419 420 private: 421 enum class Index : size_t { 422 CallSiteSpIndex = 0, 423 TypeIndex, 424 PrevFpIndex, 425 ReturnAddrIndex, 426 NumOfMembers 427 }; 428 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 429 GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame430 static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp) 431 { 432 return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp) - 433 MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp)); 434 } GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame435 inline JSTaggedType* GetPrevFrameFp() const 436 { 437 return prevFp; 438 } GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame439 uintptr_t GetReturnAddr() const 440 { 441 return returnAddr; 442 } GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame443 uintptr_t GetPrevFrameSp() const 444 { 445 return callSiteSp; 446 } 447 alignas(EAS) uintptr_t callSiteSp {0}; 448 alignas(EAS) FrameType type {0}; 449 alignas(EAS) JSTaggedType *prevFp {nullptr}; 450 alignas(EAS) uintptr_t returnAddr {0}; 451 friend class FrameIterator; 452 }; 453 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame), 454 OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64); 455 456 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following: 457 // +--------------------------+ 458 // | arg[N-1] | 459 // +--------------------------+ 460 // | . . . . | 461 // +--------------------------+ 462 // | arg[0] | 463 // +--------------------------+ 464 // | argC | 465 // sp ---> +--------------------------+ ----------------- 466 // | | ^ 467 // | prevFP | | 468 // fp ---> |--------------------------| OptimizedJSFunctionArgsConfigFrame 469 // | frameType | | 470 // | | V 471 // +--------------------------+ ----------------- 472 // 473 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 474 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 475 base::AlignedPointer, 476 base::AlignedPointer> { 477 public: 478 static size_t GetTypeOffset(bool isArch32 = false) 479 { 480 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 481 } 482 483 static size_t GetPrevOffset(bool isArch32 = false) 484 { 485 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 486 } 487 GetTypeOptimizedJSFunctionArgConfigFrame488 FrameType GetType() const 489 { 490 return type; 491 } 492 493 private: 494 enum class Index : size_t { 495 TypeIndex = 0, 496 PrevFpIndex, 497 NumOfMembers 498 }; 499 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 500 GetFrameFromSpOptimizedJSFunctionArgConfigFrame501 static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp) 502 { 503 return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp) - 504 MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp)); 505 } GetPrevFrameFpOptimizedJSFunctionArgConfigFrame506 inline JSTaggedType* GetPrevFrameFp() 507 { 508 return prevFp; 509 } 510 511 alignas(EAS) FrameType type {0}; 512 alignas(EAS) JSTaggedType *prevFp {nullptr}; 513 friend class FrameIterator; 514 }; 515 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame), 516 OptimizedJSFunctionArgConfigFrame::SizeArch32, 517 OptimizedJSFunctionArgConfigFrame::SizeArch64); 518 519 // * OptimizedJSFunctionFrame layout description as the following: 520 // +----------------------------------------+ 521 // | arg[N-1] | 522 // +----------------------------------------+ 523 // | ... | 524 // +----------------------------------------+ 525 // | arg[1] | 526 // +----------------------------------------+ 527 // | arg[0] | 528 // +----------------------------------------+ 529 // | this | 530 // +----------------------------------------+ 531 // | new-target [not exist in fastcall] | 532 // +----------------------------------------+ 533 // | call-target | 534 // argv ---> +----------------------------------------+ 535 // | argv [not exist in fastcall] | 536 // |----------------------------------------| 537 // | argc [not exist in fastcall] | 538 // callerSp ---> |----------------------------------------|---------------- 539 // | returnAddr | ^ 540 // |----------------------------------------| | 541 // | callsiteFp | | 542 // fp ---> |----------------------------------------| OptimizedJSFunctionFrame 543 // | frameType | | 544 // |----------------------------------------| | 545 // | call-target | v 546 // calleeSP ---> +----------------------------------------+---------------- 547 // 548 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 549 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 550 JSTaggedValue, 551 base::AlignedPointer, 552 base::AlignedPointer, 553 base::AlignedPointer> { 554 public: 555 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 556 enum class Index : size_t { 557 JSFuncIndex = 0, 558 TypeIndex, 559 PrevFpIndex, 560 ReturnAddrIndex, 561 NumOfMembers 562 }; 563 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 564 GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame565 static constexpr size_t GetFunctionDeltaReturnAddr() 566 { 567 return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex); 568 } 569 GetPrevFrameFpOptimizedJSFunctionFrame570 inline JSTaggedType* GetPrevFrameFp() 571 { 572 return prevFp; 573 } 574 GetArgvOptimizedJSFunctionFrame575 JSTaggedType* GetArgv(uintptr_t *preFrameSp) const 576 { 577 const size_t offset = 2; // 2: skip argc and argv. 578 return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t)); 579 } 580 GetArgcOptimizedJSFunctionFrame581 size_t GetArgc(uintptr_t *preFrameSp) const 582 { 583 return *preFrameSp; 584 } 585 586 JSTaggedType* GetArgv(const FrameIterator &it) const; 587 GetReturnAddrOptimizedJSFunctionFrame588 uintptr_t GetReturnAddr() const 589 { 590 return returnAddr; 591 } 592 593 void GCIterate(const FrameIterator &it, RootVisitor &visitor, FrameType frameType) const; 594 void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const; 595 GetFunctionOptimizedJSFunctionFrame596 inline JSTaggedValue GetFunction() const 597 { 598 return jsFunc; 599 } 600 ComputeArgsConfigFrameSpOptimizedJSFunctionFrame601 static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp) 602 { 603 const size_t offset = 2; // 2: skip prevFp and return address. 604 return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t); 605 } 606 607 static size_t GetTypeOffset(bool isArch32 = false) 608 { 609 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 610 } 611 612 static size_t GetPrevOffset(bool isArch32 = false) 613 { 614 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 615 } 616 617 static size_t GetFunctionOffset(bool isArch32 = false) 618 { 619 return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32); 620 } 621 622 static size_t GetReturnAddrOffset(bool isArch32 = false) 623 { 624 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 625 } 626 ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame627 static size_t ComputeReservedJSFuncOffset(size_t slotSize) 628 { 629 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex); 630 return slotSize * slotOffset; 631 } 632 GetFrmaeTypeToFpDeltaOptimizedJSFunctionFrame633 static int GetFrmaeTypeToFpDelta() 634 { 635 return -(int)sizeof(uintptr_t); 636 } 637 GetFunctionToFpDeltaOptimizedJSFunctionFrame638 static int GetFunctionToFpDelta() 639 { 640 int slotOffset = static_cast<int>(Index::JSFuncIndex) - static_cast<int>(Index::TypeIndex); 641 return slotOffset * static_cast<int>(JSTaggedValue::TaggedTypeSize()) + GetFrmaeTypeToFpDelta(); 642 } 643 GetTypeOptimizedJSFunctionFrame644 FrameType GetType() const 645 { 646 return type; 647 } 648 649 friend class FrameIterator; 650 friend class FrameHandler; 651 void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const; 652 void GetFuncCalleeRegAndOffset( 653 const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const; 654 uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const; 655 656 private: GetFrameFromSpOptimizedJSFunctionFrame657 static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) 658 { 659 return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) - 660 MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp)); 661 } 662 663 // dynamic callee saveregisters for x86-64 664 alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()}; 665 alignas(EAS) FrameType type {0}; 666 alignas(EAS) JSTaggedType *prevFp {nullptr}; 667 alignas(EAS) uintptr_t returnAddr {0}; 668 // dynamic callee saveregisters for arm64 669 }; 670 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame), 671 OptimizedJSFunctionFrame::SizeArch32, 672 OptimizedJSFunctionFrame::SizeArch64); 673 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time. 674 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1); 675 676 // * The JSFunctionEntry Frame's structure is illustrated as the following: 677 // +--------------------------+ 678 // | . . . . . . | 679 // callerSP --> +--------------------------+ ----------------- 680 // | prevFP | ^ 681 // fp --> |--------------------------| | 682 // | frameType | JSFunctionEntryFrame 683 // |--------------------------| | 684 // | preLeaveFrameFp | v 685 // calleeSP --> +--------------------------+ ----------------- 686 687 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 688 base::AlignedPointer, 689 base::AlignedPointer, 690 base::AlignedPointer> { 691 public: 692 enum class CallType : size_t { 693 CALL_FUNC = 0, 694 CALL_NEW, 695 }; 696 697 enum class Index : size_t { 698 PreLeaveFrameFpIndex = 0, 699 TypeIndex, 700 PrevFpIndex, 701 NumOfMembers 702 }; 703 704 static size_t GetTypeOffset(bool isArch32 = false) 705 { 706 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 707 } 708 709 static size_t GetLeaveFrameFpOffset(bool isArch32 = false) 710 { 711 return GetOffset<static_cast<size_t>(Index::PreLeaveFrameFpIndex)>(isArch32); 712 } 713 GetPrevFrameFpOptimizedEntryFrame714 inline JSTaggedType* GetPrevFrameFp() 715 { 716 return preLeaveFrameFp; 717 } 718 ComputeReservedSizeOptimizedEntryFrame719 static size_t ComputeReservedSize(size_t slotSize) 720 { 721 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex); 722 return slotSize * slotOffset; 723 } 724 GetTypeOptimizedEntryFrame725 FrameType GetType() const 726 { 727 return type; 728 } 729 friend class FrameIterator; 730 731 private: GetFrameFromSpOptimizedEntryFrame732 static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 733 { 734 return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) - 735 MEMBER_OFFSET(OptimizedEntryFrame, prevFp)); 736 } 737 GetLeaveFpOptimizedEntryFrame738 JSTaggedType* GetLeaveFp() const 739 { 740 return preLeaveFrameFp; 741 } 742 GetPrevFpOptimizedEntryFrame743 JSTaggedType* GetPrevFp() const 744 { 745 return prevFp; 746 } 747 748 alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr}; 749 alignas(EAS) FrameType type {0}; 750 alignas(EAS) JSTaggedType *prevFp {nullptr}; 751 }; 752 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64); 753 754 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 755 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(), 756 base::AlignedPointer, 757 base::AlignedSize> { 758 enum class Index : size_t { 759 PrevIndex = 0, 760 TypeIndex, 761 NumOfMembers 762 }; 763 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 764 GetPrevFrameFpInterpretedFrameBase765 inline JSTaggedType* GetPrevFrameFp() 766 { 767 return prev; 768 } 769 GetFrameFromSpInterpretedFrameBase770 static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp) 771 { 772 return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1; 773 } 774 775 static size_t GetPrevOffset(bool isArch32 = false) 776 { 777 return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32); 778 } 779 780 static size_t GetTypeOffset(bool isArch32 = false) 781 { 782 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 783 } 784 GetSizeInterpretedFrameBase785 static constexpr size_t GetSize(bool isArch32) 786 { 787 return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64; 788 } 789 790 alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc 791 alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0 792 }; 793 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase), 794 InterpretedFrameBase::SizeArch32, 795 InterpretedFrameBase::SizeArch64); 796 797 // Interpreter Frame Layout as the following: 798 // +----------------------------------+ 799 // | argv[n-1] | 800 // |----------------------------------| 801 // | ...... | 802 // |----------------------------------| 803 // | thisArg [maybe not exist] | 804 // |----------------------------------| 805 // | newTarget [maybe not exist] | 806 // |----------------------------------| 807 // | ...... | 808 // |----------------------------------| 809 // | Vregs [not exist in native] | 810 // +----------------------------------+--------+ 811 // | base.frameType | ^ 812 // |----------------------------------| | 813 // | base.prev(prev stack pointer) | | 814 // |----------------------------------| | 815 // | pc(bytecode addr) | | 816 // |----------------------------------| | 817 // | sp(current stack pointer) | | 818 // |----------------------------------| | 819 // | env | | 820 // |----------------------------------| | 821 // | acc | | 822 // |----------------------------------| InterpretedFrame 823 // | profileTypeInfo | | 824 // |----------------------------------| | 825 // | thisObj | | 826 // |----------------------------------| | 827 // | function | | 828 // |----------------------------------| | 829 // | constpool | v 830 // +----------------------------------+--------+ 831 // 832 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 833 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 834 JSTaggedValue, 835 JSTaggedValue, 836 JSTaggedValue, 837 JSTaggedValue, 838 JSTaggedValue, 839 JSTaggedValue, 840 base::AlignedPointer, 841 InterpretedFrameBase> { 842 public: 843 enum class Index : size_t { 844 ConstPoolIndex = 0, 845 FunctionIndex, 846 ThisObjIndex, 847 ProFileTypeInfoIndex, 848 AccIndex, 849 EnvIndex, 850 PcIndex, 851 BaseIndex, 852 NumOfMembers 853 }; 854 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 855 GetPrevFrameFpInterpretedFrame856 inline JSTaggedType* GetPrevFrameFp() const 857 { 858 return base.prev; 859 } 860 GetFrameFromSpInterpretedFrame861 static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 862 { 863 return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 864 } 865 GetPcInterpretedFrame866 inline const uint8_t *GetPc() const 867 { 868 return pc; 869 } 870 GetEnvInterpretedFrame871 inline JSTaggedValue GetEnv() const 872 { 873 return env; 874 } 875 NumOfMembersInterpretedFrame876 static uint32_t NumOfMembers() 877 { 878 return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 879 } 880 GetPcOffsetInterpretedFrame881 static size_t GetPcOffset(bool isArch32) 882 { 883 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 884 } 885 886 static size_t GetTypeOffset(bool isArch32 = false) 887 { 888 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 889 InterpretedFrameBase::GetTypeOffset(isArch32); 890 } 891 892 static size_t GetPrevOffset(bool isArch32 = false) 893 { 894 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 895 InterpretedFrameBase::GetPrevOffset(isArch32); 896 } 897 898 static size_t GetFunctionOffset(bool isArch32 = false) 899 { 900 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 901 } 902 903 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 904 905 alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()}; 906 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 907 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 908 alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()}; 909 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 910 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 911 alignas(EAS) const uint8_t *pc {nullptr}; 912 alignas(EAS) InterpretedFrameBase base; 913 friend class FrameIterator; 914 }; 915 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64); 916 917 // * InterpretedBuiltinFrame layout description as the following: 918 // |--------------------------| --------------- 919 // | . . . . . | ^ 920 // | InterpretedFrameBase | | 921 // | . . . . . | | 922 // |--------------------------| InterpretedBuiltinFrame 923 // | bytecode-PC | | 924 // |--------------------------| | 925 // | call-target | v 926 // +--------------------------+ --------------- 927 // 928 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 929 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 930 JSTaggedValue, 931 base::AlignedPointer, 932 InterpretedFrameBase> { 933 enum class Index : size_t { 934 FunctionIndex = 0, 935 PcIndex, 936 BaseIndex, 937 NumOfMembers 938 }; 939 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 940 GetPrevFrameFpInterpretedBuiltinFrame941 inline JSTaggedType* GetPrevFrameFp() 942 { 943 return base.prev; 944 } 945 GetFrameFromSpInterpretedBuiltinFrame946 static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 947 { 948 return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 949 } 950 NumOfMembersInterpretedBuiltinFrame951 static uint32_t NumOfMembers() 952 { 953 return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize(); 954 } 955 956 static size_t GetTypeOffset(bool isArch32 = false) 957 { 958 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 959 InterpretedFrameBase::GetTypeOffset(isArch32); 960 } 961 962 static size_t GetPrevOffset(bool isArch32 = false) 963 { 964 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 965 InterpretedFrameBase::GetPrevOffset(isArch32); 966 } 967 968 static size_t GetFunctionOffset(bool isArch32 = false) 969 { 970 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 971 } 972 973 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 974 975 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 976 alignas(EAS) const uint8_t *pc {nullptr}; 977 alignas(EAS) InterpretedFrameBase base; 978 }; 979 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame), 980 InterpretedBuiltinFrame::SizeArch32, 981 InterpretedBuiltinFrame::SizeArch64); 982 983 // AsmInterpretedFrame Layout as the following: 984 // +----------------------------------+ 985 // | argv[n-1] | 986 // |----------------------------------| 987 // | ...... | 988 // |----------------------------------| 989 // | thisArg [maybe not exist] | 990 // |----------------------------------| 991 // | newTarget [maybe not exist] | 992 // |----------------------------------| 993 // | ...... | 994 // |----------------------------------| 995 // | Vregs [not exist in native] | 996 // +----------------------------------+--------+ 997 // | . . . . | ^ 998 // | InterpretedFrameBase | | 999 // | . . . . | | 1000 // |----------------------------------| | 1001 // | pc(bytecode addr) | | 1002 // |----------------------------------| | 1003 // | sp(current stack pointer) | | 1004 // |----------------------------------| AsmInterpretedFrame 1005 // | callSize | | 1006 // |----------------------------------| | 1007 // | env | | 1008 // |----------------------------------| | 1009 // | acc | | 1010 // |----------------------------------| | 1011 // | thisObj | | 1012 // |----------------------------------| | 1013 // | call-target | v 1014 // +----------------------------------+--------+ 1015 // 1016 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1017 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1018 JSTaggedValue, 1019 JSTaggedValue, 1020 JSTaggedValue, 1021 JSTaggedValue, 1022 base::AlignedPointer, 1023 base::AlignedPointer, 1024 base::AlignedPointer, 1025 InterpretedFrameBase> { 1026 enum class Index : size_t { 1027 FunctionIndex = 0, 1028 ThisObjIndex, 1029 AccIndex, 1030 EnvIndex, 1031 CallSizeIndex, 1032 FpIndex, 1033 PcIndex, 1034 BaseIndex, 1035 NumOfMembers 1036 }; 1037 1038 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1039 GetCurrentFramePointerAsmInterpretedFrame1040 inline JSTaggedType* GetCurrentFramePointer() 1041 { 1042 return fp; 1043 } 1044 GetPrevFrameFpAsmInterpretedFrame1045 inline JSTaggedType* GetPrevFrameFp() 1046 { 1047 return base.prev; 1048 } 1049 GetFrameFromSpAsmInterpretedFrame1050 static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 1051 { 1052 return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1053 } 1054 GetFpOffsetAsmInterpretedFrame1055 static size_t GetFpOffset(bool isArch32) 1056 { 1057 return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32); 1058 } 1059 GetCallSizeOffsetAsmInterpretedFrame1060 static size_t GetCallSizeOffset(bool isArch32) 1061 { 1062 return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32); 1063 } 1064 GetFunctionOffsetAsmInterpretedFrame1065 static size_t GetFunctionOffset(bool isArch32) 1066 { 1067 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 1068 } 1069 GetThisOffsetAsmInterpretedFrame1070 static size_t GetThisOffset(bool isArch32) 1071 { 1072 return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32); 1073 } 1074 GetAccOffsetAsmInterpretedFrame1075 static size_t GetAccOffset(bool isArch32) 1076 { 1077 return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32); 1078 } 1079 GetEnvOffsetAsmInterpretedFrame1080 static size_t GetEnvOffset(bool isArch32) 1081 { 1082 return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32); 1083 } 1084 GetBaseOffsetAsmInterpretedFrame1085 static size_t GetBaseOffset(bool isArch32) 1086 { 1087 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 1088 } 1089 GetPcOffsetAsmInterpretedFrame1090 static size_t GetPcOffset(bool isArch32) 1091 { 1092 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 1093 } 1094 GetSizeAsmInterpretedFrame1095 static constexpr size_t GetSize(bool isArch32) 1096 { 1097 return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64; 1098 } 1099 GetFpOffsetAsIntptrAsmInterpretedFrame1100 static intptr_t GetFpOffsetAsIntptr(bool isArch32) 1101 { 1102 return static_cast<intptr_t>(GetFpOffset(isArch32)); 1103 } 1104 GetFunctionOffsetAsIntptrAsmInterpretedFrame1105 static intptr_t GetFunctionOffsetAsIntptr(bool isArch32) 1106 { 1107 return static_cast<intptr_t>(GetFunctionOffset(isArch32)); 1108 } 1109 GetSizeAsIntptrAsmInterpretedFrame1110 static intptr_t GetSizeAsIntptr(bool isArch32) 1111 { 1112 return static_cast<intptr_t>(GetSize(isArch32)); 1113 } 1114 NumOfMembersAsmInterpretedFrame1115 static uint32_t NumOfMembers() 1116 { 1117 return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 1118 } 1119 void GCIterate(const FrameIterator &it, RootVisitor &visitor, bool isBaselineFrame) const; 1120 GetEnvAsmInterpretedFrame1121 JSTaggedValue GetEnv() const 1122 { 1123 return env; 1124 } 1125 GetPcAsmInterpretedFrame1126 const uint8_t *GetPc() const 1127 { 1128 return pc; 1129 } 1130 GetTypeOffsetAsmInterpretedFrame1131 static size_t GetTypeOffset() 1132 { 1133 return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type); 1134 } 1135 GetPrevOffsetAsmInterpretedFrame1136 static size_t GetPrevOffset() 1137 { 1138 return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev); 1139 } 1140 1141 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 1142 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 1143 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 1144 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 1145 alignas(EAS) uintptr_t callSize {0}; 1146 alignas(EAS) JSTaggedType *fp {nullptr}; 1147 alignas(EAS) const uint8_t *pc {nullptr}; 1148 alignas(EAS) InterpretedFrameBase base; 1149 // vregs, not exist in native 1150 // args, may be truncated if not extra 1151 }; 1152 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64); 1153 1154 // InterpretedEntryFrame Layout as the following: 1155 // +----------------------------------+--------------- 1156 // | . . . . | ^ 1157 // | InterpretedFrameBase | | 1158 // | . . . . | InterpretedEntryFrame 1159 // |----------------------------------| | 1160 // | pc(bytecode addr) | v 1161 // |----------------------------------|--------------- 1162 // 1163 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1164 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1165 base::AlignedPointer, 1166 InterpretedFrameBase> { 1167 enum class Index : size_t { 1168 PcIndex = 0, 1169 BaseIndex, 1170 NumOfMembers 1171 }; 1172 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1173 GetPrevFrameFpInterpretedEntryFrame1174 inline JSTaggedType* GetPrevFrameFp() 1175 { 1176 return base.prev; 1177 } 1178 GetFrameFromSpInterpretedEntryFrame1179 static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 1180 { 1181 return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1182 } 1183 NumOfMembersInterpretedEntryFrame1184 static uint32_t NumOfMembers() 1185 { 1186 return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize(); 1187 } 1188 1189 static size_t GetTypeOffset(bool isArch32 = false) 1190 { 1191 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1192 InterpretedFrameBase::GetTypeOffset(isArch32); 1193 } 1194 1195 static size_t GetPrevOffset(bool isArch32 = false) 1196 { 1197 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1198 InterpretedFrameBase::GetPrevOffset(isArch32); 1199 } 1200 1201 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1202 alignas(EAS) const uint8_t *pc {nullptr}; 1203 alignas(EAS) InterpretedFrameBase base; 1204 }; 1205 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame), 1206 InterpretedEntryFrame::SizeArch32, 1207 InterpretedEntryFrame::SizeArch64); 1208 1209 1210 // AsmInterpretedEntryFrame Layout as the following: 1211 // +----------------------------------+--------------- 1212 // | . . . . | ^ 1213 // | InterpretedFrameBase | | 1214 // | . . . . | AsmInterpretedEntryFrame 1215 // |----------------------------------| | 1216 // | pc(bytecode addr) | v 1217 // |----------------------------------|--------------- 1218 // 1219 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1220 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1221 base::AlignedPointer, 1222 InterpretedFrameBase> { 1223 enum class Index : size_t { 1224 PcIndex = 0, 1225 BaseIndex, 1226 NumOfMembers 1227 }; 1228 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1229 GetPrevFrameFpAsmInterpretedEntryFrame1230 inline JSTaggedType* GetPrevFrameFp() 1231 { 1232 return base.prev; 1233 } 1234 GetBaseOffsetAsmInterpretedEntryFrame1235 static size_t GetBaseOffset(bool isArch32) 1236 { 1237 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 1238 } 1239 GetFrameFromSpAsmInterpretedEntryFrame1240 static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 1241 { 1242 return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1243 } 1244 1245 static size_t GetTypeOffset(bool isArch32 = false) 1246 { 1247 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1248 InterpretedFrameBase::GetTypeOffset(isArch32); 1249 } 1250 1251 static size_t GetPrevOffset(bool isArch32 = false) 1252 { 1253 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1254 InterpretedFrameBase::GetPrevOffset(isArch32); 1255 } 1256 1257 alignas(EAS) const uint8_t *pc {nullptr}; 1258 alignas(EAS) InterpretedFrameBase base; 1259 }; 1260 1261 // AsmInterpretedBridgeFrame Layout as the following: 1262 // +----------------------------------+--------------- 1263 // | ret-address | ^ 1264 // |----------------------------------| | 1265 // | . . . . | AsmInterpretedBridgeFrame 1266 // | AsmInterpretedEntryFrame | | 1267 // | . . . . | v 1268 // |----------------------------------|--------------- 1269 // 1270 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1271 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1272 AsmInterpretedEntryFrame, 1273 base::AlignedPointer> { 1274 enum class Index : size_t { 1275 EntryIndex = 0, 1276 ReturnAddrIndex, 1277 NumOfMembers 1278 }; 1279 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1280 GetFrameFromSpAsmInterpretedBridgeFrame1281 static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 1282 { 1283 return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 1284 MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr)); 1285 } GetCallSiteSpAsmInterpretedBridgeFrame1286 uintptr_t GetCallSiteSp() const 1287 { 1288 return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame); 1289 } GetPrevFrameFpAsmInterpretedBridgeFrame1290 inline JSTaggedType* GetPrevFrameFp() 1291 { 1292 return entry.base.prev; 1293 } 1294 GetReturnAddrOffsetAsmInterpretedBridgeFrame1295 static size_t GetReturnAddrOffset(bool isArch32) 1296 { 1297 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 1298 } 1299 GetSizeAsmInterpretedBridgeFrame1300 static constexpr size_t GetSize(bool isArch32) 1301 { 1302 return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64; 1303 } 1304 1305 static size_t GetTypeOffset(bool isArch32 = false) 1306 { 1307 return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) + 1308 AsmInterpretedEntryFrame::GetBaseOffset(isArch32) + 1309 InterpretedFrameBase::GetTypeOffset(isArch32); 1310 } 1311 static size_t GetPrevOffset(bool isArch32 = false) 1312 { 1313 return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) + 1314 AsmInterpretedEntryFrame::GetBaseOffset(isArch32) + 1315 InterpretedFrameBase::GetPrevOffset(isArch32); 1316 } 1317 GetReturnAddrAsmInterpretedBridgeFrame1318 uintptr_t GetReturnAddr() const 1319 { 1320 return returnAddr; 1321 } 1322 1323 AsmInterpretedEntryFrame entry; 1324 alignas(EAS) uintptr_t returnAddr {0}; 1325 }; 1326 1327 // * Optimized-leaved-frame layout as the following: 1328 // +--------------------------+ 1329 // | argv[N-1] | 1330 // |--------------------------| 1331 // | . . . . . | 1332 // |--------------------------| 1333 // | argv[0] | 1334 // +--------------------------+------------- 1335 // | argc | ^ 1336 // |--------------------------| | 1337 // | RuntimeId | | 1338 // callerSP --> |--------------------------| OptimizedLeaveFrame 1339 // | ret-addr | | 1340 // |--------------------------| | 1341 // | prevFp | | 1342 // fp --> |--------------------------| | 1343 // | frameType | v 1344 // calleeSP --> +--------------------------+------------- 1345 // 1346 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1347 struct OptimizedLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1348 base::AlignedPointer, 1349 base::AlignedPointer, 1350 base::AlignedPointer, 1351 base::AlignedUint64, 1352 base::AlignedUint64> { 1353 // argv[0]...argv[argc-1] dynamic according to agc GetFrameFromSpOptimizedLeaveFrame1354 static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1355 { 1356 return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1357 MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp)); 1358 } 1359 GetCallSiteSpOptimizedLeaveFrame1360 uintptr_t GetCallSiteSp() const 1361 { 1362 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId); 1363 } 1364 GetPrevFrameFpOptimizedLeaveFrame1365 inline JSTaggedType* GetPrevFrameFp() const 1366 { 1367 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1368 } 1369 GetReturnAddrOptimizedLeaveFrame1370 uintptr_t GetReturnAddr() const 1371 { 1372 return returnAddr; 1373 } 1374 GetTypeOffsetOptimizedLeaveFrame1375 static size_t GetTypeOffset() 1376 { 1377 return MEMBER_OFFSET(OptimizedLeaveFrame, type); 1378 } 1379 GetPrevOffsetOptimizedLeaveFrame1380 static size_t GetPrevOffset() 1381 { 1382 return MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp); 1383 } 1384 GetReturnAddrOffsetOptimizedLeaveFrame1385 static size_t GetReturnAddrOffset() 1386 { 1387 return MEMBER_OFFSET(OptimizedLeaveFrame, returnAddr); 1388 } 1389 1390 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1391 1392 alignas(EAS) FrameType type {0}; 1393 alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here 1394 alignas(EAS) uintptr_t returnAddr {0}; 1395 alignas(EAS) uint64_t argRuntimeId {0}; 1396 alignas(EAS) uint64_t argc {0}; 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 1414 struct OptimizedWithArgvLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1415 base::AlignedPointer, 1416 base::AlignedPointer, 1417 base::AlignedPointer, 1418 base::AlignedUint64, 1419 base::AlignedUint64> { GetFrameFromSpOptimizedWithArgvLeaveFrame1420 static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1421 { 1422 return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1423 MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp)); 1424 } 1425 GetCallSiteSpOptimizedWithArgvLeaveFrame1426 uintptr_t GetCallSiteSp() const 1427 { 1428 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId); 1429 } 1430 GetPrevFrameFpOptimizedWithArgvLeaveFrame1431 inline JSTaggedType* GetPrevFrameFp() 1432 { 1433 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1434 } 1435 GetReturnAddrOptimizedWithArgvLeaveFrame1436 uintptr_t GetReturnAddr() const 1437 { 1438 return returnAddr; 1439 } 1440 GetTypeOffsetOptimizedWithArgvLeaveFrame1441 static size_t GetTypeOffset() 1442 { 1443 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type); 1444 } 1445 GetPrevOffsetOptimizedWithArgvLeaveFrame1446 static size_t GetPrevOffset() 1447 { 1448 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp); 1449 } 1450 GetReturnAddrOffsetOptimizedWithArgvLeaveFrame1451 static size_t GetReturnAddrOffset() 1452 { 1453 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, returnAddr); 1454 } 1455 1456 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1457 1458 alignas(EAS) FrameType type {0}; 1459 alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here 1460 alignas(EAS) uintptr_t returnAddr {0}; 1461 alignas(EAS) uint64_t argRuntimeId {0}; 1462 alignas(EAS) uint64_t argc {0}; 1463 }; 1464 1465 // * Optimized-builtin-leave-frame layout as the following: 1466 // +--------------------------+ 1467 // | argv[N-1] | 1468 // |--------------------------| 1469 // | . . . . . | 1470 // |--------------------------| 1471 // | argv[0] | 1472 // +--------------------------+------------- 1473 // | argc | ^ 1474 // |--------------------------| | 1475 // | thread | | 1476 // callerSP --> +--------------------------+ | 1477 // | ret-addr | | 1478 // |--------------------------| OptimizedBuiltinLeaveFrame 1479 // | prevFp | | 1480 // fp --> |--------------------------| | 1481 // | frameType | | 1482 // |--------------------------| | 1483 // | align byte | v 1484 // calleeSP --> +--------------------------+------------- 1485 // 1486 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1487 struct OptimizedBuiltinLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1488 base::AlignedPointer, 1489 base::AlignedPointer, 1490 base::AlignedPointer, 1491 JSTaggedValue, 1492 base::AlignedUint64> { 1493 public: GetFrameFromSpOptimizedBuiltinLeaveFrame1494 static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1495 { 1496 return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1497 MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp)); 1498 } 1499 GetCallSiteSpOptimizedBuiltinLeaveFrame1500 uintptr_t GetCallSiteSp() const 1501 { 1502 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, thread); 1503 } 1504 GetPrevFrameFpOptimizedBuiltinLeaveFrame1505 inline JSTaggedType* GetPrevFrameFp() const 1506 { 1507 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1508 } 1509 GetReturnAddrOptimizedBuiltinLeaveFrame1510 uintptr_t GetReturnAddr() const 1511 { 1512 return returnAddr; 1513 } 1514 1515 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1516 GetTypeOffsetOptimizedBuiltinLeaveFrame1517 static size_t GetTypeOffset() 1518 { 1519 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type); 1520 } 1521 GetPrevOffsetOptimizedBuiltinLeaveFrame1522 static size_t GetPrevOffset() 1523 { 1524 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp); 1525 } 1526 GetReturnAddrOffsetOptimizedBuiltinLeaveFrame1527 static size_t GetReturnAddrOffset() 1528 { 1529 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, returnAddr); 1530 } 1531 GetFunctionOffsetOptimizedBuiltinLeaveFrame1532 static size_t GetFunctionOffset() 1533 { 1534 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argc) + 1; 1535 } 1536 GetArgvOptimizedBuiltinLeaveFrame1537 const JSTaggedType* GetArgv() const 1538 { 1539 return reinterpret_cast<const JSTaggedType *>(&argc + 1); 1540 } 1541 GetTypeOptimizedBuiltinLeaveFrame1542 FrameType GetType() const 1543 { 1544 return type; 1545 } 1546 1547 private: 1548 alignas(EAS) FrameType type {0}; 1549 alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here 1550 alignas(EAS) uintptr_t returnAddr {0}; 1551 alignas(EAS) JSTaggedValue thread {JSTaggedValue::Hole()}; 1552 alignas(EAS) uint64_t argc {0}; 1553 // argv[0]...argv[argc-1] dynamic according to agc 1554 }; 1555 1556 // * BuiltinFrame layout as the following: 1557 // +--------------------------+ 1558 // | argV[N - 1] | 1559 // |--------------------------| 1560 // | . . . . | 1561 // |--------------------------+ 1562 // | argV[2]=this | 1563 // +--------------------------+ 1564 // | argV[1]=new-target | 1565 // +--------------------------+ 1566 // | argV[0]=call-target | 1567 // +--------------------------+ --------- 1568 // | argc | ^ 1569 // |--------------------------| | 1570 // | thread | | 1571 // callerSP --> |--------------------------| | 1572 // | returnAddr | BuiltinFrame 1573 // |--------------------------| | 1574 // | callsiteFp | | 1575 // fp --> |--------------------------| | 1576 // | frameType | v 1577 // calleeSP --> +--------------------------+ --------- 1578 // 1579 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1580 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1581 base::AlignedSize, 1582 base::AlignedPointer, 1583 base::AlignedPointer, 1584 base::AlignedPointer, 1585 base::AlignedUint32, 1586 base::AlignedPointer> { 1587 enum class Index : size_t { 1588 TypeIndex = 0, 1589 PrevFpIndex, 1590 ReturnAddrIndex, 1591 ThreadIndex, 1592 NumArgsIndex, 1593 StackArgsIndex, 1594 NumOfMembers 1595 }; 1596 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1597 GetFrameFromSpBuiltinFrame1598 static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 1599 { 1600 return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) - 1601 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1602 } 1603 GetPrevFrameFpBuiltinFrame1604 inline JSTaggedType* GetPrevFrameFp() 1605 { 1606 return prevFp; 1607 } 1608 GetCallSiteSpBuiltinFrame1609 uintptr_t GetCallSiteSp() const 1610 { 1611 return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread); 1612 } 1613 GetPreFpOffsetBuiltinFrame1614 static size_t GetPreFpOffset(bool isArch32) 1615 { 1616 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1617 } 1618 GetNumArgsToFpDeltaBuiltinFrame1619 static size_t GetNumArgsToFpDelta(bool isArch32) 1620 { 1621 auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32); 1622 return offset - GetPreFpOffset(isArch32); 1623 } 1624 GetStackArgsToFpDeltaBuiltinFrame1625 static size_t GetStackArgsToFpDelta(bool isArch32) 1626 { 1627 auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 1628 return offset - GetPreFpOffset(isArch32); 1629 } 1630 GetStackArgsAddressBuiltinFrame1631 uintptr_t GetStackArgsAddress() 1632 { 1633 return reinterpret_cast<uintptr_t>(&stackArgs); 1634 } 1635 GetFunctionBuiltinFrame1636 JSTaggedValue GetFunction() 1637 { 1638 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1639 return JSTaggedValue(*functionAddress); 1640 } 1641 GetNumArgsBuiltinFrame1642 uint32_t GetNumArgs() 1643 { 1644 return numArgs; 1645 } 1646 GetReturnAddrBuiltinFrame1647 uintptr_t GetReturnAddr() const 1648 { 1649 return returnAddr; 1650 } 1651 1652 static size_t GetStackArgsOffset(bool isArch32 = false) 1653 { 1654 return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 1655 } 1656 1657 static size_t GetTypeOffset(bool isArch32 = false) 1658 { 1659 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1660 } 1661 1662 static size_t GetPrevOffset(bool isArch32 = false) 1663 { 1664 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1665 } 1666 1667 static size_t GetReturnAddrOffset(bool isArch32 = false) 1668 { 1669 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 1670 } 1671 1672 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1673 1674 alignas(EAS) FrameType type {0}; 1675 alignas(EAS) JSTaggedType *prevFp {nullptr}; 1676 alignas(EAS) uintptr_t returnAddr {0}; 1677 alignas(EAS) uintptr_t thread {0}; 1678 alignas(EAS) uint32_t numArgs {0}; 1679 alignas(EAS) uintptr_t stackArgs {0}; 1680 }; 1681 1682 // * BuiltinWithArgvFrame layout as the following: 1683 // +--------------------------+ --------- 1684 // | . . . . . | ^ 1685 // callerSP --> |--------------------------| | 1686 // | returnAddr | | 1687 // |--------------------------| | 1688 // | callsiteFp | BuiltinWithArgvFrame 1689 // fp --> |--------------------------| | 1690 // | frameType | | 1691 // +--------------------------+ | 1692 // | argc | v 1693 // +--------------------------+ --------- 1694 // | argV[0] | 1695 // +--------------------------+ 1696 // | argV[1] | 1697 // +--------------------------+ 1698 // | . . . . | 1699 // calleeSP --> +--------------------------+ 1700 // 1701 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1702 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1703 base::AlignedSize, 1704 base::AlignedPointer, 1705 base::AlignedPointer> { 1706 enum class Index : int { 1707 StackArgsTopIndex = -1, 1708 NumArgsIndex = -1, 1709 TypeIndex = 0, 1710 PrevFpIndex, 1711 ReturnAddrIndex, 1712 NumOfMembers 1713 }; 1714 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1715 GetFrameFromSpBuiltinWithArgvFrame1716 static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp) 1717 { 1718 return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) - 1719 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1720 } 1721 GetPrevFrameFpBuiltinWithArgvFrame1722 inline JSTaggedType* GetPrevFrameFp() 1723 { 1724 return prevFp; 1725 } 1726 GetCallSiteSpBuiltinWithArgvFrame1727 uintptr_t GetCallSiteSp() const 1728 { 1729 return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame); 1730 } 1731 GetStackArgsAddressBuiltinWithArgvFrame1732 uintptr_t GetStackArgsAddress() 1733 { 1734 auto topAddress = ToUintPtr(this) + 1735 (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t)); 1736 auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS; 1737 return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t); 1738 } 1739 GetFunctionBuiltinWithArgvFrame1740 JSTaggedValue GetFunction() 1741 { 1742 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1743 return JSTaggedValue(*functionAddress); 1744 } 1745 GetNumArgsBuiltinWithArgvFrame1746 int32_t GetNumArgs() 1747 { 1748 auto argcAddress = reinterpret_cast<int32_t *>( 1749 ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t))); 1750 return *argcAddress; 1751 } 1752 GetReturnAddrBuiltinWithArgvFrame1753 uintptr_t GetReturnAddr() const 1754 { 1755 return returnAddr; 1756 } 1757 1758 static size_t GetTypeOffset(bool isArch32 = false) 1759 { 1760 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1761 } 1762 1763 static size_t GetPrevOffset(bool isArch32 = false) 1764 { 1765 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1766 } 1767 1768 static size_t GetReturnAddrOffset(bool isArch32 = false) 1769 { 1770 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 1771 } 1772 1773 void GCIterate(const FrameIterator &it, RootVisitor &visitor) const; 1774 // argv(... this, new.target, function) 1775 // numargs 1776 alignas(EAS) FrameType type {0}; 1777 alignas(EAS) JSTaggedType *prevFp {nullptr}; 1778 alignas(EAS) uintptr_t returnAddr {0}; 1779 }; 1780 1781 // * FASTJITFunctionFrame layout description as the following: 1782 // +--------------------------+ 1783 // | arg[N-1] | 1784 // +--------------------------+ 1785 // | ... | 1786 // +--------------------------+ 1787 // | arg[1] | 1788 // +--------------------------+ 1789 // | arg[0] | 1790 // +--------------------------+ 1791 // | this | 1792 // +--------------------------+ 1793 // | new-target | 1794 // +--------------------------+ 1795 // | call-target | 1796 // |--------------------------| 1797 // | argc | 1798 // callerSp ---> |--------------------------| --------------- 1799 // | returnAddr | ^ 1800 // |--------------------------| | 1801 // | callsiteFp | | 1802 // |--------------------------| | 1803 // | frameType | FASTJITFunctionFrame 1804 // |--------------------------| | 1805 // | call-target | | 1806 // |--------------------------| | 1807 // | pc(bytecode pc) | v 1808 // calleeSP ---> +--------------------------+ --------------- 1809 // 1810 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1811 struct FASTJITFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1812 JSTaggedValue, 1813 JSTaggedValue, 1814 base::AlignedPointer, 1815 base::AlignedPointer, 1816 base::AlignedPointer> { 1817 public: 1818 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 1819 enum class Index : size_t { 1820 PcIndex = 0, 1821 JSFuncIndex, 1822 TypeIndex, 1823 PrevFpIndex, 1824 ReturnAddrIndex, 1825 NumOfMembers 1826 }; 1827 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1828 GetFunctionDeltaReturnAddrFASTJITFunctionFrame1829 static constexpr size_t GetFunctionDeltaReturnAddr() 1830 { 1831 return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex); 1832 } 1833 GetPrevFrameFpFASTJITFunctionFrame1834 inline JSTaggedType* GetPrevFrameFp() 1835 { 1836 return prevFp; 1837 } 1838 GetArgvFASTJITFunctionFrame1839 JSTaggedType* GetArgv(uintptr_t *preFrameSp) const 1840 { 1841 const size_t offset = 2; // 2: skip argc and argv. 1842 return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t)); 1843 } 1844 GetArgcFASTJITFunctionFrame1845 size_t GetArgc(uintptr_t *preFrameSp) const 1846 { 1847 return *preFrameSp; 1848 } 1849 1850 JSTaggedType* GetArgv(const FrameIterator &it) const; 1851 GetReturnAddrFASTJITFunctionFrame1852 uintptr_t GetReturnAddr() const 1853 { 1854 return returnAddr; 1855 } 1856 1857 void GCIterate(const FrameIterator &it, RootVisitor &visitor, FrameType frameType) const; 1858 void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const; 1859 GetFunctionFASTJITFunctionFrame1860 inline JSTaggedValue GetFunction() const 1861 { 1862 return jsFunc; 1863 } 1864 ComputeArgsConfigFrameSpFASTJITFunctionFrame1865 static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp) 1866 { 1867 const size_t offset = 2; // 2: skip prevFp and return address. 1868 return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t); 1869 } 1870 1871 static size_t GetTypeOffset(bool isArch32 = false) 1872 { 1873 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1874 } 1875 1876 static size_t GetPcOffset(bool isArch32 = false) 1877 { 1878 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 1879 } 1880 1881 static size_t GetPrevOffset(bool isArch32 = false) 1882 { 1883 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1884 } 1885 1886 static size_t GetFunctionOffset(bool isArch32 = false) 1887 { 1888 return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32); 1889 } 1890 ComputeReservedJSFuncOffsetFASTJITFunctionFrame1891 static size_t ComputeReservedJSFuncOffset(size_t slotSize) 1892 { 1893 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex); 1894 return slotSize * slotOffset; 1895 } 1896 ComputeReservedPcOffsetFASTJITFunctionFrame1897 static size_t ComputeReservedPcOffset(size_t slotSize) 1898 { 1899 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PcIndex); 1900 return slotSize * slotOffset; 1901 } 1902 GetFrmaeTypeToFpDeltaFASTJITFunctionFrame1903 static int GetFrmaeTypeToFpDelta() 1904 { 1905 return -(int)sizeof(uintptr_t); 1906 } 1907 GetFunctionToFpDeltaFASTJITFunctionFrame1908 static int GetFunctionToFpDelta() 1909 { 1910 int slotOffset = static_cast<int>(Index::JSFuncIndex) - static_cast<int>(Index::TypeIndex); 1911 return slotOffset * static_cast<int>(JSTaggedValue::TaggedTypeSize()) + GetFrmaeTypeToFpDelta(); 1912 } 1913 GetTypeFASTJITFunctionFrame1914 FrameType GetType() const 1915 { 1916 return type; 1917 } 1918 GetPcFASTJITFunctionFrame1919 inline const uint8_t *GetPc() const 1920 { 1921 return pc; 1922 } 1923 1924 friend class FrameIterator; 1925 friend class FrameHandler; 1926 void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const; 1927 void GetFuncCalleeRegAndOffset( 1928 const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const; 1929 uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const; 1930 1931 private: GetFrameFromSpFASTJITFunctionFrame1932 static FASTJITFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) 1933 { 1934 return reinterpret_cast<FASTJITFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) - 1935 MEMBER_OFFSET(FASTJITFunctionFrame, prevFp)); 1936 } 1937 GetFuncAddrFromSpFASTJITFunctionFrame1938 static uintptr_t GetFuncAddrFromSp(const JSTaggedType *sp) 1939 { 1940 return reinterpret_cast<uintptr_t>(sp) - MEMBER_OFFSET(FASTJITFunctionFrame, type); 1941 } 1942 1943 // dynamic callee saveregisters for x86-64 1944 alignas(EAS) const uint8_t *pc {nullptr}; 1945 alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()}; 1946 alignas(EAS) FrameType type {0}; 1947 alignas(EAS) JSTaggedType *prevFp {nullptr}; 1948 alignas(EAS) uintptr_t returnAddr {0}; 1949 // dynamic callee saveregisters for arm64 1950 }; 1951 1952 enum class GCVisitedFlag : uint8_t { 1953 VISITED = 0, 1954 IGNORED, 1955 HYBRID_STACK, 1956 DEOPT, 1957 }; 1958 1959 class FrameIterator { 1960 public: 1961 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 1962 using CallSiteInfo = std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec>; 1963 explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr); GetFrameType()1964 FrameType GetFrameType() const 1965 { 1966 ASSERT(current_ != nullptr); 1967 FrameType *typeAddr = reinterpret_cast<FrameType *>( 1968 reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType)); 1969 return *typeAddr; 1970 } 1971 1972 template<class T> GetFrame()1973 T* GetFrame() 1974 { 1975 return T::GetFrameFromSp(current_); 1976 } 1977 1978 template<class T> GetFrame()1979 const T* GetFrame() const 1980 { 1981 return T::GetFrameFromSp(current_); 1982 } 1983 Done()1984 bool Done() const 1985 { 1986 return current_ == nullptr; 1987 } GetSp()1988 JSTaggedType *GetSp() const 1989 { 1990 return current_; 1991 } GetSp()1992 JSTaggedType *GetSp() 1993 { 1994 return current_; 1995 } GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)1996 void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const 1997 { 1998 ret = calleeRegInfo_; 1999 } 2000 int ComputeDelta(const Method *method = nullptr) const; 2001 template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED> 2002 void Advance(); 2003 std::map<uint32_t, uint32_t> GetInlinedMethodInfo(); 2004 uint32_t GetBytecodeOffset() const; 2005 uintptr_t GetPrevFrameCallSiteSp() const; 2006 uintptr_t GetPrevFrame() const; GetCallSiteSp()2007 uintptr_t GetCallSiteSp() const 2008 { 2009 return optimizedCallSiteSp_; 2010 } GetOptimizedReturnAddr()2011 uintptr_t GetOptimizedReturnAddr() const 2012 { 2013 return optimizedReturnAddr_; 2014 } GetThread()2015 const JSThread *GetThread() const 2016 { 2017 return thread_; 2018 } 2019 bool IteratorStackMap(RootVisitor &visitor) const; 2020 void CollectPcOffsetInfo(ConstInfo &info) const; 2021 void CollectMethodOffsetInfo(std::map<uint32_t, uint32_t> &info) const; 2022 void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const; 2023 std::pair<CallSiteInfo, bool> CalCallSiteInfo(uintptr_t retAddr, bool isDeopt) const; 2024 CallSiteInfo TryCalCallSiteInfoFromMachineCode(uintptr_t retAddr) const; 2025 2026 Method *CheckAndGetMethod() const; 2027 JSTaggedValue GetFunction() const; 2028 IsLeaveFrame()2029 bool IsLeaveFrame() const 2030 { 2031 FrameType type = GetFrameType(); 2032 return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV); 2033 } 2034 IsOptimizedFrame()2035 bool IsOptimizedFrame() const 2036 { 2037 FrameType type = GetFrameType(); 2038 return (type == FrameType::OPTIMIZED_FRAME); 2039 } 2040 IsInterpretedFrame(FrameType type)2041 bool IsInterpretedFrame(FrameType type) const 2042 { 2043 return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST); 2044 } 2045 IsJSFrame()2046 bool IsJSFrame() const 2047 { 2048 FrameType type = GetFrameType(); 2049 return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type) || IsFastJitFunctionFrame(type); 2050 } 2051 IsOptimizedJSFunctionFrame(FrameType type)2052 bool IsOptimizedJSFunctionFrame(FrameType type) const 2053 { 2054 return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || 2055 type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME; 2056 } 2057 IsOptimizedJSFunctionFrame()2058 bool IsOptimizedJSFunctionFrame() const 2059 { 2060 FrameType type = GetFrameType(); 2061 return IsOptimizedJSFunctionFrame(type); 2062 } 2063 IsFastJitFunctionFrame(FrameType type)2064 bool IsFastJitFunctionFrame(FrameType type) const 2065 { 2066 return type == FrameType::FASTJIT_FUNCTION_FRAME || 2067 type == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME; 2068 } 2069 IsFastJitFunctionFrame()2070 bool IsFastJitFunctionFrame() const 2071 { 2072 FrameType type = GetFrameType(); 2073 return IsFastJitFunctionFrame(type); 2074 } 2075 IsAotOrJitFunctionFrame()2076 bool IsAotOrJitFunctionFrame() const 2077 { 2078 return IsOptimizedJSFunctionFrame() || IsFastJitFunctionFrame(); 2079 } 2080 GetMachineCodeSlot()2081 JSTaggedType *GetMachineCodeSlot() const 2082 { 2083 return const_cast<JSTaggedType*>(&machineCode_); 2084 } 2085 2086 private: 2087 uint32_t GetBaselineBytecodeOffset() const; 2088 2089 JSTaggedType *current_ {nullptr}; 2090 const JSThread *thread_ {nullptr}; 2091 const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr}; 2092 uintptr_t optimizedCallSiteSp_ {0}; 2093 uintptr_t optimizedReturnAddr_ {0}; 2094 uint8_t *stackMapAddr_ {nullptr}; 2095 kungfu::CalleeRegAndOffsetVec calleeRegInfo_; 2096 2097 // in jit, delta on method is not set, get it from iterator 2098 bool isJITFrame_ {false}; 2099 int fpDeltaPrevFrameSp_ {0}; 2100 2101 // cache current machine code, it's nonmovable 2102 JSTaggedType machineCode_ {JSTaggedValue::VALUE_UNDEFINED}; 2103 uintptr_t baselineNativePc_ {0}; // For baselineJit upFrame 2104 }; 2105 } // namespace panda::ecmascript 2106 #endif // ECMASCRIPT_FRAMES_H 2107