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 ASM_BRIDGE_FRAME, 118 LEAVE_FRAME, 119 LEAVE_FRAME_WITH_ARGV, 120 BUILTIN_CALL_LEAVE_FRAME, 121 INTERPRETER_FRAME, 122 ASM_INTERPRETER_FRAME, 123 INTERPRETER_CONSTRUCTOR_FRAME, 124 BUILTIN_FRAME, 125 BUILTIN_FRAME_WITH_ARGV, 126 BUILTIN_ENTRY_FRAME, 127 INTERPRETER_BUILTIN_FRAME, 128 INTERPRETER_FAST_NEW_FRAME, 129 INTERPRETER_ENTRY_FRAME, 130 ASM_INTERPRETER_ENTRY_FRAME, 131 ASM_INTERPRETER_BRIDGE_FRAME, 132 OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME, 133 OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, 134 135 FRAME_TYPE_FIRST = OPTIMIZED_FRAME, 136 FRAME_TYPE_LAST = OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, 137 INTERPRETER_FIRST = INTERPRETER_FRAME, 138 INTERPRETER_LAST = INTERPRETER_FAST_NEW_FRAME, 139 BUILTIN_FIRST = BUILTIN_FRAME, 140 BUILTIN_LAST = BUILTIN_ENTRY_FRAME, 141 }; 142 143 enum class JSCallMode : uintptr_t { 144 CALL_ARG0 = 0, 145 CALL_ARG1, 146 CALL_ARG2, 147 CALL_ARG3, 148 CALL_THIS_ARG0, 149 CALL_THIS_ARG1, 150 CALL_THIS_ARG2, 151 CALL_THIS_ARG3, 152 CALL_WITH_ARGV, 153 CALL_THIS_WITH_ARGV, 154 CALL_CONSTRUCTOR_WITH_ARGV, 155 DEPRECATED_CALL_ARG0, 156 DEPRECATED_CALL_ARG1, 157 DEPRECATED_CALL_ARG2, 158 DEPRECATED_CALL_ARG3, 159 DEPRECATED_CALL_WITH_ARGV, 160 DEPRECATED_CALL_THIS_WITH_ARGV, 161 DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV, 162 CALL_GETTER, 163 CALL_SETTER, 164 CALL_THIS_ARG3_WITH_RETURN, 165 CALL_ENTRY, 166 CALL_GENERATOR, 167 CALL_FROM_AOT, 168 }; 169 170 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 171 struct OptimizedFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 172 base::AlignedPointer, 173 base::AlignedPointer, 174 base::AlignedPointer> { 175 public: 176 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 177 const RootBaseAndDerivedVisitor &derivedVisitor) const; 178 GetTypeOffsetOptimizedFrame179 static size_t GetTypeOffset() 180 { 181 return MEMBER_OFFSET(OptimizedFrame, type); 182 } GetPrevOffsetOptimizedFrame183 static size_t GetPrevOffset() 184 { 185 return MEMBER_OFFSET(OptimizedFrame, prevFp); 186 } ComputeReservedSizeOptimizedFrame187 static size_t ComputeReservedSize(size_t slotSize) 188 { 189 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex); 190 return slotSize * slotOffset; 191 } 192 private: 193 enum class Index : size_t { 194 TypeIndex = 0, 195 PrevFpIndex, 196 ReturnAddrIndex, 197 NumOfMembers 198 }; 199 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 200 GetFrameFromSpOptimizedFrame201 static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp) 202 { 203 return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp) 204 - MEMBER_OFFSET(OptimizedFrame, prevFp)); 205 } GetPrevFrameFpOptimizedFrame206 inline JSTaggedType* GetPrevFrameFp() 207 { 208 return prevFp; 209 } GetReturnAddrOptimizedFrame210 uintptr_t GetReturnAddr() const 211 { 212 return returnAddr; 213 } 214 [[maybe_unused]] alignas(EAS) FrameType type {0}; 215 alignas(EAS) JSTaggedType *prevFp {nullptr}; 216 alignas(EAS) uintptr_t returnAddr {0}; 217 friend class FrameIterator; 218 }; 219 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64); 220 221 struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 222 base::AlignedPointer, 223 base::AlignedPointer, 224 base::AlignedPointer> { 225 public: GetTypeOffsetAsmBridgeFrame226 static size_t GetTypeOffset() 227 { 228 return MEMBER_OFFSET(AsmBridgeFrame, type); 229 } 230 GetPrevOffsetAsmBridgeFrame231 static size_t GetPrevOffset() 232 { 233 return MEMBER_OFFSET(AsmBridgeFrame, prevFp); 234 } 235 GetCallSiteSpAsmBridgeFrame236 uintptr_t GetCallSiteSp() const 237 { 238 return ToUintPtr(this) + sizeof(AsmBridgeFrame); 239 } 240 GetTypeAsmBridgeFrame241 FrameType GetType() const 242 { 243 return type; 244 } 245 246 private: 247 enum class Index : size_t { 248 TypeIndex = 0, 249 PrevFpIndex, 250 ReturnAddrIndex, 251 NumOfMembers 252 }; 253 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 254 GetFrameFromSpAsmBridgeFrame255 static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 256 { 257 return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 258 MEMBER_OFFSET(AsmBridgeFrame, prevFp)); 259 } GetPrevFrameFpAsmBridgeFrame260 inline JSTaggedType* GetPrevFrameFp() 261 { 262 return prevFp; 263 } GetReturnAddrAsmBridgeFrame264 uintptr_t GetReturnAddr() const 265 { 266 return returnAddr; 267 } 268 alignas(EAS) FrameType type {0}; 269 alignas(EAS) JSTaggedType *prevFp {nullptr}; 270 alignas(EAS) uintptr_t returnAddr {0}; 271 friend class FrameIterator; 272 }; 273 STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64); 274 275 // * OptimizedUnfoldArgVFrame layout description as the following: 276 // sp ----> |--------------------------| --------------- 277 // | returnAddr | ^ 278 // currentFp--> |--------------------------| | 279 // | prevFp | | 280 // |--------------------------| OptimizedUnfoldArgVFrame 281 // | frameType | | 282 // |--------------------------| | 283 // | currentFp | v 284 // +--------------------------+ --------------- 285 // 286 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 287 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 288 base::AlignedPointer, 289 base::AlignedPointer, 290 base::AlignedPointer, 291 base::AlignedPointer> { 292 public: GetTypeOffsetOptimizedJSFunctionUnfoldArgVFrame293 static size_t GetTypeOffset() 294 { 295 return MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, type); 296 } GetPrevOffsetOptimizedJSFunctionUnfoldArgVFrame297 static size_t GetPrevOffset() 298 { 299 return MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp); 300 } 301 private: 302 enum class Index : size_t { 303 CallSiteSpIndex = 0, 304 TypeIndex, 305 PrevFpIndex, 306 ReturnAddrIndex, 307 NumOfMembers 308 }; 309 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 310 GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame311 static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp) 312 { 313 return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp) 314 - MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp)); 315 } GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame316 inline JSTaggedType* GetPrevFrameFp() const 317 { 318 return prevFp; 319 } GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame320 uintptr_t GetReturnAddr() const 321 { 322 return returnAddr; 323 } GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame324 uintptr_t GetPrevFrameSp() const 325 { 326 return callSiteSp; 327 } 328 [[maybe_unused]] alignas(EAS) uintptr_t callSiteSp {0}; 329 [[maybe_unused]] alignas(EAS) FrameType type {0}; 330 alignas(EAS) JSTaggedType *prevFp {nullptr}; 331 alignas(EAS) uintptr_t returnAddr {0}; 332 friend class FrameIterator; 333 }; 334 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame), 335 OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64); 336 337 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following: 338 // +--------------------------+ 339 // | arg[N-1] | 340 // +--------------------------+ 341 // | . . . . | 342 // +--------------------------+ 343 // | arg[0] | 344 // +--------------------------+ 345 // | argC | 346 // sp ---> +--------------------------+ ----------------- 347 // | | ^ 348 // | prevFP | | 349 // |--------------------------| OptimizedJSFunctionArgsConfigFrame 350 // | frameType | | 351 // | | V 352 // +--------------------------+ ----------------- 353 // 354 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 355 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 356 base::AlignedPointer, 357 base::AlignedPointer> { 358 public: GetTypeOffsetOptimizedJSFunctionArgConfigFrame359 static size_t GetTypeOffset() 360 { 361 return MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, type); 362 } GetPrevOffsetOptimizedJSFunctionArgConfigFrame363 static size_t GetPrevOffset() 364 { 365 return MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp); 366 } 367 private: 368 enum class Index : size_t { 369 TypeIndex = 0, 370 PrevFpIndex, 371 NumOfMembers 372 }; 373 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 374 GetFrameFromSpOptimizedJSFunctionArgConfigFrame375 static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp) 376 { 377 return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp) 378 - MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp)); 379 } GetPrevFrameFpOptimizedJSFunctionArgConfigFrame380 inline JSTaggedType* GetPrevFrameFp() 381 { 382 return prevFp; 383 } 384 [[maybe_unused]] alignas(EAS) FrameType type {0}; 385 alignas(EAS) JSTaggedType *prevFp {nullptr}; 386 friend class FrameIterator; 387 }; 388 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame), 389 OptimizedJSFunctionArgConfigFrame::SizeArch32, 390 OptimizedJSFunctionArgConfigFrame::SizeArch64); 391 392 // * OptimizedJSFunctionFrame layout description as the following: 393 // +--------------------------+ 394 // | arg[N-1] | 395 // +--------------------------+ 396 // | ... | 397 // +--------------------------+ 398 // | arg[1] | 399 // +--------------------------+ 400 // | arg[0] | 401 // +--------------------------+ 402 // | this | 403 // +--------------------------+ 404 // | new-target | 405 // +--------------------------+ 406 // | call-target | 407 // |--------------------------| 408 // | argc | 409 // |--------------------------| 410 // | lexEnv | 411 // sp ----> |--------------------------| --------------- 412 // | returnAddr | ^ 413 // |--------------------------| | 414 // | callsiteFp | | 415 // |--------------------------| OptimizedJSFunctionFrame 416 // | frameType | | 417 // |--------------------------| | 418 // | call-target | v 419 // +--------------------------+ --------------- 420 // 421 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 422 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 423 JSTaggedValue, 424 base::AlignedPointer, 425 base::AlignedPointer, 426 base::AlignedPointer> { 427 public: 428 static constexpr size_t ENV_SLOT_DIFF = 2; 429 enum class Index : size_t { 430 JSFuncIndex = 0, 431 TypeIndex, 432 PrevFpIndex, 433 ReturnAddrIndex, 434 NumOfMembers 435 }; 436 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 437 GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame438 static constexpr size_t GetFunctionDeltaReturnAddr() 439 { 440 return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex); 441 } 442 GetPrevFrameFpOptimizedJSFunctionFrame443 inline JSTaggedType* GetPrevFrameFp() 444 { 445 return prevFp; 446 } 447 GetArgvOptimizedJSFunctionFrame448 JSTaggedType* GetArgv(uintptr_t *preFrameSp) const 449 { 450 return reinterpret_cast<JSTaggedType *>(preFrameSp + ENV_SLOT_DIFF * sizeof(uint64_t) / sizeof(uintptr_t)); 451 } 452 GetArgcOptimizedJSFunctionFrame453 size_t GetArgc(uintptr_t *preFrameSp) const 454 { 455 return *(preFrameSp + sizeof(uint64_t) / sizeof(uintptr_t)); 456 } 457 458 JSTaggedType* GetArgv(const FrameIterator &it) const; 459 GetReturnAddrOptimizedJSFunctionFrame460 uintptr_t GetReturnAddr() const 461 { 462 return returnAddr; 463 } 464 465 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 466 const RootBaseAndDerivedVisitor &derivedVisitor) const; 467 void CollectBCOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const; 468 GetFunctionOptimizedJSFunctionFrame469 inline JSTaggedValue GetFunction() const 470 { 471 return jsFunc; 472 } 473 ComputeArgsConfigFrameSpOptimizedJSFunctionFrame474 static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp) 475 { 476 const size_t offset = 2; // 2: skip prevFp and return address. 477 return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t); 478 } 479 GetTypeOffsetOptimizedJSFunctionFrame480 static size_t GetTypeOffset() 481 { 482 return MEMBER_OFFSET(OptimizedJSFunctionFrame, type); 483 } 484 GetPrevOffsetOptimizedJSFunctionFrame485 static size_t GetPrevOffset() 486 { 487 return MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp); 488 } 489 ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame490 static size_t ComputeReservedJSFuncOffset(size_t slotSize) 491 { 492 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex); 493 return slotSize * slotOffset; 494 } 495 496 friend class FrameIterator; 497 friend class FrameHandler; 498 void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const; 499 void GetFuncCalleeRegAndOffset( 500 const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const; 501 uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const; 502 503 private: GetFrameFromSpOptimizedJSFunctionFrame504 static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) 505 { 506 return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) 507 - MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp)); 508 } 509 510 // dynamic callee saveregisters for x86-64 511 alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()}; 512 [[maybe_unused]] alignas(EAS) FrameType type {0}; 513 alignas(EAS) JSTaggedType *prevFp {nullptr}; 514 alignas(EAS) uintptr_t returnAddr {0}; 515 // dynamic callee saveregisters for arm64 516 }; 517 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame), 518 OptimizedJSFunctionFrame::SizeArch32, 519 OptimizedJSFunctionFrame::SizeArch64); 520 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time. 521 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1); 522 523 // * The JSFunctionEntry Frame's structure is illustrated as the following: 524 // +--------------------------+ 525 // | . . . . . . | 526 // sp ---> +--------------------------+ ----------------- 527 // | prevFP | ^ 528 // |--------------------------| | 529 // | frameType | JSFunctionEntryFrame 530 // |--------------------------| | 531 // | preLeaveFrameFp | v 532 // +--------------------------+ ----------------- 533 534 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 535 base::AlignedPointer, 536 base::AlignedPointer, 537 base::AlignedPointer> { 538 public: 539 enum class CallType : size_t { 540 CALL_FUNC = 0, 541 CALL_NEW, 542 }; 543 544 enum class Index : size_t { 545 PreLeaveFrameFpIndex = 0, 546 TypeIndex, 547 PrevFpIndex, 548 NumOfMembers 549 }; 550 GetTypeOffsetOptimizedEntryFrame551 static size_t GetTypeOffset() 552 { 553 return MEMBER_OFFSET(OptimizedEntryFrame, type); 554 } 555 GetLeaveFrameFpOffsetOptimizedEntryFrame556 static size_t GetLeaveFrameFpOffset() 557 { 558 return MEMBER_OFFSET(OptimizedEntryFrame, preLeaveFrameFp); 559 } 560 GetPrevFrameFpOptimizedEntryFrame561 inline JSTaggedType* GetPrevFrameFp() 562 { 563 return preLeaveFrameFp; 564 } 565 ComputeReservedSizeOptimizedEntryFrame566 static size_t ComputeReservedSize(size_t slotSize) 567 { 568 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex); 569 return slotSize * slotOffset; 570 } 571 friend class FrameIterator; 572 573 private: 574 alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr}; 575 alignas(EAS) [[maybe_unused]] FrameType type {0}; 576 alignas(EAS) [[maybe_unused]] JSTaggedType *prevFp {nullptr}; GetFrameFromSpOptimizedEntryFrame577 static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 578 { 579 return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) - 580 MEMBER_OFFSET(OptimizedEntryFrame, prevFp)); 581 } 582 }; 583 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64); 584 585 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 586 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(), 587 base::AlignedPointer, 588 base::AlignedSize> { 589 enum class Index : size_t { 590 PrevIndex = 0, 591 TypeIndex, 592 NumOfMembers 593 }; 594 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 595 GetPrevFrameFpInterpretedFrameBase596 inline JSTaggedType* GetPrevFrameFp() 597 { 598 return prev; 599 } 600 GetFrameFromSpInterpretedFrameBase601 static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp) 602 { 603 return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1; 604 } 605 GetPrevOffsetInterpretedFrameBase606 static size_t GetPrevOffset(bool isArch32) 607 { 608 return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32); 609 } 610 GetTypeOffsetInterpretedFrameBase611 static size_t GetTypeOffset(bool isArch32) 612 { 613 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 614 } 615 GetSizeInterpretedFrameBase616 static constexpr size_t GetSize(bool isArch32) 617 { 618 return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64; 619 } 620 621 alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc 622 alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0 623 }; 624 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase), 625 InterpretedFrameBase::SizeArch32, 626 InterpretedFrameBase::SizeArch64); 627 628 // Interpreter Frame Layout as the following: 629 // +----------------------------------+ 630 // | argv[n-1] | 631 // |----------------------------------| 632 // | ...... | 633 // |----------------------------------| 634 // | thisArg [maybe not exist] | 635 // |----------------------------------| 636 // | newTarget [maybe not exist] | 637 // |----------------------------------| 638 // | ...... | 639 // |----------------------------------| 640 // | Vregs [not exist in native] | 641 // +----------------------------------+--------+ 642 // | base.frameType | ^ 643 // |----------------------------------| | 644 // | base.prev(prev stack pointer) | | 645 // |----------------------------------| | 646 // | pc(bytecode addr) | | 647 // |----------------------------------| | 648 // | sp(current stack pointer) | | 649 // |----------------------------------| | 650 // | env | | 651 // |----------------------------------| | 652 // | acc | | 653 // |----------------------------------| InterpretedFrame 654 // | profileTypeInfo | | 655 // |----------------------------------| | 656 // | thisObj | | 657 // |----------------------------------| | 658 // | function | | 659 // |----------------------------------| | 660 // | constpool | v 661 // +----------------------------------+--------+ 662 // 663 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 664 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 665 JSTaggedValue, 666 JSTaggedValue, 667 JSTaggedValue, 668 JSTaggedValue, 669 JSTaggedValue, 670 JSTaggedValue, 671 base::AlignedPointer, 672 InterpretedFrameBase> { 673 public: 674 enum class Index : size_t { 675 ConstPoolIndex = 0, 676 FunctionIndex, 677 ThisObjIndex, 678 ProFileTypeInfoIndex, 679 AccIndex, 680 EnvIndex, 681 PcIndex, 682 BaseIndex, 683 NumOfMembers 684 }; 685 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 686 GetPrevFrameFpInterpretedFrame687 inline JSTaggedType* GetPrevFrameFp() const 688 { 689 return base.prev; 690 } 691 GetFrameFromSpInterpretedFrame692 static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 693 { 694 return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 695 } 696 GetPcInterpretedFrame697 inline const uint8_t *GetPc() const 698 { 699 return pc; 700 } 701 GetEnvInterpretedFrame702 inline JSTaggedValue GetEnv() const 703 { 704 return env; 705 } 706 NumOfMembersInterpretedFrame707 static uint32_t NumOfMembers() 708 { 709 return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 710 } 711 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 712 713 alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()}; 714 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 715 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 716 alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()}; 717 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 718 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 719 alignas(EAS) const uint8_t *pc {nullptr}; 720 alignas(EAS) InterpretedFrameBase base; 721 friend class FrameIterator; 722 }; 723 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64); 724 725 // * InterpretedBuiltinFrame layout description as the following: 726 // |--------------------------| --------------- 727 // | . . . . . | ^ 728 // | InterpretedFrameBase | | 729 // | . . . . . | | 730 // |--------------------------| InterpretedBuiltinFrame 731 // | bytecode-PC | | 732 // |--------------------------| | 733 // | call-target | v 734 // +--------------------------+ --------------- 735 // 736 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 737 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 738 JSTaggedValue, 739 base::AlignedPointer, 740 InterpretedFrameBase> { 741 enum class Index : size_t { 742 FunctionIndex = 0, 743 PcIndex, 744 BaseIndex, 745 NumOfMembers 746 }; 747 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 748 GetPrevFrameFpInterpretedBuiltinFrame749 inline JSTaggedType* GetPrevFrameFp() 750 { 751 return base.prev; 752 } 753 GetFrameFromSpInterpretedBuiltinFrame754 static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 755 { 756 return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 757 } 758 NumOfMembersInterpretedBuiltinFrame759 static uint32_t NumOfMembers() 760 { 761 return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize(); 762 } 763 764 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 765 766 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 767 alignas(EAS) const uint8_t *pc {nullptr}; 768 alignas(EAS) InterpretedFrameBase base; 769 }; 770 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame), 771 InterpretedBuiltinFrame::SizeArch32, 772 InterpretedBuiltinFrame::SizeArch64); 773 774 // AsmInterpretedFrame Layout as the following: 775 // +----------------------------------+ 776 // | argv[n-1] | 777 // |----------------------------------| 778 // | ...... | 779 // |----------------------------------| 780 // | thisArg [maybe not exist] | 781 // |----------------------------------| 782 // | newTarget [maybe not exist] | 783 // |----------------------------------| 784 // | ...... | 785 // |----------------------------------| 786 // | Vregs [not exist in native] | 787 // +----------------------------------+--------+ 788 // | . . . . | ^ 789 // | InterpretedFrameBase | | 790 // | . . . . | | 791 // |----------------------------------| | 792 // | pc(bytecode addr) | | 793 // |----------------------------------| | 794 // | sp(current stack pointer) | | 795 // |----------------------------------| AsmInterpretedFrame 796 // | callSize | | 797 // |----------------------------------| | 798 // | env | | 799 // |----------------------------------| | 800 // | acc | | 801 // |----------------------------------| | 802 // | thisObj | | 803 // |----------------------------------| | 804 // | call-target | v 805 // +----------------------------------+--------+ 806 // 807 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 808 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 809 JSTaggedValue, 810 JSTaggedValue, 811 JSTaggedValue, 812 JSTaggedValue, 813 base::AlignedPointer, 814 base::AlignedPointer, 815 base::AlignedPointer, 816 InterpretedFrameBase> { 817 enum class Index : size_t { 818 FunctionIndex = 0, 819 ThisObjIndex, 820 AccIndex, 821 EnvIndex, 822 CallSizeIndex, 823 FpIndex, 824 PcIndex, 825 BaseIndex, 826 NumOfMembers 827 }; 828 829 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 830 GetCurrentFramePointerAsmInterpretedFrame831 inline JSTaggedType* GetCurrentFramePointer() 832 { 833 return fp; 834 } 835 GetPrevFrameFpAsmInterpretedFrame836 inline JSTaggedType* GetPrevFrameFp() 837 { 838 return base.prev; 839 } 840 GetFrameFromSpAsmInterpretedFrame841 static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 842 { 843 return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 844 } 845 GetFpOffsetAsmInterpretedFrame846 static size_t GetFpOffset(bool isArch32) 847 { 848 return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32); 849 } 850 GetCallSizeOffsetAsmInterpretedFrame851 static size_t GetCallSizeOffset(bool isArch32) 852 { 853 return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32); 854 } 855 GetFunctionOffsetAsmInterpretedFrame856 static size_t GetFunctionOffset(bool isArch32) 857 { 858 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 859 } 860 GetThisOffsetAsmInterpretedFrame861 static size_t GetThisOffset(bool isArch32) 862 { 863 return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32); 864 } 865 GetAccOffsetAsmInterpretedFrame866 static size_t GetAccOffset(bool isArch32) 867 { 868 return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32); 869 } 870 GetEnvOffsetAsmInterpretedFrame871 static size_t GetEnvOffset(bool isArch32) 872 { 873 return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32); 874 } 875 GetBaseOffsetAsmInterpretedFrame876 static size_t GetBaseOffset(bool isArch32) 877 { 878 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 879 } 880 GetPcOffsetAsmInterpretedFrame881 static size_t GetPcOffset(bool isArch32) 882 { 883 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 884 } 885 GetSizeAsmInterpretedFrame886 static constexpr size_t GetSize(bool isArch32) 887 { 888 return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64; 889 } 890 NumOfMembersAsmInterpretedFrame891 static uint32_t NumOfMembers() 892 { 893 return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 894 } 895 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 896 const RootBaseAndDerivedVisitor &derivedVisitor) const; 897 GetEnvAsmInterpretedFrame898 JSTaggedValue GetEnv() const 899 { 900 return env; 901 } 902 GetPcAsmInterpretedFrame903 const uint8_t *GetPc() const 904 { 905 return pc; 906 } 907 908 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 909 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 910 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 911 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 912 alignas(EAS) uintptr_t callSize {0}; 913 alignas(EAS) JSTaggedType *fp {nullptr}; 914 alignas(EAS) const uint8_t *pc {nullptr}; 915 alignas(EAS) InterpretedFrameBase base; 916 // vregs, not exist in native 917 // args, may be truncated if not extra 918 }; 919 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64); 920 921 // InterpretedEntryFrame Layout as the following: 922 // +----------------------------------+--------------- 923 // | . . . . | ^ 924 // | InterpretedFrameBase | | 925 // | . . . . | InterpretedEntryFrame 926 // |----------------------------------| | 927 // | pc(bytecode addr) | v 928 // |----------------------------------|--------------- 929 // 930 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 931 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 932 base::AlignedPointer, 933 InterpretedFrameBase> { 934 enum class Index : size_t { 935 PcIndex = 0, 936 BaseIndex, 937 NumOfMembers 938 }; 939 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 940 GetPrevFrameFpInterpretedEntryFrame941 inline JSTaggedType* GetPrevFrameFp() 942 { 943 return base.prev; 944 } 945 GetFrameFromSpInterpretedEntryFrame946 static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 947 { 948 return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 949 } 950 NumOfMembersInterpretedEntryFrame951 static uint32_t NumOfMembers() 952 { 953 return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize(); 954 } 955 956 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, 957 const RootRangeVisitor &rangeVisitor) const; 958 alignas(EAS) const uint8_t *pc {nullptr}; 959 alignas(EAS) InterpretedFrameBase base; 960 }; 961 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame), 962 InterpretedEntryFrame::SizeArch32, 963 InterpretedEntryFrame::SizeArch64); 964 965 966 // AsmInterpretedEntryFrame Layout as the following: 967 // +----------------------------------+--------------- 968 // | . . . . | ^ 969 // | InterpretedFrameBase | | 970 // | . . . . | AsmInterpretedEntryFrame 971 // |----------------------------------| | 972 // | pc(bytecode addr) | v 973 // |----------------------------------|--------------- 974 // 975 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 976 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 977 base::AlignedPointer, 978 InterpretedFrameBase> { 979 enum class Index : size_t { 980 PcIndex = 0, 981 BaseIndex, 982 NumOfMembers 983 }; 984 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 985 GetPrevFrameFpAsmInterpretedEntryFrame986 inline JSTaggedType* GetPrevFrameFp() 987 { 988 return base.prev; 989 } 990 GetBaseOffsetAsmInterpretedEntryFrame991 static size_t GetBaseOffset(bool isArch32) 992 { 993 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 994 } 995 GetFrameFromSpAsmInterpretedEntryFrame996 static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 997 { 998 return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 999 } 1000 1001 alignas(EAS) const uint8_t *pc {nullptr}; 1002 alignas(EAS) InterpretedFrameBase base; 1003 }; 1004 1005 // AsmInterpretedBridgeFrame Layout as the following: 1006 // +----------------------------------+--------------- 1007 // | ret-address | ^ 1008 // |----------------------------------| | 1009 // | . . . . | AsmInterpretedBridgeFrame 1010 // | AsmInterpretedEntryFrame | | 1011 // | . . . . | v 1012 // |----------------------------------|--------------- 1013 // 1014 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1015 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1016 AsmInterpretedEntryFrame, 1017 base::AlignedPointer> { 1018 enum class Index : size_t { 1019 EntryIndex = 0, 1020 ReturnAddrIndex, 1021 NumOfMembers 1022 }; 1023 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1024 GetFrameFromSpAsmInterpretedBridgeFrame1025 static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 1026 { 1027 return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 1028 MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr)); 1029 } GetCallSiteSpAsmInterpretedBridgeFrame1030 uintptr_t GetCallSiteSp() const 1031 { 1032 return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame); 1033 } GetPrevFrameFpAsmInterpretedBridgeFrame1034 inline JSTaggedType* GetPrevFrameFp() 1035 { 1036 return entry.base.prev; 1037 } 1038 GetReturnAddrOffsetAsmInterpretedBridgeFrame1039 static size_t GetReturnAddrOffset(bool isArch32) 1040 { 1041 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 1042 } 1043 GetSizeAsmInterpretedBridgeFrame1044 static constexpr size_t GetSize(bool isArch32) 1045 { 1046 return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64; 1047 } 1048 1049 AsmInterpretedEntryFrame entry; 1050 alignas(EAS) uintptr_t returnAddr; GetReturnAddrAsmInterpretedBridgeFrame1051 uintptr_t GetReturnAddr() const 1052 { 1053 return returnAddr; 1054 } 1055 }; 1056 1057 // * Optimized-leaved-frame layout as the following: 1058 // +--------------------------+ 1059 // | argv[N-1] | 1060 // |--------------------------| 1061 // | . . . . . | 1062 // |--------------------------| 1063 // | argv[0] | 1064 // +--------------------------+------------- 1065 // | argc | ^ 1066 // |--------------------------| | 1067 // | RuntimeId | | 1068 // sp --> |--------------------------| OptimizedLeaveFrame 1069 // | ret-addr | | 1070 // |--------------------------| | 1071 // | prevFp | | 1072 // |--------------------------| | 1073 // | frameType | v 1074 // +--------------------------+------------- 1075 // 1076 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1077 struct OptimizedLeaveFrame { 1078 FrameType type; 1079 uintptr_t callsiteFp; // thread sp set here 1080 uintptr_t returnAddr; 1081 uint64_t argRuntimeId; 1082 uint64_t argc; 1083 // argv[0]...argv[argc-1] dynamic according to agc GetFrameFromSpOptimizedLeaveFrame1084 static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1085 { 1086 return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1087 MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp)); 1088 } GetCallSiteSpOptimizedLeaveFrame1089 uintptr_t GetCallSiteSp() const 1090 { 1091 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId); 1092 } GetPrevFrameFpOptimizedLeaveFrame1093 inline JSTaggedType* GetPrevFrameFp() const 1094 { 1095 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1096 } 1097 GetReturnAddrOptimizedLeaveFrame1098 uintptr_t GetReturnAddr() const 1099 { 1100 return returnAddr; 1101 } 1102 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1103 }; 1104 1105 // * Optimized-leaved-frame-with-argv layout as the following: 1106 // +--------------------------+ 1107 // | argv[] | 1108 // +--------------------------+------------- 1109 // | argc | ^ 1110 // |--------------------------| | 1111 // | RuntimeId | OptimizedWithArgvLeaveFrame 1112 // sp --> |--------------------------| | 1113 // | returnAddr | | 1114 // |--------------------------| | 1115 // | callsiteFp | | 1116 // |--------------------------| | 1117 // | frameType | v 1118 // +--------------------------+------------- 1119 1120 struct OptimizedWithArgvLeaveFrame { 1121 FrameType type; 1122 uintptr_t callsiteFp; // thread sp set here 1123 uintptr_t returnAddr; 1124 uint64_t argRuntimeId; 1125 uint64_t argc; 1126 GetFrameFromSpOptimizedWithArgvLeaveFrame1127 static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1128 { 1129 return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1130 MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp)); 1131 } GetCallSiteSpOptimizedWithArgvLeaveFrame1132 uintptr_t GetCallSiteSp() const 1133 { 1134 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId); 1135 } GetPrevFrameFpOptimizedWithArgvLeaveFrame1136 inline JSTaggedType* GetPrevFrameFp() 1137 { 1138 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1139 } GetReturnAddrOptimizedWithArgvLeaveFrame1140 uintptr_t GetReturnAddr() const 1141 { 1142 return returnAddr; 1143 } 1144 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1145 }; 1146 1147 // * OptimizedBuiltinLeaveFrame layout as the following: 1148 // +--------------------------+ 1149 // | argv[N-1] | 1150 // |--------------------------| 1151 // | . . . . . | 1152 // |--------------------------| 1153 // | argv[0] | 1154 // +--------------------------+------------- 1155 // | argc | ^ 1156 // |--------------------------| | 1157 // | env | | 1158 // +--------------------------+ | 1159 // | ret-addr | | 1160 // sp --> |--------------------------| OptimizedBuiltinLeaveFrame 1161 // | prevFp | | 1162 // |--------------------------| | 1163 // | frameType | | 1164 // |--------------------------| | 1165 // | align byte | v 1166 // +--------------------------+------------- 1167 // 1168 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1169 struct OptimizedBuiltinLeaveFrame { 1170 public: GetFrameFromSpOptimizedBuiltinLeaveFrame1171 static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1172 { 1173 return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1174 MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp)); 1175 } GetCallSiteSpOptimizedBuiltinLeaveFrame1176 uintptr_t GetCallSiteSp() const 1177 { 1178 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, thread); 1179 } GetPrevFrameFpOptimizedBuiltinLeaveFrame1180 inline JSTaggedType* GetPrevFrameFp() const 1181 { 1182 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1183 } GetReturnAddrOptimizedBuiltinLeaveFrame1184 uintptr_t GetReturnAddr() const 1185 { 1186 return returnAddr; 1187 } 1188 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; GetTypeOffsetOptimizedBuiltinLeaveFrame1189 static size_t GetTypeOffset() 1190 { 1191 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type); 1192 } GetPrevOffsetOptimizedBuiltinLeaveFrame1193 static size_t GetPrevOffset() 1194 { 1195 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp); 1196 } GetArgvOptimizedBuiltinLeaveFrame1197 const JSTaggedType* GetArgv() const 1198 { 1199 return reinterpret_cast<const JSTaggedType *>(&argc + 1); 1200 } 1201 1202 private: 1203 [[maybe_unused]] FrameType type; 1204 uintptr_t callsiteFp; // thread sp set here 1205 uintptr_t returnAddr; 1206 JSTaggedValue thread; 1207 uint64_t argc; 1208 // argv[0]...argv[argc-1] dynamic according to agc 1209 }; 1210 1211 // * BuiltinFrame layout as the following: 1212 // +--------------------------+ 1213 // | argV[N - 1] | 1214 // |--------------------------| 1215 // | . . . . | 1216 // |--------------------------+ 1217 // | argV[2]=this | 1218 // +--------------------------+ 1219 // | argV[1]=new-target | 1220 // +--------------------------+ 1221 // | argV[0]=call-target | 1222 // +--------------------------+ --------- 1223 // | argc | ^ 1224 // |--------------------------| | 1225 // | thread | | 1226 // |--------------------------| | 1227 // | returnAddr | BuiltinFrame 1228 // |--------------------------| | 1229 // | callsiteFp | | 1230 // |--------------------------| | 1231 // | frameType | v 1232 // +--------------------------+ --------- 1233 // 1234 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1235 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1236 base::AlignedSize, 1237 base::AlignedPointer, 1238 base::AlignedPointer, 1239 base::AlignedPointer, 1240 base::AlignedPointer, 1241 base::AlignedPointer> { 1242 enum class Index : size_t { 1243 TypeIndex = 0, 1244 PrevFpIndex, 1245 ReturnAddrIndex, 1246 ThreadIndex, 1247 NumArgsIndex, 1248 StackArgsIndex, 1249 NumOfMembers 1250 }; 1251 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1252 GetFrameFromSpBuiltinFrame1253 static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 1254 { 1255 return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) - 1256 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1257 } GetPrevFrameFpBuiltinFrame1258 inline JSTaggedType* GetPrevFrameFp() 1259 { 1260 return prevFp; 1261 } GetCallSiteSpBuiltinFrame1262 uintptr_t GetCallSiteSp() const 1263 { 1264 return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread); 1265 } GetPreFpOffsetBuiltinFrame1266 static size_t GetPreFpOffset(bool isArch32) 1267 { 1268 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1269 } GetNumArgsToFpDeltaBuiltinFrame1270 static size_t GetNumArgsToFpDelta(bool isArch32) 1271 { 1272 auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32); 1273 return offset - GetPreFpOffset(isArch32); 1274 } GetStackArgsToFpDeltaBuiltinFrame1275 static size_t GetStackArgsToFpDelta(bool isArch32) 1276 { 1277 auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 1278 return offset - GetPreFpOffset(isArch32); 1279 } GetStackArgsAddressBuiltinFrame1280 uintptr_t GetStackArgsAddress() 1281 { 1282 return reinterpret_cast<uintptr_t>(&stackArgs); 1283 } GetFunctionBuiltinFrame1284 JSTaggedValue GetFunction() 1285 { 1286 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1287 return JSTaggedValue(*functionAddress); 1288 } GetNumArgsBuiltinFrame1289 int32_t GetNumArgs() 1290 { 1291 return numArgs; 1292 } 1293 GetReturnAddrBuiltinFrame1294 uintptr_t GetReturnAddr() const 1295 { 1296 return returnAddr; 1297 } 1298 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1299 alignas(EAS) FrameType type; 1300 alignas(EAS) JSTaggedType *prevFp; 1301 alignas(EAS) uintptr_t returnAddr; 1302 alignas(EAS) uintptr_t thread; 1303 alignas(EAS) int32_t numArgs; 1304 alignas(EAS) uintptr_t stackArgs; 1305 }; 1306 1307 // * BuiltinWithArgvFrame layout as the following: 1308 // +--------------------------+ --------- 1309 // | . . . . . | ^ 1310 // |--------------------------| | 1311 // | returnAddr | | 1312 // |--------------------------| | 1313 // | callsiteFp | BuiltinWithArgvFrame 1314 // |--------------------------| | 1315 // | frameType | | 1316 // +--------------------------+ | 1317 // | argc | v 1318 // +--------------------------+ --------- 1319 // | argV[0] | 1320 // +--------------------------+ 1321 // | argV[1] | 1322 // +--------------------------+ 1323 // | . . . . | 1324 // +--------------------------+ 1325 // 1326 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1327 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1328 base::AlignedSize, 1329 base::AlignedPointer, 1330 base::AlignedPointer> { 1331 enum class Index : int { 1332 StackArgsTopIndex = -1, 1333 NumArgsIndex = -1, 1334 TypeIndex = 0, 1335 PrevFpIndex, 1336 ReturnAddrIndex, 1337 NumOfMembers 1338 }; 1339 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1340 GetFrameFromSpBuiltinWithArgvFrame1341 static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp) 1342 { 1343 return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) - 1344 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1345 } GetPrevFrameFpBuiltinWithArgvFrame1346 inline JSTaggedType* GetPrevFrameFp() 1347 { 1348 return prevFp; 1349 } GetCallSiteSpBuiltinWithArgvFrame1350 uintptr_t GetCallSiteSp() const 1351 { 1352 return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame); 1353 } GetStackArgsAddressBuiltinWithArgvFrame1354 uintptr_t GetStackArgsAddress() 1355 { 1356 auto topAddress = ToUintPtr(this) + 1357 (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t)); 1358 auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS; 1359 return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t); 1360 } GetFunctionBuiltinWithArgvFrame1361 JSTaggedValue GetFunction() 1362 { 1363 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1364 return JSTaggedValue(*functionAddress); 1365 } GetNumArgsBuiltinWithArgvFrame1366 int32_t GetNumArgs() 1367 { 1368 auto argcAddress = reinterpret_cast<int32_t *>( 1369 ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t))); 1370 return *argcAddress; 1371 } GetReturnAddrBuiltinWithArgvFrame1372 uintptr_t GetReturnAddr() const 1373 { 1374 return returnAddr; 1375 } 1376 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1377 // argv(... this, new.target, function) 1378 // numargs 1379 alignas(EAS) FrameType type; 1380 alignas(EAS) JSTaggedType *prevFp; 1381 alignas(EAS) uintptr_t returnAddr; 1382 }; 1383 1384 enum class GCVisitedFlag : bool { 1385 VISITED = true, 1386 IGNORED = false, 1387 }; 1388 1389 class FrameIterator { 1390 public: 1391 explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr); GetFrameType()1392 FrameType GetFrameType() const 1393 { 1394 ASSERT(current_ != nullptr); 1395 FrameType *typeAddr = reinterpret_cast<FrameType *>( 1396 reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType)); 1397 return *typeAddr; 1398 } 1399 1400 template<class T> GetFrame()1401 T* GetFrame() 1402 { 1403 return T::GetFrameFromSp(current_); 1404 } 1405 1406 template<class T> GetFrame()1407 const T* GetFrame() const 1408 { 1409 return T::GetFrameFromSp(current_); 1410 } 1411 Done()1412 bool Done() const 1413 { 1414 return current_ == nullptr; 1415 } GetSp()1416 JSTaggedType *GetSp() const 1417 { 1418 return current_; 1419 } GetSp()1420 JSTaggedType *GetSp() 1421 { 1422 return current_; 1423 } GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)1424 void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const 1425 { 1426 ret = calleeRegInfo_; 1427 } 1428 int ComputeDelta() const; 1429 template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED> 1430 void Advance(); 1431 uint32_t GetBytecodeOffset() const; 1432 uintptr_t GetPrevFrameCallSiteSp([[maybe_unused]] uintptr_t curPc = 0) const; 1433 uintptr_t GetPrevFrame() const; GetCallSiteSp()1434 uintptr_t GetCallSiteSp() const 1435 { 1436 return optimizedCallSiteSp_; 1437 } GetOptimizedReturnAddr()1438 uintptr_t GetOptimizedReturnAddr() const 1439 { 1440 return optimizedReturnAddr_; 1441 } GetThread()1442 const JSThread *GetThread() const 1443 { 1444 return thread_; 1445 } 1446 bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const; 1447 void CollectBCOffsetInfo(kungfu::ConstInfo &info) const; 1448 void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const; 1449 std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const; 1450 int GetCallSiteDelta(uintptr_t retAddr) const; 1451 1452 Method *CheckAndGetMethod() const; 1453 JSTaggedValue GetFunction() const; 1454 IsLeaveFrame()1455 bool IsLeaveFrame() const 1456 { 1457 FrameType type = GetFrameType(); 1458 return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV); 1459 } 1460 IsOptimizedFrame()1461 bool IsOptimizedFrame() const 1462 { 1463 FrameType type = GetFrameType(); 1464 return (type == FrameType::OPTIMIZED_FRAME); 1465 } 1466 IsOptimizedJSFunctionFrame()1467 bool IsOptimizedJSFunctionFrame() const 1468 { 1469 FrameType type = GetFrameType(); 1470 return (type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME); 1471 } 1472 1473 private: 1474 JSTaggedType *current_ {nullptr}; 1475 const JSThread *thread_ {nullptr}; 1476 const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr}; 1477 uintptr_t optimizedCallSiteSp_ {0}; 1478 uintptr_t optimizedReturnAddr_ {0}; 1479 uint8_t *stackMapAddr_ {nullptr}; 1480 int fpDeltaPrevFrameSp_ {0}; 1481 kungfu::CalleeRegAndOffsetVec calleeRegInfo_; 1482 }; 1483 } // namespace panda::ecmascript 1484 extern "C" int step_ark_managed_native_frame( 1485 int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp, char *buf, size_t buf_sz); 1486 #endif // ECMASCRIPT_FRAMES_H 1487