• 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     LEAVE_FRAME,
118     LEAVE_FRAME_WITH_ARGV,
119     BUILTIN_CALL_LEAVE_FRAME,
120     INTERPRETER_FRAME,
121     ASM_INTERPRETER_FRAME,
122     INTERPRETER_CONSTRUCTOR_FRAME,
123     BUILTIN_FRAME,
124     BUILTIN_FRAME_WITH_ARGV,
125     BUILTIN_ENTRY_FRAME,
126     INTERPRETER_BUILTIN_FRAME,
127     INTERPRETER_FAST_NEW_FRAME,
128     INTERPRETER_ENTRY_FRAME,
129     ASM_INTERPRETER_ENTRY_FRAME,
130     ASM_INTERPRETER_BRIDGE_FRAME,
131     OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME,
132     OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME,
133 
134     FRAME_TYPE_FIRST = OPTIMIZED_FRAME,
135     FRAME_TYPE_LAST = OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME,
136     INTERPRETER_FIRST = INTERPRETER_FRAME,
137     INTERPRETER_LAST = INTERPRETER_FAST_NEW_FRAME,
138     BUILTIN_FIRST = BUILTIN_FRAME,
139     BUILTIN_LAST = BUILTIN_ENTRY_FRAME,
140 };
141 
142 enum class JSCallMode : uintptr_t {
143     CALL_ARG0 = 0,
144     CALL_ARG1,
145     CALL_ARG2,
146     CALL_ARG3,
147     CALL_THIS_ARG0,
148     CALL_THIS_ARG1,
149     CALL_THIS_ARG2,
150     CALL_THIS_ARG3,
151     CALL_WITH_ARGV,
152     CALL_THIS_WITH_ARGV,
153     CALL_CONSTRUCTOR_WITH_ARGV,
154     DEPRECATED_CALL_ARG0,
155     DEPRECATED_CALL_ARG1,
156     DEPRECATED_CALL_ARG2,
157     DEPRECATED_CALL_ARG3,
158     DEPRECATED_CALL_WITH_ARGV,
159     DEPRECATED_CALL_THIS_WITH_ARGV,
160     DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV,
161     CALL_GETTER,
162     CALL_SETTER,
163     CALL_THIS_ARG3_WITH_RETURN,
164     CALL_ENTRY,
165     CALL_GENERATOR,
166     CALL_FROM_AOT,
167 };
168 
169 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
170 struct OptimizedFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
171                                                    base::AlignedPointer,
172                                                    base::AlignedPointer,
173                                                    base::AlignedPointer> {
174 public:
175     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
176         const RootBaseAndDerivedVisitor &derivedVisitor) const;
177 
GetTypeOffsetOptimizedFrame178     static size_t GetTypeOffset()
179     {
180         return MEMBER_OFFSET(OptimizedFrame, type);
181     }
GetPrevOffsetOptimizedFrame182     static size_t GetPrevOffset()
183     {
184         return MEMBER_OFFSET(OptimizedFrame, prevFp);
185     }
ComputeReservedSizeOptimizedFrame186     static size_t ComputeReservedSize(size_t slotSize)
187     {
188         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::TypeIndex);
189         return slotSize * slotOffset;
190     }
191 private:
192     enum class Index : size_t {
193         TypeIndex = 0,
194         PrevFpIndex,
195         ReturnAddrIndex,
196         NumOfMembers
197     };
198     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
199 
GetFrameFromSpOptimizedFrame200     static OptimizedFrame* GetFrameFromSp(const JSTaggedType *sp)
201     {
202         return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp)
203             - MEMBER_OFFSET(OptimizedFrame, prevFp));
204     }
GetPrevFrameFpOptimizedFrame205     inline JSTaggedType* GetPrevFrameFp()
206     {
207         return prevFp;
208     }
GetReturnAddrOptimizedFrame209     uintptr_t GetReturnAddr() const
210     {
211         return returnAddr;
212     }
213     [[maybe_unused]] alignas(EAS) FrameType type {0};
214     alignas(EAS) JSTaggedType *prevFp {nullptr};
215     alignas(EAS) uintptr_t returnAddr {0};
216     friend class FrameIterator;
217 };
218 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64);
219 
220 // * OptimizedUnfoldArgVFrame layout description as the following:
221 //      sp ----> |--------------------------| ---------------
222 //               |       returnAddr         |               ^
223 //  currentFp--> |--------------------------|               |
224 //               |       prevFp             |               |
225 //               |--------------------------|   OptimizedUnfoldArgVFrame
226 //               |       frameType          |               |
227 //               |--------------------------|               |
228 //               |       currentFp          |               v
229 //               +--------------------------+ ---------------
230 //
231 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
232 struct OptimizedJSFunctionUnfoldArgVFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
233                                                                        base::AlignedPointer,
234                                                                        base::AlignedPointer,
235                                                                        base::AlignedPointer,
236                                                                        base::AlignedPointer> {
237 public:
GetTypeOffsetOptimizedJSFunctionUnfoldArgVFrame238     static size_t GetTypeOffset()
239     {
240         return MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, type);
241     }
GetPrevOffsetOptimizedJSFunctionUnfoldArgVFrame242     static size_t GetPrevOffset()
243     {
244         return MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp);
245     }
246 private:
247     enum class Index : size_t {
248         CallSiteSpIndex = 0,
249         TypeIndex,
250         PrevFpIndex,
251         ReturnAddrIndex,
252         NumOfMembers
253     };
254     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
255 
GetFrameFromSpOptimizedJSFunctionUnfoldArgVFrame256     static OptimizedJSFunctionUnfoldArgVFrame* GetFrameFromSp(const JSTaggedType *sp)
257     {
258         return reinterpret_cast<OptimizedJSFunctionUnfoldArgVFrame *>(reinterpret_cast<uintptr_t>(sp)
259             - MEMBER_OFFSET(OptimizedJSFunctionUnfoldArgVFrame, prevFp));
260     }
GetPrevFrameFpOptimizedJSFunctionUnfoldArgVFrame261     inline JSTaggedType* GetPrevFrameFp() const
262     {
263         return prevFp;
264     }
GetReturnAddrOptimizedJSFunctionUnfoldArgVFrame265     uintptr_t GetReturnAddr() const
266     {
267         return returnAddr;
268     }
GetPrevFrameSpOptimizedJSFunctionUnfoldArgVFrame269     uintptr_t GetPrevFrameSp() const
270     {
271         return callSiteSp;
272     }
273     [[maybe_unused]] alignas(EAS) uintptr_t callSiteSp {0};
274     [[maybe_unused]] alignas(EAS) FrameType type {0};
275     alignas(EAS) JSTaggedType *prevFp {nullptr};
276     alignas(EAS) uintptr_t returnAddr {0};
277     friend class FrameIterator;
278 };
279 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64);
280 
281 // * The OptimizedJSFunctionArgsConfig Frame's structure is illustrated as the following:
282 //          +--------------------------+
283 //          |         arg[N-1]         |
284 //          +--------------------------+
285 //          |         . . . .          |
286 //          +--------------------------+
287 //          |         arg[0]           |
288 //          +--------------------------+
289 //          |         argC             |
290 //  sp ---> +--------------------------+ -----------------
291 //          |                          |                 ^
292 //          |        prevFP            |                 |
293 //          |--------------------------|    OptimizedJSFunctionArgsConfigFrame
294 //          |       frameType          |                 |
295 //          |                          |                 V
296 //          +--------------------------+ -----------------
297 //
298 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
299 struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
300                                                                       base::AlignedPointer,
301                                                                       base::AlignedPointer> {
302 public:
GetTypeOffsetOptimizedJSFunctionArgConfigFrame303     static size_t GetTypeOffset()
304     {
305         return MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, type);
306     }
GetPrevOffsetOptimizedJSFunctionArgConfigFrame307     static size_t GetPrevOffset()
308     {
309         return MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp);
310     }
311 private:
312     enum class Index : size_t {
313         TypeIndex = 0,
314         PrevFpIndex,
315         NumOfMembers
316     };
317     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
318 
GetFrameFromSpOptimizedJSFunctionArgConfigFrame319     static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp)
320     {
321         return reinterpret_cast<OptimizedJSFunctionArgConfigFrame *>(reinterpret_cast<uintptr_t>(sp)
322             - MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp));
323     }
GetPrevFrameFpOptimizedJSFunctionArgConfigFrame324     inline JSTaggedType* GetPrevFrameFp()
325     {
326         return prevFp;
327     }
328     [[maybe_unused]] alignas(EAS) FrameType type {0};
329     alignas(EAS) JSTaggedType *prevFp {nullptr};
330     friend class FrameIterator;
331 };
332 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame),
333                       OptimizedJSFunctionArgConfigFrame::SizeArch32,
334                       OptimizedJSFunctionArgConfigFrame::SizeArch64);
335 
336 // * OptimizedJSFunctionFrame layout description as the following:
337 //               +--------------------------+
338 //               |        arg[N-1]          |
339 //               +--------------------------+
340 //               |       ...                |
341 //               +--------------------------+
342 //               |       arg[1]             |
343 //               +--------------------------+
344 //               |       arg[0]             |
345 //               +--------------------------+
346 //               |       this               |
347 //               +--------------------------+
348 //               |       new-target         |
349 //               +--------------------------+
350 //               |       call-target        |
351 //               |--------------------------|
352 //               |       argc               |
353 //               |--------------------------|
354 //               |       lexEnv             |
355 //      sp ----> |--------------------------| ---------------
356 //               |       returnAddr         |               ^
357 //               |--------------------------|               |
358 //               |       callsiteFp         |               |
359 //               |--------------------------|   OptimizedJSFunctionFrame
360 //               |       frameType          |               |
361 //               |--------------------------|               |
362 //               |       call-target        |               v
363 //               +--------------------------+ ---------------
364 //
365 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
366 struct OptimizedJSFunctionFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
367                                                              JSTaggedValue,
368                                                              base::AlignedPointer,
369                                                              base::AlignedPointer,
370                                                              base::AlignedPointer> {
371 public:
372     static constexpr size_t ENV_SLOT_DIFF = 2;
373     enum class Index : size_t {
374         JSFuncIndex = 0,
375         TypeIndex,
376         PrevFpIndex,
377         ReturnAddrIndex,
378         NumOfMembers
379     };
380     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
381 
GetFunctionDeltaReturnAddrOptimizedJSFunctionFrame382     static constexpr size_t GetFunctionDeltaReturnAddr()
383     {
384         return static_cast<size_t>(Index::ReturnAddrIndex) - static_cast<size_t>(Index::JSFuncIndex);
385     }
386 
GetPrevFrameFpOptimizedJSFunctionFrame387     inline JSTaggedType* GetPrevFrameFp()
388     {
389         return prevFp;
390     }
391 
GetArgvOptimizedJSFunctionFrame392     JSTaggedType* GetArgv(uintptr_t *preFrameSp) const
393     {
394         return reinterpret_cast<JSTaggedType *>(preFrameSp + ENV_SLOT_DIFF * sizeof(uint64_t) / sizeof(uintptr_t));
395     }
396 
GetArgcOptimizedJSFunctionFrame397     size_t GetArgc(uintptr_t *preFrameSp) const
398     {
399         return *(preFrameSp + sizeof(uint64_t) / sizeof(uintptr_t));
400     }
401 
402     JSTaggedType* GetArgv(const FrameIterator &it) const;
403 
GetReturnAddrOptimizedJSFunctionFrame404     uintptr_t GetReturnAddr() const
405     {
406         return returnAddr;
407     }
408 
409     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
410         const RootBaseAndDerivedVisitor &derivedVisitor) const;
411     void CollectBCOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const;
412 
GetFunctionOptimizedJSFunctionFrame413     inline JSTaggedValue GetFunction() const
414     {
415         return jsFunc;
416     }
417 
ComputeArgsConfigFrameSpOptimizedJSFunctionFrame418     static uintptr_t ComputeArgsConfigFrameSp(JSTaggedType *fp)
419     {
420         const size_t offset = 2;  // 2: skip prevFp and return address.
421         return reinterpret_cast<uintptr_t>(fp) + offset * sizeof(uintptr_t);
422     }
423 
GetTypeOffsetOptimizedJSFunctionFrame424     static size_t GetTypeOffset()
425     {
426         return MEMBER_OFFSET(OptimizedJSFunctionFrame, type);
427     }
428 
GetPrevOffsetOptimizedJSFunctionFrame429     static size_t GetPrevOffset()
430     {
431         return MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp);
432     }
433 
ComputeReservedJSFuncOffsetOptimizedJSFunctionFrame434     static size_t ComputeReservedJSFuncOffset(size_t slotSize)
435     {
436         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::JSFuncIndex);
437         return slotSize * slotOffset;
438     }
439 
440     friend class FrameIterator;
441     friend class FrameHandler;
442     void GetDeoptBundleInfo(const FrameIterator &it, std::vector<kungfu::ARKDeopt>& deopts) const;
443     void GetFuncCalleeRegAndOffset(
444         const FrameIterator &it, kungfu::CalleeRegAndOffsetVec &ret) const;
445     uintptr_t* ComputePrevFrameSp(const FrameIterator &it) const;
446 
447 private:
GetFrameFromSpOptimizedJSFunctionFrame448     static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp)
449     {
450         return reinterpret_cast<OptimizedJSFunctionFrame *>(reinterpret_cast<uintptr_t>(sp)
451             - MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp));
452     }
453 
454     // dynamic callee saveregisters for x86-64
455     alignas(EAS) JSTaggedValue jsFunc {JSTaggedValue::Undefined()};
456     [[maybe_unused]] alignas(EAS) FrameType type {0};
457     alignas(EAS) JSTaggedType *prevFp {nullptr};
458     alignas(EAS) uintptr_t returnAddr {0};
459     // dynamic callee saveregisters for arm64
460 };
461 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame),
462                       OptimizedJSFunctionFrame::SizeArch32,
463                       OptimizedJSFunctionFrame::SizeArch64);
464 // 2: return addr & prevFp, type and js function should be pairs to update type and js function at the same time.
465 static_assert((OptimizedJSFunctionFrame::GetFunctionDeltaReturnAddr() % 2) == 1);
466 
467 // * The JSFunctionEntry Frame's structure is illustrated as the following:
468 //          +--------------------------+
469 //          |      . . . . . .         |
470 //  sp ---> +--------------------------+ -----------------
471 //          |        prevFP            |                 ^
472 //          |--------------------------|                 |
473 //          |       frameType          |      JSFunctionEntryFrame
474 //          |--------------------------|                 |
475 //          |    preLeaveFrameFp       |                 v
476 //          +--------------------------+ -----------------
477 
478 struct OptimizedEntryFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
479                                                         base::AlignedPointer,
480                                                         base::AlignedPointer,
481                                                         base::AlignedPointer> {
482 public:
483     enum class CallType : size_t {
484         CALL_FUNC = 0,
485         CALL_NEW,
486     };
487 
488     enum class Index : size_t {
489         PreLeaveFrameFpIndex = 0,
490         TypeIndex,
491         PrevFpIndex,
492         NumOfMembers
493     };
494 
GetTypeOffsetOptimizedEntryFrame495     static size_t GetTypeOffset()
496     {
497         return MEMBER_OFFSET(OptimizedEntryFrame, type);
498     }
499 
GetLeaveFrameFpOffsetOptimizedEntryFrame500     static size_t GetLeaveFrameFpOffset()
501     {
502         return MEMBER_OFFSET(OptimizedEntryFrame, preLeaveFrameFp);
503     }
504 
GetPrevFrameFpOptimizedEntryFrame505     inline JSTaggedType* GetPrevFrameFp()
506     {
507         return preLeaveFrameFp;
508     }
509 
ComputeReservedSizeOptimizedEntryFrame510     static size_t ComputeReservedSize(size_t slotSize)
511     {
512         size_t slotOffset = static_cast<size_t>(Index::PrevFpIndex) - static_cast<size_t>(Index::PreLeaveFrameFpIndex);
513         return slotSize * slotOffset;
514     }
515     friend class FrameIterator;
516 
517 private:
518     alignas(EAS) JSTaggedType *preLeaveFrameFp {nullptr};
519     alignas(EAS) [[maybe_unused]] FrameType type {0};
520     alignas(EAS) [[maybe_unused]] JSTaggedType *prevFp {nullptr};
GetFrameFromSpOptimizedEntryFrame521     static OptimizedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
522     {
523         return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) -
524             MEMBER_OFFSET(OptimizedEntryFrame, prevFp));
525     }
526 };
527 STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedEntryFrame), OptimizedEntryFrame::SizeArch32, OptimizedEntryFrame::SizeArch64);
528 
529 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
530 struct InterpretedFrameBase : public base::AlignedStruct<base::AlignedPointer::Size(),
531                                                          base::AlignedPointer,
532                                                          base::AlignedSize> {
533     enum class Index : size_t {
534         PrevIndex = 0,
535         TypeIndex,
536         NumOfMembers
537     };
538     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
539 
GetPrevFrameFpInterpretedFrameBase540     inline JSTaggedType* GetPrevFrameFp()
541     {
542         return prev;
543     }
544 
GetFrameFromSpInterpretedFrameBase545     static InterpretedFrameBase* GetFrameFromSp(const JSTaggedType *sp)
546     {
547         return reinterpret_cast<InterpretedFrameBase *>(const_cast<JSTaggedType *>(sp)) - 1;
548     }
549 
GetPrevOffsetInterpretedFrameBase550     static size_t GetPrevOffset(bool isArch32)
551     {
552         return GetOffset<static_cast<size_t>(Index::PrevIndex)>(isArch32);
553     }
554 
GetTypeOffsetInterpretedFrameBase555     static size_t GetTypeOffset(bool isArch32)
556     {
557         return GetOffset<static_cast<size_t>(Index::TypeIndex)>(isArch32);
558     }
559 
GetSizeInterpretedFrameBase560     static constexpr size_t GetSize(bool isArch32)
561     {
562         return isArch32 ? InterpretedFrameBase::SizeArch32 : InterpretedFrameBase::SizeArch64;
563     }
564 
565     alignas(EAS) JSTaggedType *prev {nullptr}; // for llvm :c-fp ; for interrupt: thread-fp for gc
566     alignas(EAS) FrameType type {FrameType::OPTIMIZED_FRAME}; // 0
567 };
568 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase),
569                       InterpretedFrameBase::SizeArch32,
570                       InterpretedFrameBase::SizeArch64);
571 
572 // Interpreter Frame Layout as the following:
573 //   +----------------------------------+
574 //   |    argv[n-1]                     |
575 //   |----------------------------------|
576 //   |    ......                        |
577 //   |----------------------------------|
578 //   |    thisArg [maybe not exist]     |
579 //   |----------------------------------|
580 //   |    newTarget [maybe not exist]   |
581 //   |----------------------------------|
582 //   |    ......                        |
583 //   |----------------------------------|
584 //   |    Vregs [not exist in native]   |
585 //   +----------------------------------+--------+
586 //   |    base.frameType                |        ^
587 //   |----------------------------------|        |
588 //   |    base.prev(prev stack pointer) |        |
589 //   |----------------------------------|        |
590 //   |    pc(bytecode addr)             |        |
591 //   |----------------------------------|        |
592 //   |    sp(current stack pointer)     |        |
593 //   |----------------------------------|        |
594 //   |    env                           |        |
595 //   |----------------------------------|        |
596 //   |    acc                           |        |
597 //   |----------------------------------|   InterpretedFrame
598 //   |    profileTypeInfo               |        |
599 //   |----------------------------------|        |
600 //   |    thisObj                       |        |
601 //   |----------------------------------|        |
602 //   |    function                      |        |
603 //   |----------------------------------|        |
604 //   |    constpool                     |        v
605 //   +----------------------------------+--------+
606 //
607 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
608 struct InterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
609                                                      JSTaggedValue,
610                                                      JSTaggedValue,
611                                                      JSTaggedValue,
612                                                      JSTaggedValue,
613                                                      JSTaggedValue,
614                                                      JSTaggedValue,
615                                                      base::AlignedPointer,
616                                                      InterpretedFrameBase> {
617 public:
618     enum class Index : size_t {
619         ConstPoolIndex = 0,
620         FunctionIndex,
621         ThisObjIndex,
622         ProFileTypeInfoIndex,
623         AccIndex,
624         EnvIndex,
625         PcIndex,
626         BaseIndex,
627         NumOfMembers
628     };
629     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
630 
GetPrevFrameFpInterpretedFrame631     inline JSTaggedType* GetPrevFrameFp() const
632     {
633         return base.prev;
634     }
635 
GetFrameFromSpInterpretedFrame636     static InterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
637     {
638         return reinterpret_cast<InterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
639     }
640 
GetPcInterpretedFrame641     inline const uint8_t *GetPc() const
642     {
643         return pc;
644     }
645 
GetEnvInterpretedFrame646     inline JSTaggedValue GetEnv() const
647     {
648         return env;
649     }
650 
NumOfMembersInterpretedFrame651     static uint32_t NumOfMembers()
652     {
653         return sizeof(InterpretedFrame) / JSTaggedValue::TaggedTypeSize();
654     }
655     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
656 
657     alignas(EAS) JSTaggedValue constpool {JSTaggedValue::Hole()};
658     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
659     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
660     alignas(EAS) JSTaggedValue profileTypeInfo {JSTaggedValue::Hole()};
661     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
662     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
663     alignas(EAS) const uint8_t *pc {nullptr};
664     alignas(EAS) InterpretedFrameBase base;
665     friend class FrameIterator;
666 };
667 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrame), InterpretedFrame::SizeArch32, InterpretedFrame::SizeArch64);
668 
669 // * InterpretedBuiltinFrame layout description as the following:
670 //               |--------------------------| ---------------
671 //               |         . . . . .        |               ^
672 //               |    InterpretedFrameBase  |               |
673 //               |         . . . . .        |               |
674 //               |--------------------------|    InterpretedBuiltinFrame
675 //               |       bytecode-PC        |               |
676 //               |--------------------------|               |
677 //               |       call-target        |               v
678 //               +--------------------------+ ---------------
679 //
680 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
681 struct InterpretedBuiltinFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
682                                                             JSTaggedValue,
683                                                             base::AlignedPointer,
684                                                             InterpretedFrameBase> {
685     enum class Index : size_t {
686         FunctionIndex = 0,
687         PcIndex,
688         BaseIndex,
689         NumOfMembers
690     };
691     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
692 
GetPrevFrameFpInterpretedBuiltinFrame693     inline JSTaggedType* GetPrevFrameFp()
694     {
695         return base.prev;
696     }
697 
GetFrameFromSpInterpretedBuiltinFrame698     static InterpretedBuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
699     {
700         return reinterpret_cast<InterpretedBuiltinFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
701     }
702 
NumOfMembersInterpretedBuiltinFrame703     static uint32_t NumOfMembers()
704     {
705         return sizeof(InterpretedBuiltinFrame) / JSTaggedValue::TaggedTypeSize();
706     }
707 
708     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
709 
710     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
711     alignas(EAS) const uint8_t *pc {nullptr};
712     alignas(EAS) InterpretedFrameBase base;
713 };
714 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedBuiltinFrame),
715                       InterpretedBuiltinFrame::SizeArch32,
716                       InterpretedBuiltinFrame::SizeArch64);
717 
718 // AsmInterpretedFrame Layout as the following:
719 //   +----------------------------------+
720 //   |    argv[n-1]                     |
721 //   |----------------------------------|
722 //   |    ......                        |
723 //   |----------------------------------|
724 //   |    thisArg [maybe not exist]     |
725 //   |----------------------------------|
726 //   |    newTarget [maybe not exist]   |
727 //   |----------------------------------|
728 //   |    ......                        |
729 //   |----------------------------------|
730 //   |    Vregs [not exist in native]   |
731 //   +----------------------------------+--------+
732 //   |        .  .  .   .               |        ^
733 //   |     InterpretedFrameBase         |        |
734 //   |        .  .  .   .               |        |
735 //   |----------------------------------|        |
736 //   |    pc(bytecode addr)             |        |
737 //   |----------------------------------|        |
738 //   |    sp(current stack pointer)     |        |
739 //   |----------------------------------|   AsmInterpretedFrame
740 //   |    callSize                      |        |
741 //   |----------------------------------|        |
742 //   |    env                           |        |
743 //   |----------------------------------|        |
744 //   |    acc                           |        |
745 //   |----------------------------------|        |
746 //   |    thisObj                       |        |
747 //   |----------------------------------|        |
748 //   |    call-target                   |        v
749 //   +----------------------------------+--------+
750 //
751 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
752 struct AsmInterpretedFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
753                                                         JSTaggedValue,
754                                                         JSTaggedValue,
755                                                         JSTaggedValue,
756                                                         JSTaggedValue,
757                                                         base::AlignedPointer,
758                                                         base::AlignedPointer,
759                                                         base::AlignedPointer,
760                                                         InterpretedFrameBase> {
761     enum class Index : size_t {
762         FunctionIndex = 0,
763         ThisObjIndex,
764         AccIndex,
765         EnvIndex,
766         CallSizeIndex,
767         FpIndex,
768         PcIndex,
769         BaseIndex,
770         NumOfMembers
771     };
772 
773     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
774 
GetCurrentFramePointerAsmInterpretedFrame775     inline JSTaggedType* GetCurrentFramePointer()
776     {
777         return fp;
778     }
779 
GetPrevFrameFpAsmInterpretedFrame780     inline JSTaggedType* GetPrevFrameFp()
781     {
782         return base.prev;
783     }
784 
GetFrameFromSpAsmInterpretedFrame785     static AsmInterpretedFrame* GetFrameFromSp(const JSTaggedType *sp)
786     {
787         return reinterpret_cast<AsmInterpretedFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
788     }
789 
GetFpOffsetAsmInterpretedFrame790     static size_t GetFpOffset(bool isArch32)
791     {
792         return GetOffset<static_cast<size_t>(Index::FpIndex)>(isArch32);
793     }
794 
GetCallSizeOffsetAsmInterpretedFrame795     static size_t GetCallSizeOffset(bool isArch32)
796     {
797         return GetOffset<static_cast<size_t>(Index::CallSizeIndex)>(isArch32);
798     }
799 
GetFunctionOffsetAsmInterpretedFrame800     static size_t GetFunctionOffset(bool isArch32)
801     {
802         return GetOffset<static_cast<size_t>(Index::FunctionIndex)>(isArch32);
803     }
804 
GetThisOffsetAsmInterpretedFrame805     static size_t GetThisOffset(bool isArch32)
806     {
807         return GetOffset<static_cast<size_t>(Index::ThisObjIndex)>(isArch32);
808     }
809 
GetAccOffsetAsmInterpretedFrame810     static size_t GetAccOffset(bool isArch32)
811     {
812         return GetOffset<static_cast<size_t>(Index::AccIndex)>(isArch32);
813     }
814 
GetEnvOffsetAsmInterpretedFrame815     static size_t GetEnvOffset(bool isArch32)
816     {
817         return GetOffset<static_cast<size_t>(Index::EnvIndex)>(isArch32);
818     }
819 
GetBaseOffsetAsmInterpretedFrame820     static size_t GetBaseOffset(bool isArch32)
821     {
822         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
823     }
824 
GetPcOffsetAsmInterpretedFrame825     static size_t GetPcOffset(bool isArch32)
826     {
827         return GetOffset<static_cast<size_t>(Index::PcIndex)>(isArch32);
828     }
829 
GetSizeAsmInterpretedFrame830     static constexpr size_t GetSize(bool isArch32)
831     {
832         return isArch32 ? AsmInterpretedFrame::SizeArch32 : AsmInterpretedFrame::SizeArch64;
833     }
834 
NumOfMembersAsmInterpretedFrame835     static uint32_t NumOfMembers()
836     {
837         return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize();
838     }
839     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
840         const RootBaseAndDerivedVisitor &derivedVisitor) const;
841 
GetEnvAsmInterpretedFrame842     JSTaggedValue GetEnv() const
843     {
844         return env;
845     }
846 
GetPcAsmInterpretedFrame847     const uint8_t *GetPc() const
848     {
849         return pc;
850     }
851 
852     alignas(EAS) JSTaggedValue function {JSTaggedValue::Hole()};
853     alignas(EAS) JSTaggedValue thisObj {JSTaggedValue::Hole()};
854     alignas(EAS) JSTaggedValue acc {JSTaggedValue::Hole()};
855     alignas(EAS) JSTaggedValue env {JSTaggedValue::Hole()};
856     alignas(EAS) uintptr_t callSize {0};
857     alignas(EAS) JSTaggedType *fp {nullptr};
858     alignas(EAS) const uint8_t *pc {nullptr};
859     alignas(EAS) InterpretedFrameBase base;
860     // vregs, not exist in native
861     // args, may be truncated if not extra
862 };
863 STATIC_ASSERT_EQ_ARCH(sizeof(AsmInterpretedFrame), AsmInterpretedFrame::SizeArch32, AsmInterpretedFrame::SizeArch64);
864 
865 // InterpretedEntryFrame Layout as the following:
866 //   +----------------------------------+---------------
867 //   |        .  .  .   .               |              ^
868 //   |     InterpretedFrameBase         |              |
869 //   |        .  .  .   .               |    InterpretedEntryFrame
870 //   |----------------------------------|              |
871 //   |    pc(bytecode addr)             |              v
872 //   |----------------------------------|---------------
873 //
874 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
875 struct InterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
876                                                           base::AlignedPointer,
877                                                           InterpretedFrameBase> {
878     enum class Index : size_t {
879         PcIndex = 0,
880         BaseIndex,
881         NumOfMembers
882     };
883     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
884 
GetPrevFrameFpInterpretedEntryFrame885     inline JSTaggedType* GetPrevFrameFp()
886     {
887         return base.prev;
888     }
889 
GetFrameFromSpInterpretedEntryFrame890     static InterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
891     {
892         return reinterpret_cast<InterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
893     }
894 
NumOfMembersInterpretedEntryFrame895     static uint32_t NumOfMembers()
896     {
897         return sizeof(InterpretedEntryFrame) / JSTaggedValue::TaggedTypeSize();
898     }
899 
900     void GCIterate(const FrameIterator &it, const RootVisitor &visitor,
901         const RootRangeVisitor &rangeVisitor) const;
902     alignas(EAS) const uint8_t *pc {nullptr};
903     alignas(EAS) InterpretedFrameBase base;
904 };
905 STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedEntryFrame),
906                       InterpretedEntryFrame::SizeArch32,
907                       InterpretedEntryFrame::SizeArch64);
908 
909 
910 // AsmInterpretedEntryFrame Layout as the following:
911 //   +----------------------------------+---------------
912 //   |        .  .  .   .               |              ^
913 //   |     InterpretedFrameBase         |              |
914 //   |        .  .  .   .               |    AsmInterpretedEntryFrame
915 //   |----------------------------------|              |
916 //   |    pc(bytecode addr)             |              v
917 //   |----------------------------------|---------------
918 //
919 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
920 struct AsmInterpretedEntryFrame : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
921                                                              base::AlignedPointer,
922                                                              InterpretedFrameBase> {
923     enum class Index : size_t {
924         PcIndex = 0,
925         BaseIndex,
926         NumOfMembers
927     };
928     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
929 
GetPrevFrameFpAsmInterpretedEntryFrame930     inline JSTaggedType* GetPrevFrameFp()
931     {
932         return base.prev;
933     }
934 
GetBaseOffsetAsmInterpretedEntryFrame935     static size_t GetBaseOffset(bool isArch32)
936     {
937         return GetOffset<static_cast<size_t>(Index::BaseIndex)>(isArch32);
938     }
939 
GetFrameFromSpAsmInterpretedEntryFrame940     static AsmInterpretedEntryFrame* GetFrameFromSp(const JSTaggedType *sp)
941     {
942         return reinterpret_cast<AsmInterpretedEntryFrame *>(const_cast<JSTaggedType *>(sp)) - 1;
943     }
944 
945     alignas(EAS) const uint8_t *pc {nullptr};
946     alignas(EAS) InterpretedFrameBase base;
947 };
948 
949 // AsmInterpretedBridgeFrame Layout as the following:
950 //   +----------------------------------+---------------
951 //   |      ret-address                 |              ^
952 //   |----------------------------------|              |
953 //   |        .  .  .   .               |     AsmInterpretedBridgeFrame
954 //   |     AsmInterpretedEntryFrame     |              |
955 //   |        .  .  .   .               |              v
956 //   |----------------------------------|---------------
957 //
958 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
959 struct AsmInterpretedBridgeFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
960                                                               AsmInterpretedEntryFrame,
961                                                               base::AlignedPointer> {
962     enum class Index : size_t {
963         EntryIndex = 0,
964         ReturnAddrIndex,
965         NumOfMembers
966     };
967     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
968 
GetFrameFromSpAsmInterpretedBridgeFrame969     static AsmInterpretedBridgeFrame* GetFrameFromSp(const JSTaggedType *sp)
970     {
971         return reinterpret_cast<AsmInterpretedBridgeFrame *>(reinterpret_cast<uintptr_t>(sp) -
972             MEMBER_OFFSET(AsmInterpretedBridgeFrame, returnAddr));
973     }
GetCallSiteSpAsmInterpretedBridgeFrame974     uintptr_t GetCallSiteSp() const
975     {
976         return ToUintPtr(this) + sizeof(AsmInterpretedBridgeFrame);
977     }
GetPrevFrameFpAsmInterpretedBridgeFrame978     inline JSTaggedType* GetPrevFrameFp()
979     {
980         return entry.base.prev;
981     }
982 
GetReturnAddrOffsetAsmInterpretedBridgeFrame983     static size_t GetReturnAddrOffset(bool isArch32)
984     {
985         return GetOffset<static_cast<size_t>(Index::ReturnAddrIndex)>(isArch32);
986     }
987 
GetSizeAsmInterpretedBridgeFrame988     static constexpr size_t GetSize(bool isArch32)
989     {
990         return isArch32 ? AsmInterpretedBridgeFrame::SizeArch32 : AsmInterpretedBridgeFrame::SizeArch64;
991     }
992 
993     AsmInterpretedEntryFrame entry;
994     alignas(EAS) uintptr_t returnAddr;
GetReturnAddrAsmInterpretedBridgeFrame995     uintptr_t GetReturnAddr() const
996     {
997         return returnAddr;
998     }
999 };
1000 
1001 // * Optimized-leaved-frame layout as the following:
1002 //         +--------------------------+
1003 //         |       argv[N-1]          |
1004 //         |--------------------------|
1005 //         |       . . . . .          |
1006 //         |--------------------------|
1007 //         |       argv[0]            |
1008 //         +--------------------------+-------------
1009 //         |       argc               |            ^
1010 //         |--------------------------|            |
1011 //         |       RuntimeId          |            |
1012 //  sp --> |--------------------------|   OptimizedLeaveFrame
1013 //         |       ret-addr           |            |
1014 //         |--------------------------|            |
1015 //         |       prevFp             |            |
1016 //         |--------------------------|            |
1017 //         |       frameType          |            v
1018 //         +--------------------------+-------------
1019 //
1020 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1021 struct OptimizedLeaveFrame {
1022     FrameType type;
1023     uintptr_t callsiteFp; // thread sp set here
1024     uintptr_t returnAddr;
1025     uint64_t argRuntimeId;
1026     uint64_t argc;
1027     // argv[0]...argv[argc-1] dynamic according to agc
GetFrameFromSpOptimizedLeaveFrame1028     static OptimizedLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1029     {
1030         return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1031             MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp));
1032     }
GetCallSiteSpOptimizedLeaveFrame1033     uintptr_t GetCallSiteSp() const
1034     {
1035         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId);
1036     }
GetPrevFrameFpOptimizedLeaveFrame1037     inline JSTaggedType* GetPrevFrameFp() const
1038     {
1039         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1040     }
1041 
GetReturnAddrOptimizedLeaveFrame1042     uintptr_t GetReturnAddr() const
1043     {
1044         return returnAddr;
1045     }
1046     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1047 };
1048 
1049 // * Optimized-leaved-frame-with-argv layout as the following:
1050 //         +--------------------------+
1051 //         |       argv[]             |
1052 //         +--------------------------+-------------
1053 //         |       argc               |            ^
1054 //         |--------------------------|            |
1055 //         |       RuntimeId          |   OptimizedWithArgvLeaveFrame
1056 //  sp --> |--------------------------|            |
1057 //         |       returnAddr         |            |
1058 //         |--------------------------|            |
1059 //         |       callsiteFp         |            |
1060 //         |--------------------------|            |
1061 //         |       frameType          |            v
1062 //         +--------------------------+-------------
1063 
1064 struct OptimizedWithArgvLeaveFrame {
1065     FrameType type;
1066     uintptr_t callsiteFp; // thread sp set here
1067     uintptr_t returnAddr;
1068     uint64_t argRuntimeId;
1069     uint64_t argc;
1070 
GetFrameFromSpOptimizedWithArgvLeaveFrame1071     static OptimizedWithArgvLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1072     {
1073         return reinterpret_cast<OptimizedWithArgvLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1074             MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, callsiteFp));
1075     }
GetCallSiteSpOptimizedWithArgvLeaveFrame1076     uintptr_t GetCallSiteSp() const
1077     {
1078         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedWithArgvLeaveFrame, argRuntimeId);
1079     }
GetPrevFrameFpOptimizedWithArgvLeaveFrame1080     inline JSTaggedType* GetPrevFrameFp()
1081     {
1082         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1083     }
GetReturnAddrOptimizedWithArgvLeaveFrame1084     uintptr_t GetReturnAddr() const
1085     {
1086         return returnAddr;
1087     }
1088     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1089 };
1090 
1091 // * OptimizedBuiltinLeaveFrame layout as the following:
1092 //         +--------------------------+
1093 //         |       argv[N-1]          |
1094 //         |--------------------------|
1095 //         |       . . . . .          |
1096 //         |--------------------------|
1097 //         |       argv[0]            |
1098 //         +--------------------------+-------------
1099 //         |       argc               |            ^
1100 //         |--------------------------|            |
1101 //         |       env                |            |
1102 //         +--------------------------+            |
1103 //         |       ret-addr           |            |
1104 //  sp --> |--------------------------|   OptimizedBuiltinLeaveFrame
1105 //         |       prevFp             |            |
1106 //         |--------------------------|            |
1107 //         |       frameType          |            |
1108 //         |--------------------------|            |
1109 //         |       align byte         |            v
1110 //         +--------------------------+-------------
1111 //
1112 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1113 struct OptimizedBuiltinLeaveFrame {
1114 public:
GetFrameFromSpOptimizedBuiltinLeaveFrame1115     static OptimizedBuiltinLeaveFrame* GetFrameFromSp(const JSTaggedType *sp)
1116     {
1117         return reinterpret_cast<OptimizedBuiltinLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
1118             MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp));
1119     }
GetCallSiteSpOptimizedBuiltinLeaveFrame1120     uintptr_t GetCallSiteSp() const
1121     {
1122         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, thread);
1123     }
GetPrevFrameFpOptimizedBuiltinLeaveFrame1124     inline JSTaggedType* GetPrevFrameFp() const
1125     {
1126         return reinterpret_cast<JSTaggedType*>(callsiteFp);
1127     }
GetReturnAddrOptimizedBuiltinLeaveFrame1128     uintptr_t GetReturnAddr() const
1129     {
1130         return returnAddr;
1131     }
1132     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
GetTypeOffsetOptimizedBuiltinLeaveFrame1133     static size_t GetTypeOffset()
1134     {
1135         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, type);
1136     }
GetPrevOffsetOptimizedBuiltinLeaveFrame1137     static size_t GetPrevOffset()
1138     {
1139         return MEMBER_OFFSET(OptimizedBuiltinLeaveFrame, callsiteFp);
1140     }
GetArgvOptimizedBuiltinLeaveFrame1141     const JSTaggedType* GetArgv() const
1142     {
1143         return reinterpret_cast<const JSTaggedType *>(&argc + 1);
1144     }
1145 
1146 private:
1147     [[maybe_unused]] FrameType type;
1148     uintptr_t callsiteFp; // thread sp set here
1149     uintptr_t returnAddr;
1150     JSTaggedValue thread;
1151     uint64_t argc;
1152     // argv[0]...argv[argc-1] dynamic according to agc
1153 };
1154 
1155 // * BuiltinFrame layout as the following:
1156 //               +--------------------------+
1157 //               |     argV[N - 1]          |
1158 //               |--------------------------|
1159 //               |       . . . .            |
1160 //               |--------------------------+
1161 //               |     argV[2]=this         |
1162 //               +--------------------------+
1163 //               |     argV[1]=new-target   |
1164 //               +--------------------------+
1165 //               |     argV[0]=call-target  |
1166 //               +--------------------------+ ---------
1167 //               |       argc               |         ^
1168 //               |--------------------------|         |
1169 //               |       thread             |         |
1170 //               |--------------------------|         |
1171 //               |       returnAddr         |     BuiltinFrame
1172 //               |--------------------------|         |
1173 //               |       callsiteFp         |         |
1174 //               |--------------------------|         |
1175 //               |       frameType          |         v
1176 //               +--------------------------+ ---------
1177 //
1178 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1179 struct BuiltinFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1180                                                  base::AlignedSize,
1181                                                  base::AlignedPointer,
1182                                                  base::AlignedPointer,
1183                                                  base::AlignedPointer,
1184                                                  base::AlignedPointer,
1185                                                  base::AlignedPointer> {
1186     enum class Index : size_t {
1187         TypeIndex = 0,
1188         PrevFpIndex,
1189         ReturnAddrIndex,
1190         ThreadIndex,
1191         NumArgsIndex,
1192         StackArgsIndex,
1193         NumOfMembers
1194     };
1195     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1196 
GetFrameFromSpBuiltinFrame1197     static BuiltinFrame* GetFrameFromSp(const JSTaggedType *sp)
1198     {
1199         return reinterpret_cast<BuiltinFrame *>(reinterpret_cast<uintptr_t>(sp) -
1200             MEMBER_OFFSET(BuiltinFrame, prevFp));
1201     }
GetPrevFrameFpBuiltinFrame1202     inline JSTaggedType* GetPrevFrameFp()
1203     {
1204         return prevFp;
1205     }
GetCallSiteSpBuiltinFrame1206     uintptr_t GetCallSiteSp() const
1207     {
1208         return ToUintPtr(this) + MEMBER_OFFSET(BuiltinFrame, thread);
1209     }
GetPreFpOffsetBuiltinFrame1210     static size_t GetPreFpOffset(bool isArch32)
1211     {
1212         return GetOffset<static_cast<size_t>(Index::PrevFpIndex)>(isArch32);
1213     }
GetNumArgsToFpDeltaBuiltinFrame1214     static size_t GetNumArgsToFpDelta(bool isArch32)
1215     {
1216         auto offset = GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32);
1217         return offset - GetPreFpOffset(isArch32);
1218     }
GetStackArgsToFpDeltaBuiltinFrame1219     static size_t GetStackArgsToFpDelta(bool isArch32)
1220     {
1221         auto offset = GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
1222         return offset - GetPreFpOffset(isArch32);
1223     }
GetStackArgsAddressBuiltinFrame1224     uintptr_t GetStackArgsAddress()
1225     {
1226         return reinterpret_cast<uintptr_t>(&stackArgs);
1227     }
GetFunctionBuiltinFrame1228     JSTaggedValue GetFunction()
1229     {
1230         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1231         return JSTaggedValue(*functionAddress);
1232     }
GetNumArgsBuiltinFrame1233     int32_t GetNumArgs()
1234     {
1235         return numArgs;
1236     }
1237 
GetReturnAddrBuiltinFrame1238     uintptr_t GetReturnAddr() const
1239     {
1240         return returnAddr;
1241     }
1242     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1243     alignas(EAS) FrameType type;
1244     alignas(EAS) JSTaggedType *prevFp;
1245     alignas(EAS) uintptr_t returnAddr;
1246     alignas(EAS) uintptr_t thread;
1247     alignas(EAS) int32_t numArgs;
1248     alignas(EAS) uintptr_t stackArgs;
1249 };
1250 
1251 // * BuiltinWithArgvFrame layout as the following:
1252 //               +--------------------------+ ---------
1253 //               |       . . . . .          |         ^
1254 //               |--------------------------|         |
1255 //               |       returnAddr         |         |
1256 //               |--------------------------|         |
1257 //               |       callsiteFp         |   BuiltinWithArgvFrame
1258 //               |--------------------------|         |
1259 //               |       frameType          |         |
1260 //               +--------------------------+         |
1261 //               |        argc              |         v
1262 //               +--------------------------+ ---------
1263 //               |        argV[0]           |
1264 //               +--------------------------+
1265 //               |        argV[1]           |
1266 //               +--------------------------+
1267 //               |        . . . .           |
1268 //               +--------------------------+
1269 //
1270 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
1271 struct BuiltinWithArgvFrame : public base::AlignedStruct<base::AlignedPointer::Size(),
1272                                                          base::AlignedSize,
1273                                                          base::AlignedPointer,
1274                                                          base::AlignedPointer> {
1275     enum class Index : int {
1276         StackArgsTopIndex = -1,
1277         NumArgsIndex = -1,
1278         TypeIndex = 0,
1279         PrevFpIndex,
1280         ReturnAddrIndex,
1281         NumOfMembers
1282     };
1283     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
1284 
GetFrameFromSpBuiltinWithArgvFrame1285     static BuiltinWithArgvFrame* GetFrameFromSp(const JSTaggedType *sp)
1286     {
1287         return reinterpret_cast<BuiltinWithArgvFrame *>(reinterpret_cast<uintptr_t>(sp) -
1288             MEMBER_OFFSET(BuiltinFrame, prevFp));
1289     }
GetPrevFrameFpBuiltinWithArgvFrame1290     inline JSTaggedType* GetPrevFrameFp()
1291     {
1292         return prevFp;
1293     }
GetCallSiteSpBuiltinWithArgvFrame1294     uintptr_t GetCallSiteSp() const
1295     {
1296         return ToUintPtr(this) + sizeof(BuiltinWithArgvFrame);
1297     }
GetStackArgsAddressBuiltinWithArgvFrame1298     uintptr_t GetStackArgsAddress()
1299     {
1300         auto topAddress = ToUintPtr(this) +
1301             (static_cast<int>(Index::StackArgsTopIndex) * sizeof(uintptr_t));
1302         auto numberArgs = GetNumArgs() + NUM_MANDATORY_JSFUNC_ARGS;
1303         return topAddress - static_cast<uint32_t>(numberArgs) * sizeof(uintptr_t);
1304     }
GetFunctionBuiltinWithArgvFrame1305     JSTaggedValue GetFunction()
1306     {
1307         auto functionAddress = reinterpret_cast<JSTaggedType *>(GetStackArgsAddress());
1308         return JSTaggedValue(*functionAddress);
1309     }
GetNumArgsBuiltinWithArgvFrame1310     int32_t GetNumArgs()
1311     {
1312         auto argcAddress = reinterpret_cast<int32_t *>(
1313             ToUintPtr(this) + (static_cast<int>(Index::NumArgsIndex) * sizeof(uintptr_t)));
1314         return *argcAddress;
1315     }
GetReturnAddrBuiltinWithArgvFrame1316     uintptr_t GetReturnAddr() const
1317     {
1318         return returnAddr;
1319     }
1320     void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor) const;
1321     // argv(... this, new.target, function)
1322     // numargs
1323     alignas(EAS) FrameType type;
1324     alignas(EAS) JSTaggedType *prevFp;
1325     alignas(EAS) uintptr_t returnAddr;
1326 };
1327 
1328 enum class GCVisitedFlag : bool {
1329     VISITED = true,
1330     IGNORED = false,
1331 };
1332 
1333 class FrameIterator {
1334 public:
1335     explicit FrameIterator(JSTaggedType *sp, const JSThread *thread = nullptr);
GetFrameType()1336     FrameType GetFrameType() const
1337     {
1338         ASSERT(current_ != nullptr);
1339         FrameType *typeAddr = reinterpret_cast<FrameType *>(
1340             reinterpret_cast<uintptr_t>(current_) - sizeof(FrameType));
1341         return *typeAddr;
1342     }
1343 
1344     template<class T>
GetFrame()1345     T* GetFrame()
1346     {
1347         return T::GetFrameFromSp(current_);
1348     }
1349 
1350     template<class T>
GetFrame()1351     const T* GetFrame() const
1352     {
1353         return T::GetFrameFromSp(current_);
1354     }
1355 
Done()1356     bool Done() const
1357     {
1358         return current_ == nullptr;
1359     }
GetSp()1360     JSTaggedType *GetSp() const
1361     {
1362         return current_;
1363     }
GetSp()1364     JSTaggedType *GetSp()
1365     {
1366         return current_;
1367     }
GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec & ret)1368     void GetCalleeRegAndOffsetVec(kungfu::CalleeRegAndOffsetVec &ret) const
1369     {
1370         ret = calleeRegInfo_;
1371     }
1372     int ComputeDelta() const;
1373     template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED>
1374     void Advance();
1375     uint32_t GetBytecodeOffset() const;
1376     uintptr_t GetPrevFrameCallSiteSp([[maybe_unused]] uintptr_t curPc = 0) const;
1377     uintptr_t GetPrevFrame() const;
GetCallSiteSp()1378     uintptr_t GetCallSiteSp() const
1379     {
1380         return optimizedCallSiteSp_;
1381     }
GetOptimizedReturnAddr()1382     uintptr_t GetOptimizedReturnAddr() const
1383     {
1384         return optimizedReturnAddr_;
1385     }
GetThread()1386     const JSThread *GetThread() const
1387     {
1388         return thread_;
1389     }
1390     bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const;
1391     void CollectBCOffsetInfo(kungfu::ConstInfo &info) const;
1392     void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const;
1393     std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const;
1394     int GetCallSiteDelta(uintptr_t retAddr) const;
1395 
1396     Method *CheckAndGetMethod() const;
1397     JSTaggedValue GetFunction() const;
1398 
IsLeaveFrame()1399     bool IsLeaveFrame() const
1400     {
1401         FrameType type = GetFrameType();
1402         return (type == FrameType::LEAVE_FRAME) || (type == FrameType::LEAVE_FRAME_WITH_ARGV);
1403     }
1404 
IsOptimizedFrame()1405     bool IsOptimizedFrame() const
1406     {
1407         FrameType type = GetFrameType();
1408         return (type == FrameType::OPTIMIZED_FRAME);
1409     }
1410 
IsOptimizedJSFunctionFrame()1411     bool IsOptimizedJSFunctionFrame() const
1412     {
1413         FrameType type = GetFrameType();
1414         return (type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
1415     }
1416 
1417 private:
1418     JSTaggedType *current_ {nullptr};
1419     const JSThread *thread_ {nullptr};
1420     const kungfu::ArkStackMapParser *arkStackMapParser_ {nullptr};
1421     uintptr_t optimizedCallSiteSp_ {0};
1422     uintptr_t optimizedReturnAddr_ {0};
1423     uint8_t *stackMapAddr_ {nullptr};
1424     int fpDeltaPrevFrameSp_ {0};
1425     kungfu::CalleeRegAndOffsetVec calleeRegInfo_;
1426 };
1427 }  // namespace panda::ecmascript
1428 extern "C" int step_ark_managed_native_frame(
1429     int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp, char *buf, size_t buf_sz);
1430 #endif // ECMASCRIPT_FRAMES_H
1431