• 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, RootVisitor &visitor) const;
188 
189     static size_t GetTypeOffset(bool isArch32 = false)
190     {
191         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
192     }
193 
194     static size_t GetPrevOffset(bool isArch32 = false)
195     {
196         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
197     }
198 
199     static size_t GetReturnAddrOffset(bool isArch32 = false)
200     {
201         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
202     }
203 
ComputeReservedSizeOptimizedFrame204     static size_t ComputeReservedSize(size_t slotSize)
205     {
206         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex);
207         return slotSize * slotOffset;
208     }
209 
GetTypeOptimizedFrame210     FrameType GetType() const
211     {
212         return type;
213     }
214 
215 private:
216     enum class Index : size_t {
217         TypeIndex = 0,
218         PrevFpIndex,
219         ReturnAddrIndex,
220         NumOfMembers
221     };
222     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
223 
GetFrameFromSpOptimizedFrame224     static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp)
225     {
226         return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp) -
227             MEMBER_OFFSET(OptimizedFrame, prevFp));
228     }
GetPrevFrameFpOptimizedFrame229     inline JSTaggedType* GetPrevFrameFp()
230     {
231         return prevFp;
232     }
GetReturnAddrOptimizedFrame233     uintptr_t GetReturnAddr() const
234     {
235         return returnAddr;
236     }
237 
238     alignas(EAS) FrameType type {0};
239     alignas(EAS) JSTaggedType *prevFp {nullptr};
240     alignas(EAS) uintptr_t returnAddr {0};
241     friend class FrameIterator;
242 };
243 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64);
244 
245 // * BaselineBuiltinFrame layout as the following:
246 //               +--------------------------+ ---------
247 //               |       . . . . .          |         ^
248 // callerSP ---> |--------------------------|         |
249 //               |       returnAddr         |         |
250 //               |--------------------------|   BuiltinBuiltinFrame
251 //               |       callsiteFp         |         |
252 //       fp ---> |--------------------------|         |
253 //               |       frameType          |         v
254 //               +--------------------------+ ---------
255 //               |        . . . .           |
256 // calleeSP ---> +--------------------------+
257 //
258 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
259 struct BaselineBuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
260                                                          base::AlignedPointer,
261                                                          base::AlignedPointer,
262                                                          base::AlignedPointer> {
263 public:
264     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
265 
266     static size_t GetTypeOffset(bool isArch32 = false)
267     {
268         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
269     }
270 
271     static size_t GetPrevOffset(bool isArch32 = false)
272     {
273         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
274     }
275 
276     static size_t GetReturnAddrOffset(bool isArch32 = false)
277     {
278         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
279     }
280 
ComputeReservedSizeBaselineBuiltinFrame281     static size_t ComputeReservedSize(size_t slotSize)
282     {
283         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex);
284         return slotSize * slotOffset;
285     }
286 
GetTypeBaselineBuiltinFrame287     FrameType GetType() const
288     {
289         return type;
290     }
291 
GetReturnAddrBaselineBuiltinFrame292     uintptr_t GetReturnAddr() const
293     {
294         return returnAddr;
295     }
296 
297 private:
298     enum class Index : size_t {
299         TypeIndex = 0,
300         PrevFpIndex,
301         ReturnAddrIndex,
302         NumOfMembers
303     };
304     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
305 
GetFrameFromSpBaselineBuiltinFrame306     static BaselineBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
307     {
308         return reinterpret_cast<BaselineBuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) -
309             MEMBER_OFFSET(BaselineBuiltinFrame, prevFp));
310     }
GetPrevFrameFpBaselineBuiltinFrame311     inline JSTaggedType* GetPrevFrameFp()
312     {
313         return prevFp;
314     }
315 
316     alignas(EAS) FrameType type {0};
317     alignas(EAS) JSTaggedType *prevFp {nullptr};
318     alignas(EAS) uintptr_t returnAddr {0};
319     friend class FrameIterator;
320 };
321 STATIC_ASSERT_EQ_ARCH(sizeof(BaselineBuiltinFrame), BaselineBuiltinFrame::SizeArch32, BaselineBuiltinFrame::SizeArch64);
322 
323 struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
324                                                    base::AlignedPointer,
325                                                    base::AlignedPointer,
326                                                    base::AlignedPointer> {
327 public:
328     static size_t GetTypeOffset(bool isArch32 = false)
329     {
330         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
331     }
332 
333     static size_t GetPrevOffset(bool isArch32 = false)
334     {
335         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
336     }
337 
338     static size_t GetReturnAddrOffset(bool isArch32 = false)
339     {
340         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
341     }
342 
GetCallSiteSpAsmBridgeFrame343     uintptr_t GetCallSiteSp() const
344     {
345         return ToUintPtr(this) + sizeof(AsmBridgeFrame);
346     }
347 
GetTypeAsmBridgeFrame348     FrameType GetType() const
349     {
350         return type;
351     }
352 
353 private:
354     enum class Index : size_t {
355         TypeIndex = 0,
356         PrevFpIndex,
357         ReturnAddrIndex,
358         NumOfMembers
359     };
360     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
361 
GetFrameFromSpAsmBridgeFrame362     static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
363     {
364         return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
365             MEMBER_OFFSET(AsmBridgeFrame, prevFp));
366     }
GetPrevFrameFpAsmBridgeFrame367     inline JSTaggedType* GetPrevFrameFp()
368     {
369         return prevFp;
370     }
GetReturnAddrAsmBridgeFrame371     uintptr_t GetReturnAddr() const
372     {
373         return returnAddr;
374     }
375     alignas(EAS) FrameType type {0};
376     alignas(EAS) JSTaggedType *prevFp {nullptr};
377     alignas(EAS) uintptr_t returnAddr {0};
378     friend class FrameIterator;
379 };
380 STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64);
381 
382 // * OptimizedUnfoldArgVFrame layout description as the following:
383 // callerSP ---> |--------------------------| ---------------
384 //               |       returnAddr         |               ^
385 //               |--------------------------|               |
386 //               |       prevFp             |               |
387 //       fp ---> |--------------------------|   OptimizedUnfoldArgVFrame
388 //               |       frameType          |               |
389 //               |--------------------------|               |
390 //               |       currentFp          |               v
391 // calleESP ---> +--------------------------+ ---------------
392 //
393 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
394 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
395                                                                        base::AlignedPointer,
396                                                                        base::AlignedPointer,
397                                                                        base::AlignedPointer,
398                                                                        base::AlignedPointer> {
399 public:
400     static size_t GetTypeOffset(bool isArch32 = false)
401     {
402         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
403     }
404 
405     static size_t GetPrevOffset(bool isArch32 = false)
406     {
407         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
408     }
409 
410     static size_t GetReturnAddrOffset(bool isArch32 = false)
411     {
412         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
413     }
414 
GetTypeOptimizedJSFunctionUnfoldArgVFrame415     FrameType GetType() const
416     {
417         return type;
418     }
419 
420 private:
421     enum class Index : size_t {
422         CallSiteSpIndex = 0,
423         TypeIndex,
424         PrevFpIndex,
425         ReturnAddrIndex,
426         NumOfMembers
427     };
428     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
429 
GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame430     static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp)
431     {
432         return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp) -
433             MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp));
434     }
GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame435     inline JSTaggedType* GetPrevFrameFp() const
436     {
437         return prevFp;
438     }
GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame439     uintptr_t GetReturnAddr() const
440     {
441         return returnAddr;
442     }
GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame443     uintptr_t GetPrevFrameSp() const
444     {
445         return callSiteSp;
446     }
447     alignas(EAS) uintptr_t callSiteSp {0};
448     alignas(EAS) FrameType type {0};
449     alignas(EAS) JSTaggedType *prevFp {nullptr};
450     alignas(EAS) uintptr_t returnAddr {0};
451     friend class FrameIterator;
452 };
453 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame),
454     OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64);
455 
456 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following:
457 //          +--------------------------+
458 //          |         arg[N-1]         |
459 //          +--------------------------+
460 //          |         . . . .          |
461 //          +--------------------------+
462 //          |         arg[0]           |
463 //          +--------------------------+
464 //          |         argC             |
465 //  sp ---> +--------------------------+ -----------------
466 //          |                          |                 ^
467 //          |        prevFP            |                 |
468 //  fp ---> |--------------------------|    OptimizedJSFunctionArgsConfigFrame
469 //          |       frameType          |                 |
470 //          |                          |                 V
471 //          +--------------------------+ -----------------
472 //
473 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
474 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
475                                                                       base::AlignedPointer,
476                                                                       base::AlignedPointer> {
477 public:
478     static size_t GetTypeOffset(bool isArch32 = false)
479     {
480         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
481     }
482 
483     static size_t GetPrevOffset(bool isArch32 = false)
484     {
485         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
486     }
487 
GetTypeOptimizedJSFunctionArgConfigFrame488     FrameType GetType() const
489     {
490         return type;
491     }
492 
493 private:
494     enum class Index : size_t {
495         TypeIndex = 0,
496         PrevFpIndex,
497         NumOfMembers
498     };
499     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
500 
GetFrameFromSpOptimizedJSFunctionArgConfigFrame501     static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp)
502     {
503         return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp) -
504             MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp));
505     }
GetPrevFrameFpOptimizedJSFunctionArgConfigFrame506     inline JSTaggedType* GetPrevFrameFp()
507     {
508         return prevFp;
509     }
510 
511     alignas(EAS) FrameType type {0};
512     alignas(EAS) JSTaggedType *prevFp {nullptr};
513     friend class FrameIterator;
514 };
515 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame),
516                       OptimizedJSFunctionArgConfigFrame::SizeArch32,
517                       OptimizedJSFunctionArgConfigFrame::SizeArch64);
518 
519 // * OptimizedJSFunctionFrame layout description as the following:
520 //                 +----------------------------------------+
521 //                 |     arg[N-1]                           |
522 //                 +----------------------------------------+
523 //                 |     ...                                |
524 //                 +----------------------------------------+
525 //                 |     arg[1]                             |
526 //                 +----------------------------------------+
527 //                 |     arg[0]                             |
528 //                 +----------------------------------------+
529 //                 |     this                               |
530 //                 +----------------------------------------+
531 //                 |     new-target [not exist in fastcall] |
532 //                 +----------------------------------------+
533 //                 |     call-target                        |
534 //       argv ---> +----------------------------------------+
535 //                 |     argv   [not exist in fastcall]     |
536 //                 |----------------------------------------|
537 //                 |     argc   [not exist in fastcall]     |
538 //   callerSp ---> |----------------------------------------|----------------
539 //                 |     returnAddr                         |               ^
540 //                 |----------------------------------------|               |
541 //                 |     callsiteFp                         |               |
542 //         fp ---> |----------------------------------------|   OptimizedJSFunctionFrame
543 //                 |     frameType                          |               |
544 //                 |----------------------------------------|               |
545 //                 |     call-target                        |               v
546 //   calleeSP ---> +----------------------------------------+----------------
547 //
548 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
549 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
550                                                              JSTaggedValue,
551                                                              base::AlignedPointer,
552                                                              base::AlignedPointer,
553                                                              base::AlignedPointer> {
554 public:
555     using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
556     enum class Index : size_t {
557         JSFuncIndex = 0,
558         TypeIndex,
559         PrevFpIndex,
560         ReturnAddrIndex,
561         NumOfMembers
562     };
563     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
564 
GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame565     static constexpr size_t GetFunctionDeltaReturnAddr()
566     {
567         return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex);
568     }
569 
GetPrevFrameFpOptimizedJSFunctionFrame570     inline JSTaggedType* GetPrevFrameFp()
571     {
572         return prevFp;
573     }
574 
GetArgvOptimizedJSFunctionFrame575     JSTaggedType* GetArgv(uintptr_t *preFrameSp) const
576     {
577         const size_t offset = 2;    // 2: skip argc and argv.
578         return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t));
579     }
580 
GetArgcOptimizedJSFunctionFrame581     size_t GetArgc(uintptr_t *preFrameSp) const
582     {
583         return *preFrameSp;
584     }
585 
586     JSTaggedType* GetArgv(const FrameIterator &it) const;
587 
GetReturnAddrOptimizedJSFunctionFrame588     uintptr_t GetReturnAddr() const
589     {
590         return returnAddr;
591     }
592 
593     void GCIterate(const FrameIterator &it, RootVisitor &visitor, FrameType frameType) const;
594     void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const;
595 
GetFunctionOptimizedJSFunctionFrame596     inline JSTaggedValue GetFunction() const
597     {
598         return jsFunc;
599     }
600 
ComputeArgsConfigFrameSpOptimizedJSFunctionFrame601     static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp)
602     {
603         const size_t offset = 2;  // 2: skip prevFp and return address.
604         return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t);
605     }
606 
607     static size_t GetTypeOffset(bool isArch32 = false)
608     {
609         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
610     }
611 
612     static size_t GetPrevOffset(bool isArch32 = false)
613     {
614         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
615     }
616 
617     static size_t GetFunctionOffset(bool isArch32 = false)
618     {
619         return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32);
620     }
621 
622     static size_t GetReturnAddrOffset(bool isArch32 = false)
623     {
624         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
625     }
626 
ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame627     static size_t ComputeReservedJSFuncOffset(size_t slotSize)
628     {
629         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex);
630         return slotSize * slotOffset;
631     }
632 
GetFrmaeTypeToFpDeltaOptimizedJSFunctionFrame633     static int GetFrmaeTypeToFpDelta()
634     {
635         return -(int)sizeof(uintptr_t);
636     }
637 
GetFunctionToFpDeltaOptimizedJSFunctionFrame638     static int GetFunctionToFpDelta()
639     {
640         int slotOffset = static_cast<int>(Index::JSFuncIndex) - static_cast<int>(Index::TypeIndex);
641         return slotOffset * static_cast<int>(JSTaggedValue::TaggedTypeSize()) + GetFrmaeTypeToFpDelta();
642     }
643 
GetTypeOptimizedJSFunctionFrame644     FrameType GetType() const
645     {
646         return type;
647     }
648 
649     friend class FrameIterator;
650     friend class FrameHandler;
651     void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const;
652     void GetFuncCalleeRegAndOffset(
653         const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const;
654     uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const;
655 
656 private:
GetFrameFromSpOptimizedJSFunctionFrame657     static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp)
658     {
659         return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) -
660             MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp));
661     }
662 
663     // dynamic callee saveregisters for x86-64
664     alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()};
665     alignas(EAS) FrameType type {0};
666     alignas(EAS) JSTaggedType *prevFp {nullptr};
667     alignas(EAS) uintptr_t returnAddr {0};
668     // dynamic callee saveregisters for arm64
669 };
670 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame),
671                       OptimizedJSFunctionFrame::SizeArch32,
672                       OptimizedJSFunctionFrame::SizeArch64);
673 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time.
674 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1);
675 
676 // * The JSFunctionEntry Frame's structure is illustrated as the following:
677 //              +--------------------------+
678 //              |      . . . . . .         |
679 // callerSP --> +--------------------------+ -----------------
680 //              |        prevFP            |                 ^
681 //       fp --> |--------------------------|                 |
682 //              |       frameType          |      JSFunctionEntryFrame
683 //              |--------------------------|                 |
684 //              |    preLeaveFrameFp       |                 v
685 // calleeSP --> +--------------------------+ -----------------
686 
687 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
688                                                         base::AlignedPointer,
689                                                         base::AlignedPointer,
690                                                         base::AlignedPointer> {
691 public:
692     enum class CallType : size_t {
693         CALL_FUNC = 0,
694         CALL_NEW,
695     };
696 
697     enum class Index : size_t {
698         PreLeaveFrameFpIndex = 0,
699         TypeIndex,
700         PrevFpIndex,
701         NumOfMembers
702     };
703 
704     static size_t GetTypeOffset(bool isArch32 = false)
705     {
706         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
707     }
708 
709     static size_t GetLeaveFrameFpOffset(bool isArch32 = false)
710     {
711         return GetOffset<static_cast<size_t>(Index::PreLeaveFrameFpIndex)>(isArch32);
712     }
713 
GetPrevFrameFpOptimizedEntryFrame714     inline JSTaggedType* GetPrevFrameFp()
715     {
716         return preLeaveFrameFp;
717     }
718 
ComputeReservedSizeOptimizedEntryFrame719     static size_t ComputeReservedSize(size_t slotSize)
720     {
721         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex);
722         return slotSize * slotOffset;
723     }
724 
GetTypeOptimizedEntryFrame725     FrameType GetType() const
726     {
727         return type;
728     }
729     friend class FrameIterator;
730 
731 private:
GetFrameFromSpOptimizedEntryFrame732     static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
733     {
734         return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) -
735                                                        MEMBER_OFFSET(OptimizedEntryFrame, prevFp));
736     }
737 
GetLeaveFpOptimizedEntryFrame738     JSTaggedType* GetLeaveFp() const
739     {
740         return preLeaveFrameFp;
741     }
742 
GetPrevFpOptimizedEntryFrame743     JSTaggedType* GetPrevFp() const
744     {
745         return prevFp;
746     }
747 
748     alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr};
749     alignas(EAS) FrameType type {0};
750     alignas(EAS) JSTaggedType *prevFp {nullptr};
751 };
752 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64);
753 
754 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
755 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(),
756                                                          base::AlignedPointer,
757                                                          base::AlignedSize> {
758     enum class Index : size_t {
759         PrevIndex = 0,
760         TypeIndex,
761         NumOfMembers
762     };
763     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
764 
GetPrevFrameFpInterpretedFrameBase765     inline JSTaggedType* GetPrevFrameFp()
766     {
767         return prev;
768     }
769 
GetFrameFromSpInterpretedFrameBase770     static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp)
771     {
772         return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1;
773     }
774 
775     static size_t GetPrevOffset(bool isArch32 = false)
776     {
777         return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32);
778     }
779 
780     static size_t GetTypeOffset(bool isArch32 = false)
781     {
782         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
783     }
784 
GetSizeInterpretedFrameBase785     static constexpr size_t GetSize(bool isArch32)
786     {
787         return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64;
788     }
789 
790     alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc
791     alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0
792 };
793 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase),
794                       InterpretedFrameBase::SizeArch32,
795                       InterpretedFrameBase::SizeArch64);
796 
797 // Interpreter Frame Layout as the following:
798 //   +----------------------------------+
799 //   |    argv[n-1]                     |
800 //   |----------------------------------|
801 //   |    ......                        |
802 //   |----------------------------------|
803 //   |    thisArg [maybe not exist]     |
804 //   |----------------------------------|
805 //   |    newTarget [maybe not exist]   |
806 //   |----------------------------------|
807 //   |    ......                        |
808 //   |----------------------------------|
809 //   |    Vregs [not exist in native]   |
810 //   +----------------------------------+--------+
811 //   |    base.frameType                |        ^
812 //   |----------------------------------|        |
813 //   |    base.prev(prev stack pointer) |        |
814 //   |----------------------------------|        |
815 //   |    pc(bytecode addr)             |        |
816 //   |----------------------------------|        |
817 //   |    sp(current stack pointer)     |        |
818 //   |----------------------------------|        |
819 //   |    env                           |        |
820 //   |----------------------------------|        |
821 //   |    acc                           |        |
822 //   |----------------------------------|   InterpretedFrame
823 //   |    profileTypeInfo               |        |
824 //   |----------------------------------|        |
825 //   |    thisObj                       |        |
826 //   |----------------------------------|        |
827 //   |    function                      |        |
828 //   |----------------------------------|        |
829 //   |    constpool                     |        v
830 //   +----------------------------------+--------+
831 //
832 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
833 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
834                                                      JSTaggedValue,
835                                                      JSTaggedValue,
836                                                      JSTaggedValue,
837                                                      JSTaggedValue,
838                                                      JSTaggedValue,
839                                                      JSTaggedValue,
840                                                      base::AlignedPointer,
841                                                      InterpretedFrameBase> {
842 public:
843     enum class Index : size_t {
844         ConstPoolIndex = 0,
845         FunctionIndex,
846         ThisObjIndex,
847         ProFileTypeInfoIndex,
848         AccIndex,
849         EnvIndex,
850         PcIndex,
851         BaseIndex,
852         NumOfMembers
853     };
854     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
855 
GetPrevFrameFpInterpretedFrame856     inline JSTaggedType* GetPrevFrameFp() const
857     {
858         return base.prev;
859     }
860 
GetFrameFromSpInterpretedFrame861     static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
862     {
863         return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
864     }
865 
GetPcInterpretedFrame866     inline const uint8_t *GetPc() const
867     {
868         return pc;
869     }
870 
GetEnvInterpretedFrame871     inline JSTaggedValue GetEnv() const
872     {
873         return env;
874     }
875 
NumOfMembersInterpretedFrame876     static uint32_t NumOfMembers()
877     {
878         return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize();
879     }
880 
GetPcOffsetInterpretedFrame881     static size_t GetPcOffset(bool isArch32)
882     {
883         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
884     }
885 
886     static size_t GetTypeOffset(bool isArch32 = false)
887     {
888         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
889             InterpretedFrameBase::GetTypeOffset(isArch32);
890     }
891 
892     static size_t GetPrevOffset(bool isArch32 = false)
893     {
894         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
895             InterpretedFrameBase::GetPrevOffset(isArch32);
896     }
897 
898     static size_t GetFunctionOffset(bool isArch32 = false)
899     {
900         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
901     }
902 
903     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
904 
905     alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()};
906     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
907     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
908     alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()};
909     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
910     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
911     alignas(EAS) const uint8_t *pc {nullptr};
912     alignas(EAS) InterpretedFrameBase base;
913     friend class FrameIterator;
914 };
915 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64);
916 
917 // * InterpretedBuiltinFrame layout description as the following:
918 //               |--------------------------| ---------------
919 //               |         . . . . .        |               ^
920 //               |    InterpretedFrameBase  |               |
921 //               |         . . . . .        |               |
922 //               |--------------------------|    InterpretedBuiltinFrame
923 //               |       bytecode-PC        |               |
924 //               |--------------------------|               |
925 //               |       call-target        |               v
926 //               +--------------------------+ ---------------
927 //
928 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
929 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
930                                                             JSTaggedValue,
931                                                             base::AlignedPointer,
932                                                             InterpretedFrameBase> {
933     enum class Index : size_t {
934         FunctionIndex = 0,
935         PcIndex,
936         BaseIndex,
937         NumOfMembers
938     };
939     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
940 
GetPrevFrameFpInterpretedBuiltinFrame941     inline JSTaggedType* GetPrevFrameFp()
942     {
943         return base.prev;
944     }
945 
GetFrameFromSpInterpretedBuiltinFrame946     static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
947     {
948         return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
949     }
950 
NumOfMembersInterpretedBuiltinFrame951     static uint32_t NumOfMembers()
952     {
953         return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize();
954     }
955 
956     static size_t GetTypeOffset(bool isArch32 = false)
957     {
958         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
959             InterpretedFrameBase::GetTypeOffset(isArch32);
960     }
961 
962     static size_t GetPrevOffset(bool isArch32 = false)
963     {
964         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
965             InterpretedFrameBase::GetPrevOffset(isArch32);
966     }
967 
968     static size_t GetFunctionOffset(bool isArch32 = false)
969     {
970         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
971     }
972 
973     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
974 
975     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
976     alignas(EAS) const uint8_t *pc {nullptr};
977     alignas(EAS) InterpretedFrameBase base;
978 };
979 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame),
980                       InterpretedBuiltinFrame::SizeArch32,
981                       InterpretedBuiltinFrame::SizeArch64);
982 
983 // AsmInterpretedFrame Layout as the following:
984 //   +----------------------------------+
985 //   |    argv[n-1]                     |
986 //   |----------------------------------|
987 //   |    ......                        |
988 //   |----------------------------------|
989 //   |    thisArg [maybe not exist]     |
990 //   |----------------------------------|
991 //   |    newTarget [maybe not exist]   |
992 //   |----------------------------------|
993 //   |    ......                        |
994 //   |----------------------------------|
995 //   |    Vregs [not exist in native]   |
996 //   +----------------------------------+--------+
997 //   |        .  .  .   .               |        ^
998 //   |     InterpretedFrameBase         |        |
999 //   |        .  .  .   .               |        |
1000 //   |----------------------------------|        |
1001 //   |    pc(bytecode addr)             |        |
1002 //   |----------------------------------|        |
1003 //   |    sp(current stack pointer)     |        |
1004 //   |----------------------------------|   AsmInterpretedFrame
1005 //   |    callSize                      |        |
1006 //   |----------------------------------|        |
1007 //   |    env                           |        |
1008 //   |----------------------------------|        |
1009 //   |    acc                           |        |
1010 //   |----------------------------------|        |
1011 //   |    thisObj                       |        |
1012 //   |----------------------------------|        |
1013 //   |    call-target                   |        v
1014 //   +----------------------------------+--------+
1015 //
1016 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1017 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1018                                                         JSTaggedValue,
1019                                                         JSTaggedValue,
1020                                                         JSTaggedValue,
1021                                                         JSTaggedValue,
1022                                                         base::AlignedPointer,
1023                                                         base::AlignedPointer,
1024                                                         base::AlignedPointer,
1025                                                         InterpretedFrameBase> {
1026     enum class Index : size_t {
1027         FunctionIndex = 0,
1028         ThisObjIndex,
1029         AccIndex,
1030         EnvIndex,
1031         CallSizeIndex,
1032         FpIndex,
1033         PcIndex,
1034         BaseIndex,
1035         NumOfMembers
1036     };
1037 
1038     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1039 
GetCurrentFramePointerAsmInterpretedFrame1040     inline JSTaggedType* GetCurrentFramePointer()
1041     {
1042         return fp;
1043     }
1044 
GetPrevFrameFpAsmInterpretedFrame1045     inline JSTaggedType* GetPrevFrameFp()
1046     {
1047         return base.prev;
1048     }
1049 
GetFrameFromSpAsmInterpretedFrame1050     static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
1051     {
1052         return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
1053     }
1054 
GetFpOffsetAsmInterpretedFrame1055     static size_t GetFpOffset(bool isArch32)
1056     {
1057         return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32);
1058     }
1059 
GetCallSizeOffsetAsmInterpretedFrame1060     static size_t GetCallSizeOffset(bool isArch32)
1061     {
1062         return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32);
1063     }
1064 
GetFunctionOffsetAsmInterpretedFrame1065     static size_t GetFunctionOffset(bool isArch32)
1066     {
1067         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
1068     }
1069 
GetThisOffsetAsmInterpretedFrame1070     static size_t GetThisOffset(bool isArch32)
1071     {
1072         return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32);
1073     }
1074 
GetAccOffsetAsmInterpretedFrame1075     static size_t GetAccOffset(bool isArch32)
1076     {
1077         return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32);
1078     }
1079 
GetEnvOffsetAsmInterpretedFrame1080     static size_t GetEnvOffset(bool isArch32)
1081     {
1082         return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32);
1083     }
1084 
GetBaseOffsetAsmInterpretedFrame1085     static size_t GetBaseOffset(bool isArch32)
1086     {
1087         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
1088     }
1089 
GetPcOffsetAsmInterpretedFrame1090     static size_t GetPcOffset(bool isArch32)
1091     {
1092         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
1093     }
1094 
GetSizeAsmInterpretedFrame1095     static constexpr size_t GetSize(bool isArch32)
1096     {
1097         return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64;
1098     }
1099 
GetFpOffsetAsIntptrAsmInterpretedFrame1100     static intptr_t GetFpOffsetAsIntptr(bool isArch32)
1101     {
1102         return static_cast<intptr_t>(GetFpOffset(isArch32));
1103     }
1104 
GetFunctionOffsetAsIntptrAsmInterpretedFrame1105     static intptr_t GetFunctionOffsetAsIntptr(bool isArch32)
1106     {
1107         return static_cast<intptr_t>(GetFunctionOffset(isArch32));
1108     }
1109 
GetSizeAsIntptrAsmInterpretedFrame1110     static intptr_t GetSizeAsIntptr(bool isArch32)
1111     {
1112         return static_cast<intptr_t>(GetSize(isArch32));
1113     }
1114 
NumOfMembersAsmInterpretedFrame1115     static uint32_t NumOfMembers()
1116     {
1117         return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize();
1118     }
1119     void GCIterate(const FrameIterator &it, RootVisitor &visitor, bool isBaselineFrame) const;
1120 
GetEnvAsmInterpretedFrame1121     JSTaggedValue GetEnv() const
1122     {
1123         return env;
1124     }
1125 
GetPcAsmInterpretedFrame1126     const uint8_t *GetPc() const
1127     {
1128         return pc;
1129     }
1130 
GetTypeOffsetAsmInterpretedFrame1131     static size_t GetTypeOffset()
1132     {
1133         return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type);
1134     }
1135 
GetPrevOffsetAsmInterpretedFrame1136     static size_t GetPrevOffset()
1137     {
1138         return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev);
1139     }
1140 
1141     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
1142     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
1143     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
1144     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
1145     alignas(EAS) uintptr_t callSize {0};
1146     alignas(EAS) JSTaggedType *fp {nullptr};
1147     alignas(EAS) const uint8_t *pc {nullptr};
1148     alignas(EAS) InterpretedFrameBase base;
1149     // vregs, not exist in native
1150     // args, may be truncated if not extra
1151 };
1152 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64);
1153 
1154 // InterpretedEntryFrame Layout as the following:
1155 //   +----------------------------------+---------------
1156 //   |        .  .  .   .               |              ^
1157 //   |     InterpretedFrameBase         |              |
1158 //   |        .  .  .   .               |    InterpretedEntryFrame
1159 //   |----------------------------------|              |
1160 //   |    pc(bytecode addr)             |              v
1161 //   |----------------------------------|---------------
1162 //
1163 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1164 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1165                                                           base::AlignedPointer,
1166                                                           InterpretedFrameBase> {
1167     enum class Index : size_t {
1168         PcIndex = 0,
1169         BaseIndex,
1170         NumOfMembers
1171     };
1172     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1173 
GetPrevFrameFpInterpretedEntryFrame1174     inline JSTaggedType* GetPrevFrameFp()
1175     {
1176         return base.prev;
1177     }
1178 
GetFrameFromSpInterpretedEntryFrame1179     static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
1180     {
1181         return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
1182     }
1183 
NumOfMembersInterpretedEntryFrame1184     static uint32_t NumOfMembers()
1185     {
1186         return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize();
1187     }
1188 
1189     static size_t GetTypeOffset(bool isArch32 = false)
1190     {
1191         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1192             InterpretedFrameBase::GetTypeOffset(isArch32);
1193     }
1194 
1195     static size_t GetPrevOffset(bool isArch32 = false)
1196     {
1197         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1198             InterpretedFrameBase::GetPrevOffset(isArch32);
1199     }
1200 
1201     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1202     alignas(EAS) const uint8_t *pc {nullptr};
1203     alignas(EAS) InterpretedFrameBase base;
1204 };
1205 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame),
1206                       InterpretedEntryFrame::SizeArch32,
1207                       InterpretedEntryFrame::SizeArch64);
1208 
1209 
1210 // AsmInterpretedEntryFrame Layout as the following:
1211 //   +----------------------------------+---------------
1212 //   |        .  .  .   .               |              ^
1213 //   |     InterpretedFrameBase         |              |
1214 //   |        .  .  .   .               |    AsmInterpretedEntryFrame
1215 //   |----------------------------------|              |
1216 //   |    pc(bytecode addr)             |              v
1217 //   |----------------------------------|---------------
1218 //
1219 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1220 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1221                                                              base::AlignedPointer,
1222                                                              InterpretedFrameBase> {
1223     enum class Index : size_t {
1224         PcIndex = 0,
1225         BaseIndex,
1226         NumOfMembers
1227     };
1228     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1229 
GetPrevFrameFpAsmInterpretedEntryFrame1230     inline JSTaggedType* GetPrevFrameFp()
1231     {
1232         return base.prev;
1233     }
1234 
GetBaseOffsetAsmInterpretedEntryFrame1235     static size_t GetBaseOffset(bool isArch32)
1236     {
1237         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
1238     }
1239 
GetFrameFromSpAsmInterpretedEntryFrame1240     static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
1241     {
1242         return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
1243     }
1244 
1245     static size_t GetTypeOffset(bool isArch32 = false)
1246     {
1247         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1248             InterpretedFrameBase::GetTypeOffset(isArch32);
1249     }
1250 
1251     static size_t GetPrevOffset(bool isArch32 = false)
1252     {
1253         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1254             InterpretedFrameBase::GetPrevOffset(isArch32);
1255     }
1256 
1257     alignas(EAS) const uint8_t *pc {nullptr};
1258     alignas(EAS) InterpretedFrameBase base;
1259 };
1260 
1261 // AsmInterpretedBridgeFrame Layout as the following:
1262 //   +----------------------------------+---------------
1263 //   |      ret-address                 |              ^
1264 //   |----------------------------------|              |
1265 //   |        .  .  .   .               |     AsmInterpretedBridgeFrame
1266 //   |     AsmInterpretedEntryFrame     |              |
1267 //   |        .  .  .   .               |              v
1268 //   |----------------------------------|---------------
1269 //
1270 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1271 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1272                                                               AsmInterpretedEntryFrame,
1273                                                               base::AlignedPointer> {
1274     enum class Index : size_t {
1275         EntryIndex = 0,
1276         ReturnAddrIndex,
1277         NumOfMembers
1278     };
1279     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1280 
GetFrameFromSpAsmInterpretedBridgeFrame1281     static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
1282     {
1283         return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
1284             MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr));
1285     }
GetCallSiteSpAsmInterpretedBridgeFrame1286     uintptr_t GetCallSiteSp() const
1287     {
1288         return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame);
1289     }
GetPrevFrameFpAsmInterpretedBridgeFrame1290     inline JSTaggedType* GetPrevFrameFp()
1291     {
1292         return entry.base.prev;
1293     }
1294 
GetReturnAddrOffsetAsmInterpretedBridgeFrame1295     static size_t GetReturnAddrOffset(bool isArch32)
1296     {
1297         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
1298     }
1299 
GetSizeAsmInterpretedBridgeFrame1300     static constexpr size_t GetSize(bool isArch32)
1301     {
1302         return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64;
1303     }
1304 
1305     static size_t GetTypeOffset(bool isArch32 = false)
1306     {
1307         return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) +
1308             AsmInterpretedEntryFrame::GetBaseOffset(isArch32) +
1309             InterpretedFrameBase::GetTypeOffset(isArch32);
1310     }
1311     static size_t GetPrevOffset(bool isArch32 = false)
1312     {
1313         return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) +
1314             AsmInterpretedEntryFrame::GetBaseOffset(isArch32) +
1315             InterpretedFrameBase::GetPrevOffset(isArch32);
1316     }
1317 
GetReturnAddrAsmInterpretedBridgeFrame1318     uintptr_t GetReturnAddr() const
1319     {
1320         return returnAddr;
1321     }
1322 
1323     AsmInterpretedEntryFrame entry;
1324     alignas(EAS) uintptr_t returnAddr {0};
1325 };
1326 
1327 // * Optimized-leaved-frame layout as the following:
1328 //               +--------------------------+
1329 //               |       argv[N-1]          |
1330 //               |--------------------------|
1331 //               |       . . . . .          |
1332 //               |--------------------------|
1333 //               |       argv[0]            |
1334 //               +--------------------------+-------------
1335 //               |       argc               |            ^
1336 //               |--------------------------|            |
1337 //               |       RuntimeId          |            |
1338 //  callerSP --> |--------------------------|   OptimizedLeaveFrame
1339 //               |       ret-addr           |            |
1340 //               |--------------------------|            |
1341 //               |       prevFp             |            |
1342 //        fp --> |--------------------------|            |
1343 //               |       frameType          |            v
1344 //  calleeSP --> +--------------------------+-------------
1345 //
1346 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1347 struct OptimizedLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1348                                                         base::AlignedPointer,
1349                                                         base::AlignedPointer,
1350                                                         base::AlignedPointer,
1351                                                         base::AlignedUint64,
1352                                                         base::AlignedUint64> {
1353     // argv[0]...argv[argc-1] dynamic according to agc
GetFrameFromSpOptimizedLeaveFrame1354     static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1355     {
1356         return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1357             MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp));
1358     }
1359 
GetCallSiteSpOptimizedLeaveFrame1360     uintptr_t GetCallSiteSp() const
1361     {
1362         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId);
1363     }
1364 
GetPrevFrameFpOptimizedLeaveFrame1365     inline JSTaggedType* GetPrevFrameFp() const
1366     {
1367         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1368     }
1369 
GetReturnAddrOptimizedLeaveFrame1370     uintptr_t GetReturnAddr() const
1371     {
1372         return returnAddr;
1373     }
1374 
GetTypeOffsetOptimizedLeaveFrame1375     static size_t GetTypeOffset()
1376     {
1377         return MEMBER_OFFSET(OptimizedLeaveFrame, type);
1378     }
1379 
GetPrevOffsetOptimizedLeaveFrame1380     static size_t GetPrevOffset()
1381     {
1382         return MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp);
1383     }
1384 
GetReturnAddrOffsetOptimizedLeaveFrame1385     static size_t GetReturnAddrOffset()
1386     {
1387         return MEMBER_OFFSET(OptimizedLeaveFrame, returnAddr);
1388     }
1389 
1390     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1391 
1392     alignas(EAS) FrameType type {0};
1393     alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here
1394     alignas(EAS) uintptr_t returnAddr {0};
1395     alignas(EAS) uint64_t argRuntimeId {0};
1396     alignas(EAS) uint64_t argc {0};
1397 };
1398 
1399 // * Optimized-leaved-frame-with-argv layout as the following:
1400 //               +--------------------------+
1401 //               |       argv[]             |
1402 //               +--------------------------+-------------
1403 //               |       argc               |            ^
1404 //               |--------------------------|            |
1405 //               |       RuntimeId          |   OptimizedWithArgvLeaveFrame
1406 //  callerSP --> |--------------------------|            |
1407 //               |       returnAddr         |            |
1408 //               |--------------------------|            |
1409 //               |       callsiteFp         |            |
1410 //        fp --> |--------------------------|            |
1411 //               |       frameType          |            v
1412 //  calleeSP --> +--------------------------+-------------
1413 
1414 struct OptimizedWithArgvLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1415                                                                 base::AlignedPointer,
1416                                                                 base::AlignedPointer,
1417                                                                 base::AlignedPointer,
1418                                                                 base::AlignedUint64,
1419                                                                 base::AlignedUint64> {
GetFrameFromSpOptimizedWithArgvLeaveFrame1420     static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1421     {
1422         return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1423             MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp));
1424     }
1425 
GetCallSiteSpOptimizedWithArgvLeaveFrame1426     uintptr_t GetCallSiteSp() const
1427     {
1428         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId);
1429     }
1430 
GetPrevFrameFpOptimizedWithArgvLeaveFrame1431     inline JSTaggedType* GetPrevFrameFp()
1432     {
1433         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1434     }
1435 
GetReturnAddrOptimizedWithArgvLeaveFrame1436     uintptr_t GetReturnAddr() const
1437     {
1438         return returnAddr;
1439     }
1440 
GetTypeOffsetOptimizedWithArgvLeaveFrame1441     static size_t GetTypeOffset()
1442     {
1443         return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type);
1444     }
1445 
GetPrevOffsetOptimizedWithArgvLeaveFrame1446     static size_t GetPrevOffset()
1447     {
1448         return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp);
1449     }
1450 
GetReturnAddrOffsetOptimizedWithArgvLeaveFrame1451     static size_t GetReturnAddrOffset()
1452     {
1453         return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, returnAddr);
1454     }
1455 
1456     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1457 
1458     alignas(EAS) FrameType type {0};
1459     alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here
1460     alignas(EAS) uintptr_t returnAddr {0};
1461     alignas(EAS) uint64_t argRuntimeId {0};
1462     alignas(EAS) uint64_t argc {0};
1463 };
1464 
1465 // * Optimized-builtin-leave-frame layout as the following:
1466 //               +--------------------------+
1467 //               |       argv[N-1]          |
1468 //               |--------------------------|
1469 //               |       . . . . .          |
1470 //               |--------------------------|
1471 //               |       argv[0]            |
1472 //               +--------------------------+-------------
1473 //               |       argc               |            ^
1474 //               |--------------------------|            |
1475 //               |       thread             |            |
1476 //  callerSP --> +--------------------------+            |
1477 //               |       ret-addr           |            |
1478 //               |--------------------------|   OptimizedBuiltinLeaveFrame
1479 //               |       prevFp             |            |
1480 //        fp --> |--------------------------|            |
1481 //               |       frameType          |            |
1482 //               |--------------------------|            |
1483 //               |       align byte         |            v
1484 //  calleeSP --> +--------------------------+-------------
1485 //
1486 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1487 struct OptimizedBuiltinLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1488                                                                base::AlignedPointer,
1489                                                                base::AlignedPointer,
1490                                                                base::AlignedPointer,
1491                                                                JSTaggedValue,
1492                                                                base::AlignedUint64> {
1493 public:
GetFrameFromSpOptimizedBuiltinLeaveFrame1494     static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1495     {
1496         return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1497             MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp));
1498     }
1499 
GetCallSiteSpOptimizedBuiltinLeaveFrame1500     uintptr_t GetCallSiteSp() const
1501     {
1502         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, thread);
1503     }
1504 
GetPrevFrameFpOptimizedBuiltinLeaveFrame1505     inline JSTaggedType* GetPrevFrameFp() const
1506     {
1507         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1508     }
1509 
GetReturnAddrOptimizedBuiltinLeaveFrame1510     uintptr_t GetReturnAddr() const
1511     {
1512         return returnAddr;
1513     }
1514 
1515     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1516 
GetTypeOffsetOptimizedBuiltinLeaveFrame1517     static size_t GetTypeOffset()
1518     {
1519         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type);
1520     }
1521 
GetPrevOffsetOptimizedBuiltinLeaveFrame1522     static size_t GetPrevOffset()
1523     {
1524         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp);
1525     }
1526 
GetReturnAddrOffsetOptimizedBuiltinLeaveFrame1527     static size_t GetReturnAddrOffset()
1528     {
1529         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, returnAddr);
1530     }
1531 
GetFunctionOffsetOptimizedBuiltinLeaveFrame1532     static size_t GetFunctionOffset()
1533     {
1534         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argc) + 1;
1535     }
1536 
GetArgvOptimizedBuiltinLeaveFrame1537     const JSTaggedType* GetArgv() const
1538     {
1539         return reinterpret_cast<const JSTaggedType *>(&argc + 1);
1540     }
1541 
GetTypeOptimizedBuiltinLeaveFrame1542     FrameType GetType() const
1543     {
1544         return type;
1545     }
1546 
1547 private:
1548     alignas(EAS) FrameType type {0};
1549     alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here
1550     alignas(EAS) uintptr_t returnAddr {0};
1551     alignas(EAS) JSTaggedValue thread {JSTaggedValue::Hole()};
1552     alignas(EAS) uint64_t argc {0};
1553     // argv[0]...argv[argc-1] dynamic according to agc
1554 };
1555 
1556 // * BuiltinFrame layout as the following:
1557 //               +--------------------------+
1558 //               |     argV[N - 1]          |
1559 //               |--------------------------|
1560 //               |       . . . .            |
1561 //               |--------------------------+
1562 //               |     argV[2]=this         |
1563 //               +--------------------------+
1564 //               |     argV[1]=new-target   |
1565 //               +--------------------------+
1566 //               |     argV[0]=call-target  |
1567 //               +--------------------------+ ---------
1568 //               |       argc               |         ^
1569 //               |--------------------------|         |
1570 //               |       thread             |         |
1571 //  callerSP --> |--------------------------|         |
1572 //               |       returnAddr         |     BuiltinFrame
1573 //               |--------------------------|         |
1574 //               |       callsiteFp         |         |
1575 //        fp --> |--------------------------|         |
1576 //               |       frameType          |         v
1577 //  calleeSP --> +--------------------------+ ---------
1578 //
1579 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1580 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1581                                                  base::AlignedSize,
1582                                                  base::AlignedPointer,
1583                                                  base::AlignedPointer,
1584                                                  base::AlignedPointer,
1585                                                  base::AlignedUint32,
1586                                                  base::AlignedPointer> {
1587     enum class Index : size_t {
1588         TypeIndex = 0,
1589         PrevFpIndex,
1590         ReturnAddrIndex,
1591         ThreadIndex,
1592         NumArgsIndex,
1593         StackArgsIndex,
1594         NumOfMembers
1595     };
1596     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1597 
GetFrameFromSpBuiltinFrame1598     static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
1599     {
1600         return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) -
1601             MEMBER_OFFSET(BuiltinFrame, prevFp));
1602     }
1603 
GetPrevFrameFpBuiltinFrame1604     inline JSTaggedType* GetPrevFrameFp()
1605     {
1606         return prevFp;
1607     }
1608 
GetCallSiteSpBuiltinFrame1609     uintptr_t GetCallSiteSp() const
1610     {
1611         return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread);
1612     }
1613 
GetPreFpOffsetBuiltinFrame1614     static size_t GetPreFpOffset(bool isArch32)
1615     {
1616         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1617     }
1618 
GetNumArgsToFpDeltaBuiltinFrame1619     static size_t GetNumArgsToFpDelta(bool isArch32)
1620     {
1621         auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32);
1622         return offset - GetPreFpOffset(isArch32);
1623     }
1624 
GetStackArgsToFpDeltaBuiltinFrame1625     static size_t GetStackArgsToFpDelta(bool isArch32)
1626     {
1627         auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
1628         return offset - GetPreFpOffset(isArch32);
1629     }
1630 
GetStackArgsAddressBuiltinFrame1631     uintptr_t GetStackArgsAddress()
1632     {
1633         return reinterpret_cast<uintptr_t>(&stackArgs);
1634     }
1635 
GetFunctionBuiltinFrame1636     JSTaggedValue GetFunction()
1637     {
1638         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1639         return JSTaggedValue(*functionAddress);
1640     }
1641 
GetNumArgsBuiltinFrame1642     uint32_t GetNumArgs()
1643     {
1644         return numArgs;
1645     }
1646 
GetReturnAddrBuiltinFrame1647     uintptr_t GetReturnAddr() const
1648     {
1649         return returnAddr;
1650     }
1651 
1652     static size_t GetStackArgsOffset(bool isArch32 = false)
1653     {
1654         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
1655     }
1656 
1657     static size_t GetTypeOffset(bool isArch32 = false)
1658     {
1659         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
1660     }
1661 
1662     static size_t GetPrevOffset(bool isArch32 = false)
1663     {
1664         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1665     }
1666 
1667     static size_t GetReturnAddrOffset(bool isArch32 = false)
1668     {
1669         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
1670     }
1671 
1672     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1673 
1674     alignas(EAS) FrameType type {0};
1675     alignas(EAS) JSTaggedType *prevFp {nullptr};
1676     alignas(EAS) uintptr_t returnAddr {0};
1677     alignas(EAS) uintptr_t thread {0};
1678     alignas(EAS) uint32_t numArgs {0};
1679     alignas(EAS) uintptr_t stackArgs {0};
1680 };
1681 
1682 // * BuiltinWithArgvFrame layout as the following:
1683 //               +--------------------------+ ---------
1684 //               |       . . . . .          |         ^
1685 //  callerSP --> |--------------------------|         |
1686 //               |       returnAddr         |         |
1687 //               |--------------------------|         |
1688 //               |       callsiteFp         |   BuiltinWithArgvFrame
1689 //        fp --> |--------------------------|         |
1690 //               |       frameType          |         |
1691 //               +--------------------------+         |
1692 //               |        argc              |         v
1693 //               +--------------------------+ ---------
1694 //               |        argV[0]           |
1695 //               +--------------------------+
1696 //               |        argV[1]           |
1697 //               +--------------------------+
1698 //               |        . . . .           |
1699 //  calleeSP --> +--------------------------+
1700 //
1701 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1702 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1703                                                          base::AlignedSize,
1704                                                          base::AlignedPointer,
1705                                                          base::AlignedPointer> {
1706     enum class Index : int {
1707         StackArgsTopIndex = -1,
1708         NumArgsIndex = -1,
1709         TypeIndex = 0,
1710         PrevFpIndex,
1711         ReturnAddrIndex,
1712         NumOfMembers
1713     };
1714     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1715 
GetFrameFromSpBuiltinWithArgvFrame1716     static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp)
1717     {
1718         return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) -
1719             MEMBER_OFFSET(BuiltinFrame, prevFp));
1720     }
1721 
GetPrevFrameFpBuiltinWithArgvFrame1722     inline JSTaggedType* GetPrevFrameFp()
1723     {
1724         return prevFp;
1725     }
1726 
GetCallSiteSpBuiltinWithArgvFrame1727     uintptr_t GetCallSiteSp() const
1728     {
1729         return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame);
1730     }
1731 
GetStackArgsAddressBuiltinWithArgvFrame1732     uintptr_t GetStackArgsAddress()
1733     {
1734         auto topAddress = ToUintPtr(this) +
1735             (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t));
1736         auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS;
1737         return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t);
1738     }
1739 
GetFunctionBuiltinWithArgvFrame1740     JSTaggedValue GetFunction()
1741     {
1742         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1743         return JSTaggedValue(*functionAddress);
1744     }
1745 
GetNumArgsBuiltinWithArgvFrame1746     int32_t GetNumArgs()
1747     {
1748         auto argcAddress = reinterpret_cast<int32_t *>(
1749             ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t)));
1750         return *argcAddress;
1751     }
1752 
GetReturnAddrBuiltinWithArgvFrame1753     uintptr_t GetReturnAddr() const
1754     {
1755         return returnAddr;
1756     }
1757 
1758     static size_t GetTypeOffset(bool isArch32 = false)
1759     {
1760         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
1761     }
1762 
1763     static size_t GetPrevOffset(bool isArch32 = false)
1764     {
1765         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1766     }
1767 
1768     static size_t GetReturnAddrOffset(bool isArch32 = false)
1769     {
1770         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
1771     }
1772 
1773     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1774     // argv(... this, new.target, function)
1775     // numargs
1776     alignas(EAS) FrameType type {0};
1777     alignas(EAS) JSTaggedType *prevFp {nullptr};
1778     alignas(EAS) uintptr_t returnAddr {0};
1779 };
1780 
1781 // * FASTJITFunctionFrame layout description as the following:
1782 //               +--------------------------+
1783 //               |        arg[N-1]          |
1784 //               +--------------------------+
1785 //               |       ...                |
1786 //               +--------------------------+
1787 //               |       arg[1]             |
1788 //               +--------------------------+
1789 //               |       arg[0]             |
1790 //               +--------------------------+
1791 //               |       this               |
1792 //               +--------------------------+
1793 //               |       new-target         |
1794 //               +--------------------------+
1795 //               |       call-target        |
1796 //               |--------------------------|
1797 //               |       argc               |
1798 // callerSp ---> |--------------------------| ---------------
1799 //               |       returnAddr         |               ^
1800 //               |--------------------------|               |
1801 //               |       callsiteFp         |               |
1802 //               |--------------------------|               |
1803 //               |       frameType          |    FASTJITFunctionFrame
1804 //               |--------------------------|               |
1805 //               |       call-target        |               |
1806 //               |--------------------------|               |
1807 //               |       pc(bytecode pc)    |               v
1808 // calleeSP ---> +--------------------------+ ---------------
1809 //
1810 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1811 struct FASTJITFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1812                                                              JSTaggedValue,
1813                                                              JSTaggedValue,
1814                                                              base::AlignedPointer,
1815                                                              base::AlignedPointer,
1816                                                              base::AlignedPointer> {
1817 public:
1818     using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
1819     enum class Index : size_t {
1820         PcIndex = 0,
1821         JSFuncIndex,
1822         TypeIndex,
1823         PrevFpIndex,
1824         ReturnAddrIndex,
1825         NumOfMembers
1826     };
1827     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1828 
GetFunctionDeltaReturnAddrFASTJITFunctionFrame1829     static constexpr size_t GetFunctionDeltaReturnAddr()
1830     {
1831         return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex);
1832     }
1833 
GetPrevFrameFpFASTJITFunctionFrame1834     inline JSTaggedType* GetPrevFrameFp()
1835     {
1836         return prevFp;
1837     }
1838 
GetArgvFASTJITFunctionFrame1839     JSTaggedType* GetArgv(uintptr_t *preFrameSp) const
1840     {
1841         const size_t offset = 2;    // 2: skip argc and argv.
1842         return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t));
1843     }
1844 
GetArgcFASTJITFunctionFrame1845     size_t GetArgc(uintptr_t *preFrameSp) const
1846     {
1847         return *preFrameSp;
1848     }
1849 
1850     JSTaggedType* GetArgv(const FrameIterator &it) const;
1851 
GetReturnAddrFASTJITFunctionFrame1852     uintptr_t GetReturnAddr() const
1853     {
1854         return returnAddr;
1855     }
1856 
1857     void GCIterate(const FrameIterator &it, RootVisitor &visitor, FrameType frameType) const;
1858     void CollectPcOffsetInfo(const FrameIterator &it, ConstInfo &info) const;
1859 
GetFunctionFASTJITFunctionFrame1860     inline JSTaggedValue GetFunction() const
1861     {
1862         return jsFunc;
1863     }
1864 
ComputeArgsConfigFrameSpFASTJITFunctionFrame1865     static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp)
1866     {
1867         const size_t offset = 2;  // 2: skip prevFp and return address.
1868         return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t);
1869     }
1870 
1871     static size_t GetTypeOffset(bool isArch32 = false)
1872     {
1873         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
1874     }
1875 
1876     static size_t GetPcOffset(bool isArch32 = false)
1877     {
1878         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
1879     }
1880 
1881     static size_t GetPrevOffset(bool isArch32 = false)
1882     {
1883         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1884     }
1885 
1886     static size_t GetFunctionOffset(bool isArch32 = false)
1887     {
1888         return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32);
1889     }
1890 
ComputeReservedJSFuncOffsetFASTJITFunctionFrame1891     static size_t ComputeReservedJSFuncOffset(size_t slotSize)
1892     {
1893         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex);
1894         return slotSize * slotOffset;
1895     }
1896 
ComputeReservedPcOffsetFASTJITFunctionFrame1897     static size_t ComputeReservedPcOffset(size_t slotSize)
1898     {
1899         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PcIndex);
1900         return slotSize * slotOffset;
1901     }
1902 
GetFrmaeTypeToFpDeltaFASTJITFunctionFrame1903     static int GetFrmaeTypeToFpDelta()
1904     {
1905         return -(int)sizeof(uintptr_t);
1906     }
1907 
GetFunctionToFpDeltaFASTJITFunctionFrame1908     static int GetFunctionToFpDelta()
1909     {
1910         int slotOffset = static_cast<int>(Index::JSFuncIndex) - static_cast<int>(Index::TypeIndex);
1911         return slotOffset * static_cast<int>(JSTaggedValue::TaggedTypeSize()) + GetFrmaeTypeToFpDelta();
1912     }
1913 
GetTypeFASTJITFunctionFrame1914     FrameType GetType() const
1915     {
1916         return type;
1917     }
1918 
GetPcFASTJITFunctionFrame1919     inline const uint8_t *GetPc() const
1920     {
1921         return pc;
1922     }
1923 
1924     friend class FrameIterator;
1925     friend class FrameHandler;
1926     void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const;
1927     void GetFuncCalleeRegAndOffset(
1928         const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const;
1929     uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const;
1930 
1931 private:
GetFrameFromSpFASTJITFunctionFrame1932     static FASTJITFunctionFrame* GetFrameFromSp(const JSTaggedType *sp)
1933     {
1934         return reinterpret_cast<FASTJITFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) -
1935             MEMBER_OFFSET(FASTJITFunctionFrame, prevFp));
1936     }
1937 
GetFuncAddrFromSpFASTJITFunctionFrame1938     static uintptr_t GetFuncAddrFromSp(const JSTaggedType *sp)
1939     {
1940         return reinterpret_cast<uintptr_t>(sp) - MEMBER_OFFSET(FASTJITFunctionFrame, type);
1941     }
1942 
1943     // dynamic callee saveregisters for x86-64
1944     alignas(EAS) const uint8_t *pc {nullptr};
1945     alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()};
1946     alignas(EAS) FrameType type {0};
1947     alignas(EAS) JSTaggedType *prevFp {nullptr};
1948     alignas(EAS) uintptr_t returnAddr {0};
1949     // dynamic callee saveregisters for arm64
1950 };
1951 
1952 enum class GCVisitedFlag : uint8_t {
1953     VISITED = 0,
1954     IGNORED,
1955     HYBRID_STACK,
1956     DEOPT,
1957 };
1958 
1959 class FrameIterator {
1960 public:
1961     using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
1962     using CallSiteInfo = std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec>;
1963     explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr);
GetFrameType()1964     FrameType GetFrameType() const
1965     {
1966         ASSERT(current_ != nullptr);
1967         FrameType *typeAddr = reinterpret_cast<FrameType *>(
1968             reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType));
1969         return *typeAddr;
1970     }
1971 
1972     template<class T>
GetFrame()1973     T* GetFrame()
1974     {
1975         return T::GetFrameFromSp(current_);
1976     }
1977 
1978     template<class T>
GetFrame()1979     const T* GetFrame() const
1980     {
1981         return T::GetFrameFromSp(current_);
1982     }
1983 
Done()1984     bool Done() const
1985     {
1986         return current_ == nullptr;
1987     }
GetSp()1988     JSTaggedType *GetSp() const
1989     {
1990         return current_;
1991     }
GetSp()1992     JSTaggedType *GetSp()
1993     {
1994         return current_;
1995     }
GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)1996     void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const
1997     {
1998         ret = calleeRegInfo_;
1999     }
2000     int ComputeDelta(const Method *method = nullptr) const;
2001     template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED>
2002     void Advance();
2003     std::map<uint32_t, uint32_t> GetInlinedMethodInfo();
2004     uint32_t GetBytecodeOffset() const;
2005     uintptr_t GetPrevFrameCallSiteSp() const;
2006     uintptr_t GetPrevFrame() const;
GetCallSiteSp()2007     uintptr_t GetCallSiteSp() const
2008     {
2009         return optimizedCallSiteSp_;
2010     }
GetOptimizedReturnAddr()2011     uintptr_t GetOptimizedReturnAddr() const
2012     {
2013         return optimizedReturnAddr_;
2014     }
GetThread()2015     const JSThread *GetThread() const
2016     {
2017         return thread_;
2018     }
2019     bool IteratorStackMap(RootVisitor &visitor) const;
2020     void CollectPcOffsetInfo(ConstInfo &info) const;
2021     void CollectMethodOffsetInfo(std::map<uint32_t, uint32_t> &info) const;
2022     void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const;
2023     std::pair<CallSiteInfo, bool> CalCallSiteInfo(uintptr_t retAddr, bool isDeopt) const;
2024     CallSiteInfo TryCalCallSiteInfoFromMachineCode(uintptr_t retAddr) const;
2025 
2026     Method *CheckAndGetMethod() const;
2027     JSTaggedValue GetFunction() const;
2028 
IsLeaveFrame()2029     bool IsLeaveFrame() const
2030     {
2031         FrameType type = GetFrameType();
2032         return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV);
2033     }
2034 
IsOptimizedFrame()2035     bool IsOptimizedFrame() const
2036     {
2037         FrameType type = GetFrameType();
2038         return (type == FrameType::OPTIMIZED_FRAME);
2039     }
2040 
IsInterpretedFrame(FrameType type)2041     bool IsInterpretedFrame(FrameType type) const
2042     {
2043         return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST);
2044     }
2045 
IsJSFrame()2046     bool IsJSFrame() const
2047     {
2048         FrameType type = GetFrameType();
2049         return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type) || IsFastJitFunctionFrame(type);
2050     }
2051 
IsOptimizedJSFunctionFrame(FrameType type)2052     bool IsOptimizedJSFunctionFrame(FrameType type) const
2053     {
2054         return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME ||
2055             type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME;
2056     }
2057 
IsOptimizedJSFunctionFrame()2058     bool IsOptimizedJSFunctionFrame() const
2059     {
2060         FrameType type = GetFrameType();
2061         return IsOptimizedJSFunctionFrame(type);
2062     }
2063 
IsFastJitFunctionFrame(FrameType type)2064     bool IsFastJitFunctionFrame(FrameType type) const
2065     {
2066         return type == FrameType::FASTJIT_FUNCTION_FRAME ||
2067             type == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME;
2068     }
2069 
IsFastJitFunctionFrame()2070     bool IsFastJitFunctionFrame() const
2071     {
2072         FrameType type = GetFrameType();
2073         return IsFastJitFunctionFrame(type);
2074     }
2075 
IsAotOrJitFunctionFrame()2076     bool IsAotOrJitFunctionFrame() const
2077     {
2078         return IsOptimizedJSFunctionFrame() || IsFastJitFunctionFrame();
2079     }
2080 
GetMachineCodeSlot()2081     JSTaggedType *GetMachineCodeSlot() const
2082     {
2083         return const_cast<JSTaggedType*>(&machineCode_);
2084     }
2085 
2086 private:
2087     uint32_t GetBaselineBytecodeOffset() const;
2088 
2089     JSTaggedType *current_ {nullptr};
2090     const JSThread *thread_ {nullptr};
2091     const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr};
2092     uintptr_t optimizedCallSiteSp_ {0};
2093     uintptr_t optimizedReturnAddr_ {0};
2094     uint8_t *stackMapAddr_ {nullptr};
2095     kungfu::CalleeRegAndOffsetVec calleeRegInfo_;
2096 
2097     // in jit, delta on method is not set, get it from iterator
2098     bool isJITFrame_ {false};
2099     int fpDeltaPrevFrameSp_ {0};
2100 
2101     // cache current machine code, it's nonmovable
2102     JSTaggedType machineCode_ {JSTaggedValue::VALUE_UNDEFINED};
2103     uintptr_t baselineNativePc_ {0}; // For baselineJit upFrame
2104 };
2105 }  // namespace panda::ecmascript
2106 #endif // ECMASCRIPT_FRAMES_H
2107