• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_FRAMES_H
17 #define ECMASCRIPT_FRAMES_H
18 
19 #include "ecmascript/base/aligned_struct.h"
20 #include "ecmascript/js_tagged_value.h"
21 #include "ecmascript/mem/visitor.h"
22 #include "ecmascript/method.h"
23 #include "ecmascript/stackmap/ark_stackmap.h"
24 #include "ecmascript/stackmap/llvm_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     SUPER_CALL_WITH_ARGV,
158     SUPER_CALL_SPREAD_WITH_ARGV,
159     DEPRECATED_CALL_ARG0,
160     DEPRECATED_CALL_ARG1,
161     DEPRECATED_CALL_ARG2,
162     DEPRECATED_CALL_ARG3,
163     DEPRECATED_CALL_WITH_ARGV,
164     DEPRECATED_CALL_THIS_WITH_ARGV,
165     DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV,
166     CALL_GETTER,
167     CALL_SETTER,
168     CALL_THIS_ARG3_WITH_RETURN,
169     CALL_THIS_ARGV_WITH_RETURN,
170     CALL_ENTRY,
171     CALL_GENERATOR,
172     CALL_FROM_AOT,
173 };
174 
175 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
176 struct OptimizedFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
177                                                    base::AlignedPointer,
178                                                    base::AlignedPointer,
179                                                    base::AlignedPointer> {
180 public:
181     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
182         const RootBaseAndDerivedVisitor &derivedVisitor) const;
183 
184     static size_t GetTypeOffset(bool isArch32 = false)
185     {
186         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
187     }
188 
189     static size_t GetPrevOffset(bool isArch32 = false)
190     {
191         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
192     }
193 
ComputeReservedSizeOptimizedFrame194     static size_t ComputeReservedSize(size_t slotSize)
195     {
196         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex);
197         return slotSize * slotOffset;
198     }
199 
GetTypeOptimizedFrame200     FrameType GetType() const
201     {
202         return type;
203     }
204 private:
205     enum class Index : size_t {
206         TypeIndex = 0,
207         PrevFpIndex,
208         ReturnAddrIndex,
209         NumOfMembers
210     };
211     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
212 
GetFrameFromSpOptimizedFrame213     static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp)
214     {
215         return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp) -
216             MEMBER_OFFSET(OptimizedFrame, prevFp));
217     }
GetPrevFrameFpOptimizedFrame218     inline JSTaggedType* GetPrevFrameFp()
219     {
220         return prevFp;
221     }
GetReturnAddrOptimizedFrame222     uintptr_t GetReturnAddr() const
223     {
224         return returnAddr;
225     }
226 
227     alignas(EAS) FrameType type {0};
228     alignas(EAS) JSTaggedType *prevFp {nullptr};
229     alignas(EAS) uintptr_t returnAddr {0};
230     friend class FrameIterator;
231 };
232 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64);
233 
234 struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
235                                                    base::AlignedPointer,
236                                                    base::AlignedPointer,
237                                                    base::AlignedPointer> {
238 public:
239     static size_t GetTypeOffset(bool isArch32 = false)
240     {
241         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
242     }
243 
244     static size_t GetPrevOffset(bool isArch32 = false)
245     {
246         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
247     }
248 
GetCallSiteSpAsmBridgeFrame249     uintptr_t GetCallSiteSp() const
250     {
251         return ToUintPtr(this) + sizeof(AsmBridgeFrame);
252     }
253 
GetTypeAsmBridgeFrame254     FrameType GetType() const
255     {
256         return type;
257     }
258 
259 private:
260     enum class Index : size_t {
261         TypeIndex = 0,
262         PrevFpIndex,
263         ReturnAddrIndex,
264         NumOfMembers
265     };
266     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
267 
GetFrameFromSpAsmBridgeFrame268     static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
269     {
270         return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
271             MEMBER_OFFSET(AsmBridgeFrame, prevFp));
272     }
GetPrevFrameFpAsmBridgeFrame273     inline JSTaggedType* GetPrevFrameFp()
274     {
275         return prevFp;
276     }
GetReturnAddrAsmBridgeFrame277     uintptr_t GetReturnAddr() const
278     {
279         return returnAddr;
280     }
281     alignas(EAS) FrameType type {0};
282     alignas(EAS) JSTaggedType *prevFp {nullptr};
283     alignas(EAS) uintptr_t returnAddr {0};
284     friend class FrameIterator;
285 };
286 STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64);
287 
288 // * OptimizedUnfoldArgVFrame layout description as the following:
289 //      sp ----> |--------------------------| ---------------
290 //               |       returnAddr         |               ^
291 //  currentFp--> |--------------------------|               |
292 //               |       prevFp             |               |
293 //               |--------------------------|   OptimizedUnfoldArgVFrame
294 //               |       frameType          |               |
295 //               |--------------------------|               |
296 //               |       currentFp          |               v
297 //               +--------------------------+ ---------------
298 //
299 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
300 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
301                                                                        base::AlignedPointer,
302                                                                        base::AlignedPointer,
303                                                                        base::AlignedPointer,
304                                                                        base::AlignedPointer> {
305 public:
306     static size_t GetTypeOffset(bool isArch32 = false)
307     {
308         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
309     }
310 
311     static size_t GetPrevOffset(bool isArch32 = false)
312     {
313         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
314     }
315 
GetTypeOptimizedJSFunctionUnfoldArgVFrame316     FrameType GetType() const
317     {
318         return type;
319     }
320 
321 private:
322     enum class Index : size_t {
323         CallSiteSpIndex = 0,
324         TypeIndex,
325         PrevFpIndex,
326         ReturnAddrIndex,
327         NumOfMembers
328     };
329     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
330 
GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame331     static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp)
332     {
333         return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp) -
334             MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp));
335     }
GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame336     inline JSTaggedType* GetPrevFrameFp() const
337     {
338         return prevFp;
339     }
GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame340     uintptr_t GetReturnAddr() const
341     {
342         return returnAddr;
343     }
GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame344     uintptr_t GetPrevFrameSp() const
345     {
346         return callSiteSp;
347     }
348     alignas(EAS) uintptr_t callSiteSp {0};
349     alignas(EAS) FrameType type {0};
350     alignas(EAS) JSTaggedType *prevFp {nullptr};
351     alignas(EAS) uintptr_t returnAddr {0};
352     friend class FrameIterator;
353 };
354 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame),
355     OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64);
356 
357 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following:
358 //          +--------------------------+
359 //          |         arg[N-1]         |
360 //          +--------------------------+
361 //          |         . . . .          |
362 //          +--------------------------+
363 //          |         arg[0]           |
364 //          +--------------------------+
365 //          |         argC             |
366 //  sp ---> +--------------------------+ -----------------
367 //          |                          |                 ^
368 //          |        prevFP            |                 |
369 //          |--------------------------|    OptimizedJSFunctionArgsConfigFrame
370 //          |       frameType          |                 |
371 //          |                          |                 V
372 //          +--------------------------+ -----------------
373 //
374 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
375 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
376                                                                       base::AlignedPointer,
377                                                                       base::AlignedPointer> {
378 public:
379     static size_t GetTypeOffset(bool isArch32 = false)
380     {
381         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
382     }
383 
384     static size_t GetPrevOffset(bool isArch32 = false)
385     {
386         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
387     }
388 
GetTypeOptimizedJSFunctionArgConfigFrame389     FrameType GetType() const
390     {
391         return type;
392     }
393 
394 private:
395     enum class Index : size_t {
396         TypeIndex = 0,
397         PrevFpIndex,
398         NumOfMembers
399     };
400     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
401 
GetFrameFromSpOptimizedJSFunctionArgConfigFrame402     static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp)
403     {
404         return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp) -
405             MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp));
406     }
GetPrevFrameFpOptimizedJSFunctionArgConfigFrame407     inline JSTaggedType* GetPrevFrameFp()
408     {
409         return prevFp;
410     }
411 
412     alignas(EAS) FrameType type {0};
413     alignas(EAS) JSTaggedType *prevFp {nullptr};
414     friend class FrameIterator;
415 };
416 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame),
417                       OptimizedJSFunctionArgConfigFrame::SizeArch32,
418                       OptimizedJSFunctionArgConfigFrame::SizeArch64);
419 
420 // * OptimizedJSFunctionFrame layout description as the following:
421 //               +--------------------------+
422 //               |        arg[N-1]          |
423 //               +--------------------------+
424 //               |       ...                |
425 //               +--------------------------+
426 //               |       arg[1]             |
427 //               +--------------------------+
428 //               |       arg[0]             |
429 //               +--------------------------+
430 //               |       this               |
431 //               +--------------------------+
432 //               |       new-target         |
433 //               +--------------------------+
434 //               |       call-target        |
435 //               |--------------------------|
436 //               |       argc               |
437 //      sp ----> |--------------------------| ---------------
438 //               |       returnAddr         |               ^
439 //               |--------------------------|               |
440 //               |       callsiteFp         |               |
441 //               |--------------------------|   OptimizedJSFunctionFrame
442 //               |       frameType          |               |
443 //               |--------------------------|               |
444 //               |       call-target        |               v
445 //               +--------------------------+ ---------------
446 //
447 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
448 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
449                                                              JSTaggedValue,
450                                                              base::AlignedPointer,
451                                                              base::AlignedPointer,
452                                                              base::AlignedPointer> {
453 public:
454     using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
455     enum class Index : size_t {
456         JSFuncIndex = 0,
457         TypeIndex,
458         PrevFpIndex,
459         ReturnAddrIndex,
460         NumOfMembers
461     };
462     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
463 
GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame464     static constexpr size_t GetFunctionDeltaReturnAddr()
465     {
466         return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex);
467     }
468 
GetPrevFrameFpOptimizedJSFunctionFrame469     inline JSTaggedType* GetPrevFrameFp()
470     {
471         return prevFp;
472     }
473 
GetArgvOptimizedJSFunctionFrame474     JSTaggedType* GetArgv(uintptr_t *preFrameSp) const
475     {
476         return reinterpret_cast<JSTaggedType *>(preFrameSp + sizeof(uint64_t) / sizeof(uintptr_t));
477     }
478 
GetArgcOptimizedJSFunctionFrame479     size_t GetArgc(uintptr_t *preFrameSp) const
480     {
481         return *preFrameSp;
482     }
483 
484     JSTaggedType* GetArgv(const FrameIterator &it) const;
485 
GetReturnAddrOptimizedJSFunctionFrame486     uintptr_t GetReturnAddr() const
487     {
488         return returnAddr;
489     }
490 
491     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
492         const RootBaseAndDerivedVisitor &derivedVisitor, FrameType frameType) const;
493     void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const;
494 
GetFunctionOptimizedJSFunctionFrame495     inline JSTaggedValue GetFunction() const
496     {
497         return jsFunc;
498     }
499 
ComputeArgsConfigFrameSpOptimizedJSFunctionFrame500     static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp)
501     {
502         const size_t offset = 2;  // 2: skip prevFp and return address.
503         return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t);
504     }
505 
506     static size_t GetTypeOffset(bool isArch32 = false)
507     {
508         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
509     }
510 
511     static size_t GetPrevOffset(bool isArch32 = false)
512     {
513         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
514     }
515 
516     static size_t GetFunctionOffset(bool isArch32 = false)
517     {
518         return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32);
519     }
520 
ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame521     static size_t ComputeReservedJSFuncOffset(size_t slotSize)
522     {
523         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex);
524         return slotSize * slotOffset;
525     }
526 
GetTypeOptimizedJSFunctionFrame527     FrameType GetType() const
528     {
529         return type;
530     }
531 
532     friend class FrameIterator;
533     friend class FrameHandler;
534     void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const;
535     void GetFuncCalleeRegAndOffset(
536         const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const;
537     uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const;
538 
539 private:
GetFrameFromSpOptimizedJSFunctionFrame540     static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp)
541     {
542         return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) -
543             MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp));
544     }
545 
546     // dynamic callee saveregisters for x86-64
547     alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()};
548     alignas(EAS) FrameType type {0};
549     alignas(EAS) JSTaggedType *prevFp {nullptr};
550     alignas(EAS) uintptr_t returnAddr {0};
551     // dynamic callee saveregisters for arm64
552 };
553 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame),
554                       OptimizedJSFunctionFrame::SizeArch32,
555                       OptimizedJSFunctionFrame::SizeArch64);
556 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time.
557 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1);
558 
559 // * The JSFunctionEntry Frame's structure is illustrated as the following:
560 //          +--------------------------+
561 //          |      . . . . . .         |
562 //  sp ---> +--------------------------+ -----------------
563 //          |        prevFP            |                 ^
564 //          |--------------------------|                 |
565 //          |       frameType          |      JSFunctionEntryFrame
566 //          |--------------------------|                 |
567 //          |    preLeaveFrameFp       |                 v
568 //          +--------------------------+ -----------------
569 
570 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
571                                                         base::AlignedPointer,
572                                                         base::AlignedPointer,
573                                                         base::AlignedPointer> {
574 public:
575     enum class CallType : size_t {
576         CALL_FUNC = 0,
577         CALL_NEW,
578     };
579 
580     enum class Index : size_t {
581         PreLeaveFrameFpIndex = 0,
582         TypeIndex,
583         PrevFpIndex,
584         NumOfMembers
585     };
586 
587     static size_t GetTypeOffset(bool isArch32 = false)
588     {
589         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
590     }
591 
592     static size_t GetLeaveFrameFpOffset(bool isArch32 = false)
593     {
594         return GetOffset<static_cast<size_t>(Index::PreLeaveFrameFpIndex)>(isArch32);
595     }
596 
GetPrevFrameFpOptimizedEntryFrame597     inline JSTaggedType* GetPrevFrameFp()
598     {
599         return preLeaveFrameFp;
600     }
601 
ComputeReservedSizeOptimizedEntryFrame602     static size_t ComputeReservedSize(size_t slotSize)
603     {
604         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex);
605         return slotSize * slotOffset;
606     }
607 
GetTypeOptimizedEntryFrame608     FrameType GetType() const
609     {
610         return type;
611     }
612     friend class FrameIterator;
613 
614 private:
GetFrameFromSpOptimizedEntryFrame615     static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
616     {
617         return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) -
618                                                        MEMBER_OFFSET(OptimizedEntryFrame, prevFp));
619     }
620 
GetLeaveFpOptimizedEntryFrame621     JSTaggedType* GetLeaveFp() const
622     {
623         return preLeaveFrameFp;
624     }
625 
GetPrevFpOptimizedEntryFrame626     JSTaggedType* GetPrevFp() const
627     {
628         return prevFp;
629     }
630 
631     alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr};
632     alignas(EAS) FrameType type {0};
633     alignas(EAS) JSTaggedType *prevFp {nullptr};
634 };
635 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64);
636 
637 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
638 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(),
639                                                          base::AlignedPointer,
640                                                          base::AlignedSize> {
641     enum class Index : size_t {
642         PrevIndex = 0,
643         TypeIndex,
644         NumOfMembers
645     };
646     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
647 
GetPrevFrameFpInterpretedFrameBase648     inline JSTaggedType* GetPrevFrameFp()
649     {
650         return prev;
651     }
652 
GetFrameFromSpInterpretedFrameBase653     static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp)
654     {
655         return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1;
656     }
657 
658     static size_t GetPrevOffset(bool isArch32 = false)
659     {
660         return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32);
661     }
662 
663     static size_t GetTypeOffset(bool isArch32 = false)
664     {
665         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
666     }
667 
GetSizeInterpretedFrameBase668     static constexpr size_t GetSize(bool isArch32)
669     {
670         return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64;
671     }
672 
673     alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc
674     alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0
675 };
676 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase),
677                       InterpretedFrameBase::SizeArch32,
678                       InterpretedFrameBase::SizeArch64);
679 
680 // Interpreter Frame Layout as the following:
681 //   +----------------------------------+
682 //   |    argv[n-1]                     |
683 //   |----------------------------------|
684 //   |    ......                        |
685 //   |----------------------------------|
686 //   |    thisArg [maybe not exist]     |
687 //   |----------------------------------|
688 //   |    newTarget [maybe not exist]   |
689 //   |----------------------------------|
690 //   |    ......                        |
691 //   |----------------------------------|
692 //   |    Vregs [not exist in native]   |
693 //   +----------------------------------+--------+
694 //   |    base.frameType                |        ^
695 //   |----------------------------------|        |
696 //   |    base.prev(prev stack pointer) |        |
697 //   |----------------------------------|        |
698 //   |    pc(bytecode addr)             |        |
699 //   |----------------------------------|        |
700 //   |    sp(current stack pointer)     |        |
701 //   |----------------------------------|        |
702 //   |    env                           |        |
703 //   |----------------------------------|        |
704 //   |    acc                           |        |
705 //   |----------------------------------|   InterpretedFrame
706 //   |    profileTypeInfo               |        |
707 //   |----------------------------------|        |
708 //   |    thisObj                       |        |
709 //   |----------------------------------|        |
710 //   |    function                      |        |
711 //   |----------------------------------|        |
712 //   |    constpool                     |        v
713 //   +----------------------------------+--------+
714 //
715 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
716 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
717                                                      JSTaggedValue,
718                                                      JSTaggedValue,
719                                                      JSTaggedValue,
720                                                      JSTaggedValue,
721                                                      JSTaggedValue,
722                                                      JSTaggedValue,
723                                                      base::AlignedPointer,
724                                                      InterpretedFrameBase> {
725 public:
726     enum class Index : size_t {
727         ConstPoolIndex = 0,
728         FunctionIndex,
729         ThisObjIndex,
730         ProFileTypeInfoIndex,
731         AccIndex,
732         EnvIndex,
733         PcIndex,
734         BaseIndex,
735         NumOfMembers
736     };
737     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
738 
GetPrevFrameFpInterpretedFrame739     inline JSTaggedType* GetPrevFrameFp() const
740     {
741         return base.prev;
742     }
743 
GetFrameFromSpInterpretedFrame744     static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
745     {
746         return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
747     }
748 
GetPcInterpretedFrame749     inline const uint8_t *GetPc() const
750     {
751         return pc;
752     }
753 
GetEnvInterpretedFrame754     inline JSTaggedValue GetEnv() const
755     {
756         return env;
757     }
758 
NumOfMembersInterpretedFrame759     static uint32_t NumOfMembers()
760     {
761         return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize();
762     }
763 
GetPcOffsetInterpretedFrame764     static size_t GetPcOffset(bool isArch32)
765     {
766         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
767     }
768 
769     static size_t GetTypeOffset(bool isArch32 = false)
770     {
771         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
772             InterpretedFrameBase::GetTypeOffset(isArch32);
773     }
774 
775     static size_t GetPrevOffset(bool isArch32 = false)
776     {
777         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
778             InterpretedFrameBase::GetPrevOffset(isArch32);
779     }
780 
781     static size_t GetFunctionOffset(bool isArch32 = false)
782     {
783         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
784     }
785 
786     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
787 
788     alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()};
789     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
790     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
791     alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()};
792     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
793     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
794     alignas(EAS) const uint8_t *pc {nullptr};
795     alignas(EAS) InterpretedFrameBase base;
796     friend class FrameIterator;
797 };
798 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64);
799 
800 // * InterpretedBuiltinFrame layout description as the following:
801 //               |--------------------------| ---------------
802 //               |         . . . . .        |               ^
803 //               |    InterpretedFrameBase  |               |
804 //               |         . . . . .        |               |
805 //               |--------------------------|    InterpretedBuiltinFrame
806 //               |       bytecode-PC        |               |
807 //               |--------------------------|               |
808 //               |       call-target        |               v
809 //               +--------------------------+ ---------------
810 //
811 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
812 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
813                                                             JSTaggedValue,
814                                                             base::AlignedPointer,
815                                                             InterpretedFrameBase> {
816     enum class Index : size_t {
817         FunctionIndex = 0,
818         PcIndex,
819         BaseIndex,
820         NumOfMembers
821     };
822     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
823 
GetPrevFrameFpInterpretedBuiltinFrame824     inline JSTaggedType* GetPrevFrameFp()
825     {
826         return base.prev;
827     }
828 
GetFrameFromSpInterpretedBuiltinFrame829     static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
830     {
831         return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
832     }
833 
NumOfMembersInterpretedBuiltinFrame834     static uint32_t NumOfMembers()
835     {
836         return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize();
837     }
838 
839     static size_t GetTypeOffset(bool isArch32 = false)
840     {
841         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
842             InterpretedFrameBase::GetTypeOffset(isArch32);
843     }
844 
845     static size_t GetPrevOffset(bool isArch32 = false)
846     {
847         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
848             InterpretedFrameBase::GetPrevOffset(isArch32);
849     }
850 
851     static size_t GetFunctionOffset(bool isArch32 = false)
852     {
853         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
854     }
855 
856     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
857 
858     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
859     alignas(EAS) const uint8_t *pc {nullptr};
860     alignas(EAS) InterpretedFrameBase base;
861 };
862 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame),
863                       InterpretedBuiltinFrame::SizeArch32,
864                       InterpretedBuiltinFrame::SizeArch64);
865 
866 // AsmInterpretedFrame Layout as the following:
867 //   +----------------------------------+
868 //   |    argv[n-1]                     |
869 //   |----------------------------------|
870 //   |    ......                        |
871 //   |----------------------------------|
872 //   |    thisArg [maybe not exist]     |
873 //   |----------------------------------|
874 //   |    newTarget [maybe not exist]   |
875 //   |----------------------------------|
876 //   |    ......                        |
877 //   |----------------------------------|
878 //   |    Vregs [not exist in native]   |
879 //   +----------------------------------+--------+
880 //   |        .  .  .   .               |        ^
881 //   |     InterpretedFrameBase         |        |
882 //   |        .  .  .   .               |        |
883 //   |----------------------------------|        |
884 //   |    pc(bytecode addr)             |        |
885 //   |----------------------------------|        |
886 //   |    sp(current stack pointer)     |        |
887 //   |----------------------------------|   AsmInterpretedFrame
888 //   |    callSize                      |        |
889 //   |----------------------------------|        |
890 //   |    env                           |        |
891 //   |----------------------------------|        |
892 //   |    acc                           |        |
893 //   |----------------------------------|        |
894 //   |    thisObj                       |        |
895 //   |----------------------------------|        |
896 //   |    call-target                   |        v
897 //   +----------------------------------+--------+
898 //
899 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
900 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
901                                                         JSTaggedValue,
902                                                         JSTaggedValue,
903                                                         JSTaggedValue,
904                                                         JSTaggedValue,
905                                                         base::AlignedPointer,
906                                                         base::AlignedPointer,
907                                                         base::AlignedPointer,
908                                                         InterpretedFrameBase> {
909     enum class Index : size_t {
910         FunctionIndex = 0,
911         ThisObjIndex,
912         AccIndex,
913         EnvIndex,
914         CallSizeIndex,
915         FpIndex,
916         PcIndex,
917         BaseIndex,
918         NumOfMembers
919     };
920 
921     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
922 
GetCurrentFramePointerAsmInterpretedFrame923     inline JSTaggedType* GetCurrentFramePointer()
924     {
925         return fp;
926     }
927 
GetPrevFrameFpAsmInterpretedFrame928     inline JSTaggedType* GetPrevFrameFp()
929     {
930         return base.prev;
931     }
932 
GetFrameFromSpAsmInterpretedFrame933     static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
934     {
935         return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
936     }
937 
GetFpOffsetAsmInterpretedFrame938     static size_t GetFpOffset(bool isArch32)
939     {
940         return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32);
941     }
942 
GetCallSizeOffsetAsmInterpretedFrame943     static size_t GetCallSizeOffset(bool isArch32)
944     {
945         return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32);
946     }
947 
GetFunctionOffsetAsmInterpretedFrame948     static size_t GetFunctionOffset(bool isArch32)
949     {
950         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
951     }
952 
GetThisOffsetAsmInterpretedFrame953     static size_t GetThisOffset(bool isArch32)
954     {
955         return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32);
956     }
957 
GetAccOffsetAsmInterpretedFrame958     static size_t GetAccOffset(bool isArch32)
959     {
960         return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32);
961     }
962 
GetEnvOffsetAsmInterpretedFrame963     static size_t GetEnvOffset(bool isArch32)
964     {
965         return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32);
966     }
967 
GetBaseOffsetAsmInterpretedFrame968     static size_t GetBaseOffset(bool isArch32)
969     {
970         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
971     }
972 
GetPcOffsetAsmInterpretedFrame973     static size_t GetPcOffset(bool isArch32)
974     {
975         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
976     }
977 
GetSizeAsmInterpretedFrame978     static constexpr size_t GetSize(bool isArch32)
979     {
980         return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64;
981     }
982 
NumOfMembersAsmInterpretedFrame983     static uint32_t NumOfMembers()
984     {
985         return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize();
986     }
987     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
988         const RootBaseAndDerivedVisitor &derivedVisitor) const;
989 
GetEnvAsmInterpretedFrame990     JSTaggedValue GetEnv() const
991     {
992         return env;
993     }
994 
GetPcAsmInterpretedFrame995     const uint8_t *GetPc() const
996     {
997         return pc;
998     }
999 
GetTypeOffsetAsmInterpretedFrame1000     static size_t GetTypeOffset()
1001     {
1002         return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type);
1003     }
1004 
GetPrevOffsetAsmInterpretedFrame1005     static size_t GetPrevOffset()
1006     {
1007         return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev);
1008     }
1009 
1010     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
1011     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
1012     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
1013     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
1014     alignas(EAS) uintptr_t callSize {0};
1015     alignas(EAS) JSTaggedType *fp {nullptr};
1016     alignas(EAS) const uint8_t *pc {nullptr};
1017     alignas(EAS) InterpretedFrameBase base;
1018     // vregs, not exist in native
1019     // args, may be truncated if not extra
1020 };
1021 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64);
1022 
1023 // InterpretedEntryFrame Layout as the following:
1024 //   +----------------------------------+---------------
1025 //   |        .  .  .   .               |              ^
1026 //   |     InterpretedFrameBase         |              |
1027 //   |        .  .  .   .               |    InterpretedEntryFrame
1028 //   |----------------------------------|              |
1029 //   |    pc(bytecode addr)             |              v
1030 //   |----------------------------------|---------------
1031 //
1032 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1033 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1034                                                           base::AlignedPointer,
1035                                                           InterpretedFrameBase> {
1036     enum class Index : size_t {
1037         PcIndex = 0,
1038         BaseIndex,
1039         NumOfMembers
1040     };
1041     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1042 
GetPrevFrameFpInterpretedEntryFrame1043     inline JSTaggedType* GetPrevFrameFp()
1044     {
1045         return base.prev;
1046     }
1047 
GetFrameFromSpInterpretedEntryFrame1048     static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
1049     {
1050         return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
1051     }
1052 
NumOfMembersInterpretedEntryFrame1053     static uint32_t NumOfMembers()
1054     {
1055         return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize();
1056     }
1057 
1058     static size_t GetTypeOffset(bool isArch32 = false)
1059     {
1060         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1061             InterpretedFrameBase::GetTypeOffset(isArch32);
1062     }
1063 
1064     static size_t GetPrevOffset(bool isArch32 = false)
1065     {
1066         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1067             InterpretedFrameBase::GetPrevOffset(isArch32);
1068     }
1069 
1070     void GCIterate(const FrameIterator &it, const RootVisitor &visitor,
1071         const RootRangeVisitor &rangeVisitor) const;
1072     alignas(EAS) const uint8_t *pc {nullptr};
1073     alignas(EAS) InterpretedFrameBase base;
1074 };
1075 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame),
1076                       InterpretedEntryFrame::SizeArch32,
1077                       InterpretedEntryFrame::SizeArch64);
1078 
1079 
1080 // AsmInterpretedEntryFrame Layout as the following:
1081 //   +----------------------------------+---------------
1082 //   |        .  .  .   .               |              ^
1083 //   |     InterpretedFrameBase         |              |
1084 //   |        .  .  .   .               |    AsmInterpretedEntryFrame
1085 //   |----------------------------------|              |
1086 //   |    pc(bytecode addr)             |              v
1087 //   |----------------------------------|---------------
1088 //
1089 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1090 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1091                                                              base::AlignedPointer,
1092                                                              InterpretedFrameBase> {
1093     enum class Index : size_t {
1094         PcIndex = 0,
1095         BaseIndex,
1096         NumOfMembers
1097     };
1098     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1099 
GetPrevFrameFpAsmInterpretedEntryFrame1100     inline JSTaggedType* GetPrevFrameFp()
1101     {
1102         return base.prev;
1103     }
1104 
GetBaseOffsetAsmInterpretedEntryFrame1105     static size_t GetBaseOffset(bool isArch32)
1106     {
1107         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
1108     }
1109 
GetFrameFromSpAsmInterpretedEntryFrame1110     static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
1111     {
1112         return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
1113     }
1114 
1115     static size_t GetTypeOffset(bool isArch32 = false)
1116     {
1117         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1118             InterpretedFrameBase::GetTypeOffset(isArch32);
1119     }
1120 
1121     static size_t GetPrevOffset(bool isArch32 = false)
1122     {
1123         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1124             InterpretedFrameBase::GetPrevOffset(isArch32);
1125     }
1126 
1127     alignas(EAS) const uint8_t *pc {nullptr};
1128     alignas(EAS) InterpretedFrameBase base;
1129 };
1130 
1131 // AsmInterpretedBridgeFrame Layout as the following:
1132 //   +----------------------------------+---------------
1133 //   |      ret-address                 |              ^
1134 //   |----------------------------------|              |
1135 //   |        .  .  .   .               |     AsmInterpretedBridgeFrame
1136 //   |     AsmInterpretedEntryFrame     |              |
1137 //   |        .  .  .   .               |              v
1138 //   |----------------------------------|---------------
1139 //
1140 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1141 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1142                                                               AsmInterpretedEntryFrame,
1143                                                               base::AlignedPointer> {
1144     enum class Index : size_t {
1145         EntryIndex = 0,
1146         ReturnAddrIndex,
1147         NumOfMembers
1148     };
1149     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1150 
GetFrameFromSpAsmInterpretedBridgeFrame1151     static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
1152     {
1153         return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
1154             MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr));
1155     }
GetCallSiteSpAsmInterpretedBridgeFrame1156     uintptr_t GetCallSiteSp() const
1157     {
1158         return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame);
1159     }
GetPrevFrameFpAsmInterpretedBridgeFrame1160     inline JSTaggedType* GetPrevFrameFp()
1161     {
1162         return entry.base.prev;
1163     }
1164 
GetReturnAddrOffsetAsmInterpretedBridgeFrame1165     static size_t GetReturnAddrOffset(bool isArch32)
1166     {
1167         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
1168     }
1169 
GetSizeAsmInterpretedBridgeFrame1170     static constexpr size_t GetSize(bool isArch32)
1171     {
1172         return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64;
1173     }
1174 
1175     static size_t GetTypeOffset(bool isArch32 = false)
1176     {
1177         return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) +
1178             AsmInterpretedEntryFrame::GetBaseOffset(isArch32) +
1179             InterpretedFrameBase::GetTypeOffset(isArch32);
1180     }
1181     static size_t GetPrevOffset(bool isArch32 = false)
1182     {
1183         return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) +
1184             AsmInterpretedEntryFrame::GetBaseOffset(isArch32) +
1185             InterpretedFrameBase::GetPrevOffset(isArch32);
1186     }
1187 
GetReturnAddrAsmInterpretedBridgeFrame1188     uintptr_t GetReturnAddr() const
1189     {
1190         return returnAddr;
1191     }
1192 
1193     AsmInterpretedEntryFrame entry;
1194     alignas(EAS) uintptr_t returnAddr;
1195 };
1196 
1197 // * Optimized-leaved-frame layout as the following:
1198 //         +--------------------------+
1199 //         |       argv[N-1]          |
1200 //         |--------------------------|
1201 //         |       . . . . .          |
1202 //         |--------------------------|
1203 //         |       argv[0]            |
1204 //         +--------------------------+-------------
1205 //         |       argc               |            ^
1206 //         |--------------------------|            |
1207 //         |       RuntimeId          |            |
1208 //  sp --> |--------------------------|   OptimizedLeaveFrame
1209 //         |       ret-addr           |            |
1210 //         |--------------------------|            |
1211 //         |       prevFp             |            |
1212 //         |--------------------------|            |
1213 //         |       frameType          |            v
1214 //         +--------------------------+-------------
1215 //
1216 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1217 struct OptimizedLeaveFrame {
1218     FrameType type;
1219     uintptr_t callsiteFp; // thread sp set here
1220     uintptr_t returnAddr;
1221     uint64_t argRuntimeId;
1222     uint64_t argc;
1223 
1224     // argv[0]...argv[argc-1] dynamic according to agc
GetFrameFromSpOptimizedLeaveFrame1225     static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1226     {
1227         return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1228             MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp));
1229     }
1230 
GetCallSiteSpOptimizedLeaveFrame1231     uintptr_t GetCallSiteSp() const
1232     {
1233         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId);
1234     }
1235 
GetPrevFrameFpOptimizedLeaveFrame1236     inline JSTaggedType* GetPrevFrameFp() const
1237     {
1238         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1239     }
1240 
GetReturnAddrOptimizedLeaveFrame1241     uintptr_t GetReturnAddr() const
1242     {
1243         return returnAddr;
1244     }
1245 
GetTypeOffsetOptimizedLeaveFrame1246     static size_t GetTypeOffset()
1247     {
1248         return MEMBER_OFFSET(OptimizedLeaveFrame, type);
1249     }
1250 
GetPrevOffsetOptimizedLeaveFrame1251     static size_t GetPrevOffset()
1252     {
1253         return MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp);
1254     }
1255 
1256     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1257 };
1258 
1259 // * Optimized-leaved-frame-with-argv layout as the following:
1260 //         +--------------------------+
1261 //         |       argv[]             |
1262 //         +--------------------------+-------------
1263 //         |       argc               |            ^
1264 //         |--------------------------|            |
1265 //         |       RuntimeId          |   OptimizedWithArgvLeaveFrame
1266 //  sp --> |--------------------------|            |
1267 //         |       returnAddr         |            |
1268 //         |--------------------------|            |
1269 //         |       callsiteFp         |            |
1270 //         |--------------------------|            |
1271 //         |       frameType          |            v
1272 //         +--------------------------+-------------
1273 
1274 struct OptimizedWithArgvLeaveFrame {
1275     FrameType type;
1276     uintptr_t callsiteFp; // thread sp set here
1277     uintptr_t returnAddr;
1278     uint64_t argRuntimeId;
1279     uint64_t argc;
1280 
GetFrameFromSpOptimizedWithArgvLeaveFrame1281     static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1282     {
1283         return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1284             MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp));
1285     }
1286 
GetCallSiteSpOptimizedWithArgvLeaveFrame1287     uintptr_t GetCallSiteSp() const
1288     {
1289         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId);
1290     }
1291 
GetPrevFrameFpOptimizedWithArgvLeaveFrame1292     inline JSTaggedType* GetPrevFrameFp()
1293     {
1294         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1295     }
1296 
GetReturnAddrOptimizedWithArgvLeaveFrame1297     uintptr_t GetReturnAddr() const
1298     {
1299         return returnAddr;
1300     }
1301 
GetTypeOffsetOptimizedWithArgvLeaveFrame1302     static size_t GetTypeOffset()
1303     {
1304         return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type);
1305     }
1306 
GetPrevOffsetOptimizedWithArgvLeaveFrame1307     static size_t GetPrevOffset()
1308     {
1309         return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp);
1310     }
1311 
1312     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1313 };
1314 
1315 // * OptimizedBuiltinLeaveFrame layout as the following:
1316 //         +--------------------------+
1317 //         |       argv[N-1]          |
1318 //         |--------------------------|
1319 //         |       . . . . .          |
1320 //         |--------------------------|
1321 //         |       argv[0]            |
1322 //         +--------------------------+-------------
1323 //         |       argc               |            ^
1324 //         |--------------------------|            |
1325 //         |       thread             |            |
1326 //         +--------------------------+            |
1327 //         |       ret-addr           |            |
1328 //  sp --> |--------------------------|   OptimizedBuiltinLeaveFrame
1329 //         |       prevFp             |            |
1330 //         |--------------------------|            |
1331 //         |       frameType          |            |
1332 //         |--------------------------|            |
1333 //         |       align byte         |            v
1334 //         +--------------------------+-------------
1335 //
1336 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1337 struct OptimizedBuiltinLeaveFrame {
1338 public:
GetFrameFromSpOptimizedBuiltinLeaveFrame1339     static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1340     {
1341         return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1342             MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp));
1343     }
1344 
GetCallSiteSpOptimizedBuiltinLeaveFrame1345     uintptr_t GetCallSiteSp() const
1346     {
1347         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argc);
1348     }
1349 
GetPrevFrameFpOptimizedBuiltinLeaveFrame1350     inline JSTaggedType* GetPrevFrameFp() const
1351     {
1352         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1353     }
1354 
GetReturnAddrOptimizedBuiltinLeaveFrame1355     uintptr_t GetReturnAddr() const
1356     {
1357         return returnAddr;
1358     }
1359 
1360     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1361 
GetTypeOffsetOptimizedBuiltinLeaveFrame1362     static size_t GetTypeOffset()
1363     {
1364         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type);
1365     }
1366 
GetPrevOffsetOptimizedBuiltinLeaveFrame1367     static size_t GetPrevOffset()
1368     {
1369         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp);
1370     }
1371 
GetFunctionOffsetOptimizedBuiltinLeaveFrame1372     static size_t GetFunctionOffset()
1373     {
1374         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argc) + 1;
1375     }
1376 
GetArgvOptimizedBuiltinLeaveFrame1377     const JSTaggedType* GetArgv() const
1378     {
1379         return reinterpret_cast<const JSTaggedType *>(&argc + 1);
1380     }
1381 
GetTypeOptimizedBuiltinLeaveFrame1382     FrameType GetType() const
1383     {
1384         return type;
1385     }
1386 
1387 private:
1388     FrameType type;
1389     uintptr_t callsiteFp; // thread sp set here
1390     uintptr_t returnAddr;
1391     JSTaggedValue thread;
1392     uint64_t argc;
1393     // argv[0]...argv[argc-1] dynamic according to agc
1394 };
1395 
1396 // * BuiltinFrame layout as the following:
1397 //               +--------------------------+
1398 //               |     argV[N - 1]          |
1399 //               |--------------------------|
1400 //               |       . . . .            |
1401 //               |--------------------------+
1402 //               |     argV[2]=this         |
1403 //               +--------------------------+
1404 //               |     argV[1]=new-target   |
1405 //               +--------------------------+
1406 //               |     argV[0]=call-target  |
1407 //               +--------------------------+ ---------
1408 //               |       argc               |         ^
1409 //               |--------------------------|         |
1410 //               |       thread             |         |
1411 //               |--------------------------|         |
1412 //               |       returnAddr         |     BuiltinFrame
1413 //               |--------------------------|         |
1414 //               |       callsiteFp         |         |
1415 //               |--------------------------|         |
1416 //               |       frameType          |         v
1417 //               +--------------------------+ ---------
1418 //
1419 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1420 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1421                                                  base::AlignedSize,
1422                                                  base::AlignedPointer,
1423                                                  base::AlignedPointer,
1424                                                  base::AlignedPointer,
1425                                                  base::AlignedPointer,
1426                                                  base::AlignedPointer> {
1427     enum class Index : size_t {
1428         TypeIndex = 0,
1429         PrevFpIndex,
1430         ReturnAddrIndex,
1431         ThreadIndex,
1432         NumArgsIndex,
1433         StackArgsIndex,
1434         NumOfMembers
1435     };
1436     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1437 
GetFrameFromSpBuiltinFrame1438     static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
1439     {
1440         return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) -
1441             MEMBER_OFFSET(BuiltinFrame, prevFp));
1442     }
1443 
GetPrevFrameFpBuiltinFrame1444     inline JSTaggedType* GetPrevFrameFp()
1445     {
1446         return prevFp;
1447     }
1448 
GetCallSiteSpBuiltinFrame1449     uintptr_t GetCallSiteSp() const
1450     {
1451         return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread);
1452     }
1453 
GetPreFpOffsetBuiltinFrame1454     static size_t GetPreFpOffset(bool isArch32)
1455     {
1456         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1457     }
1458 
GetNumArgsToFpDeltaBuiltinFrame1459     static size_t GetNumArgsToFpDelta(bool isArch32)
1460     {
1461         auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32);
1462         return offset - GetPreFpOffset(isArch32);
1463     }
1464 
GetStackArgsToFpDeltaBuiltinFrame1465     static size_t GetStackArgsToFpDelta(bool isArch32)
1466     {
1467         auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
1468         return offset - GetPreFpOffset(isArch32);
1469     }
1470 
GetStackArgsAddressBuiltinFrame1471     uintptr_t GetStackArgsAddress()
1472     {
1473         return reinterpret_cast<uintptr_t>(&stackArgs);
1474     }
1475 
GetFunctionBuiltinFrame1476     JSTaggedValue GetFunction()
1477     {
1478         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1479         return JSTaggedValue(*functionAddress);
1480     }
1481 
GetNumArgsBuiltinFrame1482     uint32_t GetNumArgs()
1483     {
1484         return numArgs;
1485     }
1486 
GetReturnAddrBuiltinFrame1487     uintptr_t GetReturnAddr() const
1488     {
1489         return returnAddr;
1490     }
1491 
1492     static size_t GetStackArgsOffset(bool isArch32 = false)
1493     {
1494         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
1495     }
1496 
1497     static size_t GetTypeOffset(bool isArch32 = false)
1498     {
1499         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
1500     }
1501 
1502     static size_t GetPrevOffset(bool isArch32 = false)
1503     {
1504         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1505     }
1506 
1507     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1508 
1509     alignas(EAS) FrameType type;
1510     alignas(EAS) JSTaggedType *prevFp;
1511     alignas(EAS) uintptr_t returnAddr;
1512     alignas(EAS) uintptr_t thread;
1513     alignas(EAS) uint32_t numArgs;
1514     alignas(EAS) uintptr_t stackArgs;
1515 };
1516 
1517 // * BuiltinWithArgvFrame layout as the following:
1518 //               +--------------------------+ ---------
1519 //               |       . . . . .          |         ^
1520 //               |--------------------------|         |
1521 //               |       returnAddr         |         |
1522 //               |--------------------------|         |
1523 //               |       callsiteFp         |   BuiltinWithArgvFrame
1524 //               |--------------------------|         |
1525 //               |       frameType          |         |
1526 //               +--------------------------+         |
1527 //               |        argc              |         v
1528 //               +--------------------------+ ---------
1529 //               |        argV[0]           |
1530 //               +--------------------------+
1531 //               |        argV[1]           |
1532 //               +--------------------------+
1533 //               |        . . . .           |
1534 //               +--------------------------+
1535 //
1536 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1537 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1538                                                          base::AlignedSize,
1539                                                          base::AlignedPointer,
1540                                                          base::AlignedPointer> {
1541     enum class Index : int {
1542         StackArgsTopIndex = -1,
1543         NumArgsIndex = -1,
1544         TypeIndex = 0,
1545         PrevFpIndex,
1546         ReturnAddrIndex,
1547         NumOfMembers
1548     };
1549     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1550 
GetFrameFromSpBuiltinWithArgvFrame1551     static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp)
1552     {
1553         return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) -
1554             MEMBER_OFFSET(BuiltinFrame, prevFp));
1555     }
1556 
GetPrevFrameFpBuiltinWithArgvFrame1557     inline JSTaggedType* GetPrevFrameFp()
1558     {
1559         return prevFp;
1560     }
1561 
GetCallSiteSpBuiltinWithArgvFrame1562     uintptr_t GetCallSiteSp() const
1563     {
1564         return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame);
1565     }
1566 
GetStackArgsAddressBuiltinWithArgvFrame1567     uintptr_t GetStackArgsAddress()
1568     {
1569         auto topAddress = ToUintPtr(this) +
1570             (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t));
1571         auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS;
1572         return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t);
1573     }
1574 
GetFunctionBuiltinWithArgvFrame1575     JSTaggedValue GetFunction()
1576     {
1577         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1578         return JSTaggedValue(*functionAddress);
1579     }
1580 
GetNumArgsBuiltinWithArgvFrame1581     int32_t GetNumArgs()
1582     {
1583         auto argcAddress = reinterpret_cast<int32_t *>(
1584             ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t)));
1585         return *argcAddress;
1586     }
1587 
GetReturnAddrBuiltinWithArgvFrame1588     uintptr_t GetReturnAddr() const
1589     {
1590         return returnAddr;
1591     }
1592 
1593     static size_t GetTypeOffset(bool isArch32 = false)
1594     {
1595         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
1596     }
1597 
1598     static size_t GetPrevOffset(bool isArch32 = false)
1599     {
1600         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1601     }
1602 
1603     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1604     // argv(... this, new.target, function)
1605     // numargs
1606     alignas(EAS) FrameType type;
1607     alignas(EAS) JSTaggedType *prevFp;
1608     alignas(EAS) uintptr_t returnAddr;
1609 };
1610 
1611 enum class GCVisitedFlag : bool {
1612     VISITED = true,
1613     IGNORED = false,
1614     HYBRID_STACK = true,
1615 };
1616 
1617 class FrameIterator {
1618 public:
1619     using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
1620     explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr);
GetFrameType()1621     FrameType GetFrameType() const
1622     {
1623         ASSERT(current_ != nullptr);
1624         FrameType *typeAddr = reinterpret_cast<FrameType *>(
1625             reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType));
1626         return *typeAddr;
1627     }
1628 
1629     template<class T>
GetFrame()1630     T* GetFrame()
1631     {
1632         return T::GetFrameFromSp(current_);
1633     }
1634 
1635     template<class T>
GetFrame()1636     const T* GetFrame() const
1637     {
1638         return T::GetFrameFromSp(current_);
1639     }
1640 
Done()1641     bool Done() const
1642     {
1643         return current_ == nullptr;
1644     }
GetSp()1645     JSTaggedType *GetSp() const
1646     {
1647         return current_;
1648     }
GetSp()1649     JSTaggedType *GetSp()
1650     {
1651         return current_;
1652     }
GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)1653     void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const
1654     {
1655         ret = calleeRegInfo_;
1656     }
1657     int ComputeDelta() const;
1658     template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED>
1659     void Advance();
1660     std::map<uint32_t, uint32_t> GetInlinedMethodInfo();
1661     uint32_t GetBytecodeOffset() const;
1662     uintptr_t GetPrevFrameCallSiteSp() const;
1663     uintptr_t GetPrevFrame() const;
GetCallSiteSp()1664     uintptr_t GetCallSiteSp() const
1665     {
1666         return optimizedCallSiteSp_;
1667     }
GetOptimizedReturnAddr()1668     uintptr_t GetOptimizedReturnAddr() const
1669     {
1670         return optimizedReturnAddr_;
1671     }
GetThread()1672     const JSThread *GetThread() const
1673     {
1674         return thread_;
1675     }
1676     bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const;
1677     void CollectPcOffsetInfo(ConstInfo &info) const;
1678     void CollectMethodOffsetInfo(std::map<uint32_t, uint32_t> &info) const;
1679     void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const;
1680     std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const;
1681     int GetCallSiteDelta(uintptr_t retAddr) const;
1682 
1683     Method *CheckAndGetMethod() const;
1684     JSTaggedValue GetFunction() const;
1685 
IsLeaveFrame()1686     bool IsLeaveFrame() const
1687     {
1688         FrameType type = GetFrameType();
1689         return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV);
1690     }
1691 
IsOptimizedFrame()1692     bool IsOptimizedFrame() const
1693     {
1694         FrameType type = GetFrameType();
1695         return (type == FrameType::OPTIMIZED_FRAME);
1696     }
1697 
IsInterpretedFrame(FrameType type)1698     bool IsInterpretedFrame(FrameType type) const
1699     {
1700         return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST);
1701     }
1702 
IsJSFrame()1703     bool IsJSFrame() const
1704     {
1705         FrameType type = GetFrameType();
1706         return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type);
1707     }
1708 
IsOptimizedJSFunctionFrame(FrameType type)1709     bool IsOptimizedJSFunctionFrame(FrameType type) const
1710     {
1711         return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME ||
1712             type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME;
1713     }
1714 
IsOptimizedJSFunctionFrame()1715     bool IsOptimizedJSFunctionFrame() const
1716     {
1717         FrameType type = GetFrameType();
1718         return IsOptimizedJSFunctionFrame(type);
1719     }
1720 
1721 private:
1722     JSTaggedType *current_ {nullptr};
1723     const JSThread *thread_ {nullptr};
1724     const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr};
1725     uintptr_t optimizedCallSiteSp_ {0};
1726     uintptr_t optimizedReturnAddr_ {0};
1727     uint8_t *stackMapAddr_ {nullptr};
1728     int fpDeltaPrevFrameSp_ {0};
1729     kungfu::CalleeRegAndOffsetVec calleeRegInfo_;
1730 };
1731 }  // namespace panda::ecmascript
1732 #endif // ECMASCRIPT_FRAMES_H
1733