1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_FRAMES_H 17 #define ECMASCRIPT_FRAMES_H 18 19 #include "ecmascript/base/aligned_struct.h" 20 #include "ecmascript/js_tagged_value.h" 21 #include "ecmascript/mem/visitor.h" 22 #include "ecmascript/method.h" 23 #include "ecmascript/stackmap/ark_stackmap.h" 24 #include "ecmascript/stackmap/llvm_stackmap_type.h" 25 26 namespace panda::ecmascript { 27 class JSThread; 28 class EcmaVM; 29 class FrameIterator; 30 namespace kungfu { 31 class ArkStackMapParser; 32 }; 33 34 // Here list all scenarios of calling between Runtime/CInterpreter/ASMInterpreter/AOTCompiler/CBuiltin/ASMBuitlin. 35 // Please note that the "[]" means a must frame while "<>" means an optional frame. Each case is from top to down. 36 // 37 // * Runtime (C++) => CInterpreter: 38 // 1) [INTERPRETER_FRAME] 39 // 40 // * Runtime (C++) -> AOTCompiler: 41 // 1) [OPTIMIZED_ENTRY_FRAME] 42 // <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME> 43 // <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME> 44 // [OPTIMIZED_JS_FUNCTION_FRAME] 45 // 46 // * Runtime (C++) => ASMInterpreter: 47 // 1) [INTERPRETER_ENTRY_FRAME][ASM_INTERPRETER_FRAME] 48 // 49 // * Runtime (C++) => CBuiltin: 50 // 1) [not supported] 51 // 52 // * Runtime (C++) => ASMBuiltin: 53 // 1) [not supported] 54 // 55 // * CInterpreter => CInterpreter: 56 // 1) [INTERPRETER_FRAME] 57 // 58 // * CInterpreter => Runtime (C++): 59 // 1) [INTERPRETER_FAST_NEW_FRAME] 60 // 2) [INTERPRETER_CONSTRUCTOR_FRAME] 61 // 62 // * CInterpreter => AOTCompiler: 63 // 1) [not supported] 64 // 65 // * CInterperter => CBuiltin: 66 // 1) [INTERPRETER_BUILTIN_FRAME] 67 // 68 // * CInterpreter => ASMBuiltin: 69 // 1) [not supported] 70 // 71 // * ASMInterpreter => Runtime (C++): 72 // 1) [LEAVE_FRAME] 73 // 2) [LEAVE_FRAME_WITH_ARGV] 74 // 75 // * ASMInterpreter => AOTCompiler: 76 // 1) [OPTIMIZED_ENTRY_FRAME] 77 // <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME> 78 // <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME> 79 // [OPTIMIZED_JS_FUNCTION_FRAME] 80 // 81 // * ASMInterpreter => ASMInterpreter: 82 // 1) [ASM_INTERPRETER_FRAME] 83 // 84 // * ASMInterpreter => AsmBuiltin: 85 // 1) [BUILTIN_ENTRY_FRAME] 86 // [BUILTIN_FRAME] 87 // 2) [BUILTIN_ENTRY_FRAME] 88 // [BUILTIN_FRAME_WITH_ARGV] 89 // 90 // * ASMInterpreter => CBuiltin: 91 // 1) [LEAVE_FRAME] 92 // 2) [LEAVE_FRAME_WITH_ARGV] 93 // 94 // * AOTCompiler => Runtime (C++): 95 // 1) [LEAVE_FRAME] 96 // 2) [LEAVE_FRAME_WITH_ARGV] 97 // 98 // * AOTCompiler => ASMInterpreter: 99 // 1) [ASM_INTERPRETER_BRIDGE_FRAME] 100 // 2) [ASM_INTERPRETER_FRAME] 101 // 102 // * AOTCompiler => CBuiltin: 103 // 1) [LEAVE_FRAME] 104 // 2) [LEAVE_FRAME_WITH_ARGV] 105 // 106 // * AOTCompiler => ASMBuiltin: 107 // 1) [BUILTIN_ENTRY_FRAME] 108 // [BUILTIN_FRAME] 109 // 2) [BUILTIN_ENTRY_FRAME] 110 // [BUILTIN_FRAME_WITH_ARGV] 111 112 113 enum class FrameType: uintptr_t { 114 OPTIMIZED_FRAME = 0, 115 OPTIMIZED_ENTRY_FRAME, 116 OPTIMIZED_JS_FUNCTION_FRAME, 117 LEAVE_FRAME, 118 LEAVE_FRAME_WITH_ARGV, 119 BUILTIN_CALL_LEAVE_FRAME, 120 INTERPRETER_FRAME, 121 ASM_INTERPRETER_FRAME, 122 INTERPRETER_CONSTRUCTOR_FRAME, 123 BUILTIN_FRAME, 124 BUILTIN_FRAME_WITH_ARGV, 125 BUILTIN_ENTRY_FRAME, 126 INTERPRETER_BUILTIN_FRAME, 127 INTERPRETER_FAST_NEW_FRAME, 128 INTERPRETER_ENTRY_FRAME, 129 ASM_INTERPRETER_ENTRY_FRAME, 130 ASM_INTERPRETER_BRIDGE_FRAME, 131 OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME, 132 OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, 133 134 FRAME_TYPE_FIRST = OPTIMIZED_FRAME, 135 FRAME_TYPE_LAST = OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, 136 INTERPRETER_FIRST = INTERPRETER_FRAME, 137 INTERPRETER_LAST = INTERPRETER_FAST_NEW_FRAME, 138 BUILTIN_FIRST = BUILTIN_FRAME, 139 BUILTIN_LAST = BUILTIN_ENTRY_FRAME, 140 }; 141 142 enum class JSCallMode : uintptr_t { 143 CALL_ARG0 = 0, 144 CALL_ARG1, 145 CALL_ARG2, 146 CALL_ARG3, 147 CALL_THIS_ARG0, 148 CALL_THIS_ARG1, 149 CALL_THIS_ARG2, 150 CALL_THIS_ARG3, 151 CALL_WITH_ARGV, 152 CALL_THIS_WITH_ARGV, 153 CALL_CONSTRUCTOR_WITH_ARGV, 154 DEPRECATED_CALL_ARG0, 155 DEPRECATED_CALL_ARG1, 156 DEPRECATED_CALL_ARG2, 157 DEPRECATED_CALL_ARG3, 158 DEPRECATED_CALL_WITH_ARGV, 159 DEPRECATED_CALL_THIS_WITH_ARGV, 160 DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV, 161 CALL_GETTER, 162 CALL_SETTER, 163 CALL_THIS_ARG3_WITH_RETURN, 164 CALL_ENTRY, 165 CALL_GENERATOR, 166 CALL_FROM_AOT, 167 }; 168 169 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 170 struct OptimizedFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 171 base::AlignedPointer, 172 base::AlignedPointer, 173 base::AlignedPointer> { 174 public: 175 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 176 const RootBaseAndDerivedVisitor &derivedVisitor) const; 177 GetTypeOffsetOptimizedFrame178 static size_t GetTypeOffset() 179 { 180 return MEMBER_OFFSET(OptimizedFrame, type); 181 } GetPrevOffsetOptimizedFrame182 static size_t GetPrevOffset() 183 { 184 return MEMBER_OFFSET(OptimizedFrame, prevFp); 185 } ComputeReservedSizeOptimizedFrame186 static size_t ComputeReservedSize(size_t slotSize) 187 { 188 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex); 189 return slotSize * slotOffset; 190 } 191 private: 192 enum class Index : size_t { 193 TypeIndex = 0, 194 PrevFpIndex, 195 ReturnAddrIndex, 196 NumOfMembers 197 }; 198 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 199 GetFrameFromSpOptimizedFrame200 static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp) 201 { 202 return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp) 203 - MEMBER_OFFSET(OptimizedFrame, prevFp)); 204 } GetPrevFrameFpOptimizedFrame205 inline JSTaggedType* GetPrevFrameFp() 206 { 207 return prevFp; 208 } GetReturnAddrOptimizedFrame209 uintptr_t GetReturnAddr() const 210 { 211 return returnAddr; 212 } 213 [[maybe_unused]] alignas(EAS) FrameType type {0}; 214 alignas(EAS) JSTaggedType *prevFp {nullptr}; 215 alignas(EAS) uintptr_t returnAddr {0}; 216 friend class FrameIterator; 217 }; 218 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64); 219 220 // * OptimizedUnfoldArgVFrame layout description as the following: 221 // sp ----> |--------------------------| --------------- 222 // | returnAddr | ^ 223 // currentFp--> |--------------------------| | 224 // | prevFp | | 225 // |--------------------------| OptimizedUnfoldArgVFrame 226 // | frameType | | 227 // |--------------------------| | 228 // | currentFp | v 229 // +--------------------------+ --------------- 230 // 231 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 232 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 233 base::AlignedPointer, 234 base::AlignedPointer, 235 base::AlignedPointer, 236 base::AlignedPointer> { 237 public: GetTypeOffsetOptimizedJSFunctionUnfoldArgVFrame238 static size_t GetTypeOffset() 239 { 240 return MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, type); 241 } GetPrevOffsetOptimizedJSFunctionUnfoldArgVFrame242 static size_t GetPrevOffset() 243 { 244 return MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp); 245 } 246 private: 247 enum class Index : size_t { 248 CallSiteSpIndex = 0, 249 TypeIndex, 250 PrevFpIndex, 251 ReturnAddrIndex, 252 NumOfMembers 253 }; 254 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 255 GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame256 static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp) 257 { 258 return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp) 259 - MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp)); 260 } GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame261 inline JSTaggedType* GetPrevFrameFp() const 262 { 263 return prevFp; 264 } GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame265 uintptr_t GetReturnAddr() const 266 { 267 return returnAddr; 268 } GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame269 uintptr_t GetPrevFrameSp() const 270 { 271 return callSiteSp; 272 } 273 [[maybe_unused]] alignas(EAS) uintptr_t callSiteSp {0}; 274 [[maybe_unused]] alignas(EAS) FrameType type {0}; 275 alignas(EAS) JSTaggedType *prevFp {nullptr}; 276 alignas(EAS) uintptr_t returnAddr {0}; 277 friend class FrameIterator; 278 }; 279 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64); 280 281 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following: 282 // +--------------------------+ 283 // | arg[N-1] | 284 // +--------------------------+ 285 // | . . . . | 286 // +--------------------------+ 287 // | arg[0] | 288 // +--------------------------+ 289 // | argC | 290 // sp ---> +--------------------------+ ----------------- 291 // | | ^ 292 // | prevFP | | 293 // |--------------------------| OptimizedJSFunctionArgsConfigFrame 294 // | frameType | | 295 // | | V 296 // +--------------------------+ ----------------- 297 // 298 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 299 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 300 base::AlignedPointer, 301 base::AlignedPointer> { 302 public: GetTypeOffsetOptimizedJSFunctionArgConfigFrame303 static size_t GetTypeOffset() 304 { 305 return MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, type); 306 } GetPrevOffsetOptimizedJSFunctionArgConfigFrame307 static size_t GetPrevOffset() 308 { 309 return MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp); 310 } 311 private: 312 enum class Index : size_t { 313 TypeIndex = 0, 314 PrevFpIndex, 315 NumOfMembers 316 }; 317 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 318 GetFrameFromSpOptimizedJSFunctionArgConfigFrame319 static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp) 320 { 321 return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp) 322 - MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp)); 323 } GetPrevFrameFpOptimizedJSFunctionArgConfigFrame324 inline JSTaggedType* GetPrevFrameFp() 325 { 326 return prevFp; 327 } 328 [[maybe_unused]] alignas(EAS) FrameType type {0}; 329 alignas(EAS) JSTaggedType *prevFp {nullptr}; 330 friend class FrameIterator; 331 }; 332 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame), 333 OptimizedJSFunctionArgConfigFrame::SizeArch32, 334 OptimizedJSFunctionArgConfigFrame::SizeArch64); 335 336 // * OptimizedJSFunctionFrame layout description as the following: 337 // +--------------------------+ 338 // | arg[N-1] | 339 // +--------------------------+ 340 // | ... | 341 // +--------------------------+ 342 // | arg[1] | 343 // +--------------------------+ 344 // | arg[0] | 345 // +--------------------------+ 346 // | this | 347 // +--------------------------+ 348 // | new-target | 349 // +--------------------------+ 350 // | call-target | 351 // |--------------------------| 352 // | argc | 353 // |--------------------------| 354 // | lexEnv | 355 // sp ----> |--------------------------| --------------- 356 // | returnAddr | ^ 357 // |--------------------------| | 358 // | callsiteFp | | 359 // |--------------------------| OptimizedJSFunctionFrame 360 // | frameType | | 361 // |--------------------------| | 362 // | call-target | v 363 // +--------------------------+ --------------- 364 // 365 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 366 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 367 JSTaggedValue, 368 base::AlignedPointer, 369 base::AlignedPointer, 370 base::AlignedPointer> { 371 public: 372 static constexpr size_t ENV_SLOT_DIFF = 2; 373 enum class Index : size_t { 374 JSFuncIndex = 0, 375 TypeIndex, 376 PrevFpIndex, 377 ReturnAddrIndex, 378 NumOfMembers 379 }; 380 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 381 GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame382 static constexpr size_t GetFunctionDeltaReturnAddr() 383 { 384 return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex); 385 } 386 GetPrevFrameFpOptimizedJSFunctionFrame387 inline JSTaggedType* GetPrevFrameFp() 388 { 389 return prevFp; 390 } 391 GetArgvOptimizedJSFunctionFrame392 JSTaggedType* GetArgv(uintptr_t *preFrameSp) const 393 { 394 return reinterpret_cast<JSTaggedType *>(preFrameSp + ENV_SLOT_DIFF * sizeof(uint64_t) / sizeof(uintptr_t)); 395 } 396 GetArgcOptimizedJSFunctionFrame397 size_t GetArgc(uintptr_t *preFrameSp) const 398 { 399 return *(preFrameSp + sizeof(uint64_t) / sizeof(uintptr_t)); 400 } 401 402 JSTaggedType* GetArgv(const FrameIterator &it) const; 403 GetReturnAddrOptimizedJSFunctionFrame404 uintptr_t GetReturnAddr() const 405 { 406 return returnAddr; 407 } 408 409 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 410 const RootBaseAndDerivedVisitor &derivedVisitor) const; 411 void CollectBCOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const; 412 GetFunctionOptimizedJSFunctionFrame413 inline JSTaggedValue GetFunction() const 414 { 415 return jsFunc; 416 } 417 ComputeArgsConfigFrameSpOptimizedJSFunctionFrame418 static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp) 419 { 420 const size_t offset = 2; // 2: skip prevFp and return address. 421 return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t); 422 } 423 GetTypeOffsetOptimizedJSFunctionFrame424 static size_t GetTypeOffset() 425 { 426 return MEMBER_OFFSET(OptimizedJSFunctionFrame, type); 427 } 428 GetPrevOffsetOptimizedJSFunctionFrame429 static size_t GetPrevOffset() 430 { 431 return MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp); 432 } 433 ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame434 static size_t ComputeReservedJSFuncOffset(size_t slotSize) 435 { 436 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex); 437 return slotSize * slotOffset; 438 } 439 440 friend class FrameIterator; 441 friend class FrameHandler; 442 void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const; 443 void GetFuncCalleeRegAndOffset( 444 const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const; 445 uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const; 446 447 private: GetFrameFromSpOptimizedJSFunctionFrame448 static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) 449 { 450 return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) 451 - MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp)); 452 } 453 454 // dynamic callee saveregisters for x86-64 455 alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()}; 456 [[maybe_unused]] alignas(EAS) FrameType type {0}; 457 alignas(EAS) JSTaggedType *prevFp {nullptr}; 458 alignas(EAS) uintptr_t returnAddr {0}; 459 // dynamic callee saveregisters for arm64 460 }; 461 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame), 462 OptimizedJSFunctionFrame::SizeArch32, 463 OptimizedJSFunctionFrame::SizeArch64); 464 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time. 465 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1); 466 467 // * The JSFunctionEntry Frame's structure is illustrated as the following: 468 // +--------------------------+ 469 // | . . . . . . | 470 // sp ---> +--------------------------+ ----------------- 471 // | prevFP | ^ 472 // |--------------------------| | 473 // | frameType | JSFunctionEntryFrame 474 // |--------------------------| | 475 // | preLeaveFrameFp | v 476 // +--------------------------+ ----------------- 477 478 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 479 base::AlignedPointer, 480 base::AlignedPointer, 481 base::AlignedPointer> { 482 public: 483 enum class CallType : size_t { 484 CALL_FUNC = 0, 485 CALL_NEW, 486 }; 487 488 enum class Index : size_t { 489 PreLeaveFrameFpIndex = 0, 490 TypeIndex, 491 PrevFpIndex, 492 NumOfMembers 493 }; 494 GetTypeOffsetOptimizedEntryFrame495 static size_t GetTypeOffset() 496 { 497 return MEMBER_OFFSET(OptimizedEntryFrame, type); 498 } 499 GetLeaveFrameFpOffsetOptimizedEntryFrame500 static size_t GetLeaveFrameFpOffset() 501 { 502 return MEMBER_OFFSET(OptimizedEntryFrame, preLeaveFrameFp); 503 } 504 GetPrevFrameFpOptimizedEntryFrame505 inline JSTaggedType* GetPrevFrameFp() 506 { 507 return preLeaveFrameFp; 508 } 509 ComputeReservedSizeOptimizedEntryFrame510 static size_t ComputeReservedSize(size_t slotSize) 511 { 512 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex); 513 return slotSize * slotOffset; 514 } 515 friend class FrameIterator; 516 517 private: 518 alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr}; 519 alignas(EAS) [[maybe_unused]] FrameType type {0}; 520 alignas(EAS) [[maybe_unused]] JSTaggedType *prevFp {nullptr}; GetFrameFromSpOptimizedEntryFrame521 static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 522 { 523 return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) - 524 MEMBER_OFFSET(OptimizedEntryFrame, prevFp)); 525 } 526 }; 527 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64); 528 529 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 530 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(), 531 base::AlignedPointer, 532 base::AlignedSize> { 533 enum class Index : size_t { 534 PrevIndex = 0, 535 TypeIndex, 536 NumOfMembers 537 }; 538 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 539 GetPrevFrameFpInterpretedFrameBase540 inline JSTaggedType* GetPrevFrameFp() 541 { 542 return prev; 543 } 544 GetFrameFromSpInterpretedFrameBase545 static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp) 546 { 547 return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1; 548 } 549 GetPrevOffsetInterpretedFrameBase550 static size_t GetPrevOffset(bool isArch32) 551 { 552 return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32); 553 } 554 GetTypeOffsetInterpretedFrameBase555 static size_t GetTypeOffset(bool isArch32) 556 { 557 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 558 } 559 GetSizeInterpretedFrameBase560 static constexpr size_t GetSize(bool isArch32) 561 { 562 return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64; 563 } 564 565 alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc 566 alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0 567 }; 568 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase), 569 InterpretedFrameBase::SizeArch32, 570 InterpretedFrameBase::SizeArch64); 571 572 // Interpreter Frame Layout as the following: 573 // +----------------------------------+ 574 // | argv[n-1] | 575 // |----------------------------------| 576 // | ...... | 577 // |----------------------------------| 578 // | thisArg [maybe not exist] | 579 // |----------------------------------| 580 // | newTarget [maybe not exist] | 581 // |----------------------------------| 582 // | ...... | 583 // |----------------------------------| 584 // | Vregs [not exist in native] | 585 // +----------------------------------+--------+ 586 // | base.frameType | ^ 587 // |----------------------------------| | 588 // | base.prev(prev stack pointer) | | 589 // |----------------------------------| | 590 // | pc(bytecode addr) | | 591 // |----------------------------------| | 592 // | sp(current stack pointer) | | 593 // |----------------------------------| | 594 // | env | | 595 // |----------------------------------| | 596 // | acc | | 597 // |----------------------------------| InterpretedFrame 598 // | profileTypeInfo | | 599 // |----------------------------------| | 600 // | thisObj | | 601 // |----------------------------------| | 602 // | function | | 603 // |----------------------------------| | 604 // | constpool | v 605 // +----------------------------------+--------+ 606 // 607 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 608 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 609 JSTaggedValue, 610 JSTaggedValue, 611 JSTaggedValue, 612 JSTaggedValue, 613 JSTaggedValue, 614 JSTaggedValue, 615 base::AlignedPointer, 616 InterpretedFrameBase> { 617 public: 618 enum class Index : size_t { 619 ConstPoolIndex = 0, 620 FunctionIndex, 621 ThisObjIndex, 622 ProFileTypeInfoIndex, 623 AccIndex, 624 EnvIndex, 625 PcIndex, 626 BaseIndex, 627 NumOfMembers 628 }; 629 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 630 GetPrevFrameFpInterpretedFrame631 inline JSTaggedType* GetPrevFrameFp() const 632 { 633 return base.prev; 634 } 635 GetFrameFromSpInterpretedFrame636 static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 637 { 638 return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 639 } 640 GetPcInterpretedFrame641 inline const uint8_t *GetPc() const 642 { 643 return pc; 644 } 645 GetEnvInterpretedFrame646 inline JSTaggedValue GetEnv() const 647 { 648 return env; 649 } 650 NumOfMembersInterpretedFrame651 static uint32_t NumOfMembers() 652 { 653 return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 654 } 655 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 656 657 alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()}; 658 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 659 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 660 alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()}; 661 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 662 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 663 alignas(EAS) const uint8_t *pc {nullptr}; 664 alignas(EAS) InterpretedFrameBase base; 665 friend class FrameIterator; 666 }; 667 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64); 668 669 // * InterpretedBuiltinFrame layout description as the following: 670 // |--------------------------| --------------- 671 // | . . . . . | ^ 672 // | InterpretedFrameBase | | 673 // | . . . . . | | 674 // |--------------------------| InterpretedBuiltinFrame 675 // | bytecode-PC | | 676 // |--------------------------| | 677 // | call-target | v 678 // +--------------------------+ --------------- 679 // 680 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 681 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 682 JSTaggedValue, 683 base::AlignedPointer, 684 InterpretedFrameBase> { 685 enum class Index : size_t { 686 FunctionIndex = 0, 687 PcIndex, 688 BaseIndex, 689 NumOfMembers 690 }; 691 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 692 GetPrevFrameFpInterpretedBuiltinFrame693 inline JSTaggedType* GetPrevFrameFp() 694 { 695 return base.prev; 696 } 697 GetFrameFromSpInterpretedBuiltinFrame698 static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 699 { 700 return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 701 } 702 NumOfMembersInterpretedBuiltinFrame703 static uint32_t NumOfMembers() 704 { 705 return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize(); 706 } 707 708 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 709 710 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 711 alignas(EAS) const uint8_t *pc {nullptr}; 712 alignas(EAS) InterpretedFrameBase base; 713 }; 714 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame), 715 InterpretedBuiltinFrame::SizeArch32, 716 InterpretedBuiltinFrame::SizeArch64); 717 718 // AsmInterpretedFrame Layout as the following: 719 // +----------------------------------+ 720 // | argv[n-1] | 721 // |----------------------------------| 722 // | ...... | 723 // |----------------------------------| 724 // | thisArg [maybe not exist] | 725 // |----------------------------------| 726 // | newTarget [maybe not exist] | 727 // |----------------------------------| 728 // | ...... | 729 // |----------------------------------| 730 // | Vregs [not exist in native] | 731 // +----------------------------------+--------+ 732 // | . . . . | ^ 733 // | InterpretedFrameBase | | 734 // | . . . . | | 735 // |----------------------------------| | 736 // | pc(bytecode addr) | | 737 // |----------------------------------| | 738 // | sp(current stack pointer) | | 739 // |----------------------------------| AsmInterpretedFrame 740 // | callSize | | 741 // |----------------------------------| | 742 // | env | | 743 // |----------------------------------| | 744 // | acc | | 745 // |----------------------------------| | 746 // | thisObj | | 747 // |----------------------------------| | 748 // | call-target | v 749 // +----------------------------------+--------+ 750 // 751 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 752 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 753 JSTaggedValue, 754 JSTaggedValue, 755 JSTaggedValue, 756 JSTaggedValue, 757 base::AlignedPointer, 758 base::AlignedPointer, 759 base::AlignedPointer, 760 InterpretedFrameBase> { 761 enum class Index : size_t { 762 FunctionIndex = 0, 763 ThisObjIndex, 764 AccIndex, 765 EnvIndex, 766 CallSizeIndex, 767 FpIndex, 768 PcIndex, 769 BaseIndex, 770 NumOfMembers 771 }; 772 773 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 774 GetCurrentFramePointerAsmInterpretedFrame775 inline JSTaggedType* GetCurrentFramePointer() 776 { 777 return fp; 778 } 779 GetPrevFrameFpAsmInterpretedFrame780 inline JSTaggedType* GetPrevFrameFp() 781 { 782 return base.prev; 783 } 784 GetFrameFromSpAsmInterpretedFrame785 static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 786 { 787 return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 788 } 789 GetFpOffsetAsmInterpretedFrame790 static size_t GetFpOffset(bool isArch32) 791 { 792 return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32); 793 } 794 GetCallSizeOffsetAsmInterpretedFrame795 static size_t GetCallSizeOffset(bool isArch32) 796 { 797 return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32); 798 } 799 GetFunctionOffsetAsmInterpretedFrame800 static size_t GetFunctionOffset(bool isArch32) 801 { 802 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 803 } 804 GetThisOffsetAsmInterpretedFrame805 static size_t GetThisOffset(bool isArch32) 806 { 807 return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32); 808 } 809 GetAccOffsetAsmInterpretedFrame810 static size_t GetAccOffset(bool isArch32) 811 { 812 return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32); 813 } 814 GetEnvOffsetAsmInterpretedFrame815 static size_t GetEnvOffset(bool isArch32) 816 { 817 return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32); 818 } 819 GetBaseOffsetAsmInterpretedFrame820 static size_t GetBaseOffset(bool isArch32) 821 { 822 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 823 } 824 GetPcOffsetAsmInterpretedFrame825 static size_t GetPcOffset(bool isArch32) 826 { 827 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 828 } 829 GetSizeAsmInterpretedFrame830 static constexpr size_t GetSize(bool isArch32) 831 { 832 return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64; 833 } 834 NumOfMembersAsmInterpretedFrame835 static uint32_t NumOfMembers() 836 { 837 return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 838 } 839 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 840 const RootBaseAndDerivedVisitor &derivedVisitor) const; 841 GetEnvAsmInterpretedFrame842 JSTaggedValue GetEnv() const 843 { 844 return env; 845 } 846 GetPcAsmInterpretedFrame847 const uint8_t *GetPc() const 848 { 849 return pc; 850 } 851 852 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 853 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 854 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 855 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 856 alignas(EAS) uintptr_t callSize {0}; 857 alignas(EAS) JSTaggedType *fp {nullptr}; 858 alignas(EAS) const uint8_t *pc {nullptr}; 859 alignas(EAS) InterpretedFrameBase base; 860 // vregs, not exist in native 861 // args, may be truncated if not extra 862 }; 863 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64); 864 865 // InterpretedEntryFrame Layout as the following: 866 // +----------------------------------+--------------- 867 // | . . . . | ^ 868 // | InterpretedFrameBase | | 869 // | . . . . | InterpretedEntryFrame 870 // |----------------------------------| | 871 // | pc(bytecode addr) | v 872 // |----------------------------------|--------------- 873 // 874 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 875 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 876 base::AlignedPointer, 877 InterpretedFrameBase> { 878 enum class Index : size_t { 879 PcIndex = 0, 880 BaseIndex, 881 NumOfMembers 882 }; 883 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 884 GetPrevFrameFpInterpretedEntryFrame885 inline JSTaggedType* GetPrevFrameFp() 886 { 887 return base.prev; 888 } 889 GetFrameFromSpInterpretedEntryFrame890 static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 891 { 892 return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 893 } 894 NumOfMembersInterpretedEntryFrame895 static uint32_t NumOfMembers() 896 { 897 return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize(); 898 } 899 900 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, 901 const RootRangeVisitor &rangeVisitor) const; 902 alignas(EAS) const uint8_t *pc {nullptr}; 903 alignas(EAS) InterpretedFrameBase base; 904 }; 905 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame), 906 InterpretedEntryFrame::SizeArch32, 907 InterpretedEntryFrame::SizeArch64); 908 909 910 // AsmInterpretedEntryFrame Layout as the following: 911 // +----------------------------------+--------------- 912 // | . . . . | ^ 913 // | InterpretedFrameBase | | 914 // | . . . . | AsmInterpretedEntryFrame 915 // |----------------------------------| | 916 // | pc(bytecode addr) | v 917 // |----------------------------------|--------------- 918 // 919 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 920 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 921 base::AlignedPointer, 922 InterpretedFrameBase> { 923 enum class Index : size_t { 924 PcIndex = 0, 925 BaseIndex, 926 NumOfMembers 927 }; 928 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 929 GetPrevFrameFpAsmInterpretedEntryFrame930 inline JSTaggedType* GetPrevFrameFp() 931 { 932 return base.prev; 933 } 934 GetBaseOffsetAsmInterpretedEntryFrame935 static size_t GetBaseOffset(bool isArch32) 936 { 937 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 938 } 939 GetFrameFromSpAsmInterpretedEntryFrame940 static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 941 { 942 return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 943 } 944 945 alignas(EAS) const uint8_t *pc {nullptr}; 946 alignas(EAS) InterpretedFrameBase base; 947 }; 948 949 // AsmInterpretedBridgeFrame Layout as the following: 950 // +----------------------------------+--------------- 951 // | ret-address | ^ 952 // |----------------------------------| | 953 // | . . . . | AsmInterpretedBridgeFrame 954 // | AsmInterpretedEntryFrame | | 955 // | . . . . | v 956 // |----------------------------------|--------------- 957 // 958 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 959 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 960 AsmInterpretedEntryFrame, 961 base::AlignedPointer> { 962 enum class Index : size_t { 963 EntryIndex = 0, 964 ReturnAddrIndex, 965 NumOfMembers 966 }; 967 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 968 GetFrameFromSpAsmInterpretedBridgeFrame969 static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 970 { 971 return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 972 MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr)); 973 } GetCallSiteSpAsmInterpretedBridgeFrame974 uintptr_t GetCallSiteSp() const 975 { 976 return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame); 977 } GetPrevFrameFpAsmInterpretedBridgeFrame978 inline JSTaggedType* GetPrevFrameFp() 979 { 980 return entry.base.prev; 981 } 982 GetReturnAddrOffsetAsmInterpretedBridgeFrame983 static size_t GetReturnAddrOffset(bool isArch32) 984 { 985 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 986 } 987 GetSizeAsmInterpretedBridgeFrame988 static constexpr size_t GetSize(bool isArch32) 989 { 990 return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64; 991 } 992 993 AsmInterpretedEntryFrame entry; 994 alignas(EAS) uintptr_t returnAddr; GetReturnAddrAsmInterpretedBridgeFrame995 uintptr_t GetReturnAddr() const 996 { 997 return returnAddr; 998 } 999 }; 1000 1001 // * Optimized-leaved-frame layout as the following: 1002 // +--------------------------+ 1003 // | argv[N-1] | 1004 // |--------------------------| 1005 // | . . . . . | 1006 // |--------------------------| 1007 // | argv[0] | 1008 // +--------------------------+------------- 1009 // | argc | ^ 1010 // |--------------------------| | 1011 // | RuntimeId | | 1012 // sp --> |--------------------------| OptimizedLeaveFrame 1013 // | ret-addr | | 1014 // |--------------------------| | 1015 // | prevFp | | 1016 // |--------------------------| | 1017 // | frameType | v 1018 // +--------------------------+------------- 1019 // 1020 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1021 struct OptimizedLeaveFrame { 1022 FrameType type; 1023 uintptr_t callsiteFp; // thread sp set here 1024 uintptr_t returnAddr; 1025 uint64_t argRuntimeId; 1026 uint64_t argc; 1027 // argv[0]...argv[argc-1] dynamic according to agc GetFrameFromSpOptimizedLeaveFrame1028 static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1029 { 1030 return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1031 MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp)); 1032 } GetCallSiteSpOptimizedLeaveFrame1033 uintptr_t GetCallSiteSp() const 1034 { 1035 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId); 1036 } GetPrevFrameFpOptimizedLeaveFrame1037 inline JSTaggedType* GetPrevFrameFp() const 1038 { 1039 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1040 } 1041 GetReturnAddrOptimizedLeaveFrame1042 uintptr_t GetReturnAddr() const 1043 { 1044 return returnAddr; 1045 } 1046 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1047 }; 1048 1049 // * Optimized-leaved-frame-with-argv layout as the following: 1050 // +--------------------------+ 1051 // | argv[] | 1052 // +--------------------------+------------- 1053 // | argc | ^ 1054 // |--------------------------| | 1055 // | RuntimeId | OptimizedWithArgvLeaveFrame 1056 // sp --> |--------------------------| | 1057 // | returnAddr | | 1058 // |--------------------------| | 1059 // | callsiteFp | | 1060 // |--------------------------| | 1061 // | frameType | v 1062 // +--------------------------+------------- 1063 1064 struct OptimizedWithArgvLeaveFrame { 1065 FrameType type; 1066 uintptr_t callsiteFp; // thread sp set here 1067 uintptr_t returnAddr; 1068 uint64_t argRuntimeId; 1069 uint64_t argc; 1070 GetFrameFromSpOptimizedWithArgvLeaveFrame1071 static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1072 { 1073 return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1074 MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp)); 1075 } GetCallSiteSpOptimizedWithArgvLeaveFrame1076 uintptr_t GetCallSiteSp() const 1077 { 1078 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId); 1079 } GetPrevFrameFpOptimizedWithArgvLeaveFrame1080 inline JSTaggedType* GetPrevFrameFp() 1081 { 1082 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1083 } GetReturnAddrOptimizedWithArgvLeaveFrame1084 uintptr_t GetReturnAddr() const 1085 { 1086 return returnAddr; 1087 } 1088 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1089 }; 1090 1091 // * OptimizedBuiltinLeaveFrame layout as the following: 1092 // +--------------------------+ 1093 // | argv[N-1] | 1094 // |--------------------------| 1095 // | . . . . . | 1096 // |--------------------------| 1097 // | argv[0] | 1098 // +--------------------------+------------- 1099 // | argc | ^ 1100 // |--------------------------| | 1101 // | env | | 1102 // +--------------------------+ | 1103 // | ret-addr | | 1104 // sp --> |--------------------------| OptimizedBuiltinLeaveFrame 1105 // | prevFp | | 1106 // |--------------------------| | 1107 // | frameType | | 1108 // |--------------------------| | 1109 // | align byte | v 1110 // +--------------------------+------------- 1111 // 1112 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1113 struct OptimizedBuiltinLeaveFrame { 1114 public: GetFrameFromSpOptimizedBuiltinLeaveFrame1115 static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1116 { 1117 return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1118 MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp)); 1119 } GetCallSiteSpOptimizedBuiltinLeaveFrame1120 uintptr_t GetCallSiteSp() const 1121 { 1122 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, thread); 1123 } GetPrevFrameFpOptimizedBuiltinLeaveFrame1124 inline JSTaggedType* GetPrevFrameFp() const 1125 { 1126 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1127 } GetReturnAddrOptimizedBuiltinLeaveFrame1128 uintptr_t GetReturnAddr() const 1129 { 1130 return returnAddr; 1131 } 1132 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; GetTypeOffsetOptimizedBuiltinLeaveFrame1133 static size_t GetTypeOffset() 1134 { 1135 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type); 1136 } GetPrevOffsetOptimizedBuiltinLeaveFrame1137 static size_t GetPrevOffset() 1138 { 1139 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp); 1140 } GetArgvOptimizedBuiltinLeaveFrame1141 const JSTaggedType* GetArgv() const 1142 { 1143 return reinterpret_cast<const JSTaggedType *>(&argc + 1); 1144 } 1145 1146 private: 1147 [[maybe_unused]] FrameType type; 1148 uintptr_t callsiteFp; // thread sp set here 1149 uintptr_t returnAddr; 1150 JSTaggedValue thread; 1151 uint64_t argc; 1152 // argv[0]...argv[argc-1] dynamic according to agc 1153 }; 1154 1155 // * BuiltinFrame layout as the following: 1156 // +--------------------------+ 1157 // | argV[N - 1] | 1158 // |--------------------------| 1159 // | . . . . | 1160 // |--------------------------+ 1161 // | argV[2]=this | 1162 // +--------------------------+ 1163 // | argV[1]=new-target | 1164 // +--------------------------+ 1165 // | argV[0]=call-target | 1166 // +--------------------------+ --------- 1167 // | argc | ^ 1168 // |--------------------------| | 1169 // | thread | | 1170 // |--------------------------| | 1171 // | returnAddr | BuiltinFrame 1172 // |--------------------------| | 1173 // | callsiteFp | | 1174 // |--------------------------| | 1175 // | frameType | v 1176 // +--------------------------+ --------- 1177 // 1178 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1179 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1180 base::AlignedSize, 1181 base::AlignedPointer, 1182 base::AlignedPointer, 1183 base::AlignedPointer, 1184 base::AlignedPointer, 1185 base::AlignedPointer> { 1186 enum class Index : size_t { 1187 TypeIndex = 0, 1188 PrevFpIndex, 1189 ReturnAddrIndex, 1190 ThreadIndex, 1191 NumArgsIndex, 1192 StackArgsIndex, 1193 NumOfMembers 1194 }; 1195 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1196 GetFrameFromSpBuiltinFrame1197 static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 1198 { 1199 return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) - 1200 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1201 } GetPrevFrameFpBuiltinFrame1202 inline JSTaggedType* GetPrevFrameFp() 1203 { 1204 return prevFp; 1205 } GetCallSiteSpBuiltinFrame1206 uintptr_t GetCallSiteSp() const 1207 { 1208 return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread); 1209 } GetPreFpOffsetBuiltinFrame1210 static size_t GetPreFpOffset(bool isArch32) 1211 { 1212 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1213 } GetNumArgsToFpDeltaBuiltinFrame1214 static size_t GetNumArgsToFpDelta(bool isArch32) 1215 { 1216 auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32); 1217 return offset - GetPreFpOffset(isArch32); 1218 } GetStackArgsToFpDeltaBuiltinFrame1219 static size_t GetStackArgsToFpDelta(bool isArch32) 1220 { 1221 auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 1222 return offset - GetPreFpOffset(isArch32); 1223 } GetStackArgsAddressBuiltinFrame1224 uintptr_t GetStackArgsAddress() 1225 { 1226 return reinterpret_cast<uintptr_t>(&stackArgs); 1227 } GetFunctionBuiltinFrame1228 JSTaggedValue GetFunction() 1229 { 1230 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1231 return JSTaggedValue(*functionAddress); 1232 } GetNumArgsBuiltinFrame1233 int32_t GetNumArgs() 1234 { 1235 return numArgs; 1236 } 1237 GetReturnAddrBuiltinFrame1238 uintptr_t GetReturnAddr() const 1239 { 1240 return returnAddr; 1241 } 1242 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1243 alignas(EAS) FrameType type; 1244 alignas(EAS) JSTaggedType *prevFp; 1245 alignas(EAS) uintptr_t returnAddr; 1246 alignas(EAS) uintptr_t thread; 1247 alignas(EAS) int32_t numArgs; 1248 alignas(EAS) uintptr_t stackArgs; 1249 }; 1250 1251 // * BuiltinWithArgvFrame layout as the following: 1252 // +--------------------------+ --------- 1253 // | . . . . . | ^ 1254 // |--------------------------| | 1255 // | returnAddr | | 1256 // |--------------------------| | 1257 // | callsiteFp | BuiltinWithArgvFrame 1258 // |--------------------------| | 1259 // | frameType | | 1260 // +--------------------------+ | 1261 // | argc | v 1262 // +--------------------------+ --------- 1263 // | argV[0] | 1264 // +--------------------------+ 1265 // | argV[1] | 1266 // +--------------------------+ 1267 // | . . . . | 1268 // +--------------------------+ 1269 // 1270 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1271 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1272 base::AlignedSize, 1273 base::AlignedPointer, 1274 base::AlignedPointer> { 1275 enum class Index : int { 1276 StackArgsTopIndex = -1, 1277 NumArgsIndex = -1, 1278 TypeIndex = 0, 1279 PrevFpIndex, 1280 ReturnAddrIndex, 1281 NumOfMembers 1282 }; 1283 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1284 GetFrameFromSpBuiltinWithArgvFrame1285 static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp) 1286 { 1287 return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) - 1288 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1289 } GetPrevFrameFpBuiltinWithArgvFrame1290 inline JSTaggedType* GetPrevFrameFp() 1291 { 1292 return prevFp; 1293 } GetCallSiteSpBuiltinWithArgvFrame1294 uintptr_t GetCallSiteSp() const 1295 { 1296 return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame); 1297 } GetStackArgsAddressBuiltinWithArgvFrame1298 uintptr_t GetStackArgsAddress() 1299 { 1300 auto topAddress = ToUintPtr(this) + 1301 (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t)); 1302 auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS; 1303 return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t); 1304 } GetFunctionBuiltinWithArgvFrame1305 JSTaggedValue GetFunction() 1306 { 1307 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1308 return JSTaggedValue(*functionAddress); 1309 } GetNumArgsBuiltinWithArgvFrame1310 int32_t GetNumArgs() 1311 { 1312 auto argcAddress = reinterpret_cast<int32_t *>( 1313 ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t))); 1314 return *argcAddress; 1315 } GetReturnAddrBuiltinWithArgvFrame1316 uintptr_t GetReturnAddr() const 1317 { 1318 return returnAddr; 1319 } 1320 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1321 // argv(... this, new.target, function) 1322 // numargs 1323 alignas(EAS) FrameType type; 1324 alignas(EAS) JSTaggedType *prevFp; 1325 alignas(EAS) uintptr_t returnAddr; 1326 }; 1327 1328 enum class GCVisitedFlag : bool { 1329 VISITED = true, 1330 IGNORED = false, 1331 }; 1332 1333 class FrameIterator { 1334 public: 1335 explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr); GetFrameType()1336 FrameType GetFrameType() const 1337 { 1338 ASSERT(current_ != nullptr); 1339 FrameType *typeAddr = reinterpret_cast<FrameType *>( 1340 reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType)); 1341 return *typeAddr; 1342 } 1343 1344 template<class T> GetFrame()1345 T* GetFrame() 1346 { 1347 return T::GetFrameFromSp(current_); 1348 } 1349 1350 template<class T> GetFrame()1351 const T* GetFrame() const 1352 { 1353 return T::GetFrameFromSp(current_); 1354 } 1355 Done()1356 bool Done() const 1357 { 1358 return current_ == nullptr; 1359 } GetSp()1360 JSTaggedType *GetSp() const 1361 { 1362 return current_; 1363 } GetSp()1364 JSTaggedType *GetSp() 1365 { 1366 return current_; 1367 } GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)1368 void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const 1369 { 1370 ret = calleeRegInfo_; 1371 } 1372 int ComputeDelta() const; 1373 template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED> 1374 void Advance(); 1375 uint32_t GetBytecodeOffset() const; 1376 uintptr_t GetPrevFrameCallSiteSp([[maybe_unused]] uintptr_t curPc = 0) const; 1377 uintptr_t GetPrevFrame() const; GetCallSiteSp()1378 uintptr_t GetCallSiteSp() const 1379 { 1380 return optimizedCallSiteSp_; 1381 } GetOptimizedReturnAddr()1382 uintptr_t GetOptimizedReturnAddr() const 1383 { 1384 return optimizedReturnAddr_; 1385 } GetThread()1386 const JSThread *GetThread() const 1387 { 1388 return thread_; 1389 } 1390 bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const; 1391 void CollectBCOffsetInfo(kungfu::ConstInfo &info) const; 1392 void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const; 1393 std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const; 1394 int GetCallSiteDelta(uintptr_t retAddr) const; 1395 1396 Method *CheckAndGetMethod() const; 1397 JSTaggedValue GetFunction() const; 1398 IsLeaveFrame()1399 bool IsLeaveFrame() const 1400 { 1401 FrameType type = GetFrameType(); 1402 return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV); 1403 } 1404 IsOptimizedFrame()1405 bool IsOptimizedFrame() const 1406 { 1407 FrameType type = GetFrameType(); 1408 return (type == FrameType::OPTIMIZED_FRAME); 1409 } 1410 IsOptimizedJSFunctionFrame()1411 bool IsOptimizedJSFunctionFrame() const 1412 { 1413 FrameType type = GetFrameType(); 1414 return (type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME); 1415 } 1416 1417 private: 1418 JSTaggedType *current_ {nullptr}; 1419 const JSThread *thread_ {nullptr}; 1420 const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr}; 1421 uintptr_t optimizedCallSiteSp_ {0}; 1422 uintptr_t optimizedReturnAddr_ {0}; 1423 uint8_t *stackMapAddr_ {nullptr}; 1424 int fpDeltaPrevFrameSp_ {0}; 1425 kungfu::CalleeRegAndOffsetVec calleeRegInfo_; 1426 }; 1427 } // namespace panda::ecmascript 1428 extern "C" int step_ark_managed_native_frame( 1429 int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp, char *buf, size_t buf_sz); 1430 #endif // ECMASCRIPT_FRAMES_H 1431