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 OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME, 118 ASM_BRIDGE_FRAME, 119 LEAVE_FRAME, 120 LEAVE_FRAME_WITH_ARGV, 121 BUILTIN_CALL_LEAVE_FRAME, 122 INTERPRETER_FRAME, 123 ASM_INTERPRETER_FRAME, 124 INTERPRETER_CONSTRUCTOR_FRAME, 125 BUILTIN_FRAME, 126 BUILTIN_FRAME_WITH_ARGV, 127 BUILTIN_ENTRY_FRAME, 128 INTERPRETER_BUILTIN_FRAME, 129 INTERPRETER_FAST_NEW_FRAME, 130 INTERPRETER_ENTRY_FRAME, 131 ASM_INTERPRETER_ENTRY_FRAME, 132 ASM_INTERPRETER_BRIDGE_FRAME, 133 OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME, 134 OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, 135 BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME, 136 137 FRAME_TYPE_FIRST = OPTIMIZED_FRAME, 138 FRAME_TYPE_LAST = OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME, 139 INTERPRETER_FIRST = INTERPRETER_FRAME, 140 INTERPRETER_LAST = INTERPRETER_FAST_NEW_FRAME, 141 BUILTIN_FIRST = BUILTIN_FRAME, 142 BUILTIN_LAST = BUILTIN_ENTRY_FRAME, 143 }; 144 145 enum class JSCallMode : uintptr_t { 146 CALL_ARG0 = 0, 147 CALL_ARG1, 148 CALL_ARG2, 149 CALL_ARG3, 150 CALL_THIS_ARG0, 151 CALL_THIS_ARG1, 152 CALL_THIS_ARG2, 153 CALL_THIS_ARG3, 154 CALL_WITH_ARGV, 155 CALL_THIS_WITH_ARGV, 156 CALL_CONSTRUCTOR_WITH_ARGV, 157 DEPRECATED_CALL_ARG0, 158 DEPRECATED_CALL_ARG1, 159 DEPRECATED_CALL_ARG2, 160 DEPRECATED_CALL_ARG3, 161 DEPRECATED_CALL_WITH_ARGV, 162 DEPRECATED_CALL_THIS_WITH_ARGV, 163 DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV, 164 CALL_GETTER, 165 CALL_SETTER, 166 CALL_THIS_ARG3_WITH_RETURN, 167 CALL_THIS_ARGV_WITH_RETURN, 168 CALL_ENTRY, 169 CALL_GENERATOR, 170 CALL_FROM_AOT, 171 }; 172 173 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 174 struct OptimizedFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 175 base::AlignedPointer, 176 base::AlignedPointer, 177 base::AlignedPointer> { 178 public: 179 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 180 const RootBaseAndDerivedVisitor &derivedVisitor) const; 181 182 static size_t GetTypeOffset(bool isArch32 = false) 183 { 184 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 185 } 186 187 static size_t GetPrevOffset(bool isArch32 = false) 188 { 189 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 190 } 191 ComputeReservedSizeOptimizedFrame192 static size_t ComputeReservedSize(size_t slotSize) 193 { 194 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex); 195 return slotSize * slotOffset; 196 } 197 GetTypeOptimizedFrame198 FrameType GetType() const 199 { 200 return type; 201 } 202 private: 203 enum class Index : size_t { 204 TypeIndex = 0, 205 PrevFpIndex, 206 ReturnAddrIndex, 207 NumOfMembers 208 }; 209 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 210 GetFrameFromSpOptimizedFrame211 static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp) 212 { 213 return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp) - 214 MEMBER_OFFSET(OptimizedFrame, prevFp)); 215 } GetPrevFrameFpOptimizedFrame216 inline JSTaggedType* GetPrevFrameFp() 217 { 218 return prevFp; 219 } GetReturnAddrOptimizedFrame220 uintptr_t GetReturnAddr() const 221 { 222 return returnAddr; 223 } 224 225 alignas(EAS) FrameType type {0}; 226 alignas(EAS) JSTaggedType *prevFp {nullptr}; 227 alignas(EAS) uintptr_t returnAddr {0}; 228 friend class FrameIterator; 229 }; 230 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64); 231 232 struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 233 base::AlignedPointer, 234 base::AlignedPointer, 235 base::AlignedPointer> { 236 public: 237 static size_t GetTypeOffset(bool isArch32 = false) 238 { 239 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 240 } 241 242 static size_t GetPrevOffset(bool isArch32 = false) 243 { 244 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 245 } 246 GetCallSiteSpAsmBridgeFrame247 uintptr_t GetCallSiteSp() const 248 { 249 return ToUintPtr(this) + sizeof(AsmBridgeFrame); 250 } 251 GetTypeAsmBridgeFrame252 FrameType GetType() const 253 { 254 return type; 255 } 256 257 private: 258 enum class Index : size_t { 259 TypeIndex = 0, 260 PrevFpIndex, 261 ReturnAddrIndex, 262 NumOfMembers 263 }; 264 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 265 GetFrameFromSpAsmBridgeFrame266 static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 267 { 268 return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 269 MEMBER_OFFSET(AsmBridgeFrame, prevFp)); 270 } GetPrevFrameFpAsmBridgeFrame271 inline JSTaggedType* GetPrevFrameFp() 272 { 273 return prevFp; 274 } GetReturnAddrAsmBridgeFrame275 uintptr_t GetReturnAddr() const 276 { 277 return returnAddr; 278 } 279 alignas(EAS) FrameType type {0}; 280 alignas(EAS) JSTaggedType *prevFp {nullptr}; 281 alignas(EAS) uintptr_t returnAddr {0}; 282 friend class FrameIterator; 283 }; 284 STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64); 285 286 // * OptimizedUnfoldArgVFrame layout description as the following: 287 // sp ----> |--------------------------| --------------- 288 // | returnAddr | ^ 289 // currentFp--> |--------------------------| | 290 // | prevFp | | 291 // |--------------------------| OptimizedUnfoldArgVFrame 292 // | frameType | | 293 // |--------------------------| | 294 // | currentFp | v 295 // +--------------------------+ --------------- 296 // 297 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 298 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 299 base::AlignedPointer, 300 base::AlignedPointer, 301 base::AlignedPointer, 302 base::AlignedPointer> { 303 public: 304 static size_t GetTypeOffset(bool isArch32 = false) 305 { 306 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 307 } 308 309 static size_t GetPrevOffset(bool isArch32 = false) 310 { 311 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 312 } 313 GetTypeOptimizedJSFunctionUnfoldArgVFrame314 FrameType GetType() const 315 { 316 return type; 317 } 318 319 private: 320 enum class Index : size_t { 321 CallSiteSpIndex = 0, 322 TypeIndex, 323 PrevFpIndex, 324 ReturnAddrIndex, 325 NumOfMembers 326 }; 327 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 328 GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame329 static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp) 330 { 331 return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp) - 332 MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp)); 333 } GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame334 inline JSTaggedType* GetPrevFrameFp() const 335 { 336 return prevFp; 337 } GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame338 uintptr_t GetReturnAddr() const 339 { 340 return returnAddr; 341 } GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame342 uintptr_t GetPrevFrameSp() const 343 { 344 return callSiteSp; 345 } 346 alignas(EAS) uintptr_t callSiteSp {0}; 347 alignas(EAS) FrameType type {0}; 348 alignas(EAS) JSTaggedType *prevFp {nullptr}; 349 alignas(EAS) uintptr_t returnAddr {0}; 350 friend class FrameIterator; 351 }; 352 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame), 353 OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64); 354 355 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following: 356 // +--------------------------+ 357 // | arg[N-1] | 358 // +--------------------------+ 359 // | . . . . | 360 // +--------------------------+ 361 // | arg[0] | 362 // +--------------------------+ 363 // | argC | 364 // sp ---> +--------------------------+ ----------------- 365 // | | ^ 366 // | prevFP | | 367 // |--------------------------| OptimizedJSFunctionArgsConfigFrame 368 // | frameType | | 369 // | | V 370 // +--------------------------+ ----------------- 371 // 372 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 373 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 374 base::AlignedPointer, 375 base::AlignedPointer> { 376 public: 377 static size_t GetTypeOffset(bool isArch32 = false) 378 { 379 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 380 } 381 382 static size_t GetPrevOffset(bool isArch32 = false) 383 { 384 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 385 } 386 GetTypeOptimizedJSFunctionArgConfigFrame387 FrameType GetType() const 388 { 389 return type; 390 } 391 392 private: 393 enum class Index : size_t { 394 TypeIndex = 0, 395 PrevFpIndex, 396 NumOfMembers 397 }; 398 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 399 GetFrameFromSpOptimizedJSFunctionArgConfigFrame400 static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp) 401 { 402 return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp) - 403 MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp)); 404 } GetPrevFrameFpOptimizedJSFunctionArgConfigFrame405 inline JSTaggedType* GetPrevFrameFp() 406 { 407 return prevFp; 408 } 409 410 alignas(EAS) FrameType type {0}; 411 alignas(EAS) JSTaggedType *prevFp {nullptr}; 412 friend class FrameIterator; 413 }; 414 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame), 415 OptimizedJSFunctionArgConfigFrame::SizeArch32, 416 OptimizedJSFunctionArgConfigFrame::SizeArch64); 417 418 // * OptimizedJSFunctionFrame layout description as the following: 419 // +--------------------------+ 420 // | arg[N-1] | 421 // +--------------------------+ 422 // | ... | 423 // +--------------------------+ 424 // | arg[1] | 425 // +--------------------------+ 426 // | arg[0] | 427 // +--------------------------+ 428 // | this | 429 // +--------------------------+ 430 // | new-target | 431 // +--------------------------+ 432 // | call-target | 433 // |--------------------------| 434 // | argc | 435 // sp ----> |--------------------------| --------------- 436 // | returnAddr | ^ 437 // |--------------------------| | 438 // | callsiteFp | | 439 // |--------------------------| OptimizedJSFunctionFrame 440 // | frameType | | 441 // |--------------------------| | 442 // | call-target | v 443 // +--------------------------+ --------------- 444 // 445 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 446 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 447 JSTaggedValue, 448 base::AlignedPointer, 449 base::AlignedPointer, 450 base::AlignedPointer> { 451 public: 452 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 453 enum class Index : size_t { 454 JSFuncIndex = 0, 455 TypeIndex, 456 PrevFpIndex, 457 ReturnAddrIndex, 458 NumOfMembers 459 }; 460 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 461 GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame462 static constexpr size_t GetFunctionDeltaReturnAddr() 463 { 464 return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex); 465 } 466 GetPrevFrameFpOptimizedJSFunctionFrame467 inline JSTaggedType* GetPrevFrameFp() 468 { 469 return prevFp; 470 } 471 GetArgvOptimizedJSFunctionFrame472 JSTaggedType* GetArgv(uintptr_t *preFrameSp) const 473 { 474 return reinterpret_cast<JSTaggedType *>(preFrameSp + sizeof(uint64_t) / sizeof(uintptr_t)); 475 } 476 GetArgcOptimizedJSFunctionFrame477 size_t GetArgc(uintptr_t *preFrameSp) const 478 { 479 return *preFrameSp; 480 } 481 482 JSTaggedType* GetArgv(const FrameIterator &it) const; 483 GetReturnAddrOptimizedJSFunctionFrame484 uintptr_t GetReturnAddr() const 485 { 486 return returnAddr; 487 } 488 489 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 490 const RootBaseAndDerivedVisitor &derivedVisitor, FrameType frameType) const; 491 void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const; 492 GetFunctionOptimizedJSFunctionFrame493 inline JSTaggedValue GetFunction() const 494 { 495 return jsFunc; 496 } 497 ComputeArgsConfigFrameSpOptimizedJSFunctionFrame498 static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp) 499 { 500 const size_t offset = 2; // 2: skip prevFp and return address. 501 return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t); 502 } 503 504 static size_t GetTypeOffset(bool isArch32 = false) 505 { 506 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 507 } 508 509 static size_t GetPrevOffset(bool isArch32 = false) 510 { 511 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 512 } 513 ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame514 static size_t ComputeReservedJSFuncOffset(size_t slotSize) 515 { 516 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex); 517 return slotSize * slotOffset; 518 } 519 GetTypeOptimizedJSFunctionFrame520 FrameType GetType() const 521 { 522 return type; 523 } 524 525 friend class FrameIterator; 526 friend class FrameHandler; 527 void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const; 528 void GetFuncCalleeRegAndOffset( 529 const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const; 530 uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const; 531 532 private: GetFrameFromSpOptimizedJSFunctionFrame533 static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) 534 { 535 return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) - 536 MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp)); 537 } 538 539 // dynamic callee saveregisters for x86-64 540 alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()}; 541 alignas(EAS) FrameType type {0}; 542 alignas(EAS) JSTaggedType *prevFp {nullptr}; 543 alignas(EAS) uintptr_t returnAddr {0}; 544 // dynamic callee saveregisters for arm64 545 }; 546 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame), 547 OptimizedJSFunctionFrame::SizeArch32, 548 OptimizedJSFunctionFrame::SizeArch64); 549 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time. 550 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1); 551 552 // * The JSFunctionEntry Frame's structure is illustrated as the following: 553 // +--------------------------+ 554 // | . . . . . . | 555 // sp ---> +--------------------------+ ----------------- 556 // | prevFP | ^ 557 // |--------------------------| | 558 // | frameType | JSFunctionEntryFrame 559 // |--------------------------| | 560 // | preLeaveFrameFp | v 561 // +--------------------------+ ----------------- 562 563 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 564 base::AlignedPointer, 565 base::AlignedPointer, 566 base::AlignedPointer> { 567 public: 568 enum class CallType : size_t { 569 CALL_FUNC = 0, 570 CALL_NEW, 571 }; 572 573 enum class Index : size_t { 574 PreLeaveFrameFpIndex = 0, 575 TypeIndex, 576 PrevFpIndex, 577 NumOfMembers 578 }; 579 580 static size_t GetTypeOffset(bool isArch32 = false) 581 { 582 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 583 } 584 585 static size_t GetLeaveFrameFpOffset(bool isArch32 = false) 586 { 587 return GetOffset<static_cast<size_t>(Index::PreLeaveFrameFpIndex)>(isArch32); 588 } 589 GetPrevFrameFpOptimizedEntryFrame590 inline JSTaggedType* GetPrevFrameFp() 591 { 592 return preLeaveFrameFp; 593 } 594 ComputeReservedSizeOptimizedEntryFrame595 static size_t ComputeReservedSize(size_t slotSize) 596 { 597 size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex); 598 return slotSize * slotOffset; 599 } 600 GetTypeOptimizedEntryFrame601 FrameType GetType() const 602 { 603 return type; 604 } 605 friend class FrameIterator; 606 607 private: GetFrameFromSpOptimizedEntryFrame608 static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 609 { 610 return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) - 611 MEMBER_OFFSET(OptimizedEntryFrame, prevFp)); 612 } 613 GetLeaveFpOptimizedEntryFrame614 JSTaggedType* GetLeaveFp() const 615 { 616 return preLeaveFrameFp; 617 } 618 GetPrevFpOptimizedEntryFrame619 JSTaggedType* GetPrevFp() const 620 { 621 return prevFp; 622 } 623 624 alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr}; 625 alignas(EAS) FrameType type {0}; 626 alignas(EAS) JSTaggedType *prevFp {nullptr}; 627 }; 628 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64); 629 630 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 631 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(), 632 base::AlignedPointer, 633 base::AlignedSize> { 634 enum class Index : size_t { 635 PrevIndex = 0, 636 TypeIndex, 637 NumOfMembers 638 }; 639 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 640 GetPrevFrameFpInterpretedFrameBase641 inline JSTaggedType* GetPrevFrameFp() 642 { 643 return prev; 644 } 645 GetFrameFromSpInterpretedFrameBase646 static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp) 647 { 648 return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1; 649 } 650 651 static size_t GetPrevOffset(bool isArch32 = false) 652 { 653 return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32); 654 } 655 656 static size_t GetTypeOffset(bool isArch32 = false) 657 { 658 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 659 } 660 GetSizeInterpretedFrameBase661 static constexpr size_t GetSize(bool isArch32) 662 { 663 return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64; 664 } 665 666 alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc 667 alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0 668 }; 669 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase), 670 InterpretedFrameBase::SizeArch32, 671 InterpretedFrameBase::SizeArch64); 672 673 // Interpreter Frame Layout as the following: 674 // +----------------------------------+ 675 // | argv[n-1] | 676 // |----------------------------------| 677 // | ...... | 678 // |----------------------------------| 679 // | thisArg [maybe not exist] | 680 // |----------------------------------| 681 // | newTarget [maybe not exist] | 682 // |----------------------------------| 683 // | ...... | 684 // |----------------------------------| 685 // | Vregs [not exist in native] | 686 // +----------------------------------+--------+ 687 // | base.frameType | ^ 688 // |----------------------------------| | 689 // | base.prev(prev stack pointer) | | 690 // |----------------------------------| | 691 // | pc(bytecode addr) | | 692 // |----------------------------------| | 693 // | sp(current stack pointer) | | 694 // |----------------------------------| | 695 // | env | | 696 // |----------------------------------| | 697 // | acc | | 698 // |----------------------------------| InterpretedFrame 699 // | profileTypeInfo | | 700 // |----------------------------------| | 701 // | thisObj | | 702 // |----------------------------------| | 703 // | function | | 704 // |----------------------------------| | 705 // | constpool | v 706 // +----------------------------------+--------+ 707 // 708 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 709 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 710 JSTaggedValue, 711 JSTaggedValue, 712 JSTaggedValue, 713 JSTaggedValue, 714 JSTaggedValue, 715 JSTaggedValue, 716 base::AlignedPointer, 717 InterpretedFrameBase> { 718 public: 719 enum class Index : size_t { 720 ConstPoolIndex = 0, 721 FunctionIndex, 722 ThisObjIndex, 723 ProFileTypeInfoIndex, 724 AccIndex, 725 EnvIndex, 726 PcIndex, 727 BaseIndex, 728 NumOfMembers 729 }; 730 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 731 GetPrevFrameFpInterpretedFrame732 inline JSTaggedType* GetPrevFrameFp() const 733 { 734 return base.prev; 735 } 736 GetFrameFromSpInterpretedFrame737 static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 738 { 739 return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 740 } 741 GetPcInterpretedFrame742 inline const uint8_t *GetPc() const 743 { 744 return pc; 745 } 746 GetEnvInterpretedFrame747 inline JSTaggedValue GetEnv() const 748 { 749 return env; 750 } 751 NumOfMembersInterpretedFrame752 static uint32_t NumOfMembers() 753 { 754 return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 755 } 756 757 static size_t GetTypeOffset(bool isArch32 = false) 758 { 759 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 760 InterpretedFrameBase::GetTypeOffset(isArch32); 761 } 762 763 static size_t GetPrevOffset(bool isArch32 = false) 764 { 765 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 766 InterpretedFrameBase::GetPrevOffset(isArch32); 767 } 768 769 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 770 771 alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()}; 772 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 773 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 774 alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()}; 775 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 776 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 777 alignas(EAS) const uint8_t *pc {nullptr}; 778 alignas(EAS) InterpretedFrameBase base; 779 friend class FrameIterator; 780 }; 781 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64); 782 783 // * InterpretedBuiltinFrame layout description as the following: 784 // |--------------------------| --------------- 785 // | . . . . . | ^ 786 // | InterpretedFrameBase | | 787 // | . . . . . | | 788 // |--------------------------| InterpretedBuiltinFrame 789 // | bytecode-PC | | 790 // |--------------------------| | 791 // | call-target | v 792 // +--------------------------+ --------------- 793 // 794 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 795 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 796 JSTaggedValue, 797 base::AlignedPointer, 798 InterpretedFrameBase> { 799 enum class Index : size_t { 800 FunctionIndex = 0, 801 PcIndex, 802 BaseIndex, 803 NumOfMembers 804 }; 805 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 806 GetPrevFrameFpInterpretedBuiltinFrame807 inline JSTaggedType* GetPrevFrameFp() 808 { 809 return base.prev; 810 } 811 GetFrameFromSpInterpretedBuiltinFrame812 static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 813 { 814 return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 815 } 816 NumOfMembersInterpretedBuiltinFrame817 static uint32_t NumOfMembers() 818 { 819 return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize(); 820 } 821 822 static size_t GetTypeOffset(bool isArch32 = false) 823 { 824 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 825 InterpretedFrameBase::GetTypeOffset(isArch32); 826 } 827 828 static size_t GetPrevOffset(bool isArch32 = false) 829 { 830 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 831 InterpretedFrameBase::GetPrevOffset(isArch32); 832 } 833 834 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 835 836 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 837 alignas(EAS) const uint8_t *pc {nullptr}; 838 alignas(EAS) InterpretedFrameBase base; 839 }; 840 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame), 841 InterpretedBuiltinFrame::SizeArch32, 842 InterpretedBuiltinFrame::SizeArch64); 843 844 // AsmInterpretedFrame Layout as the following: 845 // +----------------------------------+ 846 // | argv[n-1] | 847 // |----------------------------------| 848 // | ...... | 849 // |----------------------------------| 850 // | thisArg [maybe not exist] | 851 // |----------------------------------| 852 // | newTarget [maybe not exist] | 853 // |----------------------------------| 854 // | ...... | 855 // |----------------------------------| 856 // | Vregs [not exist in native] | 857 // +----------------------------------+--------+ 858 // | . . . . | ^ 859 // | InterpretedFrameBase | | 860 // | . . . . | | 861 // |----------------------------------| | 862 // | pc(bytecode addr) | | 863 // |----------------------------------| | 864 // | sp(current stack pointer) | | 865 // |----------------------------------| AsmInterpretedFrame 866 // | callSize | | 867 // |----------------------------------| | 868 // | env | | 869 // |----------------------------------| | 870 // | acc | | 871 // |----------------------------------| | 872 // | thisObj | | 873 // |----------------------------------| | 874 // | call-target | v 875 // +----------------------------------+--------+ 876 // 877 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 878 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 879 JSTaggedValue, 880 JSTaggedValue, 881 JSTaggedValue, 882 JSTaggedValue, 883 base::AlignedPointer, 884 base::AlignedPointer, 885 base::AlignedPointer, 886 InterpretedFrameBase> { 887 enum class Index : size_t { 888 FunctionIndex = 0, 889 ThisObjIndex, 890 AccIndex, 891 EnvIndex, 892 CallSizeIndex, 893 FpIndex, 894 PcIndex, 895 BaseIndex, 896 NumOfMembers 897 }; 898 899 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 900 GetCurrentFramePointerAsmInterpretedFrame901 inline JSTaggedType* GetCurrentFramePointer() 902 { 903 return fp; 904 } 905 GetPrevFrameFpAsmInterpretedFrame906 inline JSTaggedType* GetPrevFrameFp() 907 { 908 return base.prev; 909 } 910 GetFrameFromSpAsmInterpretedFrame911 static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp) 912 { 913 return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 914 } 915 GetFpOffsetAsmInterpretedFrame916 static size_t GetFpOffset(bool isArch32) 917 { 918 return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32); 919 } 920 GetCallSizeOffsetAsmInterpretedFrame921 static size_t GetCallSizeOffset(bool isArch32) 922 { 923 return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32); 924 } 925 GetFunctionOffsetAsmInterpretedFrame926 static size_t GetFunctionOffset(bool isArch32) 927 { 928 return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32); 929 } 930 GetThisOffsetAsmInterpretedFrame931 static size_t GetThisOffset(bool isArch32) 932 { 933 return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32); 934 } 935 GetAccOffsetAsmInterpretedFrame936 static size_t GetAccOffset(bool isArch32) 937 { 938 return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32); 939 } 940 GetEnvOffsetAsmInterpretedFrame941 static size_t GetEnvOffset(bool isArch32) 942 { 943 return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32); 944 } 945 GetBaseOffsetAsmInterpretedFrame946 static size_t GetBaseOffset(bool isArch32) 947 { 948 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 949 } 950 GetPcOffsetAsmInterpretedFrame951 static size_t GetPcOffset(bool isArch32) 952 { 953 return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32); 954 } 955 GetSizeAsmInterpretedFrame956 static constexpr size_t GetSize(bool isArch32) 957 { 958 return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64; 959 } 960 NumOfMembersAsmInterpretedFrame961 static uint32_t NumOfMembers() 962 { 963 return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize(); 964 } 965 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor, 966 const RootBaseAndDerivedVisitor &derivedVisitor) const; 967 GetEnvAsmInterpretedFrame968 JSTaggedValue GetEnv() const 969 { 970 return env; 971 } 972 GetPcAsmInterpretedFrame973 const uint8_t *GetPc() const 974 { 975 return pc; 976 } 977 GetTypeOffsetAsmInterpretedFrame978 static size_t GetTypeOffset() 979 { 980 return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type); 981 } 982 GetPrevOffsetAsmInterpretedFrame983 static size_t GetPrevOffset() 984 { 985 return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev); 986 } 987 988 alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()}; 989 alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()}; 990 alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()}; 991 alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()}; 992 alignas(EAS) uintptr_t callSize {0}; 993 alignas(EAS) JSTaggedType *fp {nullptr}; 994 alignas(EAS) const uint8_t *pc {nullptr}; 995 alignas(EAS) InterpretedFrameBase base; 996 // vregs, not exist in native 997 // args, may be truncated if not extra 998 }; 999 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64); 1000 1001 // InterpretedEntryFrame Layout as the following: 1002 // +----------------------------------+--------------- 1003 // | . . . . | ^ 1004 // | InterpretedFrameBase | | 1005 // | . . . . | InterpretedEntryFrame 1006 // |----------------------------------| | 1007 // | pc(bytecode addr) | v 1008 // |----------------------------------|--------------- 1009 // 1010 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1011 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1012 base::AlignedPointer, 1013 InterpretedFrameBase> { 1014 enum class Index : size_t { 1015 PcIndex = 0, 1016 BaseIndex, 1017 NumOfMembers 1018 }; 1019 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1020 GetPrevFrameFpInterpretedEntryFrame1021 inline JSTaggedType* GetPrevFrameFp() 1022 { 1023 return base.prev; 1024 } 1025 GetFrameFromSpInterpretedEntryFrame1026 static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 1027 { 1028 return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1029 } 1030 NumOfMembersInterpretedEntryFrame1031 static uint32_t NumOfMembers() 1032 { 1033 return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize(); 1034 } 1035 1036 static size_t GetTypeOffset(bool isArch32 = false) 1037 { 1038 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1039 InterpretedFrameBase::GetTypeOffset(isArch32); 1040 } 1041 1042 static size_t GetPrevOffset(bool isArch32 = false) 1043 { 1044 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1045 InterpretedFrameBase::GetPrevOffset(isArch32); 1046 } 1047 1048 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, 1049 const RootRangeVisitor &rangeVisitor) const; 1050 alignas(EAS) const uint8_t *pc {nullptr}; 1051 alignas(EAS) InterpretedFrameBase base; 1052 }; 1053 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame), 1054 InterpretedEntryFrame::SizeArch32, 1055 InterpretedEntryFrame::SizeArch64); 1056 1057 1058 // AsmInterpretedEntryFrame Layout as the following: 1059 // +----------------------------------+--------------- 1060 // | . . . . | ^ 1061 // | InterpretedFrameBase | | 1062 // | . . . . | AsmInterpretedEntryFrame 1063 // |----------------------------------| | 1064 // | pc(bytecode addr) | v 1065 // |----------------------------------|--------------- 1066 // 1067 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1068 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(), 1069 base::AlignedPointer, 1070 InterpretedFrameBase> { 1071 enum class Index : size_t { 1072 PcIndex = 0, 1073 BaseIndex, 1074 NumOfMembers 1075 }; 1076 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1077 GetPrevFrameFpAsmInterpretedEntryFrame1078 inline JSTaggedType* GetPrevFrameFp() 1079 { 1080 return base.prev; 1081 } 1082 GetBaseOffsetAsmInterpretedEntryFrame1083 static size_t GetBaseOffset(bool isArch32) 1084 { 1085 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32); 1086 } 1087 GetFrameFromSpAsmInterpretedEntryFrame1088 static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp) 1089 { 1090 return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1; 1091 } 1092 1093 static size_t GetTypeOffset(bool isArch32 = false) 1094 { 1095 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1096 InterpretedFrameBase::GetTypeOffset(isArch32); 1097 } 1098 1099 static size_t GetPrevOffset(bool isArch32 = false) 1100 { 1101 return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) + 1102 InterpretedFrameBase::GetPrevOffset(isArch32); 1103 } 1104 1105 alignas(EAS) const uint8_t *pc {nullptr}; 1106 alignas(EAS) InterpretedFrameBase base; 1107 }; 1108 1109 // AsmInterpretedBridgeFrame Layout as the following: 1110 // +----------------------------------+--------------- 1111 // | ret-address | ^ 1112 // |----------------------------------| | 1113 // | . . . . | AsmInterpretedBridgeFrame 1114 // | AsmInterpretedEntryFrame | | 1115 // | . . . . | v 1116 // |----------------------------------|--------------- 1117 // 1118 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1119 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1120 AsmInterpretedEntryFrame, 1121 base::AlignedPointer> { 1122 enum class Index : size_t { 1123 EntryIndex = 0, 1124 ReturnAddrIndex, 1125 NumOfMembers 1126 }; 1127 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1128 GetFrameFromSpAsmInterpretedBridgeFrame1129 static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp) 1130 { 1131 return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) - 1132 MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr)); 1133 } GetCallSiteSpAsmInterpretedBridgeFrame1134 uintptr_t GetCallSiteSp() const 1135 { 1136 return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame); 1137 } GetPrevFrameFpAsmInterpretedBridgeFrame1138 inline JSTaggedType* GetPrevFrameFp() 1139 { 1140 return entry.base.prev; 1141 } 1142 GetReturnAddrOffsetAsmInterpretedBridgeFrame1143 static size_t GetReturnAddrOffset(bool isArch32) 1144 { 1145 return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32); 1146 } 1147 GetSizeAsmInterpretedBridgeFrame1148 static constexpr size_t GetSize(bool isArch32) 1149 { 1150 return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64; 1151 } 1152 1153 static size_t GetTypeOffset(bool isArch32 = false) 1154 { 1155 return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) + 1156 AsmInterpretedEntryFrame::GetBaseOffset(isArch32) + 1157 InterpretedFrameBase::GetTypeOffset(isArch32); 1158 } 1159 static size_t GetPrevOffset(bool isArch32 = false) 1160 { 1161 return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) + 1162 AsmInterpretedEntryFrame::GetBaseOffset(isArch32) + 1163 InterpretedFrameBase::GetPrevOffset(isArch32); 1164 } 1165 GetReturnAddrAsmInterpretedBridgeFrame1166 uintptr_t GetReturnAddr() const 1167 { 1168 return returnAddr; 1169 } 1170 1171 AsmInterpretedEntryFrame entry; 1172 alignas(EAS) uintptr_t returnAddr; 1173 }; 1174 1175 // * Optimized-leaved-frame layout as the following: 1176 // +--------------------------+ 1177 // | argv[N-1] | 1178 // |--------------------------| 1179 // | . . . . . | 1180 // |--------------------------| 1181 // | argv[0] | 1182 // +--------------------------+------------- 1183 // | argc | ^ 1184 // |--------------------------| | 1185 // | RuntimeId | | 1186 // sp --> |--------------------------| OptimizedLeaveFrame 1187 // | ret-addr | | 1188 // |--------------------------| | 1189 // | prevFp | | 1190 // |--------------------------| | 1191 // | frameType | v 1192 // +--------------------------+------------- 1193 // 1194 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1195 struct OptimizedLeaveFrame { 1196 FrameType type; 1197 uintptr_t callsiteFp; // thread sp set here 1198 uintptr_t returnAddr; 1199 uint64_t argRuntimeId; 1200 uint64_t argc; 1201 1202 // argv[0]...argv[argc-1] dynamic according to agc GetFrameFromSpOptimizedLeaveFrame1203 static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1204 { 1205 return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1206 MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp)); 1207 } 1208 GetCallSiteSpOptimizedLeaveFrame1209 uintptr_t GetCallSiteSp() const 1210 { 1211 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId); 1212 } 1213 GetPrevFrameFpOptimizedLeaveFrame1214 inline JSTaggedType* GetPrevFrameFp() const 1215 { 1216 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1217 } 1218 GetReturnAddrOptimizedLeaveFrame1219 uintptr_t GetReturnAddr() const 1220 { 1221 return returnAddr; 1222 } 1223 GetTypeOffsetOptimizedLeaveFrame1224 static size_t GetTypeOffset() 1225 { 1226 return MEMBER_OFFSET(OptimizedLeaveFrame, type); 1227 } 1228 GetPrevOffsetOptimizedLeaveFrame1229 static size_t GetPrevOffset() 1230 { 1231 return MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp); 1232 } 1233 1234 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1235 }; 1236 1237 // * Optimized-leaved-frame-with-argv layout as the following: 1238 // +--------------------------+ 1239 // | argv[] | 1240 // +--------------------------+------------- 1241 // | argc | ^ 1242 // |--------------------------| | 1243 // | RuntimeId | OptimizedWithArgvLeaveFrame 1244 // sp --> |--------------------------| | 1245 // | returnAddr | | 1246 // |--------------------------| | 1247 // | callsiteFp | | 1248 // |--------------------------| | 1249 // | frameType | v 1250 // +--------------------------+------------- 1251 1252 struct OptimizedWithArgvLeaveFrame { 1253 FrameType type; 1254 uintptr_t callsiteFp; // thread sp set here 1255 uintptr_t returnAddr; 1256 uint64_t argRuntimeId; 1257 uint64_t argc; 1258 GetFrameFromSpOptimizedWithArgvLeaveFrame1259 static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1260 { 1261 return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1262 MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp)); 1263 } 1264 GetCallSiteSpOptimizedWithArgvLeaveFrame1265 uintptr_t GetCallSiteSp() const 1266 { 1267 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId); 1268 } 1269 GetPrevFrameFpOptimizedWithArgvLeaveFrame1270 inline JSTaggedType* GetPrevFrameFp() 1271 { 1272 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1273 } 1274 GetReturnAddrOptimizedWithArgvLeaveFrame1275 uintptr_t GetReturnAddr() const 1276 { 1277 return returnAddr; 1278 } 1279 GetTypeOffsetOptimizedWithArgvLeaveFrame1280 static size_t GetTypeOffset() 1281 { 1282 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type); 1283 } 1284 GetPrevOffsetOptimizedWithArgvLeaveFrame1285 static size_t GetPrevOffset() 1286 { 1287 return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp); 1288 } 1289 1290 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1291 }; 1292 1293 // * OptimizedBuiltinLeaveFrame layout as the following: 1294 // +--------------------------+ 1295 // | argv[N-1] | 1296 // |--------------------------| 1297 // | . . . . . | 1298 // |--------------------------| 1299 // | argv[0] | 1300 // +--------------------------+------------- 1301 // | argc | ^ 1302 // |--------------------------| | 1303 // | thread | | 1304 // +--------------------------+ | 1305 // | ret-addr | | 1306 // sp --> |--------------------------| OptimizedBuiltinLeaveFrame 1307 // | prevFp | | 1308 // |--------------------------| | 1309 // | frameType | | 1310 // |--------------------------| | 1311 // | align byte | v 1312 // +--------------------------+------------- 1313 // 1314 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1315 struct OptimizedBuiltinLeaveFrame { 1316 public: GetFrameFromSpOptimizedBuiltinLeaveFrame1317 static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp) 1318 { 1319 return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) - 1320 MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp)); 1321 } 1322 GetCallSiteSpOptimizedBuiltinLeaveFrame1323 uintptr_t GetCallSiteSp() const 1324 { 1325 return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argc); 1326 } 1327 GetPrevFrameFpOptimizedBuiltinLeaveFrame1328 inline JSTaggedType* GetPrevFrameFp() const 1329 { 1330 return reinterpret_cast<JSTaggedType*>(callsiteFp); 1331 } 1332 GetReturnAddrOptimizedBuiltinLeaveFrame1333 uintptr_t GetReturnAddr() const 1334 { 1335 return returnAddr; 1336 } 1337 1338 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1339 GetTypeOffsetOptimizedBuiltinLeaveFrame1340 static size_t GetTypeOffset() 1341 { 1342 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type); 1343 } 1344 GetPrevOffsetOptimizedBuiltinLeaveFrame1345 static size_t GetPrevOffset() 1346 { 1347 return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp); 1348 } 1349 GetArgvOptimizedBuiltinLeaveFrame1350 const JSTaggedType* GetArgv() const 1351 { 1352 return reinterpret_cast<const JSTaggedType *>(&argc + 1); 1353 } 1354 GetTypeOptimizedBuiltinLeaveFrame1355 FrameType GetType() const 1356 { 1357 return type; 1358 } 1359 1360 private: 1361 FrameType type; 1362 uintptr_t callsiteFp; // thread sp set here 1363 uintptr_t returnAddr; 1364 JSTaggedValue thread; 1365 uint64_t argc; 1366 // argv[0]...argv[argc-1] dynamic according to agc 1367 }; 1368 1369 // * BuiltinFrame layout as the following: 1370 // +--------------------------+ 1371 // | argV[N - 1] | 1372 // |--------------------------| 1373 // | . . . . | 1374 // |--------------------------+ 1375 // | argV[2]=this | 1376 // +--------------------------+ 1377 // | argV[1]=new-target | 1378 // +--------------------------+ 1379 // | argV[0]=call-target | 1380 // +--------------------------+ --------- 1381 // | argc | ^ 1382 // |--------------------------| | 1383 // | thread | | 1384 // |--------------------------| | 1385 // | returnAddr | BuiltinFrame 1386 // |--------------------------| | 1387 // | callsiteFp | | 1388 // |--------------------------| | 1389 // | frameType | v 1390 // +--------------------------+ --------- 1391 // 1392 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1393 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1394 base::AlignedSize, 1395 base::AlignedPointer, 1396 base::AlignedPointer, 1397 base::AlignedPointer, 1398 base::AlignedPointer, 1399 base::AlignedPointer> { 1400 enum class Index : size_t { 1401 TypeIndex = 0, 1402 PrevFpIndex, 1403 ReturnAddrIndex, 1404 ThreadIndex, 1405 NumArgsIndex, 1406 StackArgsIndex, 1407 NumOfMembers 1408 }; 1409 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1410 GetFrameFromSpBuiltinFrame1411 static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp) 1412 { 1413 return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) - 1414 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1415 } 1416 GetPrevFrameFpBuiltinFrame1417 inline JSTaggedType* GetPrevFrameFp() 1418 { 1419 return prevFp; 1420 } 1421 GetCallSiteSpBuiltinFrame1422 uintptr_t GetCallSiteSp() const 1423 { 1424 return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread); 1425 } 1426 GetPreFpOffsetBuiltinFrame1427 static size_t GetPreFpOffset(bool isArch32) 1428 { 1429 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1430 } 1431 GetNumArgsToFpDeltaBuiltinFrame1432 static size_t GetNumArgsToFpDelta(bool isArch32) 1433 { 1434 auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32); 1435 return offset - GetPreFpOffset(isArch32); 1436 } 1437 GetStackArgsToFpDeltaBuiltinFrame1438 static size_t GetStackArgsToFpDelta(bool isArch32) 1439 { 1440 auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 1441 return offset - GetPreFpOffset(isArch32); 1442 } 1443 GetStackArgsAddressBuiltinFrame1444 uintptr_t GetStackArgsAddress() 1445 { 1446 return reinterpret_cast<uintptr_t>(&stackArgs); 1447 } 1448 GetFunctionBuiltinFrame1449 JSTaggedValue GetFunction() 1450 { 1451 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1452 return JSTaggedValue(*functionAddress); 1453 } 1454 GetNumArgsBuiltinFrame1455 uint32_t GetNumArgs() 1456 { 1457 return numArgs; 1458 } 1459 GetReturnAddrBuiltinFrame1460 uintptr_t GetReturnAddr() const 1461 { 1462 return returnAddr; 1463 } 1464 1465 static size_t GetTypeOffset(bool isArch32 = false) 1466 { 1467 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1468 } 1469 1470 static size_t GetPrevOffset(bool isArch32 = false) 1471 { 1472 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1473 } 1474 1475 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1476 1477 alignas(EAS) FrameType type; 1478 alignas(EAS) JSTaggedType *prevFp; 1479 alignas(EAS) uintptr_t returnAddr; 1480 alignas(EAS) uintptr_t thread; 1481 alignas(EAS) uint32_t numArgs; 1482 alignas(EAS) uintptr_t stackArgs; 1483 }; 1484 1485 // * BuiltinWithArgvFrame layout as the following: 1486 // +--------------------------+ --------- 1487 // | . . . . . | ^ 1488 // |--------------------------| | 1489 // | returnAddr | | 1490 // |--------------------------| | 1491 // | callsiteFp | BuiltinWithArgvFrame 1492 // |--------------------------| | 1493 // | frameType | | 1494 // +--------------------------+ | 1495 // | argc | v 1496 // +--------------------------+ --------- 1497 // | argV[0] | 1498 // +--------------------------+ 1499 // | argV[1] | 1500 // +--------------------------+ 1501 // | . . . . | 1502 // +--------------------------+ 1503 // 1504 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) 1505 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(), 1506 base::AlignedSize, 1507 base::AlignedPointer, 1508 base::AlignedPointer> { 1509 enum class Index : int { 1510 StackArgsTopIndex = -1, 1511 NumArgsIndex = -1, 1512 TypeIndex = 0, 1513 PrevFpIndex, 1514 ReturnAddrIndex, 1515 NumOfMembers 1516 }; 1517 static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 1518 GetFrameFromSpBuiltinWithArgvFrame1519 static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp) 1520 { 1521 return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) - 1522 MEMBER_OFFSET(BuiltinFrame, prevFp)); 1523 } 1524 GetPrevFrameFpBuiltinWithArgvFrame1525 inline JSTaggedType* GetPrevFrameFp() 1526 { 1527 return prevFp; 1528 } 1529 GetCallSiteSpBuiltinWithArgvFrame1530 uintptr_t GetCallSiteSp() const 1531 { 1532 return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame); 1533 } 1534 GetStackArgsAddressBuiltinWithArgvFrame1535 uintptr_t GetStackArgsAddress() 1536 { 1537 auto topAddress = ToUintPtr(this) + 1538 (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t)); 1539 auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS; 1540 return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t); 1541 } 1542 GetFunctionBuiltinWithArgvFrame1543 JSTaggedValue GetFunction() 1544 { 1545 auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress()); 1546 return JSTaggedValue(*functionAddress); 1547 } 1548 GetNumArgsBuiltinWithArgvFrame1549 int32_t GetNumArgs() 1550 { 1551 auto argcAddress = reinterpret_cast<int32_t *>( 1552 ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t))); 1553 return *argcAddress; 1554 } 1555 GetReturnAddrBuiltinWithArgvFrame1556 uintptr_t GetReturnAddr() const 1557 { 1558 return returnAddr; 1559 } 1560 1561 static size_t GetTypeOffset(bool isArch32 = false) 1562 { 1563 return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32); 1564 } 1565 1566 static size_t GetPrevOffset(bool isArch32 = false) 1567 { 1568 return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32); 1569 } 1570 1571 void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const; 1572 // argv(... this, new.target, function) 1573 // numargs 1574 alignas(EAS) FrameType type; 1575 alignas(EAS) JSTaggedType *prevFp; 1576 alignas(EAS) uintptr_t returnAddr; 1577 }; 1578 1579 enum class GCVisitedFlag : bool { 1580 VISITED = true, 1581 IGNORED = false, 1582 HYBRID_STACK = true, 1583 }; 1584 1585 class FrameIterator { 1586 public: 1587 using ConstInfo = kungfu::LLVMStackMapType::ConstInfo; 1588 explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr); GetFrameType()1589 FrameType GetFrameType() const 1590 { 1591 ASSERT(current_ != nullptr); 1592 FrameType *typeAddr = reinterpret_cast<FrameType *>( 1593 reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType)); 1594 return *typeAddr; 1595 } 1596 1597 template<class T> GetFrame()1598 T* GetFrame() 1599 { 1600 return T::GetFrameFromSp(current_); 1601 } 1602 1603 template<class T> GetFrame()1604 const T* GetFrame() const 1605 { 1606 return T::GetFrameFromSp(current_); 1607 } 1608 Done()1609 bool Done() const 1610 { 1611 return current_ == nullptr; 1612 } GetSp()1613 JSTaggedType *GetSp() const 1614 { 1615 return current_; 1616 } GetSp()1617 JSTaggedType *GetSp() 1618 { 1619 return current_; 1620 } GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)1621 void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const 1622 { 1623 ret = calleeRegInfo_; 1624 } 1625 int ComputeDelta() const; 1626 template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED> 1627 void Advance(); 1628 uint32_t GetBytecodeOffset() const; 1629 uintptr_t GetPrevFrameCallSiteSp() const; 1630 uintptr_t GetPrevFrame() const; GetCallSiteSp()1631 uintptr_t GetCallSiteSp() const 1632 { 1633 return optimizedCallSiteSp_; 1634 } GetOptimizedReturnAddr()1635 uintptr_t GetOptimizedReturnAddr() const 1636 { 1637 return optimizedReturnAddr_; 1638 } GetThread()1639 const JSThread *GetThread() const 1640 { 1641 return thread_; 1642 } 1643 bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const; 1644 void CollectPcOffsetInfo(ConstInfo &info) const; 1645 void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const; 1646 std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const; 1647 int GetCallSiteDelta(uintptr_t retAddr) const; 1648 1649 Method *CheckAndGetMethod() const; 1650 JSTaggedValue GetFunction() const; 1651 IsLeaveFrame()1652 bool IsLeaveFrame() const 1653 { 1654 FrameType type = GetFrameType(); 1655 return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV); 1656 } 1657 IsOptimizedFrame()1658 bool IsOptimizedFrame() const 1659 { 1660 FrameType type = GetFrameType(); 1661 return (type == FrameType::OPTIMIZED_FRAME); 1662 } 1663 IsInterpretedFrame(FrameType type)1664 bool IsInterpretedFrame(FrameType type) const 1665 { 1666 return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST); 1667 } 1668 IsJSFrame()1669 bool IsJSFrame() const 1670 { 1671 FrameType type = GetFrameType(); 1672 return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type); 1673 } 1674 IsOptimizedJSFunctionFrame(FrameType type)1675 bool IsOptimizedJSFunctionFrame(FrameType type) const 1676 { 1677 return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || 1678 type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME; 1679 } 1680 IsOptimizedJSFunctionFrame()1681 bool IsOptimizedJSFunctionFrame() const 1682 { 1683 FrameType type = GetFrameType(); 1684 return IsOptimizedJSFunctionFrame(type); 1685 } 1686 1687 private: 1688 JSTaggedType *current_ {nullptr}; 1689 const JSThread *thread_ {nullptr}; 1690 const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr}; 1691 uintptr_t optimizedCallSiteSp_ {0}; 1692 uintptr_t optimizedReturnAddr_ {0}; 1693 uint8_t *stackMapAddr_ {nullptr}; 1694 int fpDeltaPrevFrameSp_ {0}; 1695 kungfu::CalleeRegAndOffsetVec calleeRegInfo_; 1696 }; 1697 } // namespace panda::ecmascript 1698 #endif // ECMASCRIPT_FRAMES_H 1699