• 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 // Here list all scenarios of calling between Runtime/CInterpreter/ASMInterpreter/AOTCompiler/CBuiltin/ASMBuitlin.
36 // Please note that the "[]" means a must frame while "<>" means an optional frame. Each case is from top to down.
37 //
38 // * Runtime (C++) => CInterpreter:
39 //          1) [INTERPRETER_FRAME]
40 //
41 // * Runtime (C++) -> AOTCompiler:
42 //          1) [OPTIMIZED_ENTRY_FRAME]
43 //             <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME>
44 //             <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME>
45 //             [OPTIMIZED_JS_FUNCTION_FRAME]
46 //
47 // * Runtime (C++) => ASMInterpreter:
48 //          1) [INTERPRETER_ENTRY_FRAME][ASM_INTERPRETER_FRAME]
49 //
50 // * Runtime (C++) => CBuiltin:
51 //          1) [not supported]
52 //
53 // * Runtime (C++) => ASMBuiltin:
54 //          1) [not supported]
55 //
56 // * CInterpreter => CInterpreter:
57 //          1) [INTERPRETER_FRAME]
58 //
59 // * CInterpreter => Runtime (C++):
60 //          1) [INTERPRETER_FAST_NEW_FRAME]
61 //          2) [INTERPRETER_CONSTRUCTOR_FRAME]
62 //
63 // * CInterpreter => AOTCompiler:
64 //          1) [not supported]
65 //
66 // * CInterperter => CBuiltin:
67 //          1) [INTERPRETER_BUILTIN_FRAME]
68 //
69 // * CInterpreter => ASMBuiltin:
70 //          1) [not supported]
71 //
72 // * ASMInterpreter => Runtime (C++):
73 //          1) [LEAVE_FRAME]
74 //          2) [LEAVE_FRAME_WITH_ARGV]
75 //
76 // * ASMInterpreter => AOTCompiler:
77 //          1) [OPTIMIZED_ENTRY_FRAME]
78 //             <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME>
79 //             <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME>
80 //             [OPTIMIZED_JS_FUNCTION_FRAME]
81 //
82 // * ASMInterpreter => ASMInterpreter:
83 //          1) [ASM_INTERPRETER_FRAME]
84 //
85 // * ASMInterpreter => AsmBuiltin:
86 //          1) [BUILTIN_ENTRY_FRAME]
87 //             [BUILTIN_FRAME]
88 //          2) [BUILTIN_ENTRY_FRAME]
89 //             [BUILTIN_FRAME_WITH_ARGV]
90 //
91 // * ASMInterpreter => CBuiltin:
92 //          1) [LEAVE_FRAME]
93 //          2) [LEAVE_FRAME_WITH_ARGV]
94 //
95 // * AOTCompiler => Runtime (C++):
96 //          1) [LEAVE_FRAME]
97 //          2) [LEAVE_FRAME_WITH_ARGV]
98 //
99 // * AOTCompiler => ASMInterpreter:
100 //          1) [ASM_INTERPRETER_BRIDGE_FRAME]
101 //          2) [ASM_INTERPRETER_FRAME]
102 //
103 // * AOTCompiler => CBuiltin:
104 //          1) [LEAVE_FRAME]
105 //          2) [LEAVE_FRAME_WITH_ARGV]
106 //
107 // * AOTCompiler => ASMBuiltin:
108 //          1) [BUILTIN_ENTRY_FRAME]
109 //             [BUILTIN_FRAME]
110 //          2) [BUILTIN_ENTRY_FRAME]
111 //             [BUILTIN_FRAME_WITH_ARGV]
112 
113 
114 enum class FrameType: uintptr_t {
115     OPTIMIZED_FRAME = 0,
116     OPTIMIZED_ENTRY_FRAME,
117     OPTIMIZED_JS_FUNCTION_FRAME,
118     OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME,
119     FASTJIT_FUNCTION_FRAME,
120     FASTJIT_FAST_CALL_FUNCTION_FRAME,
121     ASM_BRIDGE_FRAME,
122     LEAVE_FRAME,
123     LEAVE_FRAME_WITH_ARGV,
124     BUILTIN_CALL_LEAVE_FRAME,
125     INTERPRETER_FRAME,
126     ASM_INTERPRETER_FRAME,
127     INTERPRETER_CONSTRUCTOR_FRAME,
128     BUILTIN_FRAME,
129     BUILTIN_FRAME_WITH_ARGV,
130     BUILTIN_ENTRY_FRAME,
131     INTERPRETER_BUILTIN_FRAME,
132     INTERPRETER_FAST_NEW_FRAME,
133     INTERPRETER_ENTRY_FRAME,
134     ASM_INTERPRETER_ENTRY_FRAME,
135     ASM_INTERPRETER_BRIDGE_FRAME,
136     OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME,
137     OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME,
138     BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME,
139     BASELINE_BUILTIN_FRAME,
140 
141     FRAME_TYPE_FIRST = OPTIMIZED_FRAME,
142     FRAME_TYPE_LAST = OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME,
143     INTERPRETER_FIRST = INTERPRETER_FRAME,
144     INTERPRETER_LAST = INTERPRETER_FAST_NEW_FRAME,
145     BUILTIN_FIRST = BUILTIN_FRAME,
146     BUILTIN_LAST = BUILTIN_ENTRY_FRAME,
147 };
148 
149 enum class JSCallMode : uintptr_t {
150     CALL_ARG0 = 0,
151     CALL_ARG1,
152     CALL_ARG2,
153     CALL_ARG3,
154     CALL_THIS_ARG0,
155     CALL_THIS_ARG1,
156     CALL_THIS_ARG2,
157     CALL_THIS_ARG3,
158     CALL_WITH_ARGV,
159     CALL_THIS_WITH_ARGV,
160     CALL_CONSTRUCTOR_WITH_ARGV,
161     SUPER_CALL_WITH_ARGV,
162     SUPER_CALL_SPREAD_WITH_ARGV,
163     DEPRECATED_CALL_ARG0,
164     DEPRECATED_CALL_ARG1,
165     DEPRECATED_CALL_ARG2,
166     DEPRECATED_CALL_ARG3,
167     DEPRECATED_CALL_WITH_ARGV,
168     DEPRECATED_CALL_THIS_WITH_ARGV,
169     DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV,
170     CALL_GETTER,
171     CALL_SETTER,
172     CALL_THIS_ARG2_WITH_RETURN,
173     CALL_THIS_ARG3_WITH_RETURN,
174     CALL_THIS_ARGV_WITH_RETURN,
175     CALL_ENTRY,
176     CALL_GENERATOR,
177     CALL_FROM_AOT,
178 };
179 
180 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
181 struct OptimizedFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
182                                                    base::AlignedPointer,
183                                                    base::AlignedPointer,
184                                                    base::AlignedPointer> {
185 public:
186     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
187 
188     static size_t GetTypeOffset(bool isArch32 = false)
189     {
190         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
191     }
192 
193     static size_t GetPrevOffset(bool isArch32 = false)
194     {
195         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
196     }
197 
198     static size_t GetReturnAddrOffset(bool isArch32 = false)
199     {
200         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
201     }
202 
ComputeReservedSizeOptimizedFrame203     static size_t ComputeReservedSize(size_t slotSize)
204     {
205         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex);
206         return slotSize * slotOffset;
207     }
208 
GetTypeOptimizedFrame209     FrameType GetType() const
210     {
211         return type;
212     }
213 
214 private:
215     enum class Index : size_t {
216         TypeIndex = 0,
217         PrevFpIndex,
218         ReturnAddrIndex,
219         NumOfMembers
220     };
221     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
222 
GetFrameFromSpOptimizedFrame223     static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp)
224     {
225         return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp) -
226             MEMBER_OFFSET(OptimizedFrame, prevFp));
227     }
GetPrevFrameFpOptimizedFrame228     inline JSTaggedType* GetPrevFrameFp()
229     {
230         return prevFp;
231     }
GetReturnAddrOptimizedFrame232     uintptr_t GetReturnAddr() const
233     {
234         return returnAddr;
235     }
236 
GetReturnAddrAddressOptimizedFrame237     const uintptr_t *GetReturnAddrAddress() const
238     {
239         return &returnAddr;
240     }
241 
242     alignas(EAS) FrameType type {0};
243     alignas(EAS) JSTaggedType *prevFp {nullptr};
244     alignas(EAS) uintptr_t returnAddr {0};
245     friend class FrameIterator;
246 };
247 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64);
248 
249 // * BaselineBuiltinFrame layout as the following:
250 //               +--------------------------+ ---------
251 //               |       . . . . .          |         ^
252 // callerSP ---> |--------------------------|         |
253 //               |       returnAddr         |         |
254 //               |--------------------------|   BuiltinBuiltinFrame
255 //               |       callsiteFp         |         |
256 //       fp ---> |--------------------------|         |
257 //               |       frameType          |         v
258 //               +--------------------------+ ---------
259 //               |        . . . .           |
260 // calleeSP ---> +--------------------------+
261 //
262 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
263 struct BaselineBuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
264                                                          base::AlignedPointer,
265                                                          base::AlignedPointer,
266                                                          base::AlignedPointer> {
267 public:
268     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
269 
270     static size_t GetTypeOffset(bool isArch32 = false)
271     {
272         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
273     }
274 
275     static size_t GetPrevOffset(bool isArch32 = false)
276     {
277         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
278     }
279 
280     static size_t GetReturnAddrOffset(bool isArch32 = false)
281     {
282         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
283     }
284 
ComputeReservedSizeBaselineBuiltinFrame285     static size_t ComputeReservedSize(size_t slotSize)
286     {
287         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex);
288         return slotSize * slotOffset;
289     }
290 
GetTypeBaselineBuiltinFrame291     FrameType GetType() const
292     {
293         return type;
294     }
295 
GetReturnAddrBaselineBuiltinFrame296     uintptr_t GetReturnAddr() const
297     {
298         return returnAddr;
299     }
300 
GetReturnAddrAddressBaselineBuiltinFrame301     const uintptr_t *GetReturnAddrAddress() const
302     {
303         return &returnAddr;
304     }
305 private:
306     enum class Index : size_t {
307         TypeIndex = 0,
308         PrevFpIndex,
309         ReturnAddrIndex,
310         NumOfMembers
311     };
312     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
313 
GetFrameFromSpBaselineBuiltinFrame314     static BaselineBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
315     {
316         return reinterpret_cast<BaselineBuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) -
317             MEMBER_OFFSET(BaselineBuiltinFrame, prevFp));
318     }
GetPrevFrameFpBaselineBuiltinFrame319     inline JSTaggedType* GetPrevFrameFp()
320     {
321         return prevFp;
322     }
323 
324     alignas(EAS) FrameType type {0};
325     alignas(EAS) JSTaggedType *prevFp {nullptr};
326     alignas(EAS) uintptr_t returnAddr {0};
327     friend class FrameIterator;
328 };
329 STATIC_ASSERT_EQ_ARCH(sizeof(BaselineBuiltinFrame), BaselineBuiltinFrame::SizeArch32, BaselineBuiltinFrame::SizeArch64);
330 
331 struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
332                                                    base::AlignedPointer,
333                                                    base::AlignedPointer,
334                                                    base::AlignedPointer> {
335 public:
336     static size_t GetTypeOffset(bool isArch32 = false)
337     {
338         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
339     }
340 
341     static size_t GetPrevOffset(bool isArch32 = false)
342     {
343         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
344     }
345 
346     static size_t GetReturnAddrOffset(bool isArch32 = false)
347     {
348         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
349     }
350 
GetCallSiteSpAsmBridgeFrame351     uintptr_t GetCallSiteSp() const
352     {
353         return ToUintPtr(this) + sizeof(AsmBridgeFrame);
354     }
355 
GetTypeAsmBridgeFrame356     FrameType GetType() const
357     {
358         return type;
359     }
360 
361 private:
362     enum class Index : size_t {
363         TypeIndex = 0,
364         PrevFpIndex,
365         ReturnAddrIndex,
366         NumOfMembers
367     };
368     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
369 
GetFrameFromSpAsmBridgeFrame370     static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
371     {
372         return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
373             MEMBER_OFFSET(AsmBridgeFrame, prevFp));
374     }
GetPrevFrameFpAsmBridgeFrame375     inline JSTaggedType* GetPrevFrameFp()
376     {
377         return prevFp;
378     }
379 
GetReturnAddrAsmBridgeFrame380     uintptr_t GetReturnAddr() const
381     {
382         return returnAddr;
383     }
384 
GetReturnAddrAddressAsmBridgeFrame385     const uintptr_t *GetReturnAddrAddress() const
386     {
387         return &returnAddr;
388     }
389 
390     alignas(EAS) FrameType type {0};
391     alignas(EAS) JSTaggedType *prevFp {nullptr};
392     alignas(EAS) uintptr_t returnAddr {0};
393     friend class FrameIterator;
394 };
395 STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64);
396 
397 // * OptimizedUnfoldArgVFrame layout description as the following:
398 // callerSP ---> |--------------------------| ---------------
399 //               |       returnAddr         |               ^
400 //               |--------------------------|               |
401 //               |       prevFp             |               |
402 //       fp ---> |--------------------------|   OptimizedUnfoldArgVFrame
403 //               |       frameType          |               |
404 //               |--------------------------|               |
405 //               |       currentFp          |               v
406 // calleESP ---> +--------------------------+ ---------------
407 //
408 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
409 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
410                                                                        base::AlignedPointer,
411                                                                        base::AlignedPointer,
412                                                                        base::AlignedPointer,
413                                                                        base::AlignedPointer> {
414 public:
415     static size_t GetTypeOffset(bool isArch32 = false)
416     {
417         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
418     }
419 
420     static size_t GetPrevOffset(bool isArch32 = false)
421     {
422         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
423     }
424 
425     static size_t GetReturnAddrOffset(bool isArch32 = false)
426     {
427         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
428     }
429 
GetTypeOptimizedJSFunctionUnfoldArgVFrame430     FrameType GetType() const
431     {
432         return type;
433     }
434 
435 private:
436     enum class Index : size_t {
437         CallSiteSpIndex = 0,
438         TypeIndex,
439         PrevFpIndex,
440         ReturnAddrIndex,
441         NumOfMembers
442     };
443     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
444 
GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame445     static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp)
446     {
447         return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp) -
448             MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp));
449     }
GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame450     inline JSTaggedType* GetPrevFrameFp() const
451     {
452         return prevFp;
453     }
454 
GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame455     uintptr_t GetReturnAddr() const
456     {
457         return returnAddr;
458     }
459 
GetReturnAddrAddressOptimizedJSFunctionUnfoldArgVFrame460     const uintptr_t *GetReturnAddrAddress() const
461     {
462         return &returnAddr;
463     }
464 
GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame465     uintptr_t GetPrevFrameSp() const
466     {
467         return callSiteSp;
468     }
469 
470     alignas(EAS) uintptr_t callSiteSp {0};
471     alignas(EAS) FrameType type {0};
472     alignas(EAS) JSTaggedType *prevFp {nullptr};
473     alignas(EAS) uintptr_t returnAddr {0};
474     friend class FrameIterator;
475 };
476 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame),
477     OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64);
478 
479 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following:
480 //          +--------------------------+
481 //          |         arg[N-1]         |
482 //          +--------------------------+
483 //          |         . . . .          |
484 //          +--------------------------+
485 //          |         arg[0]           |
486 //          +--------------------------+
487 //          |         argC             |
488 //  sp ---> +--------------------------+ -----------------
489 //          |                          |                 ^
490 //          |        prevFP            |                 |
491 //  fp ---> |--------------------------|    OptimizedJSFunctionArgsConfigFrame
492 //          |       frameType          |                 |
493 //          |                          |                 V
494 //          +--------------------------+ -----------------
495 //
496 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
497 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
498                                                                       base::AlignedPointer,
499                                                                       base::AlignedPointer> {
500 public:
501     static size_t GetTypeOffset(bool isArch32 = false)
502     {
503         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
504     }
505 
506     static size_t GetPrevOffset(bool isArch32 = false)
507     {
508         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
509     }
510 
GetTypeOptimizedJSFunctionArgConfigFrame511     FrameType GetType() const
512     {
513         return type;
514     }
515 
516 private:
517     enum class Index : size_t {
518         TypeIndex = 0,
519         PrevFpIndex,
520         NumOfMembers
521     };
522     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
523 
GetFrameFromSpOptimizedJSFunctionArgConfigFrame524     static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp)
525     {
526         return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp) -
527             MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp));
528     }
GetPrevFrameFpOptimizedJSFunctionArgConfigFrame529     inline JSTaggedType* GetPrevFrameFp()
530     {
531         return prevFp;
532     }
533 
534     alignas(EAS) FrameType type {0};
535     alignas(EAS) JSTaggedType *prevFp {nullptr};
536     friend class FrameIterator;
537 };
538 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame),
539                       OptimizedJSFunctionArgConfigFrame::SizeArch32,
540                       OptimizedJSFunctionArgConfigFrame::SizeArch64);
541 
542 // * OptimizedJSFunctionFrame layout description as the following:
543 //                 +----------------------------------------+
544 //                 |     arg[N-1]                           |
545 //                 +----------------------------------------+
546 //                 |     ...                                |
547 //                 +----------------------------------------+
548 //                 |     arg[1]                             |
549 //                 +----------------------------------------+
550 //                 |     arg[0]                             |
551 //                 +----------------------------------------+
552 //                 |     this                               |
553 //                 +----------------------------------------+
554 //                 |     new-target [not exist in fastcall] |
555 //                 +----------------------------------------+
556 //                 |     call-target                        |
557 //       argv ---> +----------------------------------------+
558 //                 |     argv   [not exist in fastcall]     |
559 //                 |----------------------------------------|
560 //                 |     argc   [not exist in fastcall]     |
561 //   callerSp ---> |----------------------------------------|----------------
562 //                 |     returnAddr                         |               ^
563 //                 |----------------------------------------|               |
564 //                 |     callsiteFp                         |               |
565 //         fp ---> |----------------------------------------|   OptimizedJSFunctionFrame
566 //                 |     frameType                          |               |
567 //                 |----------------------------------------|               |
568 //                 |     call-target                        |               v
569 //   calleeSP ---> +----------------------------------------+----------------
570 //
571 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
572 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
573                                                              JSTaggedValue,
574                                                              base::AlignedPointer,
575                                                              base::AlignedPointer,
576                                                              base::AlignedPointer> {
577 public:
578     using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
579     enum class Index : size_t {
580         JSFuncIndex = 0,
581         TypeIndex,
582         PrevFpIndex,
583         ReturnAddrIndex,
584         NumOfMembers
585     };
586     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
587 
GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame588     static constexpr size_t GetFunctionDeltaReturnAddr()
589     {
590         return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex);
591     }
592 
GetPrevFrameFpOptimizedJSFunctionFrame593     inline JSTaggedType* GetPrevFrameFp()
594     {
595         return prevFp;
596     }
597 
GetArgvOptimizedJSFunctionFrame598     JSTaggedType* GetArgv(uintptr_t *preFrameSp) const
599     {
600         const size_t offset = 2;    // 2: skip argc and argv.
601         return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t));
602     }
603 
GetArgcOptimizedJSFunctionFrame604     size_t GetArgc(uintptr_t *preFrameSp) const
605     {
606         return *preFrameSp;
607     }
608 
609     JSTaggedType* GetArgv(const FrameIterator &it) const;
610 
GetReturnAddrOptimizedJSFunctionFrame611     uintptr_t GetReturnAddr() const
612     {
613         return returnAddr;
614     }
615 
GetReturnAddrAddressOptimizedJSFunctionFrame616     const uintptr_t *GetReturnAddrAddress() const
617     {
618         return &returnAddr;
619     }
620 
621     void GCIterate(const FrameIterator &it, RootVisitor &visitor, FrameType frameType) const;
622 
GetFunctionOptimizedJSFunctionFrame623     inline JSTaggedValue GetFunction() const
624     {
625         return jsFunc;
626     }
627 
ComputeArgsConfigFrameSpOptimizedJSFunctionFrame628     static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp)
629     {
630         const size_t offset = 2;  // 2: skip prevFp and return address.
631         return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t);
632     }
633 
634     static size_t GetTypeOffset(bool isArch32 = false)
635     {
636         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
637     }
638 
639     static size_t GetPrevOffset(bool isArch32 = false)
640     {
641         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
642     }
643 
644     static size_t GetFunctionOffset(bool isArch32 = false)
645     {
646         return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32);
647     }
648 
649     static size_t GetReturnAddrOffset(bool isArch32 = false)
650     {
651         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
652     }
653 
ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame654     static size_t ComputeReservedJSFuncOffset(size_t slotSize)
655     {
656         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex);
657         return slotSize * slotOffset;
658     }
659 
GetFrmaeTypeToFpDeltaOptimizedJSFunctionFrame660     static int GetFrmaeTypeToFpDelta()
661     {
662         return -(int)sizeof(uintptr_t);
663     }
664 
GetFunctionToFpDeltaOptimizedJSFunctionFrame665     static int GetFunctionToFpDelta()
666     {
667         int slotOffset = static_cast<int>(Index::JSFuncIndex) - static_cast<int>(Index::TypeIndex);
668         return slotOffset * static_cast<int>(JSTaggedValue::TaggedTypeSize()) + GetFrmaeTypeToFpDelta();
669     }
670 
GetTypeOptimizedJSFunctionFrame671     FrameType GetType() const
672     {
673         return type;
674     }
675 
676     friend class FrameIterator;
677     friend class FrameHandler;
678     void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const;
679     void GetFuncCalleeRegAndOffset(
680         const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const;
681     uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const;
682 
683 private:
GetFrameFromSpOptimizedJSFunctionFrame684     static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp)
685     {
686         return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) -
687             MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp));
688     }
689 
690     // dynamic callee saveregisters for x86-64
691     alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()};
692     alignas(EAS) FrameType type {0};
693     alignas(EAS) JSTaggedType *prevFp {nullptr};
694     alignas(EAS) uintptr_t returnAddr {0};
695     // dynamic callee saveregisters for arm64
696 };
697 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame),
698                       OptimizedJSFunctionFrame::SizeArch32,
699                       OptimizedJSFunctionFrame::SizeArch64);
700 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time.
701 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1);
702 
703 // * The JSFunctionEntry Frame's structure is illustrated as the following:
704 //              +--------------------------+
705 //              |      . . . . . .         |
706 // callerSP --> +--------------------------+ -----------------
707 //              |        prevFP            |                 ^
708 //       fp --> |--------------------------|                 |
709 //              |       frameType          |      JSFunctionEntryFrame
710 //              |--------------------------|                 |
711 //              |    preLeaveFrameFp       |                 v
712 // calleeSP --> +--------------------------+ -----------------
713 
714 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
715                                                         base::AlignedPointer,
716                                                         base::AlignedPointer,
717                                                         base::AlignedPointer> {
718 public:
719     enum class CallType : size_t {
720         CALL_FUNC = 0,
721         CALL_NEW,
722     };
723 
724     enum class Index : size_t {
725         PreLeaveFrameFpIndex = 0,
726         TypeIndex,
727         PrevFpIndex,
728         NumOfMembers
729     };
730 
731     static size_t GetTypeOffset(bool isArch32 = false)
732     {
733         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
734     }
735 
736     static size_t GetLeaveFrameFpOffset(bool isArch32 = false)
737     {
738         return GetOffset<static_cast<size_t>(Index::PreLeaveFrameFpIndex)>(isArch32);
739     }
740 
GetPrevFrameFpOptimizedEntryFrame741     inline JSTaggedType* GetPrevFrameFp()
742     {
743         return preLeaveFrameFp;
744     }
745 
ComputeReservedSizeOptimizedEntryFrame746     static size_t ComputeReservedSize(size_t slotSize)
747     {
748         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex);
749         return slotSize * slotOffset;
750     }
751 
GetTypeOptimizedEntryFrame752     FrameType GetType() const
753     {
754         return type;
755     }
756     friend class FrameIterator;
757 
758 private:
GetFrameFromSpOptimizedEntryFrame759     static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
760     {
761         return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) -
762                                                        MEMBER_OFFSET(OptimizedEntryFrame, prevFp));
763     }
764 
GetLeaveFpOptimizedEntryFrame765     JSTaggedType* GetLeaveFp() const
766     {
767         return preLeaveFrameFp;
768     }
769 
GetPrevFpOptimizedEntryFrame770     JSTaggedType* GetPrevFp() const
771     {
772         return prevFp;
773     }
774 
775     alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr};
776     alignas(EAS) FrameType type {0};
777     alignas(EAS) JSTaggedType *prevFp {nullptr};
778 };
779 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64);
780 
781 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
782 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(),
783                                                          base::AlignedPointer,
784                                                          base::AlignedSize> {
785     enum class Index : size_t {
786         PrevIndex = 0,
787         TypeIndex,
788         NumOfMembers
789     };
790     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
791 
GetPrevFrameFpInterpretedFrameBase792     inline JSTaggedType* GetPrevFrameFp()
793     {
794         return prev;
795     }
796 
GetFrameFromSpInterpretedFrameBase797     static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp)
798     {
799         return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1;
800     }
801 
802     static size_t GetPrevOffset(bool isArch32 = false)
803     {
804         return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32);
805     }
806 
807     static size_t GetTypeOffset(bool isArch32 = false)
808     {
809         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
810     }
811 
GetSizeInterpretedFrameBase812     static constexpr size_t GetSize(bool isArch32)
813     {
814         return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64;
815     }
816 
817     alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc
818     alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0
819 };
820 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase),
821                       InterpretedFrameBase::SizeArch32,
822                       InterpretedFrameBase::SizeArch64);
823 
824 // Interpreter Frame Layout as the following:
825 //   +----------------------------------+
826 //   |    argv[n-1]                     |
827 //   |----------------------------------|
828 //   |    ......                        |
829 //   |----------------------------------|
830 //   |    thisArg [maybe not exist]     |
831 //   |----------------------------------|
832 //   |    newTarget [maybe not exist]   |
833 //   |----------------------------------|
834 //   |    ......                        |
835 //   |----------------------------------|
836 //   |    Vregs [not exist in native]   |
837 //   +----------------------------------+--------+
838 //   |    base.frameType                |        ^
839 //   |----------------------------------|        |
840 //   |    base.prev(prev stack pointer) |        |
841 //   |----------------------------------|        |
842 //   |    pc(bytecode addr)             |        |
843 //   |----------------------------------|        |
844 //   |    sp(current stack pointer)     |        |
845 //   |----------------------------------|        |
846 //   |    env                           |        |
847 //   |----------------------------------|        |
848 //   |    acc                           |        |
849 //   |----------------------------------|   InterpretedFrame
850 //   |    profileTypeInfo               |        |
851 //   |----------------------------------|        |
852 //   |    thisObj                       |        |
853 //   |----------------------------------|        |
854 //   |    function                      |        |
855 //   |----------------------------------|        |
856 //   |    constpool                     |        v
857 //   +----------------------------------+--------+
858 //
859 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
860 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
861                                                      JSTaggedValue,
862                                                      JSTaggedValue,
863                                                      JSTaggedValue,
864                                                      JSTaggedValue,
865                                                      JSTaggedValue,
866                                                      JSTaggedValue,
867                                                      base::AlignedPointer,
868                                                      InterpretedFrameBase> {
869 public:
870     enum class Index : size_t {
871         ConstPoolIndex = 0,
872         FunctionIndex,
873         ThisObjIndex,
874         ProFileTypeInfoIndex,
875         AccIndex,
876         EnvIndex,
877         PcIndex,
878         BaseIndex,
879         NumOfMembers
880     };
881     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
882 
GetPrevFrameFpInterpretedFrame883     inline JSTaggedType* GetPrevFrameFp() const
884     {
885         return base.prev;
886     }
887 
GetFrameFromSpInterpretedFrame888     static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
889     {
890         return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
891     }
892 
GetPcInterpretedFrame893     inline const uint8_t *GetPc() const
894     {
895         return pc;
896     }
897 
GetEnvInterpretedFrame898     inline JSTaggedValue GetEnv() const
899     {
900         return env;
901     }
902 
NumOfMembersInterpretedFrame903     static uint32_t NumOfMembers()
904     {
905         return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize();
906     }
907 
GetPcOffsetInterpretedFrame908     static size_t GetPcOffset(bool isArch32)
909     {
910         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
911     }
912 
913     static size_t GetTypeOffset(bool isArch32 = false)
914     {
915         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
916             InterpretedFrameBase::GetTypeOffset(isArch32);
917     }
918 
919     static size_t GetPrevOffset(bool isArch32 = false)
920     {
921         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
922             InterpretedFrameBase::GetPrevOffset(isArch32);
923     }
924 
925     static size_t GetFunctionOffset(bool isArch32 = false)
926     {
927         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
928     }
929 
930     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
931 
932     alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()};
933     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
934     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
935     alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()};
936     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
937     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
938     alignas(EAS) const uint8_t *pc {nullptr};
939     alignas(EAS) InterpretedFrameBase base;
940     friend class FrameIterator;
941 };
942 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64);
943 
944 // * InterpretedBuiltinFrame layout description as the following:
945 //               |--------------------------| ---------------
946 //               |         . . . . .        |               ^
947 //               |    InterpretedFrameBase  |               |
948 //               |         . . . . .        |               |
949 //               |--------------------------|    InterpretedBuiltinFrame
950 //               |       bytecode-PC        |               |
951 //               |--------------------------|               |
952 //               |       call-target        |               v
953 //               +--------------------------+ ---------------
954 //
955 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
956 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
957                                                             JSTaggedValue,
958                                                             base::AlignedPointer,
959                                                             InterpretedFrameBase> {
960     enum class Index : size_t {
961         FunctionIndex = 0,
962         PcIndex,
963         BaseIndex,
964         NumOfMembers
965     };
966     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
967 
GetPrevFrameFpInterpretedBuiltinFrame968     inline JSTaggedType* GetPrevFrameFp()
969     {
970         return base.prev;
971     }
972 
GetFrameFromSpInterpretedBuiltinFrame973     static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
974     {
975         return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
976     }
977 
NumOfMembersInterpretedBuiltinFrame978     static uint32_t NumOfMembers()
979     {
980         return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize();
981     }
982 
983     static size_t GetTypeOffset(bool isArch32 = false)
984     {
985         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
986             InterpretedFrameBase::GetTypeOffset(isArch32);
987     }
988 
989     static size_t GetPrevOffset(bool isArch32 = false)
990     {
991         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
992             InterpretedFrameBase::GetPrevOffset(isArch32);
993     }
994 
995     static size_t GetFunctionOffset(bool isArch32 = false)
996     {
997         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
998     }
999 
1000     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1001 
1002     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
1003     alignas(EAS) const uint8_t *pc {nullptr};
1004     alignas(EAS) InterpretedFrameBase base;
1005 };
1006 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame),
1007                       InterpretedBuiltinFrame::SizeArch32,
1008                       InterpretedBuiltinFrame::SizeArch64);
1009 
1010 // AsmInterpretedFrame Layout as the following:
1011 //   +----------------------------------+
1012 //   |    argv[n-1]                     |
1013 //   |----------------------------------|
1014 //   |    ......                        |
1015 //   |----------------------------------|
1016 //   |    thisArg [maybe not exist]     |
1017 //   |----------------------------------|
1018 //   |    newTarget [maybe not exist]   |
1019 //   |----------------------------------|
1020 //   |    ......                        |
1021 //   |----------------------------------|
1022 //   |    Vregs [not exist in native]   |
1023 //   +----------------------------------+--------+
1024 //   |        .  .  .   .               |        ^
1025 //   |     InterpretedFrameBase         |        |
1026 //   |        .  .  .   .               |        |
1027 //   |----------------------------------|        |
1028 //   |    pc(bytecode addr)             |        |
1029 //   |----------------------------------|        |
1030 //   |    sp(current stack pointer)     |        |
1031 //   |----------------------------------|   AsmInterpretedFrame
1032 //   |    callSize                      |        |
1033 //   |----------------------------------|        |
1034 //   |    env                           |        |
1035 //   |----------------------------------|        |
1036 //   |    acc                           |        |
1037 //   |----------------------------------|        |
1038 //   |    thisObj                       |        |
1039 //   |----------------------------------|        |
1040 //   |    call-target                   |        v
1041 //   +----------------------------------+--------+
1042 //
1043 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1044 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1045                                                         JSTaggedValue,
1046                                                         JSTaggedValue,
1047                                                         JSTaggedValue,
1048                                                         JSTaggedValue,
1049                                                         base::AlignedPointer,
1050                                                         base::AlignedPointer,
1051                                                         base::AlignedPointer,
1052                                                         InterpretedFrameBase> {
1053     enum class Index : size_t {
1054         FunctionIndex = 0,
1055         ThisObjIndex,
1056         AccIndex,
1057         EnvIndex,
1058         CallSizeIndex,
1059         FpIndex,
1060         PcIndex,
1061         BaseIndex,
1062         NumOfMembers
1063     };
1064 
1065     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1066 
GetCurrentFramePointerAsmInterpretedFrame1067     inline JSTaggedType* GetCurrentFramePointer()
1068     {
1069         return fp;
1070     }
1071 
GetPrevFrameFpAsmInterpretedFrame1072     inline JSTaggedType* GetPrevFrameFp()
1073     {
1074         return base.prev;
1075     }
1076 
GetFrameFromSpAsmInterpretedFrame1077     static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
1078     {
1079         return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
1080     }
1081 
GetFpOffsetAsmInterpretedFrame1082     static size_t GetFpOffset(bool isArch32)
1083     {
1084         return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32);
1085     }
1086 
GetCallSizeOffsetAsmInterpretedFrame1087     static size_t GetCallSizeOffset(bool isArch32)
1088     {
1089         return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32);
1090     }
1091 
GetFunctionOffsetAsmInterpretedFrame1092     static size_t GetFunctionOffset(bool isArch32)
1093     {
1094         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
1095     }
1096 
GetThisOffsetAsmInterpretedFrame1097     static size_t GetThisOffset(bool isArch32)
1098     {
1099         return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32);
1100     }
1101 
GetAccOffsetAsmInterpretedFrame1102     static size_t GetAccOffset(bool isArch32)
1103     {
1104         return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32);
1105     }
1106 
GetEnvOffsetAsmInterpretedFrame1107     static size_t GetEnvOffset(bool isArch32)
1108     {
1109         return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32);
1110     }
1111 
GetBaseOffsetAsmInterpretedFrame1112     static size_t GetBaseOffset(bool isArch32)
1113     {
1114         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
1115     }
1116 
GetPcOffsetAsmInterpretedFrame1117     static size_t GetPcOffset(bool isArch32)
1118     {
1119         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
1120     }
1121 
GetSizeAsmInterpretedFrame1122     static constexpr size_t GetSize(bool isArch32)
1123     {
1124         return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64;
1125     }
1126 
GetFpOffsetAsIntptrAsmInterpretedFrame1127     static intptr_t GetFpOffsetAsIntptr(bool isArch32)
1128     {
1129         return static_cast<intptr_t>(GetFpOffset(isArch32));
1130     }
1131 
GetFunctionOffsetAsIntptrAsmInterpretedFrame1132     static intptr_t GetFunctionOffsetAsIntptr(bool isArch32)
1133     {
1134         return static_cast<intptr_t>(GetFunctionOffset(isArch32));
1135     }
1136 
GetSizeAsIntptrAsmInterpretedFrame1137     static intptr_t GetSizeAsIntptr(bool isArch32)
1138     {
1139         return static_cast<intptr_t>(GetSize(isArch32));
1140     }
1141 
NumOfMembersAsmInterpretedFrame1142     static uint32_t NumOfMembers()
1143     {
1144         return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize();
1145     }
1146     void GCIterate(const FrameIterator &it, RootVisitor &visitor, bool isBaselineFrame) const;
1147 
GetEnvAsmInterpretedFrame1148     JSTaggedValue GetEnv() const
1149     {
1150         return env;
1151     }
1152 
GetPcAsmInterpretedFrame1153     const uint8_t *GetPc() const
1154     {
1155         return pc;
1156     }
1157 
GetTypeOffsetAsmInterpretedFrame1158     static size_t GetTypeOffset()
1159     {
1160         return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type);
1161     }
1162 
GetPrevOffsetAsmInterpretedFrame1163     static size_t GetPrevOffset()
1164     {
1165         return MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, prev);
1166     }
1167 
1168     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
1169     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
1170     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
1171     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
1172     alignas(EAS) uintptr_t callSize {0};
1173     alignas(EAS) JSTaggedType *fp {nullptr};
1174     alignas(EAS) const uint8_t *pc {nullptr};
1175     alignas(EAS) InterpretedFrameBase base;
1176     // vregs, not exist in native
1177     // args, may be truncated if not extra
1178 };
1179 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64);
1180 
1181 // InterpretedEntryFrame Layout as the following:
1182 //   +----------------------------------+---------------
1183 //   |        .  .  .   .               |              ^
1184 //   |     InterpretedFrameBase         |              |
1185 //   |        .  .  .   .               |    InterpretedEntryFrame
1186 //   |----------------------------------|              |
1187 //   |    pc(bytecode addr)             |              v
1188 //   |----------------------------------|---------------
1189 //
1190 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1191 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1192                                                           base::AlignedPointer,
1193                                                           InterpretedFrameBase> {
1194     enum class Index : size_t {
1195         PcIndex = 0,
1196         BaseIndex,
1197         NumOfMembers
1198     };
1199     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1200 
GetPrevFrameFpInterpretedEntryFrame1201     inline JSTaggedType* GetPrevFrameFp()
1202     {
1203         return base.prev;
1204     }
1205 
GetFrameFromSpInterpretedEntryFrame1206     static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
1207     {
1208         return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
1209     }
1210 
NumOfMembersInterpretedEntryFrame1211     static uint32_t NumOfMembers()
1212     {
1213         return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize();
1214     }
1215 
1216     static size_t GetTypeOffset(bool isArch32 = false)
1217     {
1218         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1219             InterpretedFrameBase::GetTypeOffset(isArch32);
1220     }
1221 
1222     static size_t GetPrevOffset(bool isArch32 = false)
1223     {
1224         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1225             InterpretedFrameBase::GetPrevOffset(isArch32);
1226     }
1227 
1228     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1229     alignas(EAS) const uint8_t *pc {nullptr};
1230     alignas(EAS) InterpretedFrameBase base;
1231 };
1232 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame),
1233                       InterpretedEntryFrame::SizeArch32,
1234                       InterpretedEntryFrame::SizeArch64);
1235 
1236 
1237 // AsmInterpretedEntryFrame Layout as the following:
1238 //   +----------------------------------+---------------
1239 //   |        .  .  .   .               |              ^
1240 //   |     InterpretedFrameBase         |              |
1241 //   |        .  .  .   .               |    AsmInterpretedEntryFrame
1242 //   |----------------------------------|              |
1243 //   |    pc(bytecode addr)             |              v
1244 //   |----------------------------------|---------------
1245 //
1246 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1247 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1248                                                              base::AlignedPointer,
1249                                                              InterpretedFrameBase> {
1250     enum class Index : size_t {
1251         PcIndex = 0,
1252         BaseIndex,
1253         NumOfMembers
1254     };
1255     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1256 
GetPrevFrameFpAsmInterpretedEntryFrame1257     inline JSTaggedType* GetPrevFrameFp()
1258     {
1259         return base.prev;
1260     }
1261 
GetBaseOffsetAsmInterpretedEntryFrame1262     static size_t GetBaseOffset(bool isArch32)
1263     {
1264         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
1265     }
1266 
GetFrameFromSpAsmInterpretedEntryFrame1267     static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
1268     {
1269         return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
1270     }
1271 
1272     static size_t GetTypeOffset(bool isArch32 = false)
1273     {
1274         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1275             InterpretedFrameBase::GetTypeOffset(isArch32);
1276     }
1277 
1278     static size_t GetPrevOffset(bool isArch32 = false)
1279     {
1280         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32) +
1281             InterpretedFrameBase::GetPrevOffset(isArch32);
1282     }
1283 
1284     alignas(EAS) const uint8_t *pc {nullptr};
1285     alignas(EAS) InterpretedFrameBase base;
1286 };
1287 
1288 // AsmInterpretedBridgeFrame Layout as the following:
1289 //   +----------------------------------+---------------
1290 //   |      ret-address                 |              ^
1291 //   |----------------------------------|              |
1292 //   |        .  .  .   .               |     AsmInterpretedBridgeFrame
1293 //   |     AsmInterpretedEntryFrame     |              |
1294 //   |        .  .  .   .               |              v
1295 //   |----------------------------------|---------------
1296 //
1297 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1298 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1299                                                               AsmInterpretedEntryFrame,
1300                                                               base::AlignedPointer> {
1301     enum class Index : size_t {
1302         EntryIndex = 0,
1303         ReturnAddrIndex,
1304         NumOfMembers
1305     };
1306     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1307 
GetFrameFromSpAsmInterpretedBridgeFrame1308     static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
1309     {
1310         return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
1311             MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr));
1312     }
GetCallSiteSpAsmInterpretedBridgeFrame1313     uintptr_t GetCallSiteSp() const
1314     {
1315         return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame);
1316     }
GetPrevFrameFpAsmInterpretedBridgeFrame1317     inline JSTaggedType* GetPrevFrameFp()
1318     {
1319         return entry.base.prev;
1320     }
1321 
GetReturnAddrOffsetAsmInterpretedBridgeFrame1322     static size_t GetReturnAddrOffset(bool isArch32)
1323     {
1324         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
1325     }
1326 
GetSizeAsmInterpretedBridgeFrame1327     static constexpr size_t GetSize(bool isArch32)
1328     {
1329         return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64;
1330     }
1331 
1332     static size_t GetTypeOffset(bool isArch32 = false)
1333     {
1334         return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) +
1335             AsmInterpretedEntryFrame::GetBaseOffset(isArch32) +
1336             InterpretedFrameBase::GetTypeOffset(isArch32);
1337     }
1338     static size_t GetPrevOffset(bool isArch32 = false)
1339     {
1340         return GetOffset<static_cast<size_t>(Index::EntryIndex)>(isArch32) +
1341             AsmInterpretedEntryFrame::GetBaseOffset(isArch32) +
1342             InterpretedFrameBase::GetPrevOffset(isArch32);
1343     }
1344 
GetReturnAddrAsmInterpretedBridgeFrame1345     uintptr_t GetReturnAddr() const
1346     {
1347         return returnAddr;
1348     }
1349 
GetReturnAddrAddressAsmInterpretedBridgeFrame1350     const uintptr_t *GetReturnAddrAddress() const
1351     {
1352         return &returnAddr;
1353     }
1354 
1355     AsmInterpretedEntryFrame entry;
1356     alignas(EAS) uintptr_t returnAddr {0};
1357 };
1358 
1359 // * Optimized-leaved-frame layout as the following:
1360 //               +--------------------------+
1361 //               |       argv[N-1]          |
1362 //               |--------------------------|
1363 //               |       . . . . .          |
1364 //               |--------------------------|
1365 //               |       argv[0]            |
1366 //               +--------------------------+-------------
1367 //               |       argc               |            ^
1368 //               |--------------------------|            |
1369 //               |       RuntimeId          |            |
1370 //  callerSP --> |--------------------------|   OptimizedLeaveFrame
1371 //               |       ret-addr           |            |
1372 //               |--------------------------|            |
1373 //               |       prevFp             |            |
1374 //        fp --> |--------------------------|            |
1375 //               |       frameType          |            v
1376 //  calleeSP --> +--------------------------+-------------
1377 //
1378 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1379 struct OptimizedLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1380                                                         base::AlignedPointer,
1381                                                         base::AlignedPointer,
1382                                                         base::AlignedPointer,
1383                                                         base::AlignedUint64,
1384                                                         base::AlignedUint64> {
1385     // argv[0]...argv[argc-1] dynamic according to agc
GetFrameFromSpOptimizedLeaveFrame1386     static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1387     {
1388         return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1389             MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp));
1390     }
1391 
GetCallSiteSpOptimizedLeaveFrame1392     uintptr_t GetCallSiteSp() const
1393     {
1394         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId);
1395     }
1396 
GetPrevFrameFpOptimizedLeaveFrame1397     inline JSTaggedType* GetPrevFrameFp() const
1398     {
1399         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1400     }
1401 
GetReturnAddrOptimizedLeaveFrame1402     uintptr_t GetReturnAddr() const
1403     {
1404         return returnAddr;
1405     }
1406 
GetReturnAddrAddressOptimizedLeaveFrame1407     const uintptr_t *GetReturnAddrAddress() const
1408     {
1409         return &returnAddr;
1410     }
1411 
GetTypeOffsetOptimizedLeaveFrame1412     static size_t GetTypeOffset()
1413     {
1414         return MEMBER_OFFSET(OptimizedLeaveFrame, type);
1415     }
1416 
GetPrevOffsetOptimizedLeaveFrame1417     static size_t GetPrevOffset()
1418     {
1419         return MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp);
1420     }
1421 
GetReturnAddrOffsetOptimizedLeaveFrame1422     static size_t GetReturnAddrOffset()
1423     {
1424         return MEMBER_OFFSET(OptimizedLeaveFrame, returnAddr);
1425     }
1426 
1427     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1428 
1429     alignas(EAS) FrameType type {0};
1430     alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here
1431     alignas(EAS) uintptr_t returnAddr {0};
1432     alignas(EAS) uint64_t argRuntimeId {0};
1433     alignas(EAS) uint64_t argc {0};
1434 };
1435 
1436 // * Optimized-leaved-frame-with-argv layout as the following:
1437 //               +--------------------------+
1438 //               |       argv[]             |
1439 //               +--------------------------+-------------
1440 //               |       argc               |            ^
1441 //               |--------------------------|            |
1442 //               |       RuntimeId          |   OptimizedWithArgvLeaveFrame
1443 //  callerSP --> |--------------------------|            |
1444 //               |       returnAddr         |            |
1445 //               |--------------------------|            |
1446 //               |       callsiteFp         |            |
1447 //        fp --> |--------------------------|            |
1448 //               |       frameType          |            v
1449 //  calleeSP --> +--------------------------+-------------
1450 
1451 struct OptimizedWithArgvLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1452                                                                 base::AlignedPointer,
1453                                                                 base::AlignedPointer,
1454                                                                 base::AlignedPointer,
1455                                                                 base::AlignedUint64,
1456                                                                 base::AlignedUint64> {
GetFrameFromSpOptimizedWithArgvLeaveFrame1457     static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1458     {
1459         return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1460             MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp));
1461     }
1462 
GetCallSiteSpOptimizedWithArgvLeaveFrame1463     uintptr_t GetCallSiteSp() const
1464     {
1465         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId);
1466     }
1467 
GetPrevFrameFpOptimizedWithArgvLeaveFrame1468     inline JSTaggedType* GetPrevFrameFp()
1469     {
1470         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1471     }
1472 
GetReturnAddrOptimizedWithArgvLeaveFrame1473     uintptr_t GetReturnAddr() const
1474     {
1475         return returnAddr;
1476     }
1477 
GetReturnAddrAddressOptimizedWithArgvLeaveFrame1478     const uintptr_t *GetReturnAddrAddress() const
1479     {
1480         return &returnAddr;
1481     }
1482 
GetTypeOffsetOptimizedWithArgvLeaveFrame1483     static size_t GetTypeOffset()
1484     {
1485         return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, type);
1486     }
1487 
GetPrevOffsetOptimizedWithArgvLeaveFrame1488     static size_t GetPrevOffset()
1489     {
1490         return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp);
1491     }
1492 
GetReturnAddrOffsetOptimizedWithArgvLeaveFrame1493     static size_t GetReturnAddrOffset()
1494     {
1495         return MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, returnAddr);
1496     }
1497 
1498     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1499 
1500     alignas(EAS) FrameType type {0};
1501     alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here
1502     alignas(EAS) uintptr_t returnAddr {0};
1503     alignas(EAS) uint64_t argRuntimeId {0};
1504     alignas(EAS) uint64_t argc {0};
1505 };
1506 
1507 // * Optimized-builtin-leave-frame layout as the following:
1508 //               +--------------------------+
1509 //               |       argv[N-1]          |
1510 //               |--------------------------|
1511 //               |       . . . . .          |
1512 //               |--------------------------|
1513 //               |       argv[0]            |
1514 //               +--------------------------+-------------
1515 //               |       argc               |            ^
1516 //               |--------------------------|            |
1517 //               |       thread             |            |
1518 //  callerSP --> +--------------------------+            |
1519 //               |       ret-addr           |            |
1520 //               |--------------------------|   OptimizedBuiltinLeaveFrame
1521 //               |       prevFp             |            |
1522 //        fp --> |--------------------------|            |
1523 //               |       frameType          |            |
1524 //               |--------------------------|            |
1525 //               |       align byte         |            v
1526 //  calleeSP --> +--------------------------+-------------
1527 //
1528 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1529 struct OptimizedBuiltinLeaveFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1530                                                                base::AlignedPointer,
1531                                                                base::AlignedPointer,
1532                                                                base::AlignedPointer,
1533                                                                JSTaggedValue,
1534                                                                base::AlignedUint64> {
1535 public:
GetFrameFromSpOptimizedBuiltinLeaveFrame1536     static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1537     {
1538         return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1539             MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp));
1540     }
1541 
GetCallSiteSpOptimizedBuiltinLeaveFrame1542     uintptr_t GetCallSiteSp() const
1543     {
1544         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, thread);
1545     }
1546 
GetPrevFrameFpOptimizedBuiltinLeaveFrame1547     inline JSTaggedType* GetPrevFrameFp() const
1548     {
1549         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1550     }
1551 
GetReturnAddrOptimizedBuiltinLeaveFrame1552     uintptr_t GetReturnAddr() const
1553     {
1554         return returnAddr;
1555     }
1556 
GetReturnAddrAddressOptimizedBuiltinLeaveFrame1557     const uintptr_t *GetReturnAddrAddress() const
1558     {
1559         return &returnAddr;
1560     }
1561 
1562     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1563 
GetTypeOffsetOptimizedBuiltinLeaveFrame1564     static size_t GetTypeOffset()
1565     {
1566         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type);
1567     }
1568 
GetPrevOffsetOptimizedBuiltinLeaveFrame1569     static size_t GetPrevOffset()
1570     {
1571         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp);
1572     }
1573 
GetReturnAddrOffsetOptimizedBuiltinLeaveFrame1574     static size_t GetReturnAddrOffset()
1575     {
1576         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, returnAddr);
1577     }
1578 
GetFunctionOffsetOptimizedBuiltinLeaveFrame1579     static size_t GetFunctionOffset()
1580     {
1581         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, argc) + 1;
1582     }
1583 
GetArgvOptimizedBuiltinLeaveFrame1584     const JSTaggedType* GetArgv() const
1585     {
1586         return reinterpret_cast<const JSTaggedType *>(&argc + 1);
1587     }
1588 
GetTypeOptimizedBuiltinLeaveFrame1589     FrameType GetType() const
1590     {
1591         return type;
1592     }
1593 
1594 private:
1595     alignas(EAS) FrameType type {0};
1596     alignas(EAS) uintptr_t callsiteFp {0}; // thread sp set here
1597     alignas(EAS) uintptr_t returnAddr {0};
1598     alignas(EAS) JSTaggedValue thread {JSTaggedValue::Hole()};
1599     alignas(EAS) uint64_t argc {0};
1600     // argv[0]...argv[argc-1] dynamic according to agc
1601 };
1602 
1603 // * BuiltinFrame layout as the following:
1604 //               +--------------------------+
1605 //               |     argV[N - 1]          |
1606 //               |--------------------------|
1607 //               |       . . . .            |
1608 //               |--------------------------+
1609 //               |     argV[2]=this         |
1610 //               +--------------------------+
1611 //               |     argV[1]=new-target   |
1612 //               +--------------------------+
1613 //               |     argV[0]=call-target  |
1614 //               +--------------------------+ ---------
1615 //               |       argc               |         ^
1616 //               |--------------------------|         |
1617 //               |       thread             |         |
1618 //  callerSP --> |--------------------------|         |
1619 //               |       returnAddr         |     BuiltinFrame
1620 //               |--------------------------|         |
1621 //               |       callsiteFp         |         |
1622 //        fp --> |--------------------------|         |
1623 //               |       frameType          |         v
1624 //  calleeSP --> +--------------------------+ ---------
1625 //
1626 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1627 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1628                                                  base::AlignedSize,
1629                                                  base::AlignedPointer,
1630                                                  base::AlignedPointer,
1631                                                  base::AlignedPointer,
1632                                                  base::AlignedUint32,
1633                                                  base::AlignedPointer> {
1634     enum class Index : size_t {
1635         TypeIndex = 0,
1636         PrevFpIndex,
1637         ReturnAddrIndex,
1638         ThreadIndex,
1639         NumArgsIndex,
1640         StackArgsIndex,
1641         NumOfMembers
1642     };
1643     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1644 
GetFrameFromSpBuiltinFrame1645     static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
1646     {
1647         return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) -
1648             MEMBER_OFFSET(BuiltinFrame, prevFp));
1649     }
1650 
GetPrevFrameFpBuiltinFrame1651     inline JSTaggedType* GetPrevFrameFp()
1652     {
1653         return prevFp;
1654     }
1655 
GetCallSiteSpBuiltinFrame1656     uintptr_t GetCallSiteSp() const
1657     {
1658         return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread);
1659     }
1660 
GetPreFpOffsetBuiltinFrame1661     static size_t GetPreFpOffset(bool isArch32)
1662     {
1663         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1664     }
1665 
GetNumArgsToFpDeltaBuiltinFrame1666     static size_t GetNumArgsToFpDelta(bool isArch32)
1667     {
1668         auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32);
1669         return offset - GetPreFpOffset(isArch32);
1670     }
1671 
GetStackArgsToFpDeltaBuiltinFrame1672     static size_t GetStackArgsToFpDelta(bool isArch32)
1673     {
1674         auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
1675         return offset - GetPreFpOffset(isArch32);
1676     }
1677 
GetStackArgsAddressBuiltinFrame1678     uintptr_t GetStackArgsAddress()
1679     {
1680         return reinterpret_cast<uintptr_t>(&stackArgs);
1681     }
1682 
GetFunctionBuiltinFrame1683     JSTaggedValue GetFunction()
1684     {
1685         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1686         return JSTaggedValue(*functionAddress);
1687     }
1688 
GetNumArgsBuiltinFrame1689     uint32_t GetNumArgs()
1690     {
1691         return numArgs;
1692     }
1693 
GetReturnAddrBuiltinFrame1694     uintptr_t GetReturnAddr() const
1695     {
1696         return returnAddr;
1697     }
1698 
GetReturnAddrAddressBuiltinFrame1699     const uintptr_t *GetReturnAddrAddress() const
1700     {
1701         return &returnAddr;
1702     }
1703 
1704     static size_t GetStackArgsOffset(bool isArch32 = false)
1705     {
1706         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
1707     }
1708 
1709     static size_t GetTypeOffset(bool isArch32 = false)
1710     {
1711         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
1712     }
1713 
1714     static size_t GetPrevOffset(bool isArch32 = false)
1715     {
1716         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1717     }
1718 
1719     static size_t GetReturnAddrOffset(bool isArch32 = false)
1720     {
1721         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
1722     }
1723 
1724     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1725 
1726     alignas(EAS) FrameType type {0};
1727     alignas(EAS) JSTaggedType *prevFp {nullptr};
1728     alignas(EAS) uintptr_t returnAddr {0};
1729     alignas(EAS) uintptr_t thread {0};
1730     alignas(EAS) uint32_t numArgs {0};
1731     alignas(EAS) uintptr_t stackArgs {0};
1732 };
1733 
1734 // * BuiltinWithArgvFrame layout as the following:
1735 //               +--------------------------+ ---------
1736 //               |       . . . . .          |         ^
1737 //  callerSP --> |--------------------------|         |
1738 //               |       returnAddr         |         |
1739 //               |--------------------------|         |
1740 //               |       callsiteFp         |   BuiltinWithArgvFrame
1741 //        fp --> |--------------------------|         |
1742 //               |       frameType          |         |
1743 //               +--------------------------+         |
1744 //               |        argc              |         v
1745 //               +--------------------------+ ---------
1746 //               |        argV[0]           |
1747 //               +--------------------------+
1748 //               |        argV[1]           |
1749 //               +--------------------------+
1750 //               |        . . . .           |
1751 //  calleeSP --> +--------------------------+
1752 //
1753 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1754 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1755                                                          base::AlignedSize,
1756                                                          base::AlignedPointer,
1757                                                          base::AlignedPointer> {
1758     enum class Index : int {
1759         StackArgsTopIndex = -1,
1760         NumArgsIndex = -1,
1761         TypeIndex = 0,
1762         PrevFpIndex,
1763         ReturnAddrIndex,
1764         NumOfMembers
1765     };
1766     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1767 
GetFrameFromSpBuiltinWithArgvFrame1768     static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp)
1769     {
1770         return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) -
1771             MEMBER_OFFSET(BuiltinFrame, prevFp));
1772     }
1773 
GetPrevFrameFpBuiltinWithArgvFrame1774     inline JSTaggedType* GetPrevFrameFp()
1775     {
1776         return prevFp;
1777     }
1778 
GetCallSiteSpBuiltinWithArgvFrame1779     uintptr_t GetCallSiteSp() const
1780     {
1781         return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame);
1782     }
1783 
GetStackArgsAddressBuiltinWithArgvFrame1784     uintptr_t GetStackArgsAddress()
1785     {
1786         auto topAddress = ToUintPtr(this) +
1787             (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t));
1788         auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS;
1789         return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t);
1790     }
1791 
GetFunctionBuiltinWithArgvFrame1792     JSTaggedValue GetFunction()
1793     {
1794         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1795         return JSTaggedValue(*functionAddress);
1796     }
1797 
GetNumArgsBuiltinWithArgvFrame1798     int32_t GetNumArgs()
1799     {
1800         auto argcAddress = reinterpret_cast<int32_t *>(
1801             ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t)));
1802         return *argcAddress;
1803     }
1804 
GetReturnAddrBuiltinWithArgvFrame1805     uintptr_t GetReturnAddr() const
1806     {
1807         return returnAddr;
1808     }
1809 
GetReturnAddrAddressBuiltinWithArgvFrame1810     const uintptr_t *GetReturnAddrAddress() const
1811     {
1812         return &returnAddr;
1813     }
1814 
1815     static size_t GetTypeOffset(bool isArch32 = false)
1816     {
1817         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
1818     }
1819 
1820     static size_t GetPrevOffset(bool isArch32 = false)
1821     {
1822         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1823     }
1824 
1825     static size_t GetReturnAddrOffset(bool isArch32 = false)
1826     {
1827         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
1828     }
1829 
1830     void GCIterate(const FrameIterator &it, RootVisitor &visitor) const;
1831     // argv(... this, new.target, function)
1832     // numargs
1833     alignas(EAS) FrameType type {0};
1834     alignas(EAS) JSTaggedType *prevFp {nullptr};
1835     alignas(EAS) uintptr_t returnAddr {0};
1836 };
1837 
1838 // * FASTJITFunctionFrame layout description as the following:
1839 //               +--------------------------+
1840 //               |        arg[N-1]          |
1841 //               +--------------------------+
1842 //               |       ...                |
1843 //               +--------------------------+
1844 //               |       arg[1]             |
1845 //               +--------------------------+
1846 //               |       arg[0]             |
1847 //               +--------------------------+
1848 //               |       this               |
1849 //               +--------------------------+
1850 //               |       new-target         |
1851 //               +--------------------------+
1852 //               |       call-target        |
1853 //               |--------------------------|
1854 //               |       argc               |
1855 // callerSp ---> |--------------------------| ---------------
1856 //               |       returnAddr         |               ^
1857 //               |--------------------------|               |
1858 //               |       callsiteFp         |               |
1859 //               |--------------------------|               |
1860 //               |       frameType          |    FASTJITFunctionFrame
1861 //               |--------------------------|               |
1862 //               |       call-target        |               |
1863 //               |--------------------------|               |
1864 //               |       pc(bytecode pc)    |               v
1865 // calleeSP ---> +--------------------------+ ---------------
1866 //
1867 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1868 struct FASTJITFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
1869                                                              JSTaggedValue,
1870                                                              JSTaggedValue,
1871                                                              base::AlignedPointer,
1872                                                              base::AlignedPointer,
1873                                                              base::AlignedPointer> {
1874 public:
1875     using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
1876     enum class Index : size_t {
1877         PcIndex = 0,
1878         JSFuncIndex,
1879         TypeIndex,
1880         PrevFpIndex,
1881         ReturnAddrIndex,
1882         NumOfMembers
1883     };
1884     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1885 
GetFunctionDeltaReturnAddrFASTJITFunctionFrame1886     static constexpr size_t GetFunctionDeltaReturnAddr()
1887     {
1888         return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex);
1889     }
1890 
GetPrevFrameFpFASTJITFunctionFrame1891     inline JSTaggedType* GetPrevFrameFp()
1892     {
1893         return prevFp;
1894     }
1895 
GetArgvFASTJITFunctionFrame1896     JSTaggedType* GetArgv(uintptr_t *preFrameSp) const
1897     {
1898         const size_t offset = 2;    // 2: skip argc and argv.
1899         return reinterpret_cast<JSTaggedType *>(preFrameSp + offset * sizeof(uint64_t) / sizeof(uintptr_t));
1900     }
1901 
GetArgcFASTJITFunctionFrame1902     size_t GetArgc(uintptr_t *preFrameSp) const
1903     {
1904         return *preFrameSp;
1905     }
1906 
1907     JSTaggedType* GetArgv(const FrameIterator &it) const;
1908 
GetReturnAddrFASTJITFunctionFrame1909     uintptr_t GetReturnAddr() const
1910     {
1911         return returnAddr;
1912     }
1913 
GetReturnAddrAddressFASTJITFunctionFrame1914     const uintptr_t *GetReturnAddrAddress() const
1915     {
1916         return &returnAddr;
1917     }
1918 
1919     void GCIterate(const FrameIterator &it, RootVisitor &visitor, FrameType frameType) const;
1920 
GetFunctionFASTJITFunctionFrame1921     inline JSTaggedValue GetFunction() const
1922     {
1923         return jsFunc;
1924     }
1925 
ComputeArgsConfigFrameSpFASTJITFunctionFrame1926     static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp)
1927     {
1928         const size_t offset = 2;  // 2: skip prevFp and return address.
1929         return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t);
1930     }
1931 
1932     static size_t GetTypeOffset(bool isArch32 = false)
1933     {
1934         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
1935     }
1936 
1937     static size_t GetPcOffset(bool isArch32 = false)
1938     {
1939         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
1940     }
1941 
1942     static size_t GetPrevOffset(bool isArch32 = false)
1943     {
1944         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1945     }
1946 
1947     static size_t GetFunctionOffset(bool isArch32 = false)
1948     {
1949         return GetOffset<static_cast<size_t>(Index::JSFuncIndex)>(isArch32);
1950     }
1951 
ComputeReservedJSFuncOffsetFASTJITFunctionFrame1952     static size_t ComputeReservedJSFuncOffset(size_t slotSize)
1953     {
1954         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex);
1955         return slotSize * slotOffset;
1956     }
1957 
ComputeReservedPcOffsetFASTJITFunctionFrame1958     static size_t ComputeReservedPcOffset(size_t slotSize)
1959     {
1960         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PcIndex);
1961         return slotSize * slotOffset;
1962     }
1963 
GetFrmaeTypeToFpDeltaFASTJITFunctionFrame1964     static int GetFrmaeTypeToFpDelta()
1965     {
1966         return -(int)sizeof(uintptr_t);
1967     }
1968 
GetFunctionToFpDeltaFASTJITFunctionFrame1969     static int GetFunctionToFpDelta()
1970     {
1971         int slotOffset = static_cast<int>(Index::JSFuncIndex) - static_cast<int>(Index::TypeIndex);
1972         return slotOffset * static_cast<int>(JSTaggedValue::TaggedTypeSize()) + GetFrmaeTypeToFpDelta();
1973     }
1974 
GetTypeFASTJITFunctionFrame1975     FrameType GetType() const
1976     {
1977         return type;
1978     }
1979 
GetPcFASTJITFunctionFrame1980     inline const uint8_t *GetPc() const
1981     {
1982         return pc;
1983     }
1984 
1985     friend class FrameIterator;
1986     friend class FrameHandler;
1987     void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const;
1988     void GetFuncCalleeRegAndOffset(
1989         const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const;
1990     uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const;
1991 
1992 private:
GetFrameFromSpFASTJITFunctionFrame1993     static FASTJITFunctionFrame* GetFrameFromSp(const JSTaggedType *sp)
1994     {
1995         return reinterpret_cast<FASTJITFunctionFrame *>(reinterpret_cast<uintptr_t>(sp) -
1996             MEMBER_OFFSET(FASTJITFunctionFrame, prevFp));
1997     }
1998 
GetFuncAddrFromSpFASTJITFunctionFrame1999     static uintptr_t GetFuncAddrFromSp(const JSTaggedType *sp)
2000     {
2001         return reinterpret_cast<uintptr_t>(sp) - MEMBER_OFFSET(FASTJITFunctionFrame, type);
2002     }
2003 
2004     // dynamic callee saveregisters for x86-64
2005     alignas(EAS) const uint8_t *pc {nullptr};
2006     alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()};
2007     alignas(EAS) FrameType type {0};
2008     alignas(EAS) JSTaggedType *prevFp {nullptr};
2009     alignas(EAS) uintptr_t returnAddr {0};
2010     // dynamic callee saveregisters for arm64
2011 };
2012 
2013 enum class GCVisitedFlag : uint8_t {
2014     VISITED = 0,
2015     IGNORED,
2016     HYBRID_STACK,
2017     DEOPT,
2018 };
2019 
2020 class FrameIterator {
2021 public:
2022     using ConstInfo = kungfu::LLVMStackMapType::ConstInfo;
2023     using CallSiteInfo = std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec>;
2024     explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr);
2025 
2026     static constexpr uint32_t LAZY_DEOPT_FLAG_BIT = 30;
2027     static constexpr uintptr_t CLEARD_LAZY_DEOPT_FLAG =
2028         static_cast<uintptr_t>(~0ULL & ~(1ULL << LAZY_DEOPT_FLAG_BIT));
2029 
TryRemoveLazyDeoptFlag(uintptr_t & type)2030     inline static void TryRemoveLazyDeoptFlag(uintptr_t& type)
2031     {
2032         type &= CLEARD_LAZY_DEOPT_FLAG;
2033     }
2034 
GetFrameType()2035     FrameType GetFrameType() const
2036     {
2037         ASSERT(current_ != nullptr);
2038         uintptr_t *typeAddr = reinterpret_cast<uintptr_t *>(
2039             reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType));
2040         return static_cast<FrameType>((*typeAddr) & CLEARD_LAZY_DEOPT_FLAG);
2041     }
2042 
GetRawFrameType()2043     FrameType GetRawFrameType() const
2044     {
2045         ASSERT(current_ != nullptr);
2046         FrameType *typeAddr = reinterpret_cast<FrameType *>(
2047             reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType));
2048         return *typeAddr;
2049     }
2050 
GetFrameTypeAddress()2051     FrameType *GetFrameTypeAddress() const
2052     {
2053         ASSERT(current_ != nullptr);
2054         FrameType *typeAddr = reinterpret_cast<FrameType *>(
2055             reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType));
2056         return typeAddr;
2057     }
2058 
IsLazyDeoptFrameType()2059     bool IsLazyDeoptFrameType() const
2060     {
2061         return IsLazyDeoptFrameType(GetRawFrameType());
2062     }
2063 
IsLazyDeoptFrameType(FrameType type)2064     static bool IsLazyDeoptFrameType(FrameType type)
2065     {
2066         return static_cast<uint64_t>(type) >= (1ULL << LAZY_DEOPT_FLAG_BIT);
2067     }
2068 
DecodeAsLazyDeoptFrameType(FrameType * type)2069     static void DecodeAsLazyDeoptFrameType(FrameType* type)
2070     {
2071         *type = static_cast<FrameType>(
2072             static_cast<uintptr_t>(*type) | (1ULL << LAZY_DEOPT_FLAG_BIT));
2073     }
2074 
2075     uintptr_t *GetReturnAddrAddress() const;
2076 
2077     template<class T>
GetFrame()2078     T* GetFrame()
2079     {
2080         return T::GetFrameFromSp(current_);
2081     }
2082 
2083     template<class T>
GetFrame()2084     const T* GetFrame() const
2085     {
2086         return T::GetFrameFromSp(current_);
2087     }
2088 
Done()2089     bool Done() const
2090     {
2091         return current_ == nullptr;
2092     }
GetSp()2093     JSTaggedType *GetSp() const
2094     {
2095         return current_;
2096     }
GetSp()2097     JSTaggedType *GetSp()
2098     {
2099         return current_;
2100     }
GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)2101     void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const
2102     {
2103         ret = calleeRegInfo_;
2104     }
2105     int ComputeDelta(const Method *method = nullptr) const;
2106     template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED>
2107     void Advance();
2108     uint32_t GetBytecodeOffset() const;
2109     void GetStackTraceInfos(std::vector<std::pair<JSTaggedType, uint32_t>> &stackTraceInfos,
2110         bool needBaselineSpecialHandling, uint32_t pcOffset) const;
2111     void CollectStackTraceInfos(std::vector<std::pair<JSTaggedType, uint32_t>> &info) const;
2112     size_t GetInlineDepth() const;
2113     uintptr_t GetPrevFrameCallSiteSp() const;
2114     uintptr_t GetPrevFrame() const;
GetCallSiteSp()2115     uintptr_t GetCallSiteSp() const
2116     {
2117         return optimizedCallSiteSp_;
2118     }
GetOptimizedReturnAddr()2119     uintptr_t GetOptimizedReturnAddr() const
2120     {
2121         return optimizedReturnAddr_;
2122     }
GetThread()2123     const JSThread *GetThread() const
2124     {
2125         return thread_;
2126     }
2127     bool IteratorStackMapAndDeopt(RootVisitor &visitor) const;
2128     void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const;
2129     std::pair<CallSiteInfo, bool> CalCallSiteInfo(uintptr_t retAddr, bool isDeopt) const;
2130     CallSiteInfo TryCalCallSiteInfoFromMachineCode(uintptr_t retAddr) const;
2131 
2132     Method *CheckAndGetMethod() const;
2133     JSTaggedValue GetFunction() const;
2134 
IsLeaveFrame()2135     bool IsLeaveFrame() const
2136     {
2137         FrameType type = GetFrameType();
2138         return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV);
2139     }
2140 
IsOptimizedFrame()2141     bool IsOptimizedFrame() const
2142     {
2143         FrameType type = GetFrameType();
2144         return (type == FrameType::OPTIMIZED_FRAME);
2145     }
2146 
IsInterpretedFrame(FrameType type)2147     bool IsInterpretedFrame(FrameType type) const
2148     {
2149         return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST);
2150     }
2151 
IsJSFrame()2152     bool IsJSFrame() const
2153     {
2154         FrameType type = GetFrameType();
2155         return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type) || IsFastJitFunctionFrame(type);
2156     }
2157 
IsOptimizedJSFunctionFrame(FrameType type)2158     bool IsOptimizedJSFunctionFrame(FrameType type) const
2159     {
2160         return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME ||
2161             type == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME;
2162     }
2163 
IsOptimizedJSFunctionFrame()2164     bool IsOptimizedJSFunctionFrame() const
2165     {
2166         FrameType type = GetFrameType();
2167         return IsOptimizedJSFunctionFrame(type);
2168     }
2169 
IsFastJitFunctionFrame(FrameType type)2170     bool IsFastJitFunctionFrame(FrameType type) const
2171     {
2172         return type == FrameType::FASTJIT_FUNCTION_FRAME ||
2173             type == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME;
2174     }
2175 
IsFastJitFunctionFrame()2176     bool IsFastJitFunctionFrame() const
2177     {
2178         FrameType type = GetFrameType();
2179         return IsFastJitFunctionFrame(type);
2180     }
2181 
IsAotOrJitFunctionFrame()2182     bool IsAotOrJitFunctionFrame() const
2183     {
2184         return IsOptimizedJSFunctionFrame() || IsFastJitFunctionFrame();
2185     }
2186 
GetMachineCodeSlot()2187     JSTaggedType *GetMachineCodeSlot() const
2188     {
2189         return const_cast<JSTaggedType*>(&machineCode_);
2190     }
2191 
2192 private:
2193     JSTaggedType *current_ {nullptr};
2194     const JSThread *thread_ {nullptr};
2195     const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr};
2196     uintptr_t optimizedCallSiteSp_ {0};
2197     uintptr_t optimizedReturnAddr_ {0};
2198     uint8_t *stackMapAddr_ {nullptr};
2199     kungfu::CalleeRegAndOffsetVec calleeRegInfo_;
2200 
2201     // in jit, delta on method is not set, get it from iterator
2202     bool isJITFrame_ {false};
2203     int fpDeltaPrevFrameSp_ {0};
2204 
2205     // cache current machine code, it's nonmovable
2206     JSTaggedType machineCode_ {JSTaggedValue::VALUE_UNDEFINED};
2207 };
2208 }  // namespace panda::ecmascript
2209 #endif // ECMASCRIPT_FRAMES_H
2210