1b1994897Sopenharmony_ci# Interaction of compiled code and the runtime
2b1994897Sopenharmony_ci
3b1994897Sopenharmony_ci## Introduction
4b1994897Sopenharmony_ci
5b1994897Sopenharmony_ciDuring execution compiled code and Panda runtime should interact with each other. This document describes the following aspects interation:  
6b1994897Sopenharmony_ci* Runtime structures  
7b1994897Sopenharmony_ci* Calling convention  
8b1994897Sopenharmony_ci* The structure of compiled code stack frames and stack traversing  
9b1994897Sopenharmony_ci* Transition from the interpeter to compiled code and vise versa  
10b1994897Sopenharmony_ci* Calling the runtime  
11b1994897Sopenharmony_ci* Deoptimization  
12b1994897Sopenharmony_ci* Stack unwinding during exception handling  
13b1994897Sopenharmony_ci
14b1994897Sopenharmony_ciDocumentation of meta information generated by the compiler is located in compiled_method_info.md document.
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci## Panda runtime (the runtime)
17b1994897Sopenharmony_ciPanda runtime as a set of functions aimed to execute managed code. The runtime consists of several modules.
18b1994897Sopenharmony_ciThe document refers to the interpreter and the compiler modules.
19b1994897Sopenharmony_ci
20b1994897Sopenharmony_ciThe interpreter is a part of the runtime aimed to execute bytecode of managed functions. The interpreter is responsible to manage
21b1994897Sopenharmony_cihotness counter (see [Structure of `panda::Method`](#structure-of-pandamethod)) of managed functions.
22b1994897Sopenharmony_ci
23b1994897Sopenharmony_ciThe compiler is aimed to translate managed function's bytecode to native code. The compiler has an interface function
24b1994897Sopenharmony_ci`panda::CompilerInterface::CompileMethodSync` which starts compilation. When the function gets compiled the compiler
25b1994897Sopenharmony_cichanges its entrypoint to newly generated code. Next time when the function gets called native code will be executed.
26b1994897Sopenharmony_ci
27b1994897Sopenharmony_ci## Calling convention
28b1994897Sopenharmony_ciPanda runtime and managed code must call functions according to the target calling convention.
29b1994897Sopenharmony_ciCompiled code of a managed function must accept one extra argumnent: the pointer to `panda::Method` which describes this function.
30b1994897Sopenharmony_ciThis argument must be the first argument.
31b1994897Sopenharmony_ci
32b1994897Sopenharmony_ciExample:  
33b1994897Sopenharmony_ciConsider a function int max(int a, int b).  
34b1994897Sopenharmony_ciWhen the compiler generates native code for this function for ARM target it must consider that
35b1994897Sopenharmony_cithe function accepts 3 arguments:  
36b1994897Sopenharmony_ci- a pointer to `panda::Method` in the register R0.  
37b1994897Sopenharmony_ci- `a` in the register R1  
38b1994897Sopenharmony_ci- `b` in the register R2  
39b1994897Sopenharmony_ci
40b1994897Sopenharmony_ciThe function must return the result in the register R0.
41b1994897Sopenharmony_ci
42b1994897Sopenharmony_ci## Structure of `panda::ManagedThread`
43b1994897Sopenharmony_ci`panda::ManagedThread` has the following fields that compiled code may use:
44b1994897Sopenharmony_ci
45b1994897Sopenharmony_ci| Field                | Type                  | Description |
46b1994897Sopenharmony_ci| ---                  | ----                  | ----------- |
47b1994897Sopenharmony_ci| sp_flag_             | bool*                 | Safepoint flag. See *Safepoints* in memory_management.md |
48b1994897Sopenharmony_ci| pending_exception_   | panda::ObjectHeader*  | A pointer to a thrown exception or 0 if there is no exception thrown. |
49b1994897Sopenharmony_ci| runtime_entrypoints_ | void*[]               | A table of runtime entrypoints (See [Runtime entrypoints](#runtime_entrypoints)). |
50b1994897Sopenharmony_ci| stack_frame_kind_    | StackFrameKind        | A kind of the current stack frame (compiled code or interpreter stack frame). |
51b1994897Sopenharmony_ci
52b1994897Sopenharmony_ci## Access to `panda::ManagedThread` from compiled code
53b1994897Sopenharmony_ciThere is an allocated register for each target architecture to store a pointer to `panda::ManagedThread`. This register is called `thread register` and 
54b1994897Sopenharmony_cimust contains a valid pointer to `panda::ManagedThread` on entry to each compiled function.
55b1994897Sopenharmony_ci
56b1994897Sopenharmony_ci## Runtime entrypoints
57b1994897Sopenharmony_ciRuntime serves compiled code via runtime entrypoints. A runtime entrypoint is a function which conforms to the target calling convention.  
58b1994897Sopenharmony_ciA table of the entrypoints is located in `panda::ManagedThread::runtime_entrypoints_` which could be accessed via `thread register`.
59b1994897Sopenharmony_ci
60b1994897Sopenharmony_ci## Structure of `panda::Method`
61b1994897Sopenharmony_ci`panda::Method` describes a managed function in the runtime.
62b1994897Sopenharmony_ciThis document refers to the following fields of `panda::Method`:
63b1994897Sopenharmony_ci
64b1994897Sopenharmony_ci| Field | Description |
65b1994897Sopenharmony_ci| ----- | ----------- |
66b1994897Sopenharmony_ci| hotness_counter_ | A hotness counter of the managed function. |
67b1994897Sopenharmony_ci| compiled_entry_point_ | Function entrypoint. |
68b1994897Sopenharmony_ci
69b1994897Sopenharmony_ci### Hotness counter
70b1994897Sopenharmony_ciThe field `hotness_counter_` reflects hotness of a managed function. The interpreter increments it each time the function gets called,
71b1994897Sopenharmony_cibackward branch is taken and call instruction is handled.
72b1994897Sopenharmony_ciWhen the hotness counter gets saturated (reaches the threshold) the interpreter triggers compilation of the function.
73b1994897Sopenharmony_ciPanda runtime provides a command line option to tune the hotness counter threshold: `--compiler-hotness-threshold`.
74b1994897Sopenharmony_ci
75b1994897Sopenharmony_ci### Entrypoint
76b1994897Sopenharmony_ciEntrypoint is a pointer to native code which can execute the function. This code must conform to the target calling convention and must accept
77b1994897Sopenharmony_cione extra argument: a pointer to `panda::Method` ( See [Calling convention](#calling_convention)).  
78b1994897Sopenharmony_ciThe managed function could have compiled code or it could be executed by the interpreter.  
79b1994897Sopenharmony_ciIn the case the function has compiled code the `compiled_entry_point_` must point to compiled code.  
80b1994897Sopenharmony_ciIn the case the function is executed by the interpreter the `compiled_entry_point_` must point to a runtime function `CompiledCodeToInterpreterBridge` which calls the interpreter.
81b1994897Sopenharmony_ci
82b1994897Sopenharmony_ci## Stack frame
83b1994897Sopenharmony_ciA stack frame contains data necessary to execute the function the frame belongs to.  
84b1994897Sopenharmony_ciThe runtime can create several kinds of stack frames. But all the frames of managed code must have the structure described in [Compiled code stack frame](#compiled-code-stack-frame).
85b1994897Sopenharmony_ci
86b1994897Sopenharmony_ci### Interpreter stack frame
87b1994897Sopenharmony_ciInterpreter stack frame is decribed by `panda::Frame` class. The class has fields to store virtual registers and a pointer to the previous stack frame.  
88b1994897Sopenharmony_ciAll the consecutive interpreter stack frames are organized into a linked list. The field `panda::Frame::prev_` contains a pointer to the previous interpreter (or compiled bridge) frame.
89b1994897Sopenharmony_ci
90b1994897Sopenharmony_ci### Compiled code stack frame
91b1994897Sopenharmony_ciEach compiled function is responsible to reserve stack frame for its purpose and then release it when the function doesn't need it. 
92b1994897Sopenharmony_ciGeneraly compiled function builds the stack frame in prolog and releases it in epilog. If a compiled function doesn't require
93b1994897Sopenharmony_cithe stack frame it can omit its creation.  
94b1994897Sopenharmony_ciWhen compiled code is executing the `stack pointer` register must point to a valid stack frame (newly created stack frame of stack frame of caller) and
95b1994897Sopenharmony_ci`frame pointer` register must point to correct place in the frame before the following operations:  
96b1994897Sopenharmony_ci* Managed objects access  
97b1994897Sopenharmony_ci* Safepoint flag access  
98b1994897Sopenharmony_ci* Call of managed functions or runtime entrypoints  
99b1994897Sopenharmony_ci
100b1994897Sopenharmony_ciRelease of the stack frame could be done by restoring values of `stack pointer` and `frame pointer` registers to the value they have at the moment of function entry.
101b1994897Sopenharmony_ci
102b1994897Sopenharmony_ciCompiled code stack frames of caller and callee must be continuous in the stack i.e. the callee's stack frame must immediately follow the caller's stack frame.
103b1994897Sopenharmony_ci
104b1994897Sopenharmony_ciA compiled code stack frame must have the following structure:  
105b1994897Sopenharmony_ci
106b1994897Sopenharmony_ci```
107b1994897Sopenharmony_ci(Stack grows in increasing order: higher slot has lower address)
108b1994897Sopenharmony_ci-----+----------------------+ <- Stack pointer
109b1994897Sopenharmony_ci     | Callee parameters    |
110b1994897Sopenharmony_ci     +----------------------+
111b1994897Sopenharmony_ci     | Spills               |
112b1994897Sopenharmony_ci     +----------------------+
113b1994897Sopenharmony_ci     | Caller saved fp regs |
114b1994897Sopenharmony_ci  D  +----------------------+
115b1994897Sopenharmony_ci  A  | Caller saved regs    |
116b1994897Sopenharmony_ci  T  +----------------------+
117b1994897Sopenharmony_ci  A  | Callee saved fp regs |
118b1994897Sopenharmony_ci     +----------------------+
119b1994897Sopenharmony_ci     | Callee saved regs    |
120b1994897Sopenharmony_ci     +----------------------+
121b1994897Sopenharmony_ci     | Locals               |
122b1994897Sopenharmony_ci-----+----------------------+
123b1994897Sopenharmony_ci  H  | Properties           |
124b1994897Sopenharmony_ci  E  +----------------------+
125b1994897Sopenharmony_ci  A  | panda::Method*       |
126b1994897Sopenharmony_ci  D  +----------------------+ <- Frame pointer
127b1994897Sopenharmony_ci  E  | Frame pointer        |
128b1994897Sopenharmony_ci  R  +----------------------+
129b1994897Sopenharmony_ci     | Return address       |
130b1994897Sopenharmony_ci-----+----------------------+
131b1994897Sopenharmony_ci```
132b1994897Sopenharmony_ciStack frame elements:  
133b1994897Sopenharmony_ci- data - arbitraty data necessary for function execution. May be omited.  
134b1994897Sopenharmony_ci- properties - define properties of the frame, f.e. whether it is OSR frame or not.
135b1994897Sopenharmony_ci- `panda::Method*` - a pointer to `panda::Method` which describes the called function.  
136b1994897Sopenharmony_ci- frame pointer - pointer to the previous frame. The value of `frame pointer` register at the moment of function entry.  
137b1994897Sopenharmony_ci- return address - address to which control will be transfered after the function gets returned.  
138b1994897Sopenharmony_ci
139b1994897Sopenharmony_ciThere are two special registers: `stack pointer` and `frame pointer`.  
140b1994897Sopenharmony_ci`stack pointer` register contains a pointer to the last stack element.
141b1994897Sopenharmony_ci`frame pointer` register contains a pointer to the place in the stack where the return address is stored.
142b1994897Sopenharmony_ci
143b1994897Sopenharmony_ciPanda contains special class for getting cframe layout: `class CFrameLayout`. Everything related to the cframe layout
144b1994897Sopenharmony_cishould be processed via this class,
145b1994897Sopenharmony_ci
146b1994897Sopenharmony_ci## Calling a function from compiled code
147b1994897Sopenharmony_ciTo call a managed function compiled code must resolve it (i.e. retreive a pointer to callee's `panda::Method`),
148b1994897Sopenharmony_ciprepare arguments in the registers and the stack (if necessary) and jump to callee's entrypoint.  
149b1994897Sopenharmony_ciResolving of a function could be done by calling the corresponding runtime entrypoint.
150b1994897Sopenharmony_ci
151b1994897Sopenharmony_ciExample:  
152b1994897Sopenharmony_ciCalling `int max(int a, int b)` function from compiled code on ARM architecture with arguments `2` and `3`
153b1994897Sopenharmony_cicould be described by the following pseudocode:  
154b1994897Sopenharmony_ci```
155b1994897Sopenharmony_ci// tr - thread register
156b1994897Sopenharmony_ci// r0 contains a pointer to the current `panda::Method`
157b1994897Sopenharmony_ci// 1st step: resolve `int max(int, int)`
158b1994897Sopenharmony_cimov r1, MAX_INT_INT_ID // MAX_INT_INT_ID - identifier of int max(int, int) function
159b1994897Sopenharmony_cildr lr, [tr, #RESOLVE_RUNTIME_ENTRYPOINT_OFFSET]
160b1994897Sopenharmony_ciblx lr // call resolve(currentMethod, MAX_INT_INT_ID)
161b1994897Sopenharmony_ci// r0 contains a pointer to `panada::Method` which describes `int max(int, int)` function.
162b1994897Sopenharmony_ci// 2nd step: prepare arguments and entrypoint to call `int max(int, int)`
163b1994897Sopenharmony_cimov r1, #2
164b1994897Sopenharmony_cimov r2, #3
165b1994897Sopenharmony_cilr = ldr [r0, #entrypoint_offset]
166b1994897Sopenharmony_ci// 3rd step: call the function
167b1994897Sopenharmony_ciblx lr // call max('max_method', 2, 3)
168b1994897Sopenharmony_ci// r0 contains the function result
169b1994897Sopenharmony_ci```
170b1994897Sopenharmony_ci
171b1994897Sopenharmony_ci## Calling a function from compiled code: Bridge function
172b1994897Sopenharmony_ciThe Compiler have an entrypoints table. Each entrypoint contains a link to the Bridge Function.
173b1994897Sopenharmony_ciThe Bridge Functions are auto-generated for each runtime function to be called using the macro assembly.
174b1994897Sopenharmony_ciThe Bridge Function sets up the Boundary Frame and performs the call to the actual runtime function.
175b1994897Sopenharmony_ci
176b1994897Sopenharmony_ciTo do a runtime call from compiled code the Compiler generates:
177b1994897Sopenharmony_ci* putting callee saved (if need) and param holding (if any) register values to the stack
178b1994897Sopenharmony_ci* (callee saved regisers goes to Bridge Function stack frame, caller saved registers goes to the current stack frame)
179b1994897Sopenharmony_ci* parameter holding registers values setup
180b1994897Sopenharmony_ci* Bridge Function address load and branch intruction
181b1994897Sopenharmony_ci* register values restore
182b1994897Sopenharmony_ci
183b1994897Sopenharmony_ciThe bridge function does:
184b1994897Sopenharmony_ci* setup the Bridge Function stack frame
185b1994897Sopenharmony_ci* push the caller saved registers (except of registers holding function parameters) to the caller's stack frame
186b1994897Sopenharmony_ci* adjust Stack Pointer, and pass execution to the runtime function
187b1994897Sopenharmony_ci* restore the Stack Pointer and caller saved registers
188b1994897Sopenharmony_ci
189b1994897Sopenharmony_ciBridge Function stack frame:
190b1994897Sopenharmony_ci```
191b1994897Sopenharmony_ci--------+------------------------------------------+
192b1994897Sopenharmony_ci        | Return address                           |
193b1994897Sopenharmony_ci        +------------------------------------------+
194b1994897Sopenharmony_ci HEADER | Frame pointer                            |
195b1994897Sopenharmony_ci        +------------------------------------------+
196b1994897Sopenharmony_ci        | COMPILED_CODE_TO_INTERPRETER_BRIDGE flag |
197b1994897Sopenharmony_ci        +------------------------------------------+
198b1994897Sopenharmony_ci        | - unused -                               |
199b1994897Sopenharmony_ci--------+------------------------------------------+
200b1994897Sopenharmony_ci        |                                          |
201b1994897Sopenharmony_ci        | Callee saved regs                        |
202b1994897Sopenharmony_ci        |                                          |
203b1994897Sopenharmony_ci DATA   +------------------------------------------+
204b1994897Sopenharmony_ci        |                                          |
205b1994897Sopenharmony_ci        | Callee saved fp regs                     |
206b1994897Sopenharmony_ci        |                                          |
207b1994897Sopenharmony_ci--------+------------------------------------------+
208b1994897Sopenharmony_ci        +  16-byte alignment pad to the next frame +
209b1994897Sopenharmony_ci```
210b1994897Sopenharmony_ci
211b1994897Sopenharmony_ci## Transition from the interpreter to compiled code
212b1994897Sopenharmony_ciWhen the interpreter handles a call instruction first it should resolve the callee method.
213b1994897Sopenharmony_ciDepending on the callee's entrypoint there may be different cases.  
214b1994897Sopenharmony_ciIf the entrypoint points to `CompiledCodeToInterpreterBridge` then the callee should be executed by the interpreter. In this case the interpreter calls itself directly.  
215b1994897Sopenharmony_ciIn other cases the interpreter calls the function `InterpreterToCompiledCodeBridge` passing to it the resolved callee function,
216b1994897Sopenharmony_cithe call instruction, the interpreter's frame and the pointer to `panda::ManagedThread`.
217b1994897Sopenharmony_ci
218b1994897Sopenharmony_ci`InterpreterToCompiledCodeBridge` function does the following:  
219b1994897Sopenharmony_ci* Build a boundary stack frame.  
220b1994897Sopenharmony_ci* Set the pointer to `panda::ManagedThread` to the thread register.  
221b1994897Sopenharmony_ci* Change stack frame kind in `panda::ManagedThread::stack_frame_kind_` to compiled code stack frame.  
222b1994897Sopenharmony_ci* Prepare the arguments according to the target calling convention. The function uses the bytecode instruction (which must be a variant of `call` instruction)
223b1994897Sopenharmony_ci    and interpreter's frame to retreive the function's arguments.  
224b1994897Sopenharmony_ci* Jump to the callee's entrypoint.  
225b1994897Sopenharmony_ci* After the return save the result to the interpreter stack frame.  
226b1994897Sopenharmony_ci* Change stack frame kind in `panda::ManagedThread::stack_frame_kind_` back to interpreter stack frame.  
227b1994897Sopenharmony_ci* Drop the boundary stack frame.  
228b1994897Sopenharmony_ci
229b1994897Sopenharmony_ci`InterpreterToCompiledCodeBridge`'s boundary stack frame is necessary to link the interpreter's frame with the compiled code's frame.  
230b1994897Sopenharmony_ciIts structure is depicted below:  
231b1994897Sopenharmony_ci```
232b1994897Sopenharmony_ci---- +----------------+ <- stack pointer
233b1994897Sopenharmony_cib s  | INTERPRETER_   |
234b1994897Sopenharmony_cio t  | TO_COMPILED_   |
235b1994897Sopenharmony_ciu a  | CODE_BRIDGE    |
236b1994897Sopenharmony_cin c  +----------------+ <- frame pointer
237b1994897Sopenharmony_cid k  | pointer to the |
238b1994897Sopenharmony_cia    | interpreter    |
239b1994897Sopenharmony_cir f  | frame          |
240b1994897Sopenharmony_ciy r  |                |
241b1994897Sopenharmony_ci  a  +----------------+
242b1994897Sopenharmony_ci  m  | return address |
243b1994897Sopenharmony_ci  e  |                |
244b1994897Sopenharmony_ci---- +----------------+
245b1994897Sopenharmony_ci```
246b1994897Sopenharmony_ci
247b1994897Sopenharmony_ciThe structure of boundary frame is the same as a stack frame of compiled code.
248b1994897Sopenharmony_ciInstead of pointer to `panda::Method` the frame contains constant `INTERPRETER_TO_COMPILED_CODE_BRIDGE`.
249b1994897Sopenharmony_ciFrame pointer points to the previous interpreter frame.
250b1994897Sopenharmony_ci
251b1994897Sopenharmony_ci## Transition from compiled code to the interpreter
252b1994897Sopenharmony_ciIf a function should be executed by the interpreter it must have `CompiledCodeToInterpreterBridge` as an entrypoint.
253b1994897Sopenharmony_ci`CompiledCodeToInterpreterBridge` does the following:  
254b1994897Sopenharmony_ci* Change stack frame kind in `panda::ManagedThread::stack_frame_kind_` to interpreter stack frame.  
255b1994897Sopenharmony_ci* Creates a boundary stack frame which contains room for interpreter frame.  
256b1994897Sopenharmony_ci* Fill in the interpreter frame by the arguments passed to `CompiledCodeToInterpreterBridge` in the registers or via the stack.  
257b1994897Sopenharmony_ci* Call the interpreter.  
258b1994897Sopenharmony_ci* Store the result in registers or in the stack according to the target calling convention.  
259b1994897Sopenharmony_ci* Drop the boundary stack frame.  
260b1994897Sopenharmony_ci* Change stack frame kind in `panda::ManagedThread::stack_frame_kind_` back to compiled code stack frame.  
261b1994897Sopenharmony_ci
262b1994897Sopenharmony_ci`CompiledCodeToInterpreterBridge`'s boundary stack frame is necessary to link the compiled code's frame with the interpreter's frame.
263b1994897Sopenharmony_ciIts structure is depicted below:  
264b1994897Sopenharmony_ci```
265b1994897Sopenharmony_ci---- +----------------+ <-+ stack pointer
266b1994897Sopenharmony_ci  s  | interpreter's  | -+ `panda::Frame::prev_`
267b1994897Sopenharmony_cib t  | frame          |  |
268b1994897Sopenharmony_cio a  +----------------+ <+ frame pointer
269b1994897Sopenharmony_ciu c  | frame pointer  |
270b1994897Sopenharmony_cin k  +----------------+
271b1994897Sopenharmony_cid    | COMPILED_CODE_ |
272b1994897Sopenharmony_cia f  | TO_            |
273b1994897Sopenharmony_cir r  | INTERPRETER_   |
274b1994897Sopenharmony_ciy a  | BRIDGE         |
275b1994897Sopenharmony_ci  m  +----------------+
276b1994897Sopenharmony_ci  e  | return address |
277b1994897Sopenharmony_ci---- +----------------+
278b1994897Sopenharmony_ci     |     ...        |
279b1994897Sopenharmony_ci```
280b1994897Sopenharmony_ci
281b1994897Sopenharmony_ciThe structure of boundary frame is the same as a stack frame of compiled code.
282b1994897Sopenharmony_ciInstead of a pointer to `panda::Method` the frame contains constant `COMPILED_CODE_TO_INTERPRETER_BRIDGE`.
283b1994897Sopenharmony_ciFrame pointer points to the previous frame in compiled code stack frame.
284b1994897Sopenharmony_ciThe field `panda::Frame::prev_` must point to the boundary frame pointer.
285b1994897Sopenharmony_ci
286b1994897Sopenharmony_ci## Stack traversing
287b1994897Sopenharmony_ciStack traversing is performed by the runtime. When the runtime examinates a managed thread's stack the thread mustn't execute any managed code.
288b1994897Sopenharmony_ciStack unwinding always starts from the top frame. Its kind could be determined from `panda::ManagedThread::stak_frame_kind_` field. A pointer
289b1994897Sopenharmony_cito the top frame could be determined depends on the kind of the top stack frame:  
290b1994897Sopenharmony_ci* The top stack frame is an interpreter stack frame. Address of the interpreter's frame could be retrieved from `panda::ManagedThread::GetCurrentFrame()`.  
291b1994897Sopenharmony_ci* The top stack frame is a compiled code stack frame. `frame pointer` register contains the address of the top stack frame.
292b1994897Sopenharmony_ci
293b1994897Sopenharmony_ciHaving a pointer to the top stack frame, its kind and structure the runtime can move to the next frame.
294b1994897Sopenharmony_ciMoving to the next frame is done according to the table below:
295b1994897Sopenharmony_ci
296b1994897Sopenharmony_ci| Kind of the current stack frame | How to get a pointer to the next stack frame | Kind of the previous stack frame |
297b1994897Sopenharmony_ci| ------------------------------- | -------------------------------------------- | -------------------------------- |
298b1994897Sopenharmony_ci| Interpreter stack frame         | Read `panda::Frame::prev_` field             | Interpreter stack frame or COMPILED_CODE_TO_INTERPRETER boundary frame |
299b1994897Sopenharmony_ci| INTERPRETER_TO_COMPILED_CODE_BRIDGE boundary stack frame | Read `pointer to the interpreter frame` from the stack | Interpreter stack frame |
300b1994897Sopenharmony_ci| COMPILED_CODE_TO_INTERPRETER_BRIDGE boundary stack frame | Read `frame pointer` from the stack | Compiled code stack frame |
301b1994897Sopenharmony_ci| Compiled code stack frame | Read `frame pointer` | Compiled code stack frame or INTERPRETER_TO_COMPILED_CODE_BRIDGE boundary frame|
302b1994897Sopenharmony_ci
303b1994897Sopenharmony_ciThus the runtime can traverse all the managed stack frames moving from one frame to the previous frame and changing frame type
304b1994897Sopenharmony_cicrossing the boundary frames.
305b1994897Sopenharmony_ci
306b1994897Sopenharmony_ciUnwinding of stack frames has specifics.  
307b1994897Sopenharmony_ci* Compiled code could be combined from several managed functions (inlined functions). If the runtime needs to get information about inlined functions
308b1994897Sopenharmony_ciduring handling a compiled code stack frame it uses meta information generated by the compiler (See compiled_method_info.md).  
309b1994897Sopenharmony_ci* Compiled code may save any callee-saved registers on the stack. Before moving to the next stack frame the runtime must restore values of these registers.
310b1994897Sopenharmony_ciTo do that the runtime uses information about callee-saved registers stored on the stack. This information is generated by the compiler (See compiled_method_info.md).
311b1994897Sopenharmony_ci* Values of virtual registers could be changed during stack unwinding. For example, when GC moves an object, it must update all the references to the object.
312b1994897Sopenharmony_ciThe runtime should provide an internal API for changing values of virtual registers.
313b1994897Sopenharmony_ci
314b1994897Sopenharmony_ciExample:
315b1994897Sopenharmony_ciConsider the following call sequence:  
316b1994897Sopenharmony_ci```
317b1994897Sopenharmony_ci         calls        calls
318b1994897Sopenharmony_ci    foo --------> bar ------> baz
319b1994897Sopenharmony_ci(interpreted)  (compiled)  (interpreted)
320b1994897Sopenharmony_ci```
321b1994897Sopenharmony_ciFunctions `foo` and `baz` are executed by the interpreter and the function `bar` has compiled code.
322b1994897Sopenharmony_ciIn this situation the stack might look as follow:  
323b1994897Sopenharmony_ci```
324b1994897Sopenharmony_ci---- +----------------+ <- stack pointer
325b1994897Sopenharmony_ciE    | native frame   |
326b1994897Sopenharmony_cix u  | of             |
327b1994897Sopenharmony_cie t  | interpreter    |
328b1994897Sopenharmony_cic e  |                |
329b1994897Sopenharmony_ci---- +----------------+ <--- `panda::ManagedThread::GetCurrentFrame()`
330b1994897Sopenharmony_cib    | baz's          | -+
331b1994897Sopenharmony_cio s  | interperer     |  |
332b1994897Sopenharmony_ciu t  | stack frame    |  |
333b1994897Sopenharmony_cin a  +----------------+<-+
334b1994897Sopenharmony_cid c  | frame pointer  | -+
335b1994897Sopenharmony_cia k  +----------------+  |
336b1994897Sopenharmony_cir    | COMPILED_CODE_ |  |
337b1994897Sopenharmony_ciy f  | TO_            |  |
338b1994897Sopenharmony_ci  r  | INTERPRETER_   |  |
339b1994897Sopenharmony_ci  a  | BRIDGE         |  |
340b1994897Sopenharmony_ci  m  +----------------+  |
341b1994897Sopenharmony_ci  e  | return address |  |
342b1994897Sopenharmony_ci---- +----------------+  |
343b1994897Sopenharmony_ci     |      data      |  |
344b1994897Sopenharmony_ci     +----------------+  |
345b1994897Sopenharmony_ci b   | panda::Method* |  |
346b1994897Sopenharmony_ci a   +----------------+ <+
347b1994897Sopenharmony_ci r   | frame pointer  | -+
348b1994897Sopenharmony_ci     +----------------+  |
349b1994897Sopenharmony_ci     | return address |  |
350b1994897Sopenharmony_ci---- +----------------+  |
351b1994897Sopenharmony_cib s  | INTERPRETER_   |  |
352b1994897Sopenharmony_cio t  | TO_COMPILED_   |  |
353b1994897Sopenharmony_ciu a  | CODE_BRIDGE    |  |
354b1994897Sopenharmony_cin c  +----------------+ <+
355b1994897Sopenharmony_cid k  | pointer to the | -+
356b1994897Sopenharmony_cia    | interpreter    |  |
357b1994897Sopenharmony_cir f  | frame          |  |
358b1994897Sopenharmony_ciy r  |                |  |
359b1994897Sopenharmony_ci  a  +----------------+  |
360b1994897Sopenharmony_ci  m  | return address |  |
361b1994897Sopenharmony_ci  e  |                |  |
362b1994897Sopenharmony_ci---- +----------------+  |
363b1994897Sopenharmony_ciE    | native frame   |  |
364b1994897Sopenharmony_cix u  | of             |  |
365b1994897Sopenharmony_cie t  | interpreter    |  |
366b1994897Sopenharmony_cic e  |                |  |
367b1994897Sopenharmony_ci---- +----------------+  |
368b1994897Sopenharmony_ci     |      ...       |  |
369b1994897Sopenharmony_ci     +----------------+ <+
370b1994897Sopenharmony_ci     | foo's          | 
371b1994897Sopenharmony_ci     | interpreter    |
372b1994897Sopenharmony_ci     | frame          |
373b1994897Sopenharmony_ci     +----------------+
374b1994897Sopenharmony_ci     |       ...      |
375b1994897Sopenharmony_ci```
376b1994897Sopenharmony_ci
377b1994897Sopenharmony_ciThe runtime determines kind of the top stack frame by reading `panda::ManagedThread::stack_frame_kind_` (the top stack frame kind must be interpreter stack frame). 
378b1994897Sopenharmony_ci`panda::ManagedThread::GetCurrentFrame()` method must return the pointer to `baz`'s interpreter stack frame. 
379b1994897Sopenharmony_ciTo go to the previous frame the runtime reads the field `panda::Frame::prev_` which must point to `COMPILED_CODE_TO_INTERPRETER_BRIDGE` boundary stack frame. 
380b1994897Sopenharmony_ciIt means that to get `bar`'s stack frame the runtime must read `frame pointer` and the kind of the next frame will be compiled code's frame. 
381b1994897Sopenharmony_ciAt this step the runtime has a pointer to `bar`'s compiled code stack frame. To go to the next frame runtime reads `frame pointer` again and gets
382b1994897Sopenharmony_ci`INTERPRETER_TO_COMPILED_CODE_BRIDGE` boundary stack frame. To reach `foo`'s interpreter stack frame the runtime reads `pointer to the interpreter's frame` field.
383b1994897Sopenharmony_ci
384b1994897Sopenharmony_ci## Deoptimization
385b1994897Sopenharmony_ciThere is may be a situation when compiled code cannot continue execution for some reason.
386b1994897Sopenharmony_ciFor such cases compiled code must call `void Deoptimize()` runtime entrypoint to continue execution of the method in the interpreter from the point where compiled code gets stopped.
387b1994897Sopenharmony_ciThe function reconstructs the interpreter stack frame and calls the interpreter.
388b1994897Sopenharmony_ciWhen compiled code is combined from several managed functions (inlined functions) `Deoptimize` reconstructs interpreter stack frame and calls the interpreter for each inlined function too. 
389b1994897Sopenharmony_ci
390b1994897Sopenharmony_ciDetails in [deoptimization documentation](deoptimization.md)
391b1994897Sopenharmony_ci## Throwing an exception
392b1994897Sopenharmony_ciThrowing an exeption from compiled code is performed by calling a runtime entrypoint `void ThrowException(panda::ObjectHeader* exception)`.  
393b1994897Sopenharmony_ciThe function `ThrowException` does the following:  
394b1994897Sopenharmony_ci* Saves all the callee-saved registers to the stack  
395b1994897Sopenharmony_ci* Stores the pointer to the exception object to `panda::ManagedThread::pending_exception_`  
396b1994897Sopenharmony_ci* Unwind compiled code stack frames to find the corresponding exception handler by going from one stack frame to the previous and making checks.  
397b1994897Sopenharmony_ci
398b1994897Sopenharmony_ciIf the corresponding catch handler is found in the current stack frame the runtime jumps to the handler.  
399b1994897Sopenharmony_ci
400b1994897Sopenharmony_ciIf a INTERPRETER_TO_COMPILED_CODE_BRIDGE boundary stack frame is reached the runtime returns to the interpreter letting it to handle the exception.  
401b1994897Sopenharmony_ciReturning to the interpreter is performed as follow:  
402b1994897Sopenharmony_ci1. Determine the return address to the boundary frame. The return address is stored in the following compiled code stack frame.  
403b1994897Sopenharmony_ci2. Set the pointer to the boundary frame into stack pointer, assign the return address determined at the previous step to program counter.
404b1994897Sopenharmony_ci
405b1994897Sopenharmony_ciIf there is no catch handler in the current frame then the runtime restores values of callee-saved registers and moves to the previous stack frame.
406b1994897Sopenharmony_ci
407b1994897Sopenharmony_ciDetails of stack travesing are described in [Stack traversing](#stack_traversing)
408b1994897Sopenharmony_ci
409b1994897Sopenharmony_ciFinding a catch handler in a compiled code stack frame is performed according meta information generated by the compiler (See compiled_method_info.md).
410b1994897Sopenharmony_ci
411b1994897Sopenharmony_ciThe interpreter must ignore the returned value if `panda::ManagedThread::pending_exception_` is not 0.
412b1994897Sopenharmony_ci
413