[interp] Small cleanups (#17229)
[mono-project.git] / mono / mini / interp / interp-internals.h
bloba3f73666d9361a73564e0264f16676163adf6c08
1 #ifndef __MONO_MINI_INTERPRETER_INTERNALS_H__
2 #define __MONO_MINI_INTERPRETER_INTERNALS_H__
4 #include <setjmp.h>
5 #include <glib.h>
6 #include <mono/metadata/loader.h>
7 #include <mono/metadata/object.h>
8 #include <mono/metadata/domain-internals.h>
9 #include <mono/metadata/class-internals.h>
10 #include <mono/metadata/debug-internals.h>
11 #include "interp.h"
13 #define MINT_TYPE_I1 0
14 #define MINT_TYPE_U1 1
15 #define MINT_TYPE_I2 2
16 #define MINT_TYPE_U2 3
17 #define MINT_TYPE_I4 4
18 #define MINT_TYPE_I8 5
19 #define MINT_TYPE_R4 6
20 #define MINT_TYPE_R8 7
21 #define MINT_TYPE_O 8
22 #define MINT_TYPE_P 9
23 #define MINT_TYPE_VT 10
25 #define INLINED_METHOD_FLAG 0xffff
27 #define MINT_VT_ALIGNMENT 8
29 enum {
30 VAL_I32 = 0,
31 VAL_DOUBLE = 1,
32 VAL_I64 = 2,
33 VAL_VALUET = 3,
34 VAL_POINTER = 4,
35 VAL_NATI = 0 + VAL_POINTER,
36 VAL_MP = 1 + VAL_POINTER,
37 VAL_TP = 2 + VAL_POINTER,
38 VAL_OBJ = 3 + VAL_POINTER
41 enum {
42 INTERP_OPT_INLINE = 1,
43 INTERP_OPT_CPROP = 2,
44 INTERP_OPT_DEFAULT = INTERP_OPT_INLINE | INTERP_OPT_CPROP
47 #if SIZEOF_VOID_P == 4
48 typedef guint32 mono_u;
49 typedef gint32 mono_i;
50 #elif SIZEOF_VOID_P == 8
51 typedef guint64 mono_u;
52 typedef gint64 mono_i;
53 #endif
57 * GC SAFETY:
59 * The interpreter executes in gc unsafe (non-preempt) mode. On wasm, the C stack is
60 * scannable but the wasm stack is not, so to make the code GC safe, the following rules
61 * should be followed:
62 * - every objref handled by the code needs to either be stored volatile or stored
63 * into a volatile; volatile stores are stack packable, volatile values are not.
64 * Use either OBJREF or stackval->data.o.
65 * This will ensure the objects are pinned. A volatile local
66 * is on the stack and not in registers. Volatile stores ditto.
67 * - minimize the number of MonoObject* locals/arguments (or make them volatile).
69 * Volatile on a type/local forces all reads and writes to go to memory/stack,
70 * and each such local to have a unique address.
72 * Volatile absence on a type/local allows multiple locals to share storage,
73 * if their lifetimes do not overlap. This is called "stack packing".
75 * Volatile absence on a type/local allows the variable to live in
76 * both stack and register, for fast reads and "write through".
78 #ifdef TARGET_WASM
80 #define WASM_VOLATILE volatile
82 static inline MonoObject * WASM_VOLATILE *
83 mono_interp_objref (MonoObject **o)
85 return o;
88 #define OBJREF(x) (*mono_interp_objref (&x))
90 #else
92 #define WASM_VOLATILE /* nothing */
94 #define OBJREF(x) x
96 #endif
100 * Value types are represented on the eval stack as pointers to the
101 * actual storage. The size field tells how much storage is allocated.
102 * A value type can't be larger than 16 MB.
104 typedef struct {
105 union {
106 gint32 i;
107 gint64 l;
108 struct {
109 gint32 lo;
110 gint32 hi;
111 } pair;
112 float f_r4;
113 double f;
114 MonoObject * WASM_VOLATILE o;
115 /* native size integer and pointer types */
116 gpointer p;
117 mono_u nati;
118 gpointer vt;
119 } data;
120 #if defined(__ppc__) || defined(__powerpc__)
121 int pad;
122 #endif
123 } stackval;
125 typedef struct _InterpFrame InterpFrame;
127 typedef void (*MonoFuncV) (void);
128 typedef void (*MonoPIFunc) (void *callme, void *margs);
131 * Structure representing a method transformed for the interpreter
132 * This is domain specific
134 typedef struct _InterpMethod
136 /* NOTE: These first two elements (method and
137 next_jit_code_hash) must be in the same order and at the
138 same offset as in MonoJitInfo, because of the jit_code_hash
139 internal hash table in MonoDomain. */
140 MonoMethod *method;
141 struct _InterpMethod *next_jit_code_hash;
142 guint32 locals_size;
143 guint32 total_locals_size;
144 guint32 stack_size;
145 guint32 vt_stack_size;
146 guint32 alloca_size;
147 unsigned int init_locals : 1;
148 unsigned int vararg : 1;
149 unsigned int needs_thread_attach : 1;
150 unsigned short *code;
151 MonoPIFunc func;
152 int num_clauses;
153 MonoExceptionClause *clauses;
154 void **data_items;
155 int transformed;
156 guint32 *local_offsets;
157 guint32 *exvar_offsets;
158 unsigned int param_count;
159 unsigned int hasthis;
160 gpointer jit_wrapper;
161 gpointer jit_addr;
162 MonoMethodSignature *jit_sig;
163 gpointer jit_entry;
164 gpointer llvmonly_unbox_entry;
165 MonoType *rtype;
166 MonoType **param_types;
167 MonoJitInfo *jinfo;
168 MonoDomain *domain;
169 MonoProfilerCallInstrumentationFlags prof_flags;
170 } InterpMethod;
172 struct _InterpFrame {
173 InterpFrame *parent; /* parent */
174 InterpMethod *imethod; /* parent */
175 stackval *retval; /* parent */
176 stackval *stack_args; /* parent */
177 stackval *stack;
178 /* exception info */
179 const unsigned short *ip;
182 #define frame_locals(frame) (((guchar*)((frame)->stack)) + (frame)->imethod->stack_size + (frame)->imethod->vt_stack_size)
184 typedef struct {
185 /* Lets interpreter know it has to resume execution after EH */
186 gboolean has_resume_state;
187 /* Frame to resume execution at */
188 InterpFrame *handler_frame;
189 /* IP to resume execution at */
190 const guint16 *handler_ip;
191 /* Clause that we are resuming to */
192 MonoJitExceptionInfo *handler_ei;
193 /* Exception that is being thrown. Set with rest of resume state */
194 guint32 exc_gchandle;
195 } ThreadContext;
197 typedef struct {
198 gint64 transform_time;
199 gint64 cprop_time;
200 gint32 stloc_nps;
201 gint32 movlocs;
202 gint32 copy_propagations;
203 gint32 killed_instructions;
204 gint32 inlined_methods;
205 gint32 inline_failures;
206 } MonoInterpStats;
208 extern MonoInterpStats mono_interp_stats;
210 extern int mono_interp_traceopt;
211 extern int mono_interp_opt;
212 extern GSList *mono_interp_jit_classes;
214 void
215 mono_interp_transform_method (InterpMethod *imethod, ThreadContext *context, MonoError *error);
217 void
218 mono_interp_transform_init (void);
220 InterpMethod *
221 mono_interp_get_imethod (MonoDomain *domain, MonoMethod *method, MonoError *error);
223 void
224 mono_interp_print_code (InterpMethod *imethod);
226 static inline int
227 mint_type(MonoType *type_)
229 MonoType *type = mini_native_type_replace_type (type_);
230 if (type->byref)
231 return MINT_TYPE_P;
232 enum_type:
233 switch (type->type) {
234 case MONO_TYPE_I1:
235 return MINT_TYPE_I1;
236 case MONO_TYPE_U1:
237 case MONO_TYPE_BOOLEAN:
238 return MINT_TYPE_U1;
239 case MONO_TYPE_I2:
240 return MINT_TYPE_I2;
241 case MONO_TYPE_U2:
242 case MONO_TYPE_CHAR:
243 return MINT_TYPE_U2;
244 case MONO_TYPE_I4:
245 case MONO_TYPE_U4:
246 return MINT_TYPE_I4;
247 case MONO_TYPE_I:
248 case MONO_TYPE_U:
249 #if SIZEOF_VOID_P == 4
250 return MINT_TYPE_I4;
251 #else
252 return MINT_TYPE_I8;
253 #endif
254 case MONO_TYPE_PTR:
255 return MINT_TYPE_P;
256 case MONO_TYPE_R4:
257 return MINT_TYPE_R4;
258 case MONO_TYPE_I8:
259 case MONO_TYPE_U8:
260 return MINT_TYPE_I8;
261 case MONO_TYPE_R8:
262 return MINT_TYPE_R8;
263 case MONO_TYPE_STRING:
264 case MONO_TYPE_SZARRAY:
265 case MONO_TYPE_CLASS:
266 case MONO_TYPE_OBJECT:
267 case MONO_TYPE_ARRAY:
268 return MINT_TYPE_O;
269 case MONO_TYPE_VALUETYPE:
270 if (m_class_is_enumtype (type->data.klass)) {
271 type = mono_class_enum_basetype_internal (type->data.klass);
272 goto enum_type;
273 } else
274 return MINT_TYPE_VT;
275 case MONO_TYPE_TYPEDBYREF:
276 return MINT_TYPE_VT;
277 case MONO_TYPE_GENERICINST:
278 type = m_class_get_byval_arg (type->data.generic_class->container_class);
279 goto enum_type;
280 default:
281 g_warning ("got type 0x%02x", type->type);
282 g_assert_not_reached ();
284 return -1;
287 #endif /* __MONO_MINI_INTERPRETER_INTERNALS_H__ */