• 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/llvm_stackmap_type.h"
25 
26 namespace panda::ecmascript {
27 class JSThread;
28 class EcmaVM;
29 class FrameIterator;
30 namespace kungfu {
31     class ArkStackMapParser;
32 };
33 
34 static constexpr int64_t BASELINEJIT_PC_FLAG = static_cast<int64_t>(std::numeric_limits<uint64_t>::max());
35 
36 // Here list all scenarios of calling between Runtime/CInterpreter/ASMInterpreter/AOTCompiler/CBuiltin/ASMBuitlin.
37 // Please note that the "[]" means a must frame while "<>" means an optional frame. Each case is from top to down.
38 //
39 // * Runtime (C++) => CInterpreter:
40 //          1) [INTERPRETER_FRAME]
41 //
42 // * Runtime (C++) -> AOTCompiler:
43 //          1) [OPTIMIZED_ENTRY_FRAME]
44 //             <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME>
45 //             <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME>
46 //             [OPTIMIZED_JS_FUNCTION_FRAME]
47 //
48 // * Runtime (C++) => ASMInterpreter:
49 //          1) [INTERPRETER_ENTRY_FRAME][ASM_INTERPRETER_FRAME]
50 //
51 // * Runtime (C++) => CBuiltin:
52 //          1) [not supported]
53 //
54 // * Runtime (C++) => ASMBuiltin:
55 //          1) [not supported]
56 //
57 // * CInterpreter => CInterpreter:
58 //          1) [INTERPRETER_FRAME]
59 //
60 // * CInterpreter => Runtime (C++):
61 //          1) [INTERPRETER_FAST_NEW_FRAME]
62 //          2) [INTERPRETER_CONSTRUCTOR_FRAME]
63 //
64 // * CInterpreter => AOTCompiler:
65 //          1) [not supported]
66 //
67 // * CInterperter => CBuiltin:
68 //          1) [INTERPRETER_BUILTIN_FRAME]
69 //
70 // * CInterpreter => ASMBuiltin:
71 //          1) [not supported]
72 //
73 // * ASMInterpreter => Runtime (C++):
74 //          1) [LEAVE_FRAME]
75 //          2) [LEAVE_FRAME_WITH_ARGV]
76 //
77 // * ASMInterpreter => AOTCompiler:
78 //          1) [OPTIMIZED_ENTRY_FRAME]
79 //             <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME>
80 //             <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME>
81 //             [OPTIMIZED_JS_FUNCTION_FRAME]
82 //
83 // * ASMInterpreter => ASMInterpreter:
84 //          1) [ASM_INTERPRETER_FRAME]
85 //
86 // * ASMInterpreter => AsmBuiltin:
87 //          1) [BUILTIN_ENTRY_FRAME]
88 //             [BUILTIN_FRAME]
89 //          2) [BUILTIN_ENTRY_FRAME]
90 //             [BUILTIN_FRAME_WITH_ARGV]
91 //
92 // * ASMInterpreter => CBuiltin:
93 //          1) [LEAVE_FRAME]
94 //          2) [LEAVE_FRAME_WITH_ARGV]
95 //
96 // * AOTCompiler => Runtime (C++):
97 //          1) [LEAVE_FRAME]
98 //          2) [LEAVE_FRAME_WITH_ARGV]
99 //
100 // * AOTCompiler => ASMInterpreter:
101 //          1) [ASM_INTERPRETER_BRIDGE_FRAME]
102 //          2) [ASM_INTERPRETER_FRAME]
103 //
104 // * AOTCompiler => CBuiltin:
105 //          1) [LEAVE_FRAME]
106 //          2) [LEAVE_FRAME_WITH_ARGV]
107 //
108 // * AOTCompiler => ASMBuiltin:
109 //          1) [BUILTIN_ENTRY_FRAME]
110 //             [BUILTIN_FRAME]
111 //          2) [BUILTIN_ENTRY_FRAME]
112 //             [BUILTIN_FRAME_WITH_ARGV]
113 
114 
115 enum class FrameType: uintptr_t {
116     OPTIMIZED_FRAME = 0,
117     OPTIMIZED_ENTRY_FRAME,
118     OPTIMIZED_JS_FUNCTION_FRAME,
119     OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME,
120     FASTJIT_FUNCTION_FRAME,
121     FASTJIT_FAST_CALL_FUNCTION_FRAME,
122     ASM_BRIDGE_FRAME,
123     LEAVE_FRAME,
124     LEAVE_FRAME_WITH_ARGV,
125     BUILTIN_CALL_LEAVE_FRAME,
126     INTERPRETER_FRAME,
127     ASM_INTERPRETER_FRAME,
128     INTERPRETER_CONSTRUCTOR_FRAME,
129     BUILTIN_FRAME,
130     BUILTIN_FRAME_WITH_ARGV,
131     BUILTIN_ENTRY_FRAME,
132     INTERPRETER_BUILTIN_FRAME,
133     INTERPRETER_FAST_NEW_FRAME,
134     INTERPRETER_ENTRY_FRAME,
135     ASM_INTERPRETER_ENTRY_FRAME,
136     ASM_INTERPRETER_BRIDGE_FRAME,
137     OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME,
138     OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME,
139     BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME,
140     BASELINE_BUILTIN_FRAME,
141 
142     FRAME_TYPE_FIRST = OPTIMIZED_FRAME,
143     FRAME_TYPE_LAST = OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME,
144     INTERPRETER_FIRST = INTERPRETER_FRAME,
145     INTERPRETER_LAST = INTERPRETER_FAST_NEW_FRAME,
146     BUILTIN_FIRST = BUILTIN_FRAME,
147     BUILTIN_LAST = BUILTIN_ENTRY_FRAME,
148 };
149 
150 enum class JSCallMode : uintptr_t {
151     CALL_ARG0 = 0,
152     CALL_ARG1,
153     CALL_ARG2,
154     CALL_ARG3,
155     CALL_THIS_ARG0,
156     CALL_THIS_ARG1,
157     CALL_THIS_ARG2,
158     CALL_THIS_ARG3,
159     CALL_WITH_ARGV,
160     CALL_THIS_WITH_ARGV,
161     CALL_CONSTRUCTOR_WITH_ARGV,
162     SUPER_CALL_WITH_ARGV,
163     SUPER_CALL_SPREAD_WITH_ARGV,
164     DEPRECATED_CALL_ARG0,
165     DEPRECATED_CALL_ARG1,
166     DEPRECATED_CALL_ARG2,
167     DEPRECATED_CALL_ARG3,
168     DEPRECATED_CALL_WITH_ARGV,
169     DEPRECATED_CALL_THIS_WITH_ARGV,
170     DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV,
171     CALL_GETTER,
172     CALL_SETTER,
173     CALL_THIS_ARG2_WITH_RETURN,
174     CALL_THIS_ARG3_WITH_RETURN,
175     CALL_THIS_ARGV_WITH_RETURN,
176     CALL_ENTRY,
177     CALL_GENERATOR,
178     CALL_FROM_AOT,
179 };
180 
181 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
182 struct OptimizedFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
183                                                    base::AlignedPointer,
184                                                    base::AlignedPointer,
185                                                    base::AlignedPointer> {
186 public:
187     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
188         const RootBaseAndDerivedVisitor &derivedVisitor) const;
189 
190     static size_t GetTypeOffset(bool isArch32 = false)
191     {
192         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
193     }
194 
195     static size_t GetPrevOffset(bool isArch32 = false)
196     {
197         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
198     }
199 
ComputeReservedSizeOptimizedFrame200     static size_t ComputeReservedSize(size_t slotSize)
201     {
202         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex);
203         return slotSize * slotOffset;
204     }
205 
GetTypeOptimizedFrame206     FrameType GetType() const
207     {
208         return type;
209     }
210 
211 private:
212     enum class Index : size_t {
213         TypeIndex = 0,
214         PrevFpIndex,
215         ReturnAddrIndex,
216         NumOfMembers
217     };
218     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
219 
GetFrameFromSpOptimizedFrame220     static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp)
221     {
222         return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp) -
223             MEMBER_OFFSET(OptimizedFrame, prevFp));
224     }
GetPrevFrameFpOptimizedFrame225     inline JSTaggedType* GetPrevFrameFp()
226     {
227         return prevFp;
228     }
GetReturnAddrOptimizedFrame229     uintptr_t GetReturnAddr() const
230     {
231         return returnAddr;
232     }
233 
234     alignas(EAS) FrameType type {0};
235     alignas(EAS) JSTaggedType *prevFp {nullptr};
236     alignas(EAS) uintptr_t returnAddr {0};
237     friend class FrameIterator;
238 };
239 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64);
240 
241 // * BaselineBuiltinFrame layout as the following:
242 //               +--------------------------+ ---------
243 //               |       . . . . .          |         ^
244 // callerSP ---> |--------------------------|         |
245 //               |       returnAddr         |         |
246 //               |--------------------------|   BuiltinBuiltinFrame
247 //               |       callsiteFp         |         |
248 //       fp ---> |--------------------------|         |
249 //               |       frameType          |         v
250 //               +--------------------------+ ---------
251 //               |        . . . .           |
252 // calleeSP ---> +--------------------------+
253 //
254 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
255 struct BaselineBuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
256                                                          base::AlignedPointer,
257                                                          base::AlignedPointer,
258                                                          base::AlignedPointer> {
259 public:
260     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
261         const RootBaseAndDerivedVisitor &derivedVisitor) const;
262 
263     static size_t GetTypeOffset(bool isArch32 = false)
264     {
265         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
266     }
267 
268     static size_t GetPrevOffset(bool isArch32 = false)
269     {
270         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
271     }
272 
ComputeReservedSizeBaselineBuiltinFrame273     static size_t ComputeReservedSize(size_t slotSize)
274     {
275         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex);
276         return slotSize * slotOffset;
277     }
278 
GetTypeBaselineBuiltinFrame279     FrameType GetType() const
280     {
281         return type;
282     }
283 
GetReturnAddrBaselineBuiltinFrame284     uintptr_t GetReturnAddr() const
285     {
286         return returnAddr;
287     }
288 
289 private:
290     enum class Index : size_t {
291         TypeIndex = 0,
292         PrevFpIndex,
293         ReturnAddrIndex,
294         NumOfMembers
295     };
296     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
297 
GetFrameFromSpBaselineBuiltinFrame298     static BaselineBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
299     {
300         return reinterpret_cast<BaselineBuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) -
301             MEMBER_OFFSET(BaselineBuiltinFrame, prevFp));
302     }
GetPrevFrameFpBaselineBuiltinFrame303     inline JSTaggedType* GetPrevFrameFp()
304     {
305         return prevFp;
306     }
307 
308     alignas(EAS) FrameType type {0};
309     alignas(EAS) JSTaggedType *prevFp {nullptr};
310     alignas(EAS) uintptr_t returnAddr {0};
311     friend class FrameIterator;
312 };
313 STATIC_ASSERT_EQ_ARCH(sizeof(BaselineBuiltinFrame), BaselineBuiltinFrame::SizeArch32, BaselineBuiltinFrame::SizeArch64);
314 
315 struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
316                                                    base::AlignedPointer,
317                                                    base::AlignedPointer,
318                                                    base::AlignedPointer> {
319 public:
320     static size_t GetTypeOffset(bool isArch32 = false)
321     {
322         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
323     }
324 
325     static size_t GetPrevOffset(bool isArch32 = false)
326     {
327         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
328     }
329 
GetCallSiteSpAsmBridgeFrame330     uintptr_t GetCallSiteSp() const
331     {
332         return ToUintPtr(this) + sizeof(AsmBridgeFrame);
333     }
334 
GetTypeAsmBridgeFrame335     FrameType GetType() const
336     {
337         return type;
338     }
339 
340 private:
341     enum class Index : size_t {
342         TypeIndex = 0,
343         PrevFpIndex,
344         ReturnAddrIndex,
345         NumOfMembers
346     };
347     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
348 
GetFrameFromSpAsmBridgeFrame349     static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
350     {
351         return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
352             MEMBER_OFFSET(AsmBridgeFrame, prevFp));
353     }
GetPrevFrameFpAsmBridgeFrame354     inline JSTaggedType* GetPrevFrameFp()
355     {
356         return prevFp;
357     }
GetReturnAddrAsmBridgeFrame358     uintptr_t GetReturnAddr() const
359     {
360         return returnAddr;
361     }
362     alignas(EAS) FrameType type {0};
363     alignas(EAS) JSTaggedType *prevFp {nullptr};
364     alignas(EAS) uintptr_t returnAddr {0};
365     friend class FrameIterator;
366 };
367 STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64);
368 
369 // * OptimizedUnfoldArgVFrame layout description as the following:
370 // callerSP ---> |--------------------------| ---------------
371 //               |       returnAddr         |               ^
372 //               |--------------------------|               |
373 //               |       prevFp             |               |
374 //       fp ---> |--------------------------|   OptimizedUnfoldArgVFrame
375 //               |       frameType          |               |
376 //               |--------------------------|               |
377 //               |       currentFp          |               v
378 // calleESP ---> +--------------------------+ ---------------
379 //
380 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
381 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
382                                                                        base::AlignedPointer,
383                                                                        base::AlignedPointer,
384                                                                        base::AlignedPointer,
385                                                                        base::AlignedPointer> {
386 public:
387     static size_t GetTypeOffset(bool isArch32 = false)
388     {
389         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
390     }
391 
392     static size_t GetPrevOffset(bool isArch32 = false)
393     {
394         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
395     }
396 
GetTypeOptimizedJSFunctionUnfoldArgVFrame397     FrameType GetType() const
398     {
399         return type;
400     }
401 
402 private:
403     enum class Index : size_t {
404         CallSiteSpIndex = 0,
405         TypeIndex,
406         PrevFpIndex,
407         ReturnAddrIndex,
408         NumOfMembers
409     };
410     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
411 
GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame412     static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp)
413     {
414         return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp) -
415             MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp));
416     }
GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame417     inline JSTaggedType* GetPrevFrameFp() const
418     {
419         return prevFp;
420     }
GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame421     uintptr_t GetReturnAddr() const
422     {
423         return returnAddr;
424     }
GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame425     uintptr_t GetPrevFrameSp() const
426     {
427         return callSiteSp;
428     }
429     alignas(EAS) uintptr_t callSiteSp {0};
430     alignas(EAS) FrameType type {0};
431     alignas(EAS) JSTaggedType *prevFp {nullptr};
432     alignas(EAS) uintptr_t returnAddr {0};
433     friend class FrameIterator;
434 };
435 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame),
436     OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64);
437 
438 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following:
439 //          +--------------------------+
440 //          |         arg[N-1]         |
441 //          +--------------------------+
442 //          |         . . . .          |
443 //          +--------------------------+
444 //          |         arg[0]           |
445 //          +--------------------------+
446 //          |         argC             |
447 //  sp ---> +--------------------------+ -----------------
448 //          |                          |                 ^
449 //          |        prevFP            |                 |
450 //  fp ---> |--------------------------|    OptimizedJSFunctionArgsConfigFrame
451 //          |       frameType          |                 |
452 //          |                          |                 V
453 //          +--------------------------+ -----------------
454 //
455 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
456 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
457                                                                       base::AlignedPointer,
458                                                                       base::AlignedPointer> {
459 public:
460     static size_t GetTypeOffset(bool isArch32 = false)
461     {
462         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
463     }
464 
465     static size_t GetPrevOffset(bool isArch32 = false)
466     {
467         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
468     }
469 
GetTypeOptimizedJSFunctionArgConfigFrame470     FrameType GetType() const
471     {
472         return type;
473     }
474 
475 private:
476     enum class Index : size_t {
477         TypeIndex = 0,
478         PrevFpIndex,
479         NumOfMembers
480     };
481     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
482 
GetFrameFromSpOptimizedJSFunctionArgConfigFrame483     static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp)
484     {
485         return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp) -
486             MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp));
487     }
GetPrevFrameFpOptimizedJSFunctionArgConfigFrame488     inline JSTaggedType* GetPrevFrameFp()
489     {
490         return prevFp;
491     }
492 
493     alignas(EAS) FrameType type {0};
494     alignas(EAS) JSTaggedType *prevFp {nullptr};
495     friend class FrameIterator;
496 };
497 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame),
498                       OptimizedJSFunctionArgConfigFrame::SizeArch32,
499                       OptimizedJSFunctionArgConfigFrame::SizeArch64);
500 
501 // * OptimizedJSFunctionFrame layout description as the following:
502 //                 +----------------------------------------+
503 //                 |     arg[N-1]                           |
504 //                 +----------------------------------------+
505 //                 |     ...                                |
506 //                 +----------------------------------------+
507 //                 |     arg[1]                             |
508 //                 +----------------------------------------+
509 //                 |     arg[0]                             |
510 //                 +----------------------------------------+
511 //                 |     this                               |
512 //                 +----------------------------------------+
513 //                 |     new-target [not exist in fastcall] |
514 //                 +----------------------------------------+
515 //                 |     call-target                        |
516 //       argv ---> +----------------------------------------+
517 //                 |     argv   [not exist in fastcall]     |
518 //                 |----------------------------------------|
519 //                 |     argc   [not exist in fastcall]     |
520 //   callerSp ---> |----------------------------------------|----------------
521 //                 |     returnAddr                         |               ^
522 //                 |----------------------------------------|               |
523 //                 |     callsiteFp                         |               |
524 //         fp ---> |----------------------------------------|   OptimizedJSFunctionFrame
525 //                 |     frameType                          |               |
526 //                 |----------------------------------------|               |
527 //                 |     call-target                        |               v
528 //   calleeSP ---> +----------------------------------------+----------------
529 //
530 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
531 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
532                                                              JSTaggedValue,
533                                                              base::AlignedPointer,
534                                                              base::AlignedPointer,
535                                                              base::AlignedPointer> {
536 public:
537     using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
538     enum class Index : size_t {
539         JSFuncIndex = 0,
540         TypeIndex,
541         PrevFpIndex,
542         ReturnAddrIndex,
543         NumOfMembers
544     };
545     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
546 
GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame547     static constexpr size_t GetFunctionDeltaReturnAddr()
548     {
549         return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex);
550     }
551 
GetPrevFrameFpOptimizedJSFunctionFrame552     inline JSTaggedType* GetPrevFrameFp()
553     {
554         return prevFp;
555     }
556 
GetArgvOptimizedJSFunctionFrame557     JSTaggedType* GetArgv(uintptr_t *preFrameSp) const
558     {
559         const size_t offset = 2;    // 2: skip argc and argv.
560         return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t));
561     }
562 
GetArgcOptimizedJSFunctionFrame563     size_t GetArgc(uintptr_t *preFrameSp) const
564     {
565         return *preFrameSp;
566     }
567 
568     JSTaggedType* GetArgv(const FrameIterator &it) const;
569 
GetReturnAddrOptimizedJSFunctionFrame570     uintptr_t GetReturnAddr() const
571     {
572         return returnAddr;
573     }
574 
575     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
576         const RootBaseAndDerivedVisitor &derivedVisitor, FrameType frameType) const;
577     void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const;
578 
GetFunctionOptimizedJSFunctionFrame579     inline JSTaggedValue GetFunction() const
580     {
581         return jsFunc;
582     }
583 
ComputeArgsConfigFrameSpOptimizedJSFunctionFrame584     static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp)
585     {
586         const size_t offset = 2;  // 2: skip prevFp and return address.
587         return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t);
588     }
589 
590     static size_t GetTypeOffset(bool isArch32 = false)
591     {
592         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
593     }
594 
595     static size_t GetPrevOffset(bool isArch32 = false)
596     {
597         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
598     }
599 
600     static size_t GetFunctionOffset(bool isArch32 = false)
601     {
602         return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32);
603     }
604 
605     static size_t GetReturnAddrOffset(bool isArch32 = false)
606     {
607         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
608     }
609 
ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame610     static size_t ComputeReservedJSFuncOffset(size_t slotSize)
611     {
612         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex);
613         return slotSize * slotOffset;
614     }
615 
GetTypeOptimizedJSFunctionFrame616     FrameType GetType() const
617     {
618         return type;
619     }
620 
621     friend class FrameIterator;
622     friend class FrameHandler;
623     void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const;
624     void GetFuncCalleeRegAndOffset(
625         const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const;
626     uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const;
627 
628 private:
GetFrameFromSpOptimizedJSFunctionFrame629     static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp)
630     {
631         return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) -
632             MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp));
633     }
634 
635     // dynamic callee saveregisters for x86-64
636     alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()};
637     alignas(EAS) FrameType type {0};
638     alignas(EAS) JSTaggedType *prevFp {nullptr};
639     alignas(EAS) uintptr_t returnAddr {0};
640     // dynamic callee saveregisters for arm64
641 };
642 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame),
643                       OptimizedJSFunctionFrame::SizeArch32,
644                       OptimizedJSFunctionFrame::SizeArch64);
645 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time.
646 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1);
647 
648 // * The JSFunctionEntry Frame's structure is illustrated as the following:
649 //              +--------------------------+
650 //              |      . . . . . .         |
651 // callerSP --> +--------------------------+ -----------------
652 //              |        prevFP            |                 ^
653 //       fp --> |--------------------------|                 |
654 //              |       frameType          |      JSFunctionEntryFrame
655 //              |--------------------------|                 |
656 //              |    preLeaveFrameFp       |                 v
657 // calleeSP --> +--------------------------+ -----------------
658 
659 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
660                                                         base::AlignedPointer,
661                                                         base::AlignedPointer,
662                                                         base::AlignedPointer> {
663 public:
664     enum class CallType : size_t {
665         CALL_FUNC = 0,
666         CALL_NEW,
667     };
668 
669     enum class Index : size_t {
670         PreLeaveFrameFpIndex = 0,
671         TypeIndex,
672         PrevFpIndex,
673         NumOfMembers
674     };
675 
676     static size_t GetTypeOffset(bool isArch32 = false)
677     {
678         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
679     }
680 
681     static size_t GetLeaveFrameFpOffset(bool isArch32 = false)
682     {
683         return GetOffset<static_cast<size_t>(Index::PreLeaveFrameFpIndex)>(isArch32);
684     }
685 
GetPrevFrameFpOptimizedEntryFrame686     inline JSTaggedType* GetPrevFrameFp()
687     {
688         return preLeaveFrameFp;
689     }
690 
ComputeReservedSizeOptimizedEntryFrame691     static size_t ComputeReservedSize(size_t slotSize)
692     {
693         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex);
694         return slotSize * slotOffset;
695     }
696 
GetTypeOptimizedEntryFrame697     FrameType GetType() const
698     {
699         return type;
700     }
701     friend class FrameIterator;
702 
703 private:
GetFrameFromSpOptimizedEntryFrame704     static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
705     {
706         return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) -
707                                                        MEMBER_OFFSET(OptimizedEntryFrame, prevFp));
708     }
709 
GetLeaveFpOptimizedEntryFrame710     JSTaggedType* GetLeaveFp() const
711     {
712         return preLeaveFrameFp;
713     }
714 
GetPrevFpOptimizedEntryFrame715     JSTaggedType* GetPrevFp() const
716     {
717         return prevFp;
718     }
719 
720     alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr};
721     alignas(EAS) FrameType type {0};
722     alignas(EAS) JSTaggedType *prevFp {nullptr};
723 };
724 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64);
725 
726 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
727 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(),
728                                                          base::AlignedPointer,
729                                                          base::AlignedSize> {
730     enum class Index : size_t {
731         PrevIndex = 0,
732         TypeIndex,
733         NumOfMembers
734     };
735     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
736 
GetPrevFrameFpInterpretedFrameBase737     inline JSTaggedType* GetPrevFrameFp()
738     {
739         return prev;
740     }
741 
GetFrameFromSpInterpretedFrameBase742     static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp)
743     {
744         return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1;
745     }
746 
747     static size_t GetPrevOffset(bool isArch32 = false)
748     {
749         return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32);
750     }
751 
752     static size_t GetTypeOffset(bool isArch32 = false)
753     {
754         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
755     }
756 
GetSizeInterpretedFrameBase757     static constexpr size_t GetSize(bool isArch32)
758     {
759         return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64;
760     }
761 
762     alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc
763     alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0
764 };
765 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase),
766                       InterpretedFrameBase::SizeArch32,
767                       InterpretedFrameBase::SizeArch64);
768 
769 // Interpreter Frame Layout as the following:
770 //   +----------------------------------+
771 //   |    argv[n-1]                     |
772 //   |----------------------------------|
773 //   |    ......                        |
774 //   |----------------------------------|
775 //   |    thisArg [maybe not exist]     |
776 //   |----------------------------------|
777 //   |    newTarget [maybe not exist]   |
778 //   |----------------------------------|
779 //   |    ......                        |
780 //   |----------------------------------|
781 //   |    Vregs [not exist in native]   |
782 //   +----------------------------------+--------+
783 //   |    base.frameType                |        ^
784 //   |----------------------------------|        |
785 //   |    base.prev(prev stack pointer) |        |
786 //   |----------------------------------|        |
787 //   |    pc(bytecode addr)             |        |
788 //   |----------------------------------|        |
789 //   |    sp(current stack pointer)     |        |
790 //   |----------------------------------|        |
791 //   |    env                           |        |
792 //   |----------------------------------|        |
793 //   |    acc                           |        |
794 //   |----------------------------------|   InterpretedFrame
795 //   |    profileTypeInfo               |        |
796 //   |----------------------------------|        |
797 //   |    thisObj                       |        |
798 //   |----------------------------------|        |
799 //   |    function                      |        |
800 //   |----------------------------------|        |
801 //   |    constpool                     |        v
802 //   +----------------------------------+--------+
803 //
804 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
805 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
806                                                      JSTaggedValue,
807                                                      JSTaggedValue,
808                                                      JSTaggedValue,
809                                                      JSTaggedValue,
810                                                      JSTaggedValue,
811                                                      JSTaggedValue,
812                                                      base::AlignedPointer,
813                                                      InterpretedFrameBase> {
814 public:
815     enum class Index : size_t {
816         ConstPoolIndex = 0,
817         FunctionIndex,
818         ThisObjIndex,
819         ProFileTypeInfoIndex,
820         AccIndex,
821         EnvIndex,
822         PcIndex,
823         BaseIndex,
824         NumOfMembers
825     };
826     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
827 
GetPrevFrameFpInterpretedFrame828     inline JSTaggedType* GetPrevFrameFp() const
829     {
830         return base.prev;
831     }
832 
GetFrameFromSpInterpretedFrame833     static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
834     {
835         return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
836     }
837 
GetPcInterpretedFrame838     inline const uint8_t *GetPc() const
839     {
840         return pc;
841     }
842 
GetEnvInterpretedFrame843     inline JSTaggedValue GetEnv() const
844     {
845         return env;
846     }
847 
NumOfMembersInterpretedFrame848     static uint32_t NumOfMembers()
849     {
850         return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize();
851     }
852 
GetPcOffsetInterpretedFrame853     static size_t GetPcOffset(bool isArch32)
854     {
855         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
856     }
857 
858     static size_t GetTypeOffset(bool isArch32 = false)
859     {
860         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
861             InterpretedFrameBase::GetTypeOffset(isArch32);
862     }
863 
864     static size_t GetPrevOffset(bool isArch32 = false)
865     {
866         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
867             InterpretedFrameBase::GetPrevOffset(isArch32);
868     }
869 
870     static size_t GetFunctionOffset(bool isArch32 = false)
871     {
872         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
873     }
874 
875     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
876 
877     alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()};
878     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
879     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
880     alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()};
881     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
882     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
883     alignas(EAS) const uint8_t *pc {nullptr};
884     alignas(EAS) InterpretedFrameBase base;
885     friend class FrameIterator;
886 };
887 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64);
888 
889 // * InterpretedBuiltinFrame layout description as the following:
890 //               |--------------------------| ---------------
891 //               |         . . . . .        |               ^
892 //               |    InterpretedFrameBase  |               |
893 //               |         . . . . .        |               |
894 //               |--------------------------|    InterpretedBuiltinFrame
895 //               |       bytecode-PC        |               |
896 //               |--------------------------|               |
897 //               |       call-target        |               v
898 //               +--------------------------+ ---------------
899 //
900 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
901 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
902                                                             JSTaggedValue,
903                                                             base::AlignedPointer,
904                                                             InterpretedFrameBase> {
905     enum class Index : size_t {
906         FunctionIndex = 0,
907         PcIndex,
908         BaseIndex,
909         NumOfMembers
910     };
911     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
912 
GetPrevFrameFpInterpretedBuiltinFrame913     inline JSTaggedType* GetPrevFrameFp()
914     {
915         return base.prev;
916     }
917 
GetFrameFromSpInterpretedBuiltinFrame918     static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
919     {
920         return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
921     }
922 
NumOfMembersInterpretedBuiltinFrame923     static uint32_t NumOfMembers()
924     {
925         return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize();
926     }
927 
928     static size_t GetTypeOffset(bool isArch32 = false)
929     {
930         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
931             InterpretedFrameBase::GetTypeOffset(isArch32);
932     }
933 
934     static size_t GetPrevOffset(bool isArch32 = false)
935     {
936         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
937             InterpretedFrameBase::GetPrevOffset(isArch32);
938     }
939 
940     static size_t GetFunctionOffset(bool isArch32 = false)
941     {
942         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
943     }
944 
945     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
946 
947     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
948     alignas(EAS) const uint8_t *pc {nullptr};
949     alignas(EAS) InterpretedFrameBase base;
950 };
951 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame),
952                       InterpretedBuiltinFrame::SizeArch32,
953                       InterpretedBuiltinFrame::SizeArch64);
954 
955 // AsmInterpretedFrame Layout as the following:
956 //   +----------------------------------+
957 //   |    argv[n-1]                     |
958 //   |----------------------------------|
959 //   |    ......                        |
960 //   |----------------------------------|
961 //   |    thisArg [maybe not exist]     |
962 //   |----------------------------------|
963 //   |    newTarget [maybe not exist]   |
964 //   |----------------------------------|
965 //   |    ......                        |
966 //   |----------------------------------|
967 //   |    Vregs [not exist in native]   |
968 //   +----------------------------------+--------+
969 //   |        .  .  .   .               |        ^
970 //   |     InterpretedFrameBase         |        |
971 //   |        .  .  .   .               |        |
972 //   |----------------------------------|        |
973 //   |    pc(bytecode addr)             |        |
974 //   |----------------------------------|        |
975 //   |    sp(current stack pointer)     |        |
976 //   |----------------------------------|   AsmInterpretedFrame
977 //   |    callSize                      |        |
978 //   |----------------------------------|        |
979 //   |    env                           |        |
980 //   |----------------------------------|        |
981 //   |    acc                           |        |
982 //   |----------------------------------|        |
983 //   |    thisObj                       |        |
984 //   |----------------------------------|        |
985 //   |    call-target                   |        v
986 //   +----------------------------------+--------+
987 //
988 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
989 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
990                                                         JSTaggedValue,
991                                                         JSTaggedValue,
992                                                         JSTaggedValue,
993                                                         JSTaggedValue,
994                                                         base::AlignedPointer,
995                                                         base::AlignedPointer,
996                                                         base::AlignedPointer,
997                                                         InterpretedFrameBase> {
998     enum class Index : size_t {
999         FunctionIndex = 0,
1000         ThisObjIndex,
1001         AccIndex,
1002         EnvIndex,
1003         CallSizeIndex,
1004         FpIndex,
1005         PcIndex,
1006         BaseIndex,
1007         NumOfMembers
1008     };
1009 
1010     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1011 
GetCurrentFramePointerAsmInterpretedFrame1012     inline JSTaggedType* GetCurrentFramePointer()
1013     {
1014         return fp;
1015     }
1016 
GetPrevFrameFpAsmInterpretedFrame1017     inline JSTaggedType* GetPrevFrameFp()
1018     {
1019         return base.prev;
1020     }
1021 
GetFrameFromSpAsmInterpretedFrame1022     static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
1023     {
1024         return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
1025     }
1026 
GetFpOffsetAsmInterpretedFrame1027     static size_t GetFpOffset(bool isArch32)
1028     {
1029         return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32);
1030     }
1031 
GetCallSizeOffsetAsmInterpretedFrame1032     static size_t GetCallSizeOffset(bool isArch32)
1033     {
1034         return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32);
1035     }
1036 
GetFunctionOffsetAsmInterpretedFrame1037     static size_t GetFunctionOffset(bool isArch32)
1038     {
1039         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
1040     }
1041 
GetThisOffsetAsmInterpretedFrame1042     static size_t GetThisOffset(bool isArch32)
1043     {
1044         return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32);
1045     }
1046 
GetAccOffsetAsmInterpretedFrame1047     static size_t GetAccOffset(bool isArch32)
1048     {
1049         return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32);
1050     }
1051 
GetEnvOffsetAsmInterpretedFrame1052     static size_t GetEnvOffset(bool isArch32)
1053     {
1054         return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32);
1055     }
1056 
GetBaseOffsetAsmInterpretedFrame1057     static size_t GetBaseOffset(bool isArch32)
1058     {
1059         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
1060     }
1061 
GetPcOffsetAsmInterpretedFrame1062     static size_t GetPcOffset(bool isArch32)
1063     {
1064         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
1065     }
1066 
GetSizeAsmInterpretedFrame1067     static constexpr size_t GetSize(bool isArch32)
1068     {
1069         return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64;
1070     }
1071 
GetFpOffsetAsIntptrAsmInterpretedFrame1072     static intptr_t GetFpOffsetAsIntptr(bool isArch32)
1073     {
1074         return static_cast<intptr_t>(GetFpOffset(isArch32));
1075     }
1076 
GetFunctionOffsetAsIntptrAsmInterpretedFrame1077     static intptr_t GetFunctionOffsetAsIntptr(bool isArch32)
1078     {
1079         return static_cast<intptr_t>(GetFunctionOffset(isArch32));
1080     }
1081 
GetSizeAsIntptrAsmInterpretedFrame1082     static intptr_t GetSizeAsIntptr(bool isArch32)
1083     {
1084         return static_cast<intptr_t>(GetSize(isArch32));
1085     }
1086 
NumOfMembersAsmInterpretedFrame1087     static uint32_t NumOfMembers()
1088     {
1089         return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize();
1090     }
1091     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
1092         const RootBaseAndDerivedVisitor &derivedVisitor, bool isBaselineFrame) const;
1093 
GetEnvAsmInterpretedFrame1094     JSTaggedValue GetEnv() const
1095     {
1096         return env;
1097     }
1098 
GetPcAsmInterpretedFrame1099     const uint8_t *GetPc() const
1100     {
1101         return pc;
1102     }
1103 
GetTypeOffsetAsmInterpretedFrame1104     static size_t GetTypeOffset()
1105     {
1106         return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type);
1107     }
1108 
GetPrevOffsetAsmInterpretedFrame1109     static size_t GetPrevOffset()
1110     {
1111         return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev);
1112     }
1113 
1114     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
1115     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
1116     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
1117     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
1118     alignas(EAS) uintptr_t callSize {0};
1119     alignas(EAS) JSTaggedType *fp {nullptr};
1120     alignas(EAS) const uint8_t *pc {nullptr};
1121     alignas(EAS) InterpretedFrameBase base;
1122     // vregs, not exist in native
1123     // args, may be truncated if not extra
1124 };
1125 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64);
1126 
1127 // InterpretedEntryFrame Layout as the following:
1128 //   +----------------------------------+---------------
1129 //   |        .  .  .   .               |              ^
1130 //   |     InterpretedFrameBase         |              |
1131 //   |        .  .  .   .               |    InterpretedEntryFrame
1132 //   |----------------------------------|              |
1133 //   |    pc(bytecode addr)             |              v
1134 //   |----------------------------------|---------------
1135 //
1136 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1137 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1138                                                           base::AlignedPointer,
1139                                                           InterpretedFrameBase> {
1140     enum class Index : size_t {
1141         PcIndex = 0,
1142         BaseIndex,
1143         NumOfMembers
1144     };
1145     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1146 
GetPrevFrameFpInterpretedEntryFrame1147     inline JSTaggedType* GetPrevFrameFp()
1148     {
1149         return base.prev;
1150     }
1151 
GetFrameFromSpInterpretedEntryFrame1152     static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
1153     {
1154         return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
1155     }
1156 
NumOfMembersInterpretedEntryFrame1157     static uint32_t NumOfMembers()
1158     {
1159         return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize();
1160     }
1161 
1162     static size_t GetTypeOffset(bool isArch32 = false)
1163     {
1164         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1165             InterpretedFrameBase::GetTypeOffset(isArch32);
1166     }
1167 
1168     static size_t GetPrevOffset(bool isArch32 = false)
1169     {
1170         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1171             InterpretedFrameBase::GetPrevOffset(isArch32);
1172     }
1173 
1174     void GCIterate(const FrameIterator &it, const RootVisitor &visitor,
1175         const RootRangeVisitor &rangeVisitor) const;
1176     alignas(EAS) const uint8_t *pc {nullptr};
1177     alignas(EAS) InterpretedFrameBase base;
1178 };
1179 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame),
1180                       InterpretedEntryFrame::SizeArch32,
1181                       InterpretedEntryFrame::SizeArch64);
1182 
1183 
1184 // AsmInterpretedEntryFrame Layout as the following:
1185 //   +----------------------------------+---------------
1186 //   |        .  .  .   .               |              ^
1187 //   |     InterpretedFrameBase         |              |
1188 //   |        .  .  .   .               |    AsmInterpretedEntryFrame
1189 //   |----------------------------------|              |
1190 //   |    pc(bytecode addr)             |              v
1191 //   |----------------------------------|---------------
1192 //
1193 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1194 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1195                                                              base::AlignedPointer,
1196                                                              InterpretedFrameBase> {
1197     enum class Index : size_t {
1198         PcIndex = 0,
1199         BaseIndex,
1200         NumOfMembers
1201     };
1202     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1203 
GetPrevFrameFpAsmInterpretedEntryFrame1204     inline JSTaggedType* GetPrevFrameFp()
1205     {
1206         return base.prev;
1207     }
1208 
GetBaseOffsetAsmInterpretedEntryFrame1209     static size_t GetBaseOffset(bool isArch32)
1210     {
1211         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
1212     }
1213 
GetFrameFromSpAsmInterpretedEntryFrame1214     static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
1215     {
1216         return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
1217     }
1218 
1219     static size_t GetTypeOffset(bool isArch32 = false)
1220     {
1221         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1222             InterpretedFrameBase::GetTypeOffset(isArch32);
1223     }
1224 
1225     static size_t GetPrevOffset(bool isArch32 = false)
1226     {
1227         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1228             InterpretedFrameBase::GetPrevOffset(isArch32);
1229     }
1230 
1231     alignas(EAS) const uint8_t *pc {nullptr};
1232     alignas(EAS) InterpretedFrameBase base;
1233 };
1234 
1235 // AsmInterpretedBridgeFrame Layout as the following:
1236 //   +----------------------------------+---------------
1237 //   |      ret-address                 |              ^
1238 //   |----------------------------------|              |
1239 //   |        .  .  .   .               |     AsmInterpretedBridgeFrame
1240 //   |     AsmInterpretedEntryFrame     |              |
1241 //   |        .  .  .   .               |              v
1242 //   |----------------------------------|---------------
1243 //
1244 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1245 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1246                                                               AsmInterpretedEntryFrame,
1247                                                               base::AlignedPointer> {
1248     enum class Index : size_t {
1249         EntryIndex = 0,
1250         ReturnAddrIndex,
1251         NumOfMembers
1252     };
1253     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1254 
GetFrameFromSpAsmInterpretedBridgeFrame1255     static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
1256     {
1257         return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
1258             MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr));
1259     }
GetCallSiteSpAsmInterpretedBridgeFrame1260     uintptr_t GetCallSiteSp() const
1261     {
1262         return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame);
1263     }
GetPrevFrameFpAsmInterpretedBridgeFrame1264     inline JSTaggedType* GetPrevFrameFp()
1265     {
1266         return entry.base.prev;
1267     }
1268 
GetReturnAddrOffsetAsmInterpretedBridgeFrame1269     static size_t GetReturnAddrOffset(bool isArch32)
1270     {
1271         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
1272     }
1273 
GetSizeAsmInterpretedBridgeFrame1274     static constexpr size_t GetSize(bool isArch32)
1275     {
1276         return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64;
1277     }
1278 
1279     static size_t GetTypeOffset(bool isArch32 = false)
1280     {
1281         return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) +
1282             AsmInterpretedEntryFrame::GetBaseOffset(isArch32) +
1283             InterpretedFrameBase::GetTypeOffset(isArch32);
1284     }
1285     static size_t GetPrevOffset(bool isArch32 = false)
1286     {
1287         return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) +
1288             AsmInterpretedEntryFrame::GetBaseOffset(isArch32) +
1289             InterpretedFrameBase::GetPrevOffset(isArch32);
1290     }
1291 
GetReturnAddrAsmInterpretedBridgeFrame1292     uintptr_t GetReturnAddr() const
1293     {
1294         return returnAddr;
1295     }
1296 
1297     AsmInterpretedEntryFrame entry;
1298     alignas(EAS) uintptr_t returnAddr;
1299 };
1300 
1301 // * Optimized-leaved-frame layout as the following:
1302 //               +--------------------------+
1303 //               |       argv[N-1]          |
1304 //               |--------------------------|
1305 //               |       . . . . .          |
1306 //               |--------------------------|
1307 //               |       argv[0]            |
1308 //               +--------------------------+-------------
1309 //               |       argc               |            ^
1310 //               |--------------------------|            |
1311 //               |       RuntimeId          |            |
1312 //  callerSP --> |--------------------------|   OptimizedLeaveFrame
1313 //               |       ret-addr           |            |
1314 //               |--------------------------|            |
1315 //               |       prevFp             |            |
1316 //        fp --> |--------------------------|            |
1317 //               |       frameType          |            v
1318 //  calleeSP --> +--------------------------+-------------
1319 //
1320 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1321 struct OptimizedLeaveFrame {
1322     FrameType type;
1323     uintptr_t callsiteFp; // thread sp set here
1324     uintptr_t returnAddr;
1325     uint64_t argRuntimeId;
1326     uint64_t argc;
1327 
1328     // argv[0]...argv[argc-1] dynamic according to agc
GetFrameFromSpOptimizedLeaveFrame1329     static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1330     {
1331         return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1332             MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp));
1333     }
1334 
GetCallSiteSpOptimizedLeaveFrame1335     uintptr_t GetCallSiteSp() const
1336     {
1337         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId);
1338     }
1339 
GetPrevFrameFpOptimizedLeaveFrame1340     inline JSTaggedType* GetPrevFrameFp() const
1341     {
1342         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1343     }
1344 
GetReturnAddrOptimizedLeaveFrame1345     uintptr_t GetReturnAddr() const
1346     {
1347         return returnAddr;
1348     }
1349 
GetTypeOffsetOptimizedLeaveFrame1350     static size_t GetTypeOffset()
1351     {
1352         return MEMBER_OFFSET(OptimizedLeaveFrame, type);
1353     }
1354 
GetPrevOffsetOptimizedLeaveFrame1355     static size_t GetPrevOffset()
1356     {
1357         return MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp);
1358     }
1359 
1360     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1361 };
1362 
1363 // * Optimized-leaved-frame-with-argv layout as the following:
1364 //               +--------------------------+
1365 //               |       argv[]             |
1366 //               +--------------------------+-------------
1367 //               |       argc               |            ^
1368 //               |--------------------------|            |
1369 //               |       RuntimeId          |   OptimizedWithArgvLeaveFrame
1370 //  callerSP --> |--------------------------|            |
1371 //               |       returnAddr         |            |
1372 //               |--------------------------|            |
1373 //               |       callsiteFp         |            |
1374 //        fp --> |--------------------------|            |
1375 //               |       frameType          |            v
1376 //  calleeSP --> +--------------------------+-------------
1377 
1378 struct OptimizedWithArgvLeaveFrame {
1379     FrameType type;
1380     uintptr_t callsiteFp; // thread sp set here
1381     uintptr_t returnAddr;
1382     uint64_t argRuntimeId;
1383     uint64_t argc;
1384 
GetFrameFromSpOptimizedWithArgvLeaveFrame1385     static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1386     {
1387         return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1388             MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp));
1389     }
1390 
GetCallSiteSpOptimizedWithArgvLeaveFrame1391     uintptr_t GetCallSiteSp() const
1392     {
1393         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId);
1394     }
1395 
GetPrevFrameFpOptimizedWithArgvLeaveFrame1396     inline JSTaggedType* GetPrevFrameFp()
1397     {
1398         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1399     }
1400 
GetReturnAddrOptimizedWithArgvLeaveFrame1401     uintptr_t GetReturnAddr() const
1402     {
1403         return returnAddr;
1404     }
1405 
GetTypeOffsetOptimizedWithArgvLeaveFrame1406     static size_t GetTypeOffset()
1407     {
1408         return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type);
1409     }
1410 
GetPrevOffsetOptimizedWithArgvLeaveFrame1411     static size_t GetPrevOffset()
1412     {
1413         return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp);
1414     }
1415 
1416     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1417 };
1418 
1419 // * OptimizedBuiltinLeaveFrame layout as the following:
1420 //               +--------------------------+
1421 //               |       argv[N-1]          |
1422 //               |--------------------------|
1423 //               |       . . . . .          |
1424 //               |--------------------------|
1425 //               |       argv[0]            |
1426 //               +--------------------------+-------------
1427 //               |       argc               |            ^
1428 //               |--------------------------|            |
1429 //               |       thread             |            |
1430 //  callerSP --> +--------------------------+            |
1431 //               |       ret-addr           |            |
1432 //               |--------------------------|   OptimizedBuiltinLeaveFrame
1433 //               |       prevFp             |            |
1434 //        fp --> |--------------------------|            |
1435 //               |       frameType          |            |
1436 //               |--------------------------|            |
1437 //               |       align byte         |            v
1438 //  calleeSP --> +--------------------------+-------------
1439 //
1440 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1441 struct OptimizedBuiltinLeaveFrame {
1442 public:
GetFrameFromSpOptimizedBuiltinLeaveFrame1443     static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1444     {
1445         return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1446             MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp));
1447     }
1448 
GetCallSiteSpOptimizedBuiltinLeaveFrame1449     uintptr_t GetCallSiteSp() const
1450     {
1451         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, thread);
1452     }
1453 
GetPrevFrameFpOptimizedBuiltinLeaveFrame1454     inline JSTaggedType* GetPrevFrameFp() const
1455     {
1456         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1457     }
1458 
GetReturnAddrOptimizedBuiltinLeaveFrame1459     uintptr_t GetReturnAddr() const
1460     {
1461         return returnAddr;
1462     }
1463 
1464     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1465 
GetTypeOffsetOptimizedBuiltinLeaveFrame1466     static size_t GetTypeOffset()
1467     {
1468         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type);
1469     }
1470 
GetPrevOffsetOptimizedBuiltinLeaveFrame1471     static size_t GetPrevOffset()
1472     {
1473         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp);
1474     }
1475 
GetFunctionOffsetOptimizedBuiltinLeaveFrame1476     static size_t GetFunctionOffset()
1477     {
1478         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argc) + 1;
1479     }
1480 
GetArgvOptimizedBuiltinLeaveFrame1481     const JSTaggedType* GetArgv() const
1482     {
1483         return reinterpret_cast<const JSTaggedType *>(&argc + 1);
1484     }
1485 
GetTypeOptimizedBuiltinLeaveFrame1486     FrameType GetType() const
1487     {
1488         return type;
1489     }
1490 
1491 private:
1492     FrameType type;
1493     uintptr_t callsiteFp; // thread sp set here
1494     uintptr_t returnAddr;
1495     JSTaggedValue thread;
1496     uint64_t argc;
1497     // argv[0]...argv[argc-1] dynamic according to agc
1498 };
1499 
1500 // * BuiltinFrame layout as the following:
1501 //               +--------------------------+
1502 //               |     argV[N - 1]          |
1503 //               |--------------------------|
1504 //               |       . . . .            |
1505 //               |--------------------------+
1506 //               |     argV[2]=this         |
1507 //               +--------------------------+
1508 //               |     argV[1]=new-target   |
1509 //               +--------------------------+
1510 //               |     argV[0]=call-target  |
1511 //               +--------------------------+ ---------
1512 //               |       argc               |         ^
1513 //               |--------------------------|         |
1514 //               |       thread             |         |
1515 //  callerSP --> |--------------------------|         |
1516 //               |       returnAddr         |     BuiltinFrame
1517 //               |--------------------------|         |
1518 //               |       callsiteFp         |         |
1519 //        fp --> |--------------------------|         |
1520 //               |       frameType          |         v
1521 //  calleeSP --> +--------------------------+ ---------
1522 //
1523 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1524 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1525                                                  base::AlignedSize,
1526                                                  base::AlignedPointer,
1527                                                  base::AlignedPointer,
1528                                                  base::AlignedPointer,
1529                                                  base::AlignedPointer,
1530                                                  base::AlignedPointer> {
1531     enum class Index : size_t {
1532         TypeIndex = 0,
1533         PrevFpIndex,
1534         ReturnAddrIndex,
1535         ThreadIndex,
1536         NumArgsIndex,
1537         StackArgsIndex,
1538         NumOfMembers
1539     };
1540     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1541 
GetFrameFromSpBuiltinFrame1542     static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
1543     {
1544         return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) -
1545             MEMBER_OFFSET(BuiltinFrame, prevFp));
1546     }
1547 
GetPrevFrameFpBuiltinFrame1548     inline JSTaggedType* GetPrevFrameFp()
1549     {
1550         return prevFp;
1551     }
1552 
GetCallSiteSpBuiltinFrame1553     uintptr_t GetCallSiteSp() const
1554     {
1555         return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread);
1556     }
1557 
GetPreFpOffsetBuiltinFrame1558     static size_t GetPreFpOffset(bool isArch32)
1559     {
1560         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1561     }
1562 
GetNumArgsToFpDeltaBuiltinFrame1563     static size_t GetNumArgsToFpDelta(bool isArch32)
1564     {
1565         auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32);
1566         return offset - GetPreFpOffset(isArch32);
1567     }
1568 
GetStackArgsToFpDeltaBuiltinFrame1569     static size_t GetStackArgsToFpDelta(bool isArch32)
1570     {
1571         auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
1572         return offset - GetPreFpOffset(isArch32);
1573     }
1574 
GetStackArgsAddressBuiltinFrame1575     uintptr_t GetStackArgsAddress()
1576     {
1577         return reinterpret_cast<uintptr_t>(&stackArgs);
1578     }
1579 
GetFunctionBuiltinFrame1580     JSTaggedValue GetFunction()
1581     {
1582         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1583         return JSTaggedValue(*functionAddress);
1584     }
1585 
GetNumArgsBuiltinFrame1586     uint32_t GetNumArgs()
1587     {
1588         return numArgs;
1589     }
1590 
GetReturnAddrBuiltinFrame1591     uintptr_t GetReturnAddr() const
1592     {
1593         return returnAddr;
1594     }
1595 
1596     static size_t GetStackArgsOffset(bool isArch32 = false)
1597     {
1598         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
1599     }
1600 
1601     static size_t GetTypeOffset(bool isArch32 = false)
1602     {
1603         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
1604     }
1605 
1606     static size_t GetPrevOffset(bool isArch32 = false)
1607     {
1608         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1609     }
1610 
1611     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1612 
1613     alignas(EAS) FrameType type;
1614     alignas(EAS) JSTaggedType *prevFp;
1615     alignas(EAS) uintptr_t returnAddr;
1616     alignas(EAS) uintptr_t thread;
1617     alignas(EAS) uint32_t numArgs;
1618     alignas(EAS) uintptr_t stackArgs;
1619 };
1620 
1621 // * BuiltinWithArgvFrame layout as the following:
1622 //               +--------------------------+ ---------
1623 //               |       . . . . .          |         ^
1624 //  callerSP --> |--------------------------|         |
1625 //               |       returnAddr         |         |
1626 //               |--------------------------|         |
1627 //               |       callsiteFp         |   BuiltinWithArgvFrame
1628 //        fp --> |--------------------------|         |
1629 //               |       frameType          |         |
1630 //               +--------------------------+         |
1631 //               |        argc              |         v
1632 //               +--------------------------+ ---------
1633 //               |        argV[0]           |
1634 //               +--------------------------+
1635 //               |        argV[1]           |
1636 //               +--------------------------+
1637 //               |        . . . .           |
1638 //  calleeSP --> +--------------------------+
1639 //
1640 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1641 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1642                                                          base::AlignedSize,
1643                                                          base::AlignedPointer,
1644                                                          base::AlignedPointer> {
1645     enum class Index : int {
1646         StackArgsTopIndex = -1,
1647         NumArgsIndex = -1,
1648         TypeIndex = 0,
1649         PrevFpIndex,
1650         ReturnAddrIndex,
1651         NumOfMembers
1652     };
1653     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1654 
GetFrameFromSpBuiltinWithArgvFrame1655     static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp)
1656     {
1657         return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) -
1658             MEMBER_OFFSET(BuiltinFrame, prevFp));
1659     }
1660 
GetPrevFrameFpBuiltinWithArgvFrame1661     inline JSTaggedType* GetPrevFrameFp()
1662     {
1663         return prevFp;
1664     }
1665 
GetCallSiteSpBuiltinWithArgvFrame1666     uintptr_t GetCallSiteSp() const
1667     {
1668         return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame);
1669     }
1670 
GetStackArgsAddressBuiltinWithArgvFrame1671     uintptr_t GetStackArgsAddress()
1672     {
1673         auto topAddress = ToUintPtr(this) +
1674             (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t));
1675         auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS;
1676         return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t);
1677     }
1678 
GetFunctionBuiltinWithArgvFrame1679     JSTaggedValue GetFunction()
1680     {
1681         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1682         return JSTaggedValue(*functionAddress);
1683     }
1684 
GetNumArgsBuiltinWithArgvFrame1685     int32_t GetNumArgs()
1686     {
1687         auto argcAddress = reinterpret_cast<int32_t *>(
1688             ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t)));
1689         return *argcAddress;
1690     }
1691 
GetReturnAddrBuiltinWithArgvFrame1692     uintptr_t GetReturnAddr() const
1693     {
1694         return returnAddr;
1695     }
1696 
1697     static size_t GetTypeOffset(bool isArch32 = false)
1698     {
1699         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
1700     }
1701 
1702     static size_t GetPrevOffset(bool isArch32 = false)
1703     {
1704         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1705     }
1706 
1707     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1708     // argv(... this, new.target, function)
1709     // numargs
1710     alignas(EAS) FrameType type;
1711     alignas(EAS) JSTaggedType *prevFp;
1712     alignas(EAS) uintptr_t returnAddr;
1713 };
1714 
1715 // * FASTJITFunctionFrame layout description as the following:
1716 //               +--------------------------+
1717 //               |        arg[N-1]          |
1718 //               +--------------------------+
1719 //               |       ...                |
1720 //               +--------------------------+
1721 //               |       arg[1]             |
1722 //               +--------------------------+
1723 //               |       arg[0]             |
1724 //               +--------------------------+
1725 //               |       this               |
1726 //               +--------------------------+
1727 //               |       new-target         |
1728 //               +--------------------------+
1729 //               |       call-target        |
1730 //               |--------------------------|
1731 //               |       argc               |
1732 // callerSp ---> |--------------------------| ---------------
1733 //               |       returnAddr         |               ^
1734 //               |--------------------------|               |
1735 //               |       callsiteFp         |               |
1736 //               |--------------------------|               |
1737 //               |       frameType          |    FASTJITFunctionFrame
1738 //               |--------------------------|               |
1739 //               |       call-target        |               |
1740 //               |--------------------------|               |
1741 //               |       pc(bytecode pc)    |               v
1742 // calleeSP ---> +--------------------------+ ---------------
1743 //
1744 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1745 struct FASTJITFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1746                                                              JSTaggedValue,
1747                                                              JSTaggedValue,
1748                                                              base::AlignedPointer,
1749                                                              base::AlignedPointer,
1750                                                              base::AlignedPointer> {
1751 public:
1752     using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
1753     enum class Index : size_t {
1754         PcIndex = 0,
1755         JSFuncIndex,
1756         TypeIndex,
1757         PrevFpIndex,
1758         ReturnAddrIndex,
1759         NumOfMembers
1760     };
1761     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1762 
GetFunctionDeltaReturnAddrFASTJITFunctionFrame1763     static constexpr size_t GetFunctionDeltaReturnAddr()
1764     {
1765         return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex);
1766     }
1767 
GetPrevFrameFpFASTJITFunctionFrame1768     inline JSTaggedType* GetPrevFrameFp()
1769     {
1770         return prevFp;
1771     }
1772 
GetArgvFASTJITFunctionFrame1773     JSTaggedType* GetArgv(uintptr_t *preFrameSp) const
1774     {
1775         const size_t offset = 2;    // 2: skip argc and argv.
1776         return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t));
1777     }
1778 
GetArgcFASTJITFunctionFrame1779     size_t GetArgc(uintptr_t *preFrameSp) const
1780     {
1781         return *preFrameSp;
1782     }
1783 
1784     JSTaggedType* GetArgv(const FrameIterator &it) const;
1785 
GetReturnAddrFASTJITFunctionFrame1786     uintptr_t GetReturnAddr() const
1787     {
1788         return returnAddr;
1789     }
1790 
1791     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
1792         const RootBaseAndDerivedVisitor &derivedVisitor, FrameType frameType) const;
1793     void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const;
1794 
GetFunctionFASTJITFunctionFrame1795     inline JSTaggedValue GetFunction() const
1796     {
1797         return jsFunc;
1798     }
1799 
ComputeArgsConfigFrameSpFASTJITFunctionFrame1800     static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp)
1801     {
1802         const size_t offset = 2;  // 2: skip prevFp and return address.
1803         return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t);
1804     }
1805 
1806     static size_t GetTypeOffset(bool isArch32 = false)
1807     {
1808         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
1809     }
1810 
1811     static size_t GetPcOffset(bool isArch32 = false)
1812     {
1813         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
1814     }
1815 
1816     static size_t GetPrevOffset(bool isArch32 = false)
1817     {
1818         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1819     }
1820 
1821     static size_t GetFunctionOffset(bool isArch32 = false)
1822     {
1823         return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32);
1824     }
1825 
ComputeReservedJSFuncOffsetFASTJITFunctionFrame1826     static size_t ComputeReservedJSFuncOffset(size_t slotSize)
1827     {
1828         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex);
1829         return slotSize * slotOffset;
1830     }
1831 
ComputeReservedPcOffsetFASTJITFunctionFrame1832     static size_t ComputeReservedPcOffset(size_t slotSize)
1833     {
1834         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PcIndex);
1835         return slotSize * slotOffset;
1836     }
1837 
GetTypeFASTJITFunctionFrame1838     FrameType GetType() const
1839     {
1840         return type;
1841     }
1842 
GetPcFASTJITFunctionFrame1843     inline const uint8_t *GetPc() const
1844     {
1845         return pc;
1846     }
1847 
1848     friend class FrameIterator;
1849     friend class FrameHandler;
1850     void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const;
1851     void GetFuncCalleeRegAndOffset(
1852         const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const;
1853     uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const;
1854 
1855 private:
GetFrameFromSpFASTJITFunctionFrame1856     static FASTJITFunctionFrame* GetFrameFromSp(const JSTaggedType *sp)
1857     {
1858         return reinterpret_cast<FASTJITFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) -
1859             MEMBER_OFFSET(FASTJITFunctionFrame, prevFp));
1860     }
1861 
GetFuncAddrFromSpFASTJITFunctionFrame1862     static uintptr_t GetFuncAddrFromSp(const JSTaggedType *sp)
1863     {
1864         return reinterpret_cast<uintptr_t>(sp) - MEMBER_OFFSET(FASTJITFunctionFrame, type);
1865     }
1866 
1867     // dynamic callee saveregisters for x86-64
1868     alignas(EAS) const uint8_t *pc {nullptr};
1869     alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()};
1870     alignas(EAS) FrameType type {0};
1871     alignas(EAS) JSTaggedType *prevFp {nullptr};
1872     alignas(EAS) uintptr_t returnAddr {0};
1873     // dynamic callee saveregisters for arm64
1874 };
1875 
1876 enum class GCVisitedFlag : uint8_t {
1877     VISITED = 0,
1878     IGNORED,
1879     HYBRID_STACK,
1880     DEOPT,
1881 };
1882 
1883 class FrameIterator {
1884 public:
1885     using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
1886     using CallSiteInfo = std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec>;
1887     explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr);
GetFrameType()1888     FrameType GetFrameType() const
1889     {
1890         ASSERT(current_ != nullptr);
1891         FrameType *typeAddr = reinterpret_cast<FrameType *>(
1892             reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType));
1893         return *typeAddr;
1894     }
1895 
1896     template<class T>
GetFrame()1897     T* GetFrame()
1898     {
1899         return T::GetFrameFromSp(current_);
1900     }
1901 
1902     template<class T>
GetFrame()1903     const T* GetFrame() const
1904     {
1905         return T::GetFrameFromSp(current_);
1906     }
1907 
Done()1908     bool Done() const
1909     {
1910         return current_ == nullptr;
1911     }
GetSp()1912     JSTaggedType *GetSp() const
1913     {
1914         return current_;
1915     }
GetSp()1916     JSTaggedType *GetSp()
1917     {
1918         return current_;
1919     }
GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)1920     void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const
1921     {
1922         ret = calleeRegInfo_;
1923     }
1924     int ComputeDelta(const Method *method = nullptr) const;
1925     template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED>
1926     void Advance();
1927     std::map<uint32_t, uint32_t> GetInlinedMethodInfo();
1928     uint32_t GetBytecodeOffset() const;
1929     uintptr_t GetPrevFrameCallSiteSp() const;
1930     uintptr_t GetPrevFrame() const;
GetCallSiteSp()1931     uintptr_t GetCallSiteSp() const
1932     {
1933         return optimizedCallSiteSp_;
1934     }
GetOptimizedReturnAddr()1935     uintptr_t GetOptimizedReturnAddr() const
1936     {
1937         return optimizedReturnAddr_;
1938     }
GetThread()1939     const JSThread *GetThread() const
1940     {
1941         return thread_;
1942     }
1943     bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const;
1944     void CollectPcOffsetInfo(ConstInfo &info) const;
1945     void CollectMethodOffsetInfo(std::map<uint32_t, uint32_t> &info) const;
1946     void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const;
1947     std::pair<CallSiteInfo, bool> CalCallSiteInfo(uintptr_t retAddr, bool isDeopt) const;
1948     CallSiteInfo TryCalCallSiteInfoFromMachineCode(uintptr_t retAddr) const;
1949 
1950     Method *CheckAndGetMethod() const;
1951     JSTaggedValue GetFunction() const;
1952 
IsLeaveFrame()1953     bool IsLeaveFrame() const
1954     {
1955         FrameType type = GetFrameType();
1956         return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV);
1957     }
1958 
IsOptimizedFrame()1959     bool IsOptimizedFrame() const
1960     {
1961         FrameType type = GetFrameType();
1962         return (type == FrameType::OPTIMIZED_FRAME);
1963     }
1964 
IsInterpretedFrame(FrameType type)1965     bool IsInterpretedFrame(FrameType type) const
1966     {
1967         return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST);
1968     }
1969 
IsJSFrame()1970     bool IsJSFrame() const
1971     {
1972         FrameType type = GetFrameType();
1973         return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type) || IsFastJitFunctionFrame(type);
1974     }
1975 
IsOptimizedJSFunctionFrame(FrameType type)1976     bool IsOptimizedJSFunctionFrame(FrameType type) const
1977     {
1978         return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME ||
1979             type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME;
1980     }
1981 
IsOptimizedJSFunctionFrame()1982     bool IsOptimizedJSFunctionFrame() const
1983     {
1984         FrameType type = GetFrameType();
1985         return IsOptimizedJSFunctionFrame(type);
1986     }
1987 
IsFastJitFunctionFrame(FrameType type)1988     bool IsFastJitFunctionFrame(FrameType type) const
1989     {
1990         return type == FrameType::FASTJIT_FUNCTION_FRAME ||
1991             type == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME;
1992     }
1993 
IsFastJitFunctionFrame()1994     bool IsFastJitFunctionFrame() const
1995     {
1996         FrameType type = GetFrameType();
1997         return IsFastJitFunctionFrame(type);
1998     }
1999 
IsAotOrJitFunctionFrame()2000     bool IsAotOrJitFunctionFrame() const
2001     {
2002         return IsOptimizedJSFunctionFrame() || IsFastJitFunctionFrame();
2003     }
2004 
GetMachineCodeSlot()2005     JSTaggedType *GetMachineCodeSlot() const
2006     {
2007         return const_cast<JSTaggedType*>(&machineCode_);
2008     }
2009 
2010 private:
2011     JSTaggedType *current_ {nullptr};
2012     const JSThread *thread_ {nullptr};
2013     const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr};
2014     uintptr_t optimizedCallSiteSp_ {0};
2015     uintptr_t optimizedReturnAddr_ {0};
2016     uint8_t *stackMapAddr_ {nullptr};
2017     kungfu::CalleeRegAndOffsetVec calleeRegInfo_;
2018 
2019     // in jit, delta on method is not set, get it from iterator
2020     bool isJITFrame_ {false};
2021     int fpDeltaPrevFrameSp_ {0};
2022 
2023     // cache current machine code, it's nonmovable
2024     JSTaggedType machineCode_ {JSTaggedValue::VALUE_UNDEFINED};
2025 };
2026 }  // namespace panda::ecmascript
2027 #endif // ECMASCRIPT_FRAMES_H
2028