• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_FRAMES_H
17 #define ECMASCRIPT_FRAMES_H
18 
19 #include "ecmascript/base/aligned_struct.h"
20 #include "ecmascript/js_tagged_value.h"
21 #include "ecmascript/mem/visitor.h"
22 #include "ecmascript/method.h"
23 #include "ecmascript/stackmap/ark_stackmap.h"
24 #include "ecmascript/stackmap/llvm_stackmap_type.h"
25 
26 namespace panda::ecmascript {
27 class JSThread;
28 class EcmaVM;
29 class FrameIterator;
30 namespace kungfu {
31     class ArkStackMapParser;
32 };
33 
34 // Here list all scenarios of calling between Runtime/CInterpreter/ASMInterpreter/AOTCompiler/CBuiltin/ASMBuitlin.
35 // Please note that the "[]" means a must frame while "<>" means an optional frame. Each case is from top to down.
36 //
37 // * Runtime (C++) => CInterpreter:
38 //          1) [INTERPRETER_FRAME]
39 //
40 // * Runtime (C++) -> AOTCompiler:
41 //          1) [OPTIMIZED_ENTRY_FRAME]
42 //             <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME>
43 //             <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME>
44 //             [OPTIMIZED_JS_FUNCTION_FRAME]
45 //
46 // * Runtime (C++) => ASMInterpreter:
47 //          1) [INTERPRETER_ENTRY_FRAME][ASM_INTERPRETER_FRAME]
48 //
49 // * Runtime (C++) => CBuiltin:
50 //          1) [not supported]
51 //
52 // * Runtime (C++) => ASMBuiltin:
53 //          1) [not supported]
54 //
55 // * CInterpreter => CInterpreter:
56 //          1) [INTERPRETER_FRAME]
57 //
58 // * CInterpreter => Runtime (C++):
59 //          1) [INTERPRETER_FAST_NEW_FRAME]
60 //          2) [INTERPRETER_CONSTRUCTOR_FRAME]
61 //
62 // * CInterpreter => AOTCompiler:
63 //          1) [not supported]
64 //
65 // * CInterperter => CBuiltin:
66 //          1) [INTERPRETER_BUILTIN_FRAME]
67 //
68 // * CInterpreter => ASMBuiltin:
69 //          1) [not supported]
70 //
71 // * ASMInterpreter => Runtime (C++):
72 //          1) [LEAVE_FRAME]
73 //          2) [LEAVE_FRAME_WITH_ARGV]
74 //
75 // * ASMInterpreter => AOTCompiler:
76 //          1) [OPTIMIZED_ENTRY_FRAME]
77 //             <OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME>
78 //             <OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME>
79 //             [OPTIMIZED_JS_FUNCTION_FRAME]
80 //
81 // * ASMInterpreter => ASMInterpreter:
82 //          1) [ASM_INTERPRETER_FRAME]
83 //
84 // * ASMInterpreter => AsmBuiltin:
85 //          1) [BUILTIN_ENTRY_FRAME]
86 //             [BUILTIN_FRAME]
87 //          2) [BUILTIN_ENTRY_FRAME]
88 //             [BUILTIN_FRAME_WITH_ARGV]
89 //
90 // * ASMInterpreter => CBuiltin:
91 //          1) [LEAVE_FRAME]
92 //          2) [LEAVE_FRAME_WITH_ARGV]
93 //
94 // * AOTCompiler => Runtime (C++):
95 //          1) [LEAVE_FRAME]
96 //          2) [LEAVE_FRAME_WITH_ARGV]
97 //
98 // * AOTCompiler => ASMInterpreter:
99 //          1) [ASM_INTERPRETER_BRIDGE_FRAME]
100 //          2) [ASM_INTERPRETER_FRAME]
101 //
102 // * AOTCompiler => CBuiltin:
103 //          1) [LEAVE_FRAME]
104 //          2) [LEAVE_FRAME_WITH_ARGV]
105 //
106 // * AOTCompiler => ASMBuiltin:
107 //          1) [BUILTIN_ENTRY_FRAME]
108 //             [BUILTIN_FRAME]
109 //          2) [BUILTIN_ENTRY_FRAME]
110 //             [BUILTIN_FRAME_WITH_ARGV]
111 
112 
113 enum class FrameType: uintptr_t {
114     OPTIMIZED_FRAME = 0,
115     OPTIMIZED_ENTRY_FRAME,
116     OPTIMIZED_JS_FUNCTION_FRAME,
117     ASM_BRIDGE_FRAME,
118     LEAVE_FRAME,
119     LEAVE_FRAME_WITH_ARGV,
120     BUILTIN_CALL_LEAVE_FRAME,
121     INTERPRETER_FRAME,
122     ASM_INTERPRETER_FRAME,
123     INTERPRETER_CONSTRUCTOR_FRAME,
124     BUILTIN_FRAME,
125     BUILTIN_FRAME_WITH_ARGV,
126     BUILTIN_ENTRY_FRAME,
127     INTERPRETER_BUILTIN_FRAME,
128     INTERPRETER_FAST_NEW_FRAME,
129     INTERPRETER_ENTRY_FRAME,
130     ASM_INTERPRETER_ENTRY_FRAME,
131     ASM_INTERPRETER_BRIDGE_FRAME,
132     OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME,
133     OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME,
134 
135     FRAME_TYPE_FIRST = OPTIMIZED_FRAME,
136     FRAME_TYPE_LAST = OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME,
137     INTERPRETER_FIRST = INTERPRETER_FRAME,
138     INTERPRETER_LAST = INTERPRETER_FAST_NEW_FRAME,
139     BUILTIN_FIRST = BUILTIN_FRAME,
140     BUILTIN_LAST = BUILTIN_ENTRY_FRAME,
141 };
142 
143 enum class JSCallMode : uintptr_t {
144     CALL_ARG0 = 0,
145     CALL_ARG1,
146     CALL_ARG2,
147     CALL_ARG3,
148     CALL_THIS_ARG0,
149     CALL_THIS_ARG1,
150     CALL_THIS_ARG2,
151     CALL_THIS_ARG3,
152     CALL_WITH_ARGV,
153     CALL_THIS_WITH_ARGV,
154     CALL_CONSTRUCTOR_WITH_ARGV,
155     DEPRECATED_CALL_ARG0,
156     DEPRECATED_CALL_ARG1,
157     DEPRECATED_CALL_ARG2,
158     DEPRECATED_CALL_ARG3,
159     DEPRECATED_CALL_WITH_ARGV,
160     DEPRECATED_CALL_THIS_WITH_ARGV,
161     DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV,
162     CALL_GETTER,
163     CALL_SETTER,
164     CALL_THIS_ARG3_WITH_RETURN,
165     CALL_ENTRY,
166     CALL_GENERATOR,
167     CALL_FROM_AOT,
168 };
169 
170 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
171 struct OptimizedFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
172                                                    base::AlignedPointer,
173                                                    base::AlignedPointer,
174                                                    base::AlignedPointer> {
175 public:
176     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
177         const RootBaseAndDerivedVisitor &derivedVisitor) const;
178 
GetTypeOffsetOptimizedFrame179     static size_t GetTypeOffset()
180     {
181         return MEMBER_OFFSET(OptimizedFrame, type);
182     }
GetPrevOffsetOptimizedFrame183     static size_t GetPrevOffset()
184     {
185         return MEMBER_OFFSET(OptimizedFrame, prevFp);
186     }
ComputeReservedSizeOptimizedFrame187     static size_t ComputeReservedSize(size_t slotSize)
188     {
189         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex);
190         return slotSize * slotOffset;
191     }
192 private:
193     enum class Index : size_t {
194         TypeIndex = 0,
195         PrevFpIndex,
196         ReturnAddrIndex,
197         NumOfMembers
198     };
199     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
200 
GetFrameFromSpOptimizedFrame201     static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp)
202     {
203         return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp)
204             - MEMBER_OFFSET(OptimizedFrame, prevFp));
205     }
GetPrevFrameFpOptimizedFrame206     inline JSTaggedType* GetPrevFrameFp()
207     {
208         return prevFp;
209     }
GetReturnAddrOptimizedFrame210     uintptr_t GetReturnAddr() const
211     {
212         return returnAddr;
213     }
214     [[maybe_unused]] alignas(EAS) FrameType type {0};
215     alignas(EAS) JSTaggedType *prevFp {nullptr};
216     alignas(EAS) uintptr_t returnAddr {0};
217     friend class FrameIterator;
218 };
219 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64);
220 
221 struct AsmBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
222                                                    base::AlignedPointer,
223                                                    base::AlignedPointer,
224                                                    base::AlignedPointer> {
225 public:
GetTypeOffsetAsmBridgeFrame226     static size_t GetTypeOffset()
227     {
228         return MEMBER_OFFSET(AsmBridgeFrame, type);
229     }
230 
GetPrevOffsetAsmBridgeFrame231     static size_t GetPrevOffset()
232     {
233         return MEMBER_OFFSET(AsmBridgeFrame, prevFp);
234     }
235 
GetCallSiteSpAsmBridgeFrame236     uintptr_t GetCallSiteSp() const
237     {
238         return ToUintPtr(this) + sizeof(AsmBridgeFrame);
239     }
240 
GetTypeAsmBridgeFrame241     FrameType GetType() const
242     {
243         return type;
244     }
245 
246 private:
247     enum class Index : size_t {
248         TypeIndex = 0,
249         PrevFpIndex,
250         ReturnAddrIndex,
251         NumOfMembers
252     };
253     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
254 
GetFrameFromSpAsmBridgeFrame255     static AsmBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
256     {
257         return reinterpret_cast<AsmBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
258             MEMBER_OFFSET(AsmBridgeFrame, prevFp));
259     }
GetPrevFrameFpAsmBridgeFrame260     inline JSTaggedType* GetPrevFrameFp()
261     {
262         return prevFp;
263     }
GetReturnAddrAsmBridgeFrame264     uintptr_t GetReturnAddr() const
265     {
266         return returnAddr;
267     }
268     alignas(EAS) FrameType type {0};
269     alignas(EAS) JSTaggedType *prevFp {nullptr};
270     alignas(EAS) uintptr_t returnAddr {0};
271     friend class FrameIterator;
272 };
273 STATIC_ASSERT_EQ_ARCH(sizeof(AsmBridgeFrame), AsmBridgeFrame::SizeArch32, AsmBridgeFrame::SizeArch64);
274 
275 // * OptimizedUnfoldArgVFrame layout description as the following:
276 //      sp ----> |--------------------------| ---------------
277 //               |       returnAddr         |               ^
278 //  currentFp--> |--------------------------|               |
279 //               |       prevFp             |               |
280 //               |--------------------------|   OptimizedUnfoldArgVFrame
281 //               |       frameType          |               |
282 //               |--------------------------|               |
283 //               |       currentFp          |               v
284 //               +--------------------------+ ---------------
285 //
286 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
287 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
288                                                                        base::AlignedPointer,
289                                                                        base::AlignedPointer,
290                                                                        base::AlignedPointer,
291                                                                        base::AlignedPointer> {
292 public:
GetTypeOffsetOptimizedJSFunctionUnfoldArgVFrame293     static size_t GetTypeOffset()
294     {
295         return MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, type);
296     }
GetPrevOffsetOptimizedJSFunctionUnfoldArgVFrame297     static size_t GetPrevOffset()
298     {
299         return MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp);
300     }
301 private:
302     enum class Index : size_t {
303         CallSiteSpIndex = 0,
304         TypeIndex,
305         PrevFpIndex,
306         ReturnAddrIndex,
307         NumOfMembers
308     };
309     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
310 
GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame311     static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp)
312     {
313         return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp)
314             - MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp));
315     }
GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame316     inline JSTaggedType* GetPrevFrameFp() const
317     {
318         return prevFp;
319     }
GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame320     uintptr_t GetReturnAddr() const
321     {
322         return returnAddr;
323     }
GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame324     uintptr_t GetPrevFrameSp() const
325     {
326         return callSiteSp;
327     }
328     [[maybe_unused]] alignas(EAS) uintptr_t callSiteSp {0};
329     [[maybe_unused]] alignas(EAS) FrameType type {0};
330     alignas(EAS) JSTaggedType *prevFp {nullptr};
331     alignas(EAS) uintptr_t returnAddr {0};
332     friend class FrameIterator;
333 };
334 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionUnfoldArgVFrame),
335     OptimizedJSFunctionUnfoldArgVFrame::SizeArch32, OptimizedJSFunctionUnfoldArgVFrame::SizeArch64);
336 
337 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following:
338 //          +--------------------------+
339 //          |         arg[N-1]         |
340 //          +--------------------------+
341 //          |         . . . .          |
342 //          +--------------------------+
343 //          |         arg[0]           |
344 //          +--------------------------+
345 //          |         argC             |
346 //  sp ---> +--------------------------+ -----------------
347 //          |                          |                 ^
348 //          |        prevFP            |                 |
349 //          |--------------------------|    OptimizedJSFunctionArgsConfigFrame
350 //          |       frameType          |                 |
351 //          |                          |                 V
352 //          +--------------------------+ -----------------
353 //
354 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
355 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
356                                                                       base::AlignedPointer,
357                                                                       base::AlignedPointer> {
358 public:
GetTypeOffsetOptimizedJSFunctionArgConfigFrame359     static size_t GetTypeOffset()
360     {
361         return MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, type);
362     }
GetPrevOffsetOptimizedJSFunctionArgConfigFrame363     static size_t GetPrevOffset()
364     {
365         return MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp);
366     }
367 private:
368     enum class Index : size_t {
369         TypeIndex = 0,
370         PrevFpIndex,
371         NumOfMembers
372     };
373     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
374 
GetFrameFromSpOptimizedJSFunctionArgConfigFrame375     static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp)
376     {
377         return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp)
378             - MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp));
379     }
GetPrevFrameFpOptimizedJSFunctionArgConfigFrame380     inline JSTaggedType* GetPrevFrameFp()
381     {
382         return prevFp;
383     }
384     [[maybe_unused]] alignas(EAS) FrameType type {0};
385     alignas(EAS) JSTaggedType *prevFp {nullptr};
386     friend class FrameIterator;
387 };
388 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame),
389                       OptimizedJSFunctionArgConfigFrame::SizeArch32,
390                       OptimizedJSFunctionArgConfigFrame::SizeArch64);
391 
392 // * OptimizedJSFunctionFrame layout description as the following:
393 //               +--------------------------+
394 //               |        arg[N-1]          |
395 //               +--------------------------+
396 //               |       ...                |
397 //               +--------------------------+
398 //               |       arg[1]             |
399 //               +--------------------------+
400 //               |       arg[0]             |
401 //               +--------------------------+
402 //               |       this               |
403 //               +--------------------------+
404 //               |       new-target         |
405 //               +--------------------------+
406 //               |       call-target        |
407 //               |--------------------------|
408 //               |       argc               |
409 //               |--------------------------|
410 //               |       lexEnv             |
411 //      sp ----> |--------------------------| ---------------
412 //               |       returnAddr         |               ^
413 //               |--------------------------|               |
414 //               |       callsiteFp         |               |
415 //               |--------------------------|   OptimizedJSFunctionFrame
416 //               |       frameType          |               |
417 //               |--------------------------|               |
418 //               |       call-target        |               v
419 //               +--------------------------+ ---------------
420 //
421 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
422 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
423                                                              JSTaggedValue,
424                                                              base::AlignedPointer,
425                                                              base::AlignedPointer,
426                                                              base::AlignedPointer> {
427 public:
428     static constexpr size_t ENV_SLOT_DIFF = 2;
429     enum class Index : size_t {
430         JSFuncIndex = 0,
431         TypeIndex,
432         PrevFpIndex,
433         ReturnAddrIndex,
434         NumOfMembers
435     };
436     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
437 
GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame438     static constexpr size_t GetFunctionDeltaReturnAddr()
439     {
440         return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex);
441     }
442 
GetPrevFrameFpOptimizedJSFunctionFrame443     inline JSTaggedType* GetPrevFrameFp()
444     {
445         return prevFp;
446     }
447 
GetArgvOptimizedJSFunctionFrame448     JSTaggedType* GetArgv(uintptr_t *preFrameSp) const
449     {
450         return reinterpret_cast<JSTaggedType *>(preFrameSp + ENV_SLOT_DIFF * sizeof(uint64_t) / sizeof(uintptr_t));
451     }
452 
GetArgcOptimizedJSFunctionFrame453     size_t GetArgc(uintptr_t *preFrameSp) const
454     {
455         return *(preFrameSp + sizeof(uint64_t) / sizeof(uintptr_t));
456     }
457 
458     JSTaggedType* GetArgv(const FrameIterator &it) const;
459 
GetReturnAddrOptimizedJSFunctionFrame460     uintptr_t GetReturnAddr() const
461     {
462         return returnAddr;
463     }
464 
465     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
466         const RootBaseAndDerivedVisitor &derivedVisitor) const;
467     void CollectBCOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const;
468 
GetFunctionOptimizedJSFunctionFrame469     inline JSTaggedValue GetFunction() const
470     {
471         return jsFunc;
472     }
473 
ComputeArgsConfigFrameSpOptimizedJSFunctionFrame474     static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp)
475     {
476         const size_t offset = 2;  // 2: skip prevFp and return address.
477         return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t);
478     }
479 
GetTypeOffsetOptimizedJSFunctionFrame480     static size_t GetTypeOffset()
481     {
482         return MEMBER_OFFSET(OptimizedJSFunctionFrame, type);
483     }
484 
GetPrevOffsetOptimizedJSFunctionFrame485     static size_t GetPrevOffset()
486     {
487         return MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp);
488     }
489 
ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame490     static size_t ComputeReservedJSFuncOffset(size_t slotSize)
491     {
492         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex);
493         return slotSize * slotOffset;
494     }
495 
496     friend class FrameIterator;
497     friend class FrameHandler;
498     void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const;
499     void GetFuncCalleeRegAndOffset(
500         const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const;
501     uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const;
502 
503 private:
GetFrameFromSpOptimizedJSFunctionFrame504     static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp)
505     {
506         return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp)
507             - MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp));
508     }
509 
510     // dynamic callee saveregisters for x86-64
511     alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()};
512     [[maybe_unused]] alignas(EAS) FrameType type {0};
513     alignas(EAS) JSTaggedType *prevFp {nullptr};
514     alignas(EAS) uintptr_t returnAddr {0};
515     // dynamic callee saveregisters for arm64
516 };
517 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame),
518                       OptimizedJSFunctionFrame::SizeArch32,
519                       OptimizedJSFunctionFrame::SizeArch64);
520 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time.
521 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1);
522 
523 // * The JSFunctionEntry Frame's structure is illustrated as the following:
524 //          +--------------------------+
525 //          |      . . . . . .         |
526 //  sp ---> +--------------------------+ -----------------
527 //          |        prevFP            |                 ^
528 //          |--------------------------|                 |
529 //          |       frameType          |      JSFunctionEntryFrame
530 //          |--------------------------|                 |
531 //          |    preLeaveFrameFp       |                 v
532 //          +--------------------------+ -----------------
533 
534 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
535                                                         base::AlignedPointer,
536                                                         base::AlignedPointer,
537                                                         base::AlignedPointer> {
538 public:
539     enum class CallType : size_t {
540         CALL_FUNC = 0,
541         CALL_NEW,
542     };
543 
544     enum class Index : size_t {
545         PreLeaveFrameFpIndex = 0,
546         TypeIndex,
547         PrevFpIndex,
548         NumOfMembers
549     };
550 
GetTypeOffsetOptimizedEntryFrame551     static size_t GetTypeOffset()
552     {
553         return MEMBER_OFFSET(OptimizedEntryFrame, type);
554     }
555 
GetLeaveFrameFpOffsetOptimizedEntryFrame556     static size_t GetLeaveFrameFpOffset()
557     {
558         return MEMBER_OFFSET(OptimizedEntryFrame, preLeaveFrameFp);
559     }
560 
GetPrevFrameFpOptimizedEntryFrame561     inline JSTaggedType* GetPrevFrameFp()
562     {
563         return preLeaveFrameFp;
564     }
565 
ComputeReservedSizeOptimizedEntryFrame566     static size_t ComputeReservedSize(size_t slotSize)
567     {
568         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex);
569         return slotSize * slotOffset;
570     }
571     friend class FrameIterator;
572 
573 private:
574     alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr};
575     alignas(EAS) [[maybe_unused]] FrameType type {0};
576     alignas(EAS) [[maybe_unused]] JSTaggedType *prevFp {nullptr};
GetFrameFromSpOptimizedEntryFrame577     static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
578     {
579         return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) -
580             MEMBER_OFFSET(OptimizedEntryFrame, prevFp));
581     }
582 };
583 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64);
584 
585 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
586 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(),
587                                                          base::AlignedPointer,
588                                                          base::AlignedSize> {
589     enum class Index : size_t {
590         PrevIndex = 0,
591         TypeIndex,
592         NumOfMembers
593     };
594     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
595 
GetPrevFrameFpInterpretedFrameBase596     inline JSTaggedType* GetPrevFrameFp()
597     {
598         return prev;
599     }
600 
GetFrameFromSpInterpretedFrameBase601     static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp)
602     {
603         return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1;
604     }
605 
GetPrevOffsetInterpretedFrameBase606     static size_t GetPrevOffset(bool isArch32)
607     {
608         return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32);
609     }
610 
GetTypeOffsetInterpretedFrameBase611     static size_t GetTypeOffset(bool isArch32)
612     {
613         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
614     }
615 
GetSizeInterpretedFrameBase616     static constexpr size_t GetSize(bool isArch32)
617     {
618         return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64;
619     }
620 
621     alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc
622     alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0
623 };
624 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase),
625                       InterpretedFrameBase::SizeArch32,
626                       InterpretedFrameBase::SizeArch64);
627 
628 // Interpreter Frame Layout as the following:
629 //   +----------------------------------+
630 //   |    argv[n-1]                     |
631 //   |----------------------------------|
632 //   |    ......                        |
633 //   |----------------------------------|
634 //   |    thisArg [maybe not exist]     |
635 //   |----------------------------------|
636 //   |    newTarget [maybe not exist]   |
637 //   |----------------------------------|
638 //   |    ......                        |
639 //   |----------------------------------|
640 //   |    Vregs [not exist in native]   |
641 //   +----------------------------------+--------+
642 //   |    base.frameType                |        ^
643 //   |----------------------------------|        |
644 //   |    base.prev(prev stack pointer) |        |
645 //   |----------------------------------|        |
646 //   |    pc(bytecode addr)             |        |
647 //   |----------------------------------|        |
648 //   |    sp(current stack pointer)     |        |
649 //   |----------------------------------|        |
650 //   |    env                           |        |
651 //   |----------------------------------|        |
652 //   |    acc                           |        |
653 //   |----------------------------------|   InterpretedFrame
654 //   |    profileTypeInfo               |        |
655 //   |----------------------------------|        |
656 //   |    thisObj                       |        |
657 //   |----------------------------------|        |
658 //   |    function                      |        |
659 //   |----------------------------------|        |
660 //   |    constpool                     |        v
661 //   +----------------------------------+--------+
662 //
663 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
664 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
665                                                      JSTaggedValue,
666                                                      JSTaggedValue,
667                                                      JSTaggedValue,
668                                                      JSTaggedValue,
669                                                      JSTaggedValue,
670                                                      JSTaggedValue,
671                                                      base::AlignedPointer,
672                                                      InterpretedFrameBase> {
673 public:
674     enum class Index : size_t {
675         ConstPoolIndex = 0,
676         FunctionIndex,
677         ThisObjIndex,
678         ProFileTypeInfoIndex,
679         AccIndex,
680         EnvIndex,
681         PcIndex,
682         BaseIndex,
683         NumOfMembers
684     };
685     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
686 
GetPrevFrameFpInterpretedFrame687     inline JSTaggedType* GetPrevFrameFp() const
688     {
689         return base.prev;
690     }
691 
GetFrameFromSpInterpretedFrame692     static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
693     {
694         return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
695     }
696 
GetPcInterpretedFrame697     inline const uint8_t *GetPc() const
698     {
699         return pc;
700     }
701 
GetEnvInterpretedFrame702     inline JSTaggedValue GetEnv() const
703     {
704         return env;
705     }
706 
NumOfMembersInterpretedFrame707     static uint32_t NumOfMembers()
708     {
709         return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize();
710     }
711     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
712 
713     alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()};
714     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
715     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
716     alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()};
717     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
718     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
719     alignas(EAS) const uint8_t *pc {nullptr};
720     alignas(EAS) InterpretedFrameBase base;
721     friend class FrameIterator;
722 };
723 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64);
724 
725 // * InterpretedBuiltinFrame layout description as the following:
726 //               |--------------------------| ---------------
727 //               |         . . . . .        |               ^
728 //               |    InterpretedFrameBase  |               |
729 //               |         . . . . .        |               |
730 //               |--------------------------|    InterpretedBuiltinFrame
731 //               |       bytecode-PC        |               |
732 //               |--------------------------|               |
733 //               |       call-target        |               v
734 //               +--------------------------+ ---------------
735 //
736 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
737 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
738                                                             JSTaggedValue,
739                                                             base::AlignedPointer,
740                                                             InterpretedFrameBase> {
741     enum class Index : size_t {
742         FunctionIndex = 0,
743         PcIndex,
744         BaseIndex,
745         NumOfMembers
746     };
747     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
748 
GetPrevFrameFpInterpretedBuiltinFrame749     inline JSTaggedType* GetPrevFrameFp()
750     {
751         return base.prev;
752     }
753 
GetFrameFromSpInterpretedBuiltinFrame754     static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
755     {
756         return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
757     }
758 
NumOfMembersInterpretedBuiltinFrame759     static uint32_t NumOfMembers()
760     {
761         return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize();
762     }
763 
764     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
765 
766     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
767     alignas(EAS) const uint8_t *pc {nullptr};
768     alignas(EAS) InterpretedFrameBase base;
769 };
770 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame),
771                       InterpretedBuiltinFrame::SizeArch32,
772                       InterpretedBuiltinFrame::SizeArch64);
773 
774 // AsmInterpretedFrame Layout as the following:
775 //   +----------------------------------+
776 //   |    argv[n-1]                     |
777 //   |----------------------------------|
778 //   |    ......                        |
779 //   |----------------------------------|
780 //   |    thisArg [maybe not exist]     |
781 //   |----------------------------------|
782 //   |    newTarget [maybe not exist]   |
783 //   |----------------------------------|
784 //   |    ......                        |
785 //   |----------------------------------|
786 //   |    Vregs [not exist in native]   |
787 //   +----------------------------------+--------+
788 //   |        .  .  .   .               |        ^
789 //   |     InterpretedFrameBase         |        |
790 //   |        .  .  .   .               |        |
791 //   |----------------------------------|        |
792 //   |    pc(bytecode addr)             |        |
793 //   |----------------------------------|        |
794 //   |    sp(current stack pointer)     |        |
795 //   |----------------------------------|   AsmInterpretedFrame
796 //   |    callSize                      |        |
797 //   |----------------------------------|        |
798 //   |    env                           |        |
799 //   |----------------------------------|        |
800 //   |    acc                           |        |
801 //   |----------------------------------|        |
802 //   |    thisObj                       |        |
803 //   |----------------------------------|        |
804 //   |    call-target                   |        v
805 //   +----------------------------------+--------+
806 //
807 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
808 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
809                                                         JSTaggedValue,
810                                                         JSTaggedValue,
811                                                         JSTaggedValue,
812                                                         JSTaggedValue,
813                                                         base::AlignedPointer,
814                                                         base::AlignedPointer,
815                                                         base::AlignedPointer,
816                                                         InterpretedFrameBase> {
817     enum class Index : size_t {
818         FunctionIndex = 0,
819         ThisObjIndex,
820         AccIndex,
821         EnvIndex,
822         CallSizeIndex,
823         FpIndex,
824         PcIndex,
825         BaseIndex,
826         NumOfMembers
827     };
828 
829     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
830 
GetCurrentFramePointerAsmInterpretedFrame831     inline JSTaggedType* GetCurrentFramePointer()
832     {
833         return fp;
834     }
835 
GetPrevFrameFpAsmInterpretedFrame836     inline JSTaggedType* GetPrevFrameFp()
837     {
838         return base.prev;
839     }
840 
GetFrameFromSpAsmInterpretedFrame841     static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
842     {
843         return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
844     }
845 
GetFpOffsetAsmInterpretedFrame846     static size_t GetFpOffset(bool isArch32)
847     {
848         return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32);
849     }
850 
GetCallSizeOffsetAsmInterpretedFrame851     static size_t GetCallSizeOffset(bool isArch32)
852     {
853         return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32);
854     }
855 
GetFunctionOffsetAsmInterpretedFrame856     static size_t GetFunctionOffset(bool isArch32)
857     {
858         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
859     }
860 
GetThisOffsetAsmInterpretedFrame861     static size_t GetThisOffset(bool isArch32)
862     {
863         return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32);
864     }
865 
GetAccOffsetAsmInterpretedFrame866     static size_t GetAccOffset(bool isArch32)
867     {
868         return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32);
869     }
870 
GetEnvOffsetAsmInterpretedFrame871     static size_t GetEnvOffset(bool isArch32)
872     {
873         return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32);
874     }
875 
GetBaseOffsetAsmInterpretedFrame876     static size_t GetBaseOffset(bool isArch32)
877     {
878         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
879     }
880 
GetPcOffsetAsmInterpretedFrame881     static size_t GetPcOffset(bool isArch32)
882     {
883         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
884     }
885 
GetSizeAsmInterpretedFrame886     static constexpr size_t GetSize(bool isArch32)
887     {
888         return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64;
889     }
890 
NumOfMembersAsmInterpretedFrame891     static uint32_t NumOfMembers()
892     {
893         return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize();
894     }
895     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
896         const RootBaseAndDerivedVisitor &derivedVisitor) const;
897 
GetEnvAsmInterpretedFrame898     JSTaggedValue GetEnv() const
899     {
900         return env;
901     }
902 
GetPcAsmInterpretedFrame903     const uint8_t *GetPc() const
904     {
905         return pc;
906     }
907 
908     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
909     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
910     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
911     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
912     alignas(EAS) uintptr_t callSize {0};
913     alignas(EAS) JSTaggedType *fp {nullptr};
914     alignas(EAS) const uint8_t *pc {nullptr};
915     alignas(EAS) InterpretedFrameBase base;
916     // vregs, not exist in native
917     // args, may be truncated if not extra
918 };
919 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64);
920 
921 // InterpretedEntryFrame Layout as the following:
922 //   +----------------------------------+---------------
923 //   |        .  .  .   .               |              ^
924 //   |     InterpretedFrameBase         |              |
925 //   |        .  .  .   .               |    InterpretedEntryFrame
926 //   |----------------------------------|              |
927 //   |    pc(bytecode addr)             |              v
928 //   |----------------------------------|---------------
929 //
930 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
931 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
932                                                           base::AlignedPointer,
933                                                           InterpretedFrameBase> {
934     enum class Index : size_t {
935         PcIndex = 0,
936         BaseIndex,
937         NumOfMembers
938     };
939     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
940 
GetPrevFrameFpInterpretedEntryFrame941     inline JSTaggedType* GetPrevFrameFp()
942     {
943         return base.prev;
944     }
945 
GetFrameFromSpInterpretedEntryFrame946     static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
947     {
948         return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
949     }
950 
NumOfMembersInterpretedEntryFrame951     static uint32_t NumOfMembers()
952     {
953         return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize();
954     }
955 
956     void GCIterate(const FrameIterator &it, const RootVisitor &visitor,
957         const RootRangeVisitor &rangeVisitor) const;
958     alignas(EAS) const uint8_t *pc {nullptr};
959     alignas(EAS) InterpretedFrameBase base;
960 };
961 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame),
962                       InterpretedEntryFrame::SizeArch32,
963                       InterpretedEntryFrame::SizeArch64);
964 
965 
966 // AsmInterpretedEntryFrame Layout as the following:
967 //   +----------------------------------+---------------
968 //   |        .  .  .   .               |              ^
969 //   |     InterpretedFrameBase         |              |
970 //   |        .  .  .   .               |    AsmInterpretedEntryFrame
971 //   |----------------------------------|              |
972 //   |    pc(bytecode addr)             |              v
973 //   |----------------------------------|---------------
974 //
975 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
976 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
977                                                              base::AlignedPointer,
978                                                              InterpretedFrameBase> {
979     enum class Index : size_t {
980         PcIndex = 0,
981         BaseIndex,
982         NumOfMembers
983     };
984     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
985 
GetPrevFrameFpAsmInterpretedEntryFrame986     inline JSTaggedType* GetPrevFrameFp()
987     {
988         return base.prev;
989     }
990 
GetBaseOffsetAsmInterpretedEntryFrame991     static size_t GetBaseOffset(bool isArch32)
992     {
993         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
994     }
995 
GetFrameFromSpAsmInterpretedEntryFrame996     static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
997     {
998         return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
999     }
1000 
1001     alignas(EAS) const uint8_t *pc {nullptr};
1002     alignas(EAS) InterpretedFrameBase base;
1003 };
1004 
1005 // AsmInterpretedBridgeFrame Layout as the following:
1006 //   +----------------------------------+---------------
1007 //   |      ret-address                 |              ^
1008 //   |----------------------------------|              |
1009 //   |        .  .  .   .               |     AsmInterpretedBridgeFrame
1010 //   |     AsmInterpretedEntryFrame     |              |
1011 //   |        .  .  .   .               |              v
1012 //   |----------------------------------|---------------
1013 //
1014 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1015 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1016                                                               AsmInterpretedEntryFrame,
1017                                                               base::AlignedPointer> {
1018     enum class Index : size_t {
1019         EntryIndex = 0,
1020         ReturnAddrIndex,
1021         NumOfMembers
1022     };
1023     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1024 
GetFrameFromSpAsmInterpretedBridgeFrame1025     static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
1026     {
1027         return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
1028             MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr));
1029     }
GetCallSiteSpAsmInterpretedBridgeFrame1030     uintptr_t GetCallSiteSp() const
1031     {
1032         return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame);
1033     }
GetPrevFrameFpAsmInterpretedBridgeFrame1034     inline JSTaggedType* GetPrevFrameFp()
1035     {
1036         return entry.base.prev;
1037     }
1038 
GetReturnAddrOffsetAsmInterpretedBridgeFrame1039     static size_t GetReturnAddrOffset(bool isArch32)
1040     {
1041         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
1042     }
1043 
GetSizeAsmInterpretedBridgeFrame1044     static constexpr size_t GetSize(bool isArch32)
1045     {
1046         return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64;
1047     }
1048 
1049     AsmInterpretedEntryFrame entry;
1050     alignas(EAS) uintptr_t returnAddr;
GetReturnAddrAsmInterpretedBridgeFrame1051     uintptr_t GetReturnAddr() const
1052     {
1053         return returnAddr;
1054     }
1055 };
1056 
1057 // * Optimized-leaved-frame layout as the following:
1058 //         +--------------------------+
1059 //         |       argv[N-1]          |
1060 //         |--------------------------|
1061 //         |       . . . . .          |
1062 //         |--------------------------|
1063 //         |       argv[0]            |
1064 //         +--------------------------+-------------
1065 //         |       argc               |            ^
1066 //         |--------------------------|            |
1067 //         |       RuntimeId          |            |
1068 //  sp --> |--------------------------|   OptimizedLeaveFrame
1069 //         |       ret-addr           |            |
1070 //         |--------------------------|            |
1071 //         |       prevFp             |            |
1072 //         |--------------------------|            |
1073 //         |       frameType          |            v
1074 //         +--------------------------+-------------
1075 //
1076 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1077 struct OptimizedLeaveFrame {
1078     FrameType type;
1079     uintptr_t callsiteFp; // thread sp set here
1080     uintptr_t returnAddr;
1081     uint64_t argRuntimeId;
1082     uint64_t argc;
1083     // argv[0]...argv[argc-1] dynamic according to agc
GetFrameFromSpOptimizedLeaveFrame1084     static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1085     {
1086         return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1087             MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp));
1088     }
GetCallSiteSpOptimizedLeaveFrame1089     uintptr_t GetCallSiteSp() const
1090     {
1091         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId);
1092     }
GetPrevFrameFpOptimizedLeaveFrame1093     inline JSTaggedType* GetPrevFrameFp() const
1094     {
1095         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1096     }
1097 
GetReturnAddrOptimizedLeaveFrame1098     uintptr_t GetReturnAddr() const
1099     {
1100         return returnAddr;
1101     }
1102     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1103 };
1104 
1105 // * Optimized-leaved-frame-with-argv layout as the following:
1106 //         +--------------------------+
1107 //         |       argv[]             |
1108 //         +--------------------------+-------------
1109 //         |       argc               |            ^
1110 //         |--------------------------|            |
1111 //         |       RuntimeId          |   OptimizedWithArgvLeaveFrame
1112 //  sp --> |--------------------------|            |
1113 //         |       returnAddr         |            |
1114 //         |--------------------------|            |
1115 //         |       callsiteFp         |            |
1116 //         |--------------------------|            |
1117 //         |       frameType          |            v
1118 //         +--------------------------+-------------
1119 
1120 struct OptimizedWithArgvLeaveFrame {
1121     FrameType type;
1122     uintptr_t callsiteFp; // thread sp set here
1123     uintptr_t returnAddr;
1124     uint64_t argRuntimeId;
1125     uint64_t argc;
1126 
GetFrameFromSpOptimizedWithArgvLeaveFrame1127     static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1128     {
1129         return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1130             MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp));
1131     }
GetCallSiteSpOptimizedWithArgvLeaveFrame1132     uintptr_t GetCallSiteSp() const
1133     {
1134         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId);
1135     }
GetPrevFrameFpOptimizedWithArgvLeaveFrame1136     inline JSTaggedType* GetPrevFrameFp()
1137     {
1138         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1139     }
GetReturnAddrOptimizedWithArgvLeaveFrame1140     uintptr_t GetReturnAddr() const
1141     {
1142         return returnAddr;
1143     }
1144     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1145 };
1146 
1147 // * OptimizedBuiltinLeaveFrame layout as the following:
1148 //         +--------------------------+
1149 //         |       argv[N-1]          |
1150 //         |--------------------------|
1151 //         |       . . . . .          |
1152 //         |--------------------------|
1153 //         |       argv[0]            |
1154 //         +--------------------------+-------------
1155 //         |       argc               |            ^
1156 //         |--------------------------|            |
1157 //         |       env                |            |
1158 //         +--------------------------+            |
1159 //         |       ret-addr           |            |
1160 //  sp --> |--------------------------|   OptimizedBuiltinLeaveFrame
1161 //         |       prevFp             |            |
1162 //         |--------------------------|            |
1163 //         |       frameType          |            |
1164 //         |--------------------------|            |
1165 //         |       align byte         |            v
1166 //         +--------------------------+-------------
1167 //
1168 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1169 struct OptimizedBuiltinLeaveFrame {
1170 public:
GetFrameFromSpOptimizedBuiltinLeaveFrame1171     static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1172     {
1173         return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1174             MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp));
1175     }
GetCallSiteSpOptimizedBuiltinLeaveFrame1176     uintptr_t GetCallSiteSp() const
1177     {
1178         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, thread);
1179     }
GetPrevFrameFpOptimizedBuiltinLeaveFrame1180     inline JSTaggedType* GetPrevFrameFp() const
1181     {
1182         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1183     }
GetReturnAddrOptimizedBuiltinLeaveFrame1184     uintptr_t GetReturnAddr() const
1185     {
1186         return returnAddr;
1187     }
1188     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
GetTypeOffsetOptimizedBuiltinLeaveFrame1189     static size_t GetTypeOffset()
1190     {
1191         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type);
1192     }
GetPrevOffsetOptimizedBuiltinLeaveFrame1193     static size_t GetPrevOffset()
1194     {
1195         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp);
1196     }
GetArgvOptimizedBuiltinLeaveFrame1197     const JSTaggedType* GetArgv() const
1198     {
1199         return reinterpret_cast<const JSTaggedType *>(&argc + 1);
1200     }
1201 
1202 private:
1203     [[maybe_unused]] FrameType type;
1204     uintptr_t callsiteFp; // thread sp set here
1205     uintptr_t returnAddr;
1206     JSTaggedValue thread;
1207     uint64_t argc;
1208     // argv[0]...argv[argc-1] dynamic according to agc
1209 };
1210 
1211 // * BuiltinFrame layout as the following:
1212 //               +--------------------------+
1213 //               |     argV[N - 1]          |
1214 //               |--------------------------|
1215 //               |       . . . .            |
1216 //               |--------------------------+
1217 //               |     argV[2]=this         |
1218 //               +--------------------------+
1219 //               |     argV[1]=new-target   |
1220 //               +--------------------------+
1221 //               |     argV[0]=call-target  |
1222 //               +--------------------------+ ---------
1223 //               |       argc               |         ^
1224 //               |--------------------------|         |
1225 //               |       thread             |         |
1226 //               |--------------------------|         |
1227 //               |       returnAddr         |     BuiltinFrame
1228 //               |--------------------------|         |
1229 //               |       callsiteFp         |         |
1230 //               |--------------------------|         |
1231 //               |       frameType          |         v
1232 //               +--------------------------+ ---------
1233 //
1234 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1235 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1236                                                  base::AlignedSize,
1237                                                  base::AlignedPointer,
1238                                                  base::AlignedPointer,
1239                                                  base::AlignedPointer,
1240                                                  base::AlignedPointer,
1241                                                  base::AlignedPointer> {
1242     enum class Index : size_t {
1243         TypeIndex = 0,
1244         PrevFpIndex,
1245         ReturnAddrIndex,
1246         ThreadIndex,
1247         NumArgsIndex,
1248         StackArgsIndex,
1249         NumOfMembers
1250     };
1251     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1252 
GetFrameFromSpBuiltinFrame1253     static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
1254     {
1255         return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) -
1256             MEMBER_OFFSET(BuiltinFrame, prevFp));
1257     }
GetPrevFrameFpBuiltinFrame1258     inline JSTaggedType* GetPrevFrameFp()
1259     {
1260         return prevFp;
1261     }
GetCallSiteSpBuiltinFrame1262     uintptr_t GetCallSiteSp() const
1263     {
1264         return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread);
1265     }
GetPreFpOffsetBuiltinFrame1266     static size_t GetPreFpOffset(bool isArch32)
1267     {
1268         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1269     }
GetNumArgsToFpDeltaBuiltinFrame1270     static size_t GetNumArgsToFpDelta(bool isArch32)
1271     {
1272         auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32);
1273         return offset - GetPreFpOffset(isArch32);
1274     }
GetStackArgsToFpDeltaBuiltinFrame1275     static size_t GetStackArgsToFpDelta(bool isArch32)
1276     {
1277         auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
1278         return offset - GetPreFpOffset(isArch32);
1279     }
GetStackArgsAddressBuiltinFrame1280     uintptr_t GetStackArgsAddress()
1281     {
1282         return reinterpret_cast<uintptr_t>(&stackArgs);
1283     }
GetFunctionBuiltinFrame1284     JSTaggedValue GetFunction()
1285     {
1286         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1287         return JSTaggedValue(*functionAddress);
1288     }
GetNumArgsBuiltinFrame1289     int32_t GetNumArgs()
1290     {
1291         return numArgs;
1292     }
1293 
GetReturnAddrBuiltinFrame1294     uintptr_t GetReturnAddr() const
1295     {
1296         return returnAddr;
1297     }
1298     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1299     alignas(EAS) FrameType type;
1300     alignas(EAS) JSTaggedType *prevFp;
1301     alignas(EAS) uintptr_t returnAddr;
1302     alignas(EAS) uintptr_t thread;
1303     alignas(EAS) int32_t numArgs;
1304     alignas(EAS) uintptr_t stackArgs;
1305 };
1306 
1307 // * BuiltinWithArgvFrame layout as the following:
1308 //               +--------------------------+ ---------
1309 //               |       . . . . .          |         ^
1310 //               |--------------------------|         |
1311 //               |       returnAddr         |         |
1312 //               |--------------------------|         |
1313 //               |       callsiteFp         |   BuiltinWithArgvFrame
1314 //               |--------------------------|         |
1315 //               |       frameType          |         |
1316 //               +--------------------------+         |
1317 //               |        argc              |         v
1318 //               +--------------------------+ ---------
1319 //               |        argV[0]           |
1320 //               +--------------------------+
1321 //               |        argV[1]           |
1322 //               +--------------------------+
1323 //               |        . . . .           |
1324 //               +--------------------------+
1325 //
1326 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1327 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1328                                                          base::AlignedSize,
1329                                                          base::AlignedPointer,
1330                                                          base::AlignedPointer> {
1331     enum class Index : int {
1332         StackArgsTopIndex = -1,
1333         NumArgsIndex = -1,
1334         TypeIndex = 0,
1335         PrevFpIndex,
1336         ReturnAddrIndex,
1337         NumOfMembers
1338     };
1339     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1340 
GetFrameFromSpBuiltinWithArgvFrame1341     static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp)
1342     {
1343         return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) -
1344             MEMBER_OFFSET(BuiltinFrame, prevFp));
1345     }
GetPrevFrameFpBuiltinWithArgvFrame1346     inline JSTaggedType* GetPrevFrameFp()
1347     {
1348         return prevFp;
1349     }
GetCallSiteSpBuiltinWithArgvFrame1350     uintptr_t GetCallSiteSp() const
1351     {
1352         return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame);
1353     }
GetStackArgsAddressBuiltinWithArgvFrame1354     uintptr_t GetStackArgsAddress()
1355     {
1356         auto topAddress = ToUintPtr(this) +
1357             (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t));
1358         auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS;
1359         return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t);
1360     }
GetFunctionBuiltinWithArgvFrame1361     JSTaggedValue GetFunction()
1362     {
1363         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1364         return JSTaggedValue(*functionAddress);
1365     }
GetNumArgsBuiltinWithArgvFrame1366     int32_t GetNumArgs()
1367     {
1368         auto argcAddress = reinterpret_cast<int32_t *>(
1369             ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t)));
1370         return *argcAddress;
1371     }
GetReturnAddrBuiltinWithArgvFrame1372     uintptr_t GetReturnAddr() const
1373     {
1374         return returnAddr;
1375     }
1376     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1377     // argv(... this, new.target, function)
1378     // numargs
1379     alignas(EAS) FrameType type;
1380     alignas(EAS) JSTaggedType *prevFp;
1381     alignas(EAS) uintptr_t returnAddr;
1382 };
1383 
1384 enum class GCVisitedFlag : bool {
1385     VISITED = true,
1386     IGNORED = false,
1387 };
1388 
1389 class FrameIterator {
1390 public:
1391     explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr);
GetFrameType()1392     FrameType GetFrameType() const
1393     {
1394         ASSERT(current_ != nullptr);
1395         FrameType *typeAddr = reinterpret_cast<FrameType *>(
1396             reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType));
1397         return *typeAddr;
1398     }
1399 
1400     template<class T>
GetFrame()1401     T* GetFrame()
1402     {
1403         return T::GetFrameFromSp(current_);
1404     }
1405 
1406     template<class T>
GetFrame()1407     const T* GetFrame() const
1408     {
1409         return T::GetFrameFromSp(current_);
1410     }
1411 
Done()1412     bool Done() const
1413     {
1414         return current_ == nullptr;
1415     }
GetSp()1416     JSTaggedType *GetSp() const
1417     {
1418         return current_;
1419     }
GetSp()1420     JSTaggedType *GetSp()
1421     {
1422         return current_;
1423     }
GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)1424     void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const
1425     {
1426         ret = calleeRegInfo_;
1427     }
1428     int ComputeDelta() const;
1429     template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED>
1430     void Advance();
1431     uint32_t GetBytecodeOffset() const;
1432     uintptr_t GetPrevFrameCallSiteSp([[maybe_unused]] uintptr_t curPc = 0) const;
1433     uintptr_t GetPrevFrame() const;
GetCallSiteSp()1434     uintptr_t GetCallSiteSp() const
1435     {
1436         return optimizedCallSiteSp_;
1437     }
GetOptimizedReturnAddr()1438     uintptr_t GetOptimizedReturnAddr() const
1439     {
1440         return optimizedReturnAddr_;
1441     }
GetThread()1442     const JSThread *GetThread() const
1443     {
1444         return thread_;
1445     }
1446     bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const;
1447     void CollectBCOffsetInfo(kungfu::ConstInfo &info) const;
1448     void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const;
1449     std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const;
1450     int GetCallSiteDelta(uintptr_t retAddr) const;
1451 
1452     Method *CheckAndGetMethod() const;
1453     JSTaggedValue GetFunction() const;
1454 
IsLeaveFrame()1455     bool IsLeaveFrame() const
1456     {
1457         FrameType type = GetFrameType();
1458         return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV);
1459     }
1460 
IsOptimizedFrame()1461     bool IsOptimizedFrame() const
1462     {
1463         FrameType type = GetFrameType();
1464         return (type == FrameType::OPTIMIZED_FRAME);
1465     }
1466 
IsOptimizedJSFunctionFrame()1467     bool IsOptimizedJSFunctionFrame() const
1468     {
1469         FrameType type = GetFrameType();
1470         return (type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
1471     }
1472 
1473 private:
1474     JSTaggedType *current_ {nullptr};
1475     const JSThread *thread_ {nullptr};
1476     const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr};
1477     uintptr_t optimizedCallSiteSp_ {0};
1478     uintptr_t optimizedReturnAddr_ {0};
1479     uint8_t *stackMapAddr_ {nullptr};
1480     int fpDeltaPrevFrameSp_ {0};
1481     kungfu::CalleeRegAndOffsetVec calleeRegInfo_;
1482 };
1483 }  // namespace panda::ecmascript
1484 extern "C" int step_ark_managed_native_frame(
1485     int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp, char *buf, size_t buf_sz);
1486 #endif // ECMASCRIPT_FRAMES_H
1487