• 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 //    in aot project, five Frames: Interpreter Frame、Runtime Frame、Optimized Entry Frame、Optimized Frame、
17 // Optimized Leave Frame.
18 //    Optimized Entry Frame: when Interpreter/RuntimeFrame call aot code, generate this kind of frame.
19 // following c-abi, we'll add the following field: frameType(distinguish frame)、sp(record callite sp register
20 // for llvm stackmap)、prev(record previous frame position).
21 //    Optimized Leave Frame: when aot code call Interpreter/RuntimeFrame, generate this kind of frame.
22 // gc related context (patchid、sp、fp) is saved to frame, prev field point to previous frame.
23 //    Optimized Frame: when aot code call aot code, generate this kind of frame.
24 // following c-abi, we'll add the following field: frameType(distinguish frame)、sp(record callite sp register
25 // for llvm stackmap).
26 
27 // Frame Layout
28 // Interpreter Frame(alias   **iframe** ) Layout as follow:
29 // ```
30 //   +----------------------------------+-------------------+
31 //   |    argv[n-1]                     |                   ^
32 //   |----------------------------------|                   |
33 //   |    ......                        |                   |
34 //   |----------------------------------|                   |
35 //   |    thisArg [maybe not exist]     |                   |
36 //   |----------------------------------|                   |
37 //   |    newTarget [maybe not exist]   |                   |
38 //   |----------------------------------|                   |
39 //   |    callTarget [deleted]          |                   |
40 //   |----------------------------------|                   |
41 //   |    ......                        |                   |
42 //   |----------------------------------|                   |
43 //   |    Vregs [not exist in native]   |                   |
44 //   +----------------------------------+--------+      interpreter frame
45 //   |    base.frameType                |        ^          |
46 //   |----------------------------------|        |          |
47 //   |    base.prev(pre stack pointer)  |        |          |
48 //   |----------------------------------|        |          |
49 //   |    numActualArgs [deleted]       |        |          |
50 //   |----------------------------------|        |          |
51 //   |    env                           |        |          |
52 //   |----------------------------------|        |          |
53 //   |    acc                           |        |          |
54 //   |----------------------------------|InterpretedFrame   |
55 //   |    profileTypeInfo               |        |          |
56 //   |----------------------------------|        |          |
57 //   |    constantpool                  |        |          |
58 //   |----------------------------------|        |          |
59 //   |    method [changed to function]  |        |          |
60 //   |----------------------------------|        |          |
61 //   |    sp(current stack point)       |        |          |
62 //   |----------------------------------|        |          |
63 //   |    pc(bytecode addr)             |        v          v
64 //   +----------------------------------+--------+----------+
65 
66 //   Optimized Leave Frame(alias OptimizedLeaveFrame) layout
67 //   +--------------------------+
68 //   |      argv[]              |
69 //   +--------------------------+ ---
70 //   |       argc               |   ^
71 //   |--------------------------|   |
72 //   |       patchID            | Fixed
73 //   |--------------------------| OptimizedLeaveFrame
74 //   |       RuntimeId          |   |
75 //   |--------------------------|   |
76 //   |       returnAddr         |   |
77 //   |--------------------------|   |
78 //   |       callsiteFp         |   |
79 //   |--------------------------|   |
80 //   |     frameType            |   v
81 //   +--------------------------+ ---
82 //   |  callee save registers   |
83 //   +--------------------------+
84 
85 //   Optimized Frame(alias OptimizedFrame) layout
86 //   +--------------------------+
87 //   | calleesave registers |   ^
88 //   |----------------------|   |
89 //   |   returnaddress      | Fixed
90 //   |----------------------| OptimizedFrame
91 //   |       prevFp         |   |
92 //   |----------------------|   |
93 //   |     frameType        |   |
94 //   |----------------------|   |
95 //   |       callsiteSp     |   v
96 //   +--------------------------+
97 
98 //   Optimized Entry Frame(alias OptimizedEntryFrame) layout
99 //   +--------------------------+
100 //   |   returnaddress      |   ^
101 //   |----------------------|   |
102 //   |calleesave registers  | Fixed
103 //   |----------------------| OptimizedEntryFrame
104 //   |      prevFp          |   |
105 //   |----------------------|   |
106 //   |      frameType       |   |
107 //   |----------------------|   |
108 //   |  prevLeaveFrameFp    |   v
109 //   +--------------------------+
110 
111 // ```
112 // address space grow from high address to low address.we add new field  **FrameType** ,
113 // the field's value is INTERPRETER_FRAME(represent interpreter frame).
114 // **currentsp**  is pointer to  callTarget field address, sp field 's value is  **currentsp** ,
115 // pre field pointer pre stack frame point. fill JSthread's sp field with iframe sp field
116 // by  calling JSThread->SetCurrentSPFrame and save pre Frame address to iframe pre field.
117 
118 // For Example:
119 // ```
120 //                     call                   call
121 //     foo    -----------------> bar   ----------------------->baz ---------------------> rtfunc
122 // (interpret frame)       (OptimizedEntryFrame)      (OptimizedFrame)     (OptimizedLeaveFrame + Runtime Frame)
123 // ```
124 
125 // Frame Layout as follow:
126 // ```
127 //   +----------------------------------+-------------------+
128 //   |    argv[n-1]                     |                   ^
129 //   |----------------------------------|                   |
130 //   |    ......                        |                   |
131 //   |----------------------------------|                   |
132 //   |    thisArg [maybe not exist]     |                   |
133 //   |----------------------------------|                   |
134 //   |    newTarget [maybe not exist]   |                   |
135 //   |----------------------------------|                   |
136 //   |    ......                        |                   |
137 //   |----------------------------------|                   |
138 //   |    Vregs                         |                   |
139 //   +----------------------------------+--------+     foo's frame
140 //   |    base.frameType                |        ^          |
141 //   |----------------------------------|        |          |
142 //   |    base.prev(pre stack pointer)  |        |          |
143 //   |----------------------------------|        |          |
144 //   |    env                           |        |          |
145 //   |----------------------------------|        |          |
146 //   |    acc                           |        |          |
147 //   |----------------------------------|        |          |
148 //   |    profileTypeInfo               |InterpretedFrame   |
149 //   |----------------------------------|        |          |
150 //   |    constantpool                  |        |          |
151 //   |----------------------------------|        |          |
152 //   |    function                      |        |          |
153 //   |----------------------------------|        |          |
154 //   |    sp(current stack point)       |        |          |
155 //   |----------------------------------|        |          |
156 //   |    pc(bytecode addr)             |        v          v
157 //   +----------------------------------+--------+----------+
158 //   |                   .............                      |
159 //   +--------------------------+---------------------------+
160 //   |   returnaddress      |   ^                           ^
161 //   |----------------------|   |                           |
162 //   |calleesave registers  | Fixed                         |
163 //   |----------------------| OptimizedEntryFrame       bar's frame
164 //   |      prevFp          |   |                           |
165 //   |----------------------|   |                           |
166 //   |      frameType       |   |                           |
167 //   |----------------------|   |                           |
168 //   |  prevLeaveFrameFp    |   v                           |
169 //   +--------------------------+                           V
170 //   +--------------------------+---------------------------+
171 //   |                   .............                      |
172 //   +--------------------------+---------------------------+
173 //   +--------------------------+---------------------------+
174 //   | calleesave registers |   ^                           ^
175 //   |----------------------|   |                           |
176 //   |   returnaddress      | Fixed                         |
177 //   |----------------------| OptimizedFrame                |
178 //   |       prevFp         |   |                           |
179 //   |----------------------|   |                       baz's frame Header
180 //   |     frameType        |   |                           |
181 //   |----------------------|   |                           |
182 //   |   callsitesp         |   v                           V
183 //   +--------------------------+---------------------------+
184 //   |                   .............                      |
185 //   +--------------------------+---------------------------+
186 //   |      argv[]              |                           ^
187 //   +--------------------------+ ---                       |
188 //   |       argc               |   ^                       |
189 //   |--------------------------|   |                       |
190 //   |       patchID            | Fixed                     |
191 //   |--------------------------| OptimizedLeaveFrame             |
192 //   |       RuntimeId          |   |                       |
193 //   |--------------------------|   |                      OptimizedLeaveFrame
194 //   |       returnAddr         |   |                       |
195 //   |--------------------------|   |                       |
196 //   |       callsiteFp         |   |                       |
197 //   |--------------------------|   |                       |
198 //   |     frameType            |   v                       |
199 //   +--------------------------+ ----                      |
200 //   |  callee save registers   |                           V
201 //   +--------------------------+---------------------------+
202 //   |                   .............                      |
203 //   +--------------------------+---------------------------+
204 //   |                                                      |
205 //   |                 rtfunc's Frame                       |
206 //   |                                                      |
207 //   +------------------------------------------------------+
208 // ```
209 // Iterator:
210 // rtfunc get OptimizedLeaveFrame by calling GetCurrentSPFrame.
211 // get baz's Frame by OptimizedLeaveFrame.prev field.
212 // get bar's Frame by baz's frame fp field
213 // get foo's Frame by bar's Frame prev field
214 
215 #ifndef ECMASCRIPT_FRAMES_H
216 #define ECMASCRIPT_FRAMES_H
217 
218 #include "ecmascript/js_tagged_value.h"
219 #include "ecmascript/trampoline/ecma_asm_defines.h"
220 
221 namespace panda::ecmascript {
222 class JSThread;
223 enum class FrameType: uint64_t {
224     OPTIMIZED_FRAME = 0,
225     OPTIMIZED_ENTRY_FRAME = 1,
226     INTERPRETER_FRAME = 2,
227     OPTIMIZED_LEAVE_FRAME = 3,
228     INTERPRETER_FAST_NEW_FRAME = 4,
229 };
230 
231 class FrameConstants {
232 public:
233 #ifdef PANDA_TARGET_AMD64
234     static constexpr int SP_DWARF_REG_NUM = 7;
235     static constexpr int FP_DWARF_REG_NUM = 6;
236     static constexpr int CALLSITE_SP_TO_FP_DELTA = -2;
237     static constexpr int INTERPER_FRAME_FP_TO_FP_DELTA = -2;
238 #else
239 #ifdef PANDA_TARGET_ARM64
240     static constexpr int SP_DWARF_REG_NUM = 31;  /* x31 */
241     static constexpr int FP_DWARF_REG_NUM = 29;  /* x29 */
242     static constexpr int CALLSITE_SP_TO_FP_DELTA = -2;
243     static constexpr int INTERPER_FRAME_FP_TO_FP_DELTA = -2;
244 #else
245 #ifdef PANDA_TARGET_ARM32
246     static constexpr int SP_DWARF_REG_NUM = 13;
247     static constexpr int FP_DWARF_REG_NUM = 11;
248     static constexpr int CALLSITE_SP_TO_FP_DELTA = 0;
249     static constexpr int INTERPER_FRAME_FP_TO_FP_DELTA = 0;
250 #else
251     static constexpr int SP_DWARF_REG_NUM = 0;
252     static constexpr int FP_DWARF_REG_NUM = 0;
253     static constexpr int CALLSITE_SP_TO_FP_DELTA = 0;
254     static constexpr int INTERPER_FRAME_FP_TO_FP_DELTA = 0;
255 #endif
256 #endif
257 #endif
258     static constexpr int AARCH64_SLOT_SIZE = sizeof(uint64_t);
259     static constexpr int AMD64_SLOT_SIZE = sizeof(uint64_t);
260     static constexpr int ARM32_SLOT_SIZE = sizeof(uint32_t);
261 };
262 
263 class OptimizedFrameBase {
264 public:
265     OptimizedFrameBase() = default;
266     ~OptimizedFrameBase() = default;
267     FrameType type;
268     JSTaggedType *prevFp; // fp register
269 };
270 
271 class OptimizedFrame {
272 public:
273     uintptr_t callsiteSp;
274     OptimizedFrameBase base;
275 public:
276     OptimizedFrame() = default;
277     ~OptimizedFrame() = default;
GetCallsiteSpToFpDelta()278     static constexpr int64_t GetCallsiteSpToFpDelta()
279     {
280         return MEMBER_OFFSET(OptimizedFrame, callsiteSp) - MEMBER_OFFSET(OptimizedFrame, base.prevFp);
281     }
GetFrameFromSp(JSTaggedType * sp)282     static OptimizedFrame* GetFrameFromSp(JSTaggedType *sp)
283     {
284         return reinterpret_cast<OptimizedFrame *>(reinterpret_cast<uintptr_t>(sp)
285             - MEMBER_OFFSET(OptimizedFrame, base.prevFp));
286     }
GetPrevFrameFp()287     inline JSTaggedType* GetPrevFrameFp()
288     {
289         return base.prevFp;
290     }
291 };
292 
293 class OptimizedEntryFrame {
294 public:
295     OptimizedEntryFrame() = default;
296     ~OptimizedEntryFrame() = default;
297     JSTaggedType *preLeaveFrameFp;
298     OptimizedFrameBase base;
299 
GetPrevFrameFp()300     inline JSTaggedType* GetPrevFrameFp()
301     {
302         return preLeaveFrameFp;
303     }
304 
GetInterpreterFrameFpToFpDelta()305     static constexpr int64_t GetInterpreterFrameFpToFpDelta()
306     {
307         return MEMBER_OFFSET(OptimizedEntryFrame, preLeaveFrameFp) -
308             MEMBER_OFFSET(OptimizedEntryFrame, base.prevFp);
309     }
310 
GetFrameFromSp(JSTaggedType * sp)311     static OptimizedEntryFrame* GetFrameFromSp(JSTaggedType *sp)
312     {
313         return reinterpret_cast<OptimizedEntryFrame *>(reinterpret_cast<uintptr_t>(sp) -
314             MEMBER_OFFSET(OptimizedEntryFrame, base.prevFp));
315     }
316 };
317 
318 #define INTERPRETED_FRAME_OFFSET_LIST(V)                                                            \
319     V(SP, PC, sizeof(uint32_t), sizeof(uint64_t))                                                   \
320     V(CONSTPOOL, SP, sizeof(uint32_t), sizeof(uint64_t))                                            \
321     V(FUNCTION, CONSTPOOL, JSTaggedValue::TaggedTypeSize(), JSTaggedValue::TaggedTypeSize())        \
322     V(PROFILETYPEINFO, FUNCTION, JSTaggedValue::TaggedTypeSize(), JSTaggedValue::TaggedTypeSize())  \
323     V(ACC, PROFILETYPEINFO, JSTaggedValue::TaggedTypeSize(), JSTaggedValue::TaggedTypeSize())       \
324     V(ENV, ACC, JSTaggedValue::TaggedTypeSize(), JSTaggedValue::TaggedTypeSize())                   \
325     V(BASE, ENV, JSTaggedValue::TaggedTypeSize(), JSTaggedValue::TaggedTypeSize())                  \
326 
327 static constexpr uint32_t INTERPRETED_FRAME_PC_OFFSET_32 = 0U;
328 static constexpr uint32_t INTERPRETED_FRAME_PC_OFFSET_64 = 0U;
329 #define INTERPRETED_FRAME_OFFSET_MACRO(name, lastName, lastSize32, lastSize64) \
330     static constexpr uint32_t INTERPRETED_FRAME_##name##_OFFSET_32 =           \
331         INTERPRETED_FRAME_##lastName##_OFFSET_32 + (lastSize32);               \
332     static constexpr uint32_t INTERPRETED_FRAME_##name##_OFFSET_64 =           \
333         INTERPRETED_FRAME_##lastName##_OFFSET_64 + (lastSize64);
334 INTERPRETED_FRAME_OFFSET_LIST(INTERPRETED_FRAME_OFFSET_MACRO)
335 #undef INTERPRETED_FRAME_OFFSET_MACRO
336 static constexpr uint32_t SIZEOF_INTERPRETED_FRAME_32 = INTERPRETED_FRAME_ENV_OFFSET_32 +
337     JSTaggedValue::TaggedTypeSize() + sizeof(uint32_t) + sizeof(uint64_t);
338 static constexpr uint32_t SIZEOF_INTERPRETED_FRAME_64 = INTERPRETED_FRAME_ENV_OFFSET_64 +
339     JSTaggedValue::TaggedTypeSize() + sizeof(uint64_t) + sizeof(uint64_t);
340 
341 class InterpretedFrameBase {
342 public:
343     InterpretedFrameBase() = default;
344     ~InterpretedFrameBase() = default;
345     JSTaggedType  *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc
346     FrameType type;
347 };
348 
349 // align with 8
350 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
351 struct InterpretedFrame {
352     const uint8_t *pc;
353     JSTaggedType *sp;
354     // aligned with 8 bits
355     alignas(sizeof(uint64_t)) JSTaggedValue constpool;
356     JSTaggedValue function;
357     JSTaggedValue profileTypeInfo;
358     JSTaggedValue acc;
359     JSTaggedValue env;
360     InterpretedFrameBase base;
GetPrevFrameFpInterpretedFrame361     inline JSTaggedType* GetPrevFrameFp()
362     {
363         return base.prev;
364     }
365 
GetFrameFromSpInterpretedFrame366     static InterpretedFrame* GetFrameFromSp(JSTaggedType *sp)
367     {
368         return reinterpret_cast<InterpretedFrame *>(sp) - 1;
369     }
370 
GetSpOffsetInterpretedFrame371     static constexpr uint32_t GetSpOffset(bool isArch32)
372     {
373         if (isArch32) {
374             return INTERPRETED_FRAME_SP_OFFSET_32;
375         }
376         return INTERPRETED_FRAME_SP_OFFSET_64;
377     }
378 
GetConstpoolOffsetInterpretedFrame379     static constexpr uint32_t GetConstpoolOffset(bool isArch32)
380     {
381         if (isArch32) {
382             return INTERPRETED_FRAME_CONSTPOOL_OFFSET_32;
383         }
384         return INTERPRETED_FRAME_CONSTPOOL_OFFSET_64;
385     }
386 
GetFunctionOffsetInterpretedFrame387     static constexpr uint32_t GetFunctionOffset(bool isArch32)
388     {
389         if (isArch32) {
390             return INTERPRETED_FRAME_FUNCTION_OFFSET_32;
391         }
392         return INTERPRETED_FRAME_FUNCTION_OFFSET_64;
393     }
394 
GetProfileTypeInfoOffsetInterpretedFrame395     static constexpr uint32_t GetProfileTypeInfoOffset(bool isArch32)
396     {
397         if (isArch32) {
398             return INTERPRETED_FRAME_PROFILETYPEINFO_OFFSET_32;
399         }
400         return INTERPRETED_FRAME_PROFILETYPEINFO_OFFSET_64;
401     }
402 
GetAccOffsetInterpretedFrame403     static constexpr uint32_t GetAccOffset(bool isArch32)
404     {
405         if (isArch32) {
406             return INTERPRETED_FRAME_ACC_OFFSET_32;
407         }
408         return INTERPRETED_FRAME_ACC_OFFSET_64;
409     }
410 
GetEnvOffsetInterpretedFrame411     static constexpr uint32_t GetEnvOffset(bool isArch32)
412     {
413         if (isArch32) {
414             return INTERPRETED_FRAME_ENV_OFFSET_32;
415         }
416         return INTERPRETED_FRAME_ENV_OFFSET_64;
417     }
418 
GetBaseOffsetInterpretedFrame419     static constexpr uint32_t GetBaseOffset(bool isArch32)
420     {
421         if (isArch32) {
422             return INTERPRETED_FRAME_BASE_OFFSET_32;
423         }
424         return INTERPRETED_FRAME_BASE_OFFSET_64;
425     }
426 
GetSizeInterpretedFrame427     static constexpr uint32_t GetSize(bool isArch32)
428     {
429         if (isArch32) {
430             return kSizeOn32Platform;
431         }
432         return kSizeOn64Platform;
433     }
434 
435     static constexpr uint32_t kSizeOn64Platform =
436         2 * sizeof(int64_t) + 5 * sizeof(JSTaggedValue) + 2 * sizeof(uint64_t);
437     static constexpr uint32_t kSizeOn32Platform =
438         2 * sizeof(int32_t) + 5 * sizeof(JSTaggedValue) + 2 * sizeof(uint64_t);
439 };
440 static_assert(sizeof(InterpretedFrame) % sizeof(uint64_t) == 0u);
441 
442 struct OptimizedLeaveFrame {
443     FrameType type;
444     uintptr_t callsiteFp; // thread sp set here
445     uintptr_t returnAddr;
446     uint64_t argRuntimeId;
447     uint64_t argPatchId;
448     uint64_t argc;
449     // argv[] is dynamic
GetFrameFromSpOptimizedLeaveFrame450     static OptimizedLeaveFrame* GetFrameFromSp(JSTaggedType *sp)
451     {
452         return reinterpret_cast<OptimizedLeaveFrame *>(reinterpret_cast<uintptr_t>(sp) -
453             MEMBER_OFFSET(OptimizedLeaveFrame, callsiteFp));
454     }
GetCallSiteSpOptimizedLeaveFrame455     uintptr_t GetCallSiteSp()
456     {
457         return ToUintPtr(this) + MEMBER_OFFSET(OptimizedLeaveFrame, argRuntimeId);
458     }
459 };
460 
461 static_assert(static_cast<uint64_t>(FrameType::OPTIMIZED_FRAME) == OPTIMIZE_FRAME_TYPE);
462 static_assert(static_cast<uint64_t>(FrameType::OPTIMIZED_ENTRY_FRAME) == JS_ENTRY_FRAME_TYPE);
463 static_assert(static_cast<uint64_t>(FrameType::OPTIMIZED_LEAVE_FRAME) == LEAVE_FRAME_TYPE);
464 #ifdef PANDA_TARGET_64
465     static_assert(InterpretedFrame::kSizeOn64Platform == sizeof(InterpretedFrame));
466     static_assert(OptimizedFrame::GetCallsiteSpToFpDelta() ==
467         FrameConstants::CALLSITE_SP_TO_FP_DELTA * sizeof(uintptr_t));
468     static_assert(OptimizedEntryFrame::GetInterpreterFrameFpToFpDelta() ==
469         FrameConstants::INTERPER_FRAME_FP_TO_FP_DELTA * sizeof(uintptr_t));
470 #endif
471 #ifdef PANDA_TARGET_32
472     static_assert(InterpretedFrame::kSizeOn32Platform == sizeof(InterpretedFrame));
473 #endif
474 }  // namespace panda::ecmascript
475 #endif // ECMASCRIPT_FRAMES_H
476