[coop] Add mono_error_set_exception_handle
[mono.git] / mono / metadata / handle.h
1 /*
2  * handle.h: Handle to object in native code
3  *
4  * Authors:
5  *  - Ludovic Henry <ludovic@xamarin.com>
6  *  - Aleksey Klieger <aleksey.klieger@xamarin.com>
7  *  - Rodrigo Kumpera <kumpera@xamarin.com>
8  *
9  * Copyright 2016 Dot net foundation.
10  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
11  */
12
13 #ifndef __MONO_HANDLE_H__
14 #define __MONO_HANDLE_H__
15
16 #include <config.h>
17 #include <glib.h>
18
19 #include <mono/metadata/object.h>
20 #include <mono/metadata/class.h>
21 #include <mono/utils/mono-error-internals.h>
22 #include <mono/utils/mono-threads.h>
23 #include <mono/utils/checked-build.h>
24
25 G_BEGIN_DECLS
26
27
28 /*
29 Handle stack.
30
31 The handle stack is designed so it's efficient to pop a large amount of entries at once.
32 The stack is made out of a series of fixed size segments.
33
34 To do bulk operations you use a stack mark.
35         
36 */
37
38 /*
39 3 is the number of fields besides the data in the struct;
40 128 words makes each chunk 512 or 1024 bytes each
41 */
42 #define OBJECTS_PER_HANDLES_CHUNK (128 - 3)
43
44 /*
45 Whether this config needs stack watermark recording to know where to start scanning from.
46 */
47 #ifdef HOST_WATCHOS
48 #define MONO_NEEDS_STACK_WATERMARK 1
49 #endif
50
51 typedef struct _HandleChunk HandleChunk;
52
53 struct _HandleChunk {
54         int size; //number of bytes
55         HandleChunk *prev, *next;
56         MonoObject *objects [OBJECTS_PER_HANDLES_CHUNK];
57 };
58
59 typedef struct {
60         HandleChunk *top; //alloc from here
61         HandleChunk *bottom; //scan from here
62 } HandleStack;
63
64 typedef struct {
65         int size;
66         HandleChunk *chunk;
67 } HandleStackMark;
68
69 typedef void *MonoRawHandle;
70
71 typedef void (*GcScanFunc) (gpointer*, gpointer);
72
73
74 MonoRawHandle mono_handle_new (MonoObject *object);
75
76 void mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data);
77 HandleStack* mono_handle_stack_alloc (void);
78 void mono_handle_stack_free (HandleStack *handlestack);
79 MonoRawHandle mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value);
80 void mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name);
81
82 static inline void
83 mono_stack_mark_init (MonoThreadInfo *info, HandleStackMark *stackmark)
84 {
85         HandleStack *handles = (HandleStack *)info->handle_stack;
86         stackmark->size = handles->top->size;
87         stackmark->chunk = handles->top;
88 }
89
90 static inline void
91 mono_stack_mark_pop (MonoThreadInfo *info, HandleStackMark *stackmark)
92 {
93         HandleStack *handles = (HandleStack *)info->handle_stack;
94         HandleChunk *old_top = stackmark->chunk;
95         old_top->size = stackmark->size;
96         mono_memory_write_barrier ();
97         handles->top = old_top;
98 }
99
100 /*
101 Icall macros
102 */
103 #define SETUP_ICALL_COMMON      \
104         do { \
105                 MonoError error;        \
106                 MonoThreadInfo *__info = mono_thread_info_current ();   \
107                 error_init (&error);    \
108
109 #define CLEAR_ICALL_COMMON      \
110         mono_error_set_pending_exception (&error);
111
112 #define SETUP_ICALL_FRAME       \
113         HandleStackMark __mark; \
114         mono_stack_mark_init (__info, &__mark);
115
116 #define CLEAR_ICALL_FRAME       \
117         mono_stack_mark_record_size (__info, &__mark, __FUNCTION__);    \
118         mono_stack_mark_pop (__info, &__mark);
119
120 #define HANDLE_FUNCTION_ENTER() do {                            \
121         MonoThreadInfo *__info = mono_thread_info_current ();   \
122         SETUP_ICALL_FRAME                                       \
123
124 #define HANDLE_FUNCTION_RETURN()                \
125         CLEAR_ICALL_FRAME;                      \
126         } while (0)
127
128 #define HANDLE_FUNCTION_RETURN_VAL(VAL)         \
129         CLEAR_ICALL_FRAME;                      \
130         return (VAL);                           \
131         } while (0)
132
133 #ifdef MONO_NEEDS_STACK_WATERMARK
134
135 static void
136 mono_thread_info_pop_stack_mark (MonoThreadInfo *info, void *old_mark)
137 {
138         info->stack_mark = old_mark;
139 }
140
141 static void*
142 mono_thread_info_push_stack_mark (MonoThreadInfo *info, void *mark)
143 {
144         void *old = info->stack_mark;
145         info->stack_mark = mark;
146         return old;
147 }
148
149 #define SETUP_STACK_WATERMARK   \
150         int __dummy;    \
151         __builtin_unwind_init ();       \
152         void *__old_stack_mark = mono_thread_info_push_stack_mark (__info, &__dummy);
153
154 #define CLEAR_STACK_WATERMARK   \
155         mono_thread_info_pop_stack_mark (__info, __old_stack_mark);
156
157 #else
158 #define SETUP_STACK_WATERMARK
159 #define CLEAR_STACK_WATERMARK
160 #endif
161
162 #define ICALL_ENTRY()   \
163         SETUP_ICALL_COMMON      \
164         SETUP_ICALL_FRAME       \
165         SETUP_STACK_WATERMARK
166
167 #define ICALL_RETURN()  \
168         do {    \
169                 CLEAR_STACK_WATERMARK   \
170                 CLEAR_ICALL_COMMON      \
171                 CLEAR_ICALL_FRAME       \
172                 return; \
173         } while (0); } while (0)
174
175 #define ICALL_RETURN_VAL(VAL)   \
176         do {    \
177                 CLEAR_STACK_WATERMARK   \
178                 CLEAR_ICALL_COMMON      \
179                 CLEAR_ICALL_FRAME       \
180                 return VAL;     \
181         } while (0); } while (0)
182
183 #define ICALL_RETURN_OBJ(HANDLE)        \
184         do {    \
185                 CLEAR_STACK_WATERMARK   \
186                 CLEAR_ICALL_COMMON      \
187                 void* __ret = MONO_HANDLE_RAW (HANDLE); \
188                 CLEAR_ICALL_FRAME       \
189                 return __ret;   \
190         } while (0); } while (0)
191
192 /*
193 Handle macros/functions
194 */
195
196 #ifdef ENABLE_CHECKED_BUILD
197 void mono_handle_verify (MonoRawHandle handle);
198 #define HANDLE_INVARIANTS(H) mono_handle_verify((void*)(H))
199 #else
200 #define HANDLE_INVARIANTS(H) (0)
201 #endif
202
203 #define TYPED_HANDLE_PAYLOAD_NAME(TYPE) TYPE ## HandlePayload
204 #define TYPED_HANDLE_NAME(TYPE) TYPE ## Handle
205 #define TYPED_OUT_HANDLE_NAME(TYPE) TYPE ## HandleOut
206
207
208 /*
209  * TYPED_HANDLE_DECL(SomeType):
210  *   Expands to a decl for handles to SomeType and to an internal payload struct.
211  *
212  * For example, TYPED_HANDLE_DECL(MonoObject) (see below) expands to:
213  *
214  * typedef struct {
215  *   MonoObject *__obj;
216  * } MonoObjectHandlePayload;
217  *
218  * typedef MonoObjectHandlePayload* MonoObjectHandle;
219  * typedef MonoObjectHandlePayload* MonoObjectHandleOut;
220  */
221 #define TYPED_HANDLE_DECL(TYPE)                                         \
222         typedef struct { TYPE *__obj; } TYPED_HANDLE_PAYLOAD_NAME (TYPE) ; \
223         typedef TYPED_HANDLE_PAYLOAD_NAME (TYPE) * TYPED_HANDLE_NAME (TYPE); \
224         typedef TYPED_HANDLE_PAYLOAD_NAME (TYPE) * TYPED_OUT_HANDLE_NAME (TYPE)
225 /* Have to double expand because MONO_STRUCT_OFFSET is doing token pasting on cross-compilers. */
226 #define MONO_HANDLE_PAYLOAD_OFFSET_(PayloadType) MONO_STRUCT_OFFSET(PayloadType, __obj)
227 #define MONO_HANDLE_PAYLOAD_OFFSET(TYPE) MONO_HANDLE_PAYLOAD_OFFSET_(TYPED_HANDLE_PAYLOAD_NAME (TYPE))
228
229 #define MONO_HANDLE_INIT ((void*) mono_null_value_handle)
230 #define NULL_HANDLE mono_null_value_handle
231
232 //XXX add functions to get/set raw, set field, set field to null, set array, set array to null
233 #define MONO_HANDLE_RAW(HANDLE) (HANDLE_INVARIANTS (HANDLE), ((HANDLE)->__obj))
234 #define MONO_HANDLE_DCL(TYPE, NAME) TYPED_HANDLE_NAME(TYPE) NAME = (TYPED_HANDLE_NAME(TYPE))(mono_handle_new ((MonoObject*)(NAME ## _raw)))
235 #define MONO_HANDLE_NEW(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( mono_handle_new ((MonoObject*)(VALUE)) )
236 #define MONO_HANDLE_CAST(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( VALUE )
237
238 #define MONO_HANDLE_IS_NULL(HANDLE) (MONO_HANDLE_RAW(HANDLE) == NULL)
239
240
241 /*
242 WARNING WARNING WARNING
243
244 The following functions require a particular evaluation ordering to ensure correctness.
245 We must not have exposed handles while any sort of evaluation is happening as that very evaluation might trigger
246 a safepoint and break us.
247
248 This is why we evaluate index and value before any call to MONO_HANDLE_RAW or other functions that deal with naked objects.
249 */
250 #define MONO_HANDLE_SETRAW(HANDLE, FIELD, VALUE) do {   \
251                 MonoObject *__val = (MonoObject*)(VALUE);       \
252                 MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, __val);    \
253         } while (0)
254
255 #define MONO_HANDLE_SET(HANDLE, FIELD, VALUE) do {      \
256                 MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE);  \
257                 MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, MONO_HANDLE_RAW (__val));  \
258         } while (0)
259
260 /* N.B. RESULT is evaluated before HANDLE */
261 #define MONO_HANDLE_GET(RESULT, HANDLE, FIELD) do {                     \
262                 MonoObjectHandle __dest = MONO_HANDLE_CAST(MonoObject, RESULT); \
263                 mono_gc_wbarrier_generic_store (&__dest->__obj,  (MonoObject*)(MONO_HANDLE_RAW(HANDLE)->FIELD)); \
264         } while (0)
265
266 #define MONO_HANDLE_GETVAL(HANDLE, FIELD) (MONO_HANDLE_RAW(HANDLE)->FIELD)
267
268 /* VS doesn't support typeof :( :( :( */
269 #define MONO_HANDLE_SETVAL(HANDLE, FIELD, TYPE, VALUE) do {     \
270                 TYPE __val = (VALUE);   \
271                 MONO_HANDLE_RAW (HANDLE)->FIELD = __val;        \
272          } while (0)
273
274 #define MONO_HANDLE_ARRAY_SETREF(HANDLE, IDX, VALUE) do {       \
275                 int __idx = (IDX);      \
276                 MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE);          \
277                 mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, MONO_HANDLE_RAW (__val));      \
278         } while (0)
279
280 #define MONO_HANDLE_ARRAY_SETVAL(HANDLE, TYPE, IDX, VALUE) do {         \
281                 int __idx = (IDX);                                      \
282                 TYPE __val = (VALUE);                   \
283                 mono_array_set (MONO_HANDLE_RAW (HANDLE), TYPE, __idx, __val); \
284         } while (0)
285
286 #define MONO_HANDLE_ARRAY_SETRAW(HANDLE, IDX, VALUE) do {       \
287                 int __idx = (IDX);      \
288                 MonoObject *__val = (MonoObject*)(VALUE);       \
289                 mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, __val); \
290         } while (0)
291
292 /* N.B. DEST is evaluated AFTER all the other arguments */
293 #define MONO_HANDLE_ARRAY_GETVAL(DEST, HANDLE, TYPE, IDX) do {          \
294                 MonoArrayHandle __arr = (HANDLE);                       \
295                 int __idx = (IDX);                                      \
296                 TYPE __result = mono_array_get (MONO_HANDLE_RAW(__arr), TYPE, __idx); \
297                 (DEST) =  __result;                                     \
298         } while (0)
299
300 #define MONO_HANDLE_ASSIGN(DESTH, SRCH)                         \
301         mono_handle_assign (MONO_HANDLE_CAST (MonoObject, (DESTH)), MONO_HANDLE_CAST(MonoObject, (SRCH)))
302
303 #define MONO_HANDLE_DOMAIN(HANDLE) (mono_object_domain (MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject, HANDLE))))
304
305 /* Baked typed handles we all want */
306 TYPED_HANDLE_DECL (MonoString);
307 TYPED_HANDLE_DECL (MonoArray);
308 TYPED_HANDLE_DECL (MonoObject);
309 TYPED_HANDLE_DECL (MonoException);
310
311 #define NULL_HANDLE_STRING MONO_HANDLE_CAST(MonoString, NULL_HANDLE)
312
313 /*
314 This is the constant for a handle that points nowhere.
315 Init values to it.
316 */
317 extern const MonoObjectHandle mono_null_value_handle;
318
319 static inline void
320 mono_handle_assign (MonoObjectHandle dest, MonoObjectHandle src)
321 {
322         mono_gc_wbarrier_generic_store (&dest->__obj, MONO_HANDLE_RAW(src));
323 }
324
325 //FIXME this should go somewhere else
326 MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data, MonoError *error);
327 MonoArrayHandle mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error);
328
329 uintptr_t mono_array_handle_length (MonoArrayHandle arr);
330
331 #define mono_handle_class(o) mono_object_class (MONO_HANDLE_RAW (o))
332
333 /* Local handles to global GC handles and back */
334
335 uint32_t
336 mono_gchandle_from_handle (MonoObjectHandle handle, mono_bool pinned);
337
338 MonoObjectHandle
339 mono_gchandle_get_target_handle (uint32_t gchandle);
340
341
342
343 /* Pins the MonoArray using a gchandle and returns a pointer to the
344  * element with the given index (where each element is of the given
345  * size.  Call mono_gchandle_free to unpin.
346  */
347 gpointer
348 mono_array_handle_pin_with_size (MonoArrayHandle handle, int size, uintptr_t index, uint32_t *gchandle);
349
350 #define MONO_ARRAY_HANDLE_PIN(handle,type,index,gchandle_out) mono_array_handle_pin_with_size (MONO_HANDLE_CAST(MonoArray,(handle)), sizeof (type), (index), (gchandle_out))
351
352 void
353 mono_error_set_exception_handle (MonoError *error, MonoExceptionHandle exc);
354
355 G_END_DECLS
356
357 #endif /* __MONO_HANDLE_H__ */