1271fad7518aed07d0922c0cd417aee7158936ff
[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 /* define MONO_HANDLE_TRACK_OWNER to store the file and line number of each call to MONO_HANDLE_NEW
54  * in the handle stack.  (This doubles the amount of memory used for handles, so it's only useful for debugging).
55  */
56 /* #define MONO_HANDLE_TRACK_OWNER */
57
58 typedef struct {
59         MonoObject *o;
60 #ifdef MONO_HANDLE_TRACK_OWNER
61         const char *owner;
62 #endif
63 } HandleChunkElem;
64
65 struct _HandleChunk {
66         int size; //number of bytes
67         HandleChunk *prev, *next;
68         HandleChunkElem objects [OBJECTS_PER_HANDLES_CHUNK];
69 };
70
71 typedef struct {
72         HandleChunk *top; //alloc from here
73         HandleChunk *bottom; //scan from here
74 } HandleStack;
75
76 typedef struct {
77         int size;
78         HandleChunk *chunk;
79 } HandleStackMark;
80
81 typedef void *MonoRawHandle;
82
83 typedef void (*GcScanFunc) (gpointer*, gpointer);
84
85
86 #ifndef MONO_HANDLE_TRACK_OWNER
87 MonoRawHandle mono_handle_new (MonoObject *object);
88 #else
89 MonoRawHandle mono_handle_new (MonoObject *object, const char* owner);
90 #endif
91
92 void mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data);
93 gboolean mono_handle_stack_is_empty (HandleStack *stack);
94 HandleStack* mono_handle_stack_alloc (void);
95 void mono_handle_stack_free (HandleStack *handlestack);
96 MonoRawHandle mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value);
97 void mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name);
98
99 static inline void
100 mono_stack_mark_init (MonoThreadInfo *info, HandleStackMark *stackmark)
101 {
102         HandleStack *handles = (HandleStack *)info->handle_stack;
103         stackmark->size = handles->top->size;
104         stackmark->chunk = handles->top;
105 }
106
107 static inline void
108 mono_stack_mark_pop (MonoThreadInfo *info, HandleStackMark *stackmark)
109 {
110         HandleStack *handles = (HandleStack *)info->handle_stack;
111         HandleChunk *old_top = stackmark->chunk;
112         old_top->size = stackmark->size;
113         mono_memory_write_barrier ();
114         handles->top = old_top;
115 }
116
117 /*
118 Icall macros
119 */
120 #define SETUP_ICALL_COMMON      \
121         do { \
122                 MonoError error;        \
123                 MonoThreadInfo *__info = mono_thread_info_current ();   \
124                 error_init (&error);    \
125
126 #define CLEAR_ICALL_COMMON      \
127         mono_error_set_pending_exception (&error);
128
129 #define SETUP_ICALL_FRAME       \
130         HandleStackMark __mark; \
131         mono_stack_mark_init (__info, &__mark);
132
133 #define CLEAR_ICALL_FRAME       \
134         mono_stack_mark_record_size (__info, &__mark, __FUNCTION__);    \
135         mono_stack_mark_pop (__info, &__mark);
136
137 #define CLEAR_ICALL_FRAME_VALUE(RESULT, HANDLE)                         \
138         mono_stack_mark_record_size (__info, &__mark, __FUNCTION__);    \
139         (RESULT) = mono_stack_mark_pop_value (__info, &__mark, (HANDLE));
140
141
142 #define HANDLE_FUNCTION_ENTER() do {                            \
143         MonoThreadInfo *__info = mono_thread_info_current ();   \
144         SETUP_ICALL_FRAME                                       \
145
146 #define HANDLE_FUNCTION_RETURN()                \
147         CLEAR_ICALL_FRAME;                      \
148         } while (0)
149
150 #define HANDLE_FUNCTION_RETURN_VAL(VAL)         \
151         CLEAR_ICALL_FRAME;                      \
152         return (VAL);                           \
153         } while (0)
154
155 #define HANDLE_FUNCTION_RETURN_OBJ(HANDLE)                      \
156         do {                                                    \
157                 void* __result = (MONO_HANDLE_RAW (HANDLE));    \
158                 CLEAR_ICALL_FRAME;                              \
159                 return __result;                                \
160         } while (0); } while (0);
161
162 #define HANDLE_FUNCTION_RETURN_REF(TYPE, HANDLE)                        \
163         do {                                                            \
164                 MonoRawHandle __result;                                 \
165                 CLEAR_ICALL_FRAME_VALUE (__result, ((MonoRawHandle) (HANDLE))); \
166                 return MONO_HANDLE_CAST (TYPE, __result);               \
167         } while (0); } while (0);
168
169 #ifdef MONO_NEEDS_STACK_WATERMARK
170
171 static void
172 mono_thread_info_pop_stack_mark (MonoThreadInfo *info, void *old_mark)
173 {
174         info->stack_mark = old_mark;
175 }
176
177 static void*
178 mono_thread_info_push_stack_mark (MonoThreadInfo *info, void *mark)
179 {
180         void *old = info->stack_mark;
181         info->stack_mark = mark;
182         return old;
183 }
184
185 #define SETUP_STACK_WATERMARK   \
186         int __dummy;    \
187         __builtin_unwind_init ();       \
188         void *__old_stack_mark = mono_thread_info_push_stack_mark (__info, &__dummy);
189
190 #define CLEAR_STACK_WATERMARK   \
191         mono_thread_info_pop_stack_mark (__info, __old_stack_mark);
192
193 #else
194 #define SETUP_STACK_WATERMARK
195 #define CLEAR_STACK_WATERMARK
196 #endif
197
198 #define ICALL_ENTRY()   \
199         SETUP_ICALL_COMMON      \
200         SETUP_ICALL_FRAME       \
201         SETUP_STACK_WATERMARK
202
203 #define ICALL_RETURN()  \
204         do {    \
205                 CLEAR_STACK_WATERMARK   \
206                 CLEAR_ICALL_COMMON      \
207                 CLEAR_ICALL_FRAME       \
208                 return; \
209         } while (0); } while (0)
210
211 #define ICALL_RETURN_VAL(VAL)   \
212         do {    \
213                 CLEAR_STACK_WATERMARK   \
214                 CLEAR_ICALL_COMMON      \
215                 CLEAR_ICALL_FRAME       \
216                 return VAL;     \
217         } while (0); } while (0)
218
219 #define ICALL_RETURN_OBJ(HANDLE)        \
220         do {    \
221                 CLEAR_STACK_WATERMARK   \
222                 CLEAR_ICALL_COMMON      \
223                 void* __ret = MONO_HANDLE_RAW (HANDLE); \
224                 CLEAR_ICALL_FRAME       \
225                 return __ret;   \
226         } while (0); } while (0)
227
228 /*
229 Handle macros/functions
230 */
231
232 #ifdef ENABLE_CHECKED_BUILD
233 void mono_handle_verify (MonoRawHandle handle);
234 #define HANDLE_INVARIANTS(H) mono_handle_verify((void*)(H))
235 #else
236 #define HANDLE_INVARIANTS(H) (0)
237 #endif
238
239 #define TYPED_HANDLE_PAYLOAD_NAME(TYPE) TYPE ## HandlePayload
240 #define TYPED_HANDLE_NAME(TYPE) TYPE ## Handle
241 #define TYPED_OUT_HANDLE_NAME(TYPE) TYPE ## HandleOut
242
243 #ifdef MONO_HANDLE_TRACK_OWNER
244 #define STRINGIFY_(x) #x
245 #define STRINGIFY(x) STRINGIFY_(x)
246 #define HANDLE_OWNER_STRINGIFY(file,lineno) (const char*) (file ":" STRINGIFY(lineno))
247 #endif
248
249
250 /*
251  * TYPED_HANDLE_DECL(SomeType):
252  *   Expands to a decl for handles to SomeType and to an internal payload struct.
253  *
254  * For example, TYPED_HANDLE_DECL(MonoObject) (see below) expands to:
255  *
256  * typedef struct {
257  *   MonoObject *__obj;
258  * } MonoObjectHandlePayload;
259  *
260  * typedef MonoObjectHandlePayload* MonoObjectHandle;
261  * typedef MonoObjectHandlePayload* MonoObjectHandleOut;
262  */
263 #define TYPED_HANDLE_DECL(TYPE)                                         \
264         typedef struct { TYPE *__obj; } TYPED_HANDLE_PAYLOAD_NAME (TYPE) ; \
265         typedef TYPED_HANDLE_PAYLOAD_NAME (TYPE) * TYPED_HANDLE_NAME (TYPE); \
266         typedef TYPED_HANDLE_PAYLOAD_NAME (TYPE) * TYPED_OUT_HANDLE_NAME (TYPE)
267 /* Have to double expand because MONO_STRUCT_OFFSET is doing token pasting on cross-compilers. */
268 #define MONO_HANDLE_PAYLOAD_OFFSET_(PayloadType) MONO_STRUCT_OFFSET(PayloadType, __obj)
269 #define MONO_HANDLE_PAYLOAD_OFFSET(TYPE) MONO_HANDLE_PAYLOAD_OFFSET_(TYPED_HANDLE_PAYLOAD_NAME (TYPE))
270
271 #define MONO_HANDLE_INIT ((void*) mono_null_value_handle)
272 #define NULL_HANDLE mono_null_value_handle
273
274 //XXX add functions to get/set raw, set field, set field to null, set array, set array to null
275 #define MONO_HANDLE_RAW(HANDLE) (HANDLE_INVARIANTS (HANDLE), ((HANDLE)->__obj))
276 #define MONO_HANDLE_DCL(TYPE, NAME) TYPED_HANDLE_NAME(TYPE) NAME = MONO_HANDLE_NEW (TYPE, (NAME ## _raw))
277
278 #ifndef MONO_HANDLE_TRACK_OWNER
279 #define MONO_HANDLE_NEW(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( mono_handle_new ((MonoObject*)(VALUE)) )
280 #else
281 #define MONO_HANDLE_NEW(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( mono_handle_new ((MonoObject*)(VALUE), HANDLE_OWNER_STRINGIFY(__FILE__, __LINE__)))
282 #endif
283
284 #define MONO_HANDLE_CAST(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( VALUE )
285
286 #define MONO_HANDLE_IS_NULL(HANDLE) (MONO_HANDLE_RAW(HANDLE) == NULL)
287
288
289 /*
290 WARNING WARNING WARNING
291
292 The following functions require a particular evaluation ordering to ensure correctness.
293 We must not have exposed handles while any sort of evaluation is happening as that very evaluation might trigger
294 a safepoint and break us.
295
296 This is why we evaluate index and value before any call to MONO_HANDLE_RAW or other functions that deal with naked objects.
297 */
298 #define MONO_HANDLE_SETRAW(HANDLE, FIELD, VALUE) do {   \
299                 MonoObject *__val = (MonoObject*)(VALUE);       \
300                 MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, __val);    \
301         } while (0)
302
303 #define MONO_HANDLE_SET(HANDLE, FIELD, VALUE) do {      \
304                 MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE);  \
305                 MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, MONO_HANDLE_RAW (__val));  \
306         } while (0)
307
308 /* N.B. RESULT is evaluated before HANDLE */
309 #define MONO_HANDLE_GET(RESULT, HANDLE, FIELD) do {                     \
310                 MonoObjectHandle __dest = MONO_HANDLE_CAST(MonoObject, RESULT); \
311                 mono_gc_wbarrier_generic_store (&__dest->__obj,  (MonoObject*)(MONO_HANDLE_RAW(HANDLE)->FIELD)); \
312         } while (0)
313
314 #define MONO_HANDLE_NEW_GET(TYPE,HANDLE,FIELD) (MONO_HANDLE_NEW(TYPE,MONO_HANDLE_RAW(HANDLE)->FIELD))
315
316 #define MONO_HANDLE_GETVAL(HANDLE, FIELD) (MONO_HANDLE_RAW(HANDLE)->FIELD)
317
318 /* VS doesn't support typeof :( :( :( */
319 #define MONO_HANDLE_SETVAL(HANDLE, FIELD, TYPE, VALUE) do {     \
320                 TYPE __val = (VALUE);   \
321                 MONO_HANDLE_RAW (HANDLE)->FIELD = __val;        \
322          } while (0)
323
324 #define MONO_HANDLE_ARRAY_SETREF(HANDLE, IDX, VALUE) do {       \
325                 int __idx = (IDX);      \
326                 MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE);          \
327                 mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, MONO_HANDLE_RAW (__val));      \
328         } while (0)
329
330 #define MONO_HANDLE_ARRAY_SETVAL(HANDLE, TYPE, IDX, VALUE) do {         \
331                 int __idx = (IDX);                                      \
332                 TYPE __val = (VALUE);                   \
333                 mono_array_set (MONO_HANDLE_RAW (HANDLE), TYPE, __idx, __val); \
334         } while (0)
335
336 #define MONO_HANDLE_ARRAY_SETRAW(HANDLE, IDX, VALUE) do {       \
337                 int __idx = (IDX);      \
338                 MonoObject *__val = (MonoObject*)(VALUE);       \
339                 mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, __val); \
340         } while (0)
341
342 /* N.B. DEST is evaluated AFTER all the other arguments */
343 #define MONO_HANDLE_ARRAY_GETVAL(DEST, HANDLE, TYPE, IDX) do {          \
344                 MonoArrayHandle __arr = (HANDLE);                       \
345                 int __idx = (IDX);                                      \
346                 TYPE __result = mono_array_get (MONO_HANDLE_RAW(__arr), TYPE, __idx); \
347                 (DEST) =  __result;                                     \
348         } while (0)
349
350 #define MONO_HANDLE_ARRAY_GETREF(DEST, HANDLE, IDX) do {                \
351                 mono_handle_array_getref (MONO_HANDLE_CAST(MonoObject, (DEST)), (HANDLE), (IDX)); \
352         } while (0)
353
354 #define MONO_HANDLE_ASSIGN(DESTH, SRCH)                         \
355         mono_handle_assign (MONO_HANDLE_CAST (MonoObject, (DESTH)), MONO_HANDLE_CAST(MonoObject, (SRCH)))
356
357 #define MONO_HANDLE_DOMAIN(HANDLE) (mono_object_domain (MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject, HANDLE))))
358
359 /* Baked typed handles we all want */
360 TYPED_HANDLE_DECL (MonoString);
361 TYPED_HANDLE_DECL (MonoArray);
362 TYPED_HANDLE_DECL (MonoObject);
363 TYPED_HANDLE_DECL (MonoException);
364
365 #define NULL_HANDLE_STRING MONO_HANDLE_CAST(MonoString, NULL_HANDLE)
366
367 /*
368 This is the constant for a handle that points nowhere.
369 Init values to it.
370 */
371 extern const MonoObjectHandle mono_null_value_handle;
372
373 static inline void
374 mono_handle_assign (MonoObjectHandleOut dest, MonoObjectHandle src)
375 {
376         mono_gc_wbarrier_generic_store (&dest->__obj, src ? MONO_HANDLE_RAW(src) : NULL);
377 }
378
379 //FIXME this should go somewhere else
380 MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data, MonoError *error);
381 MonoArrayHandle mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error);
382
383 uintptr_t mono_array_handle_length (MonoArrayHandle arr);
384
385 static inline void
386 mono_handle_array_getref (MonoObjectHandleOut dest, MonoArrayHandle array, uintptr_t index)
387 {
388         mono_gc_wbarrier_generic_store (&dest->__obj, mono_array_get (MONO_HANDLE_RAW (array),gpointer, index));
389 }
390
391 #define mono_handle_class(o) mono_object_class (MONO_HANDLE_RAW (o))
392
393 /* Local handles to global GC handles and back */
394
395 uint32_t
396 mono_gchandle_from_handle (MonoObjectHandle handle, mono_bool pinned);
397
398 MonoObjectHandle
399 mono_gchandle_get_target_handle (uint32_t gchandle);
400
401 void
402 mono_array_handle_memcpy_refs (MonoArrayHandle dest, uintptr_t dest_idx, MonoArrayHandle src, uintptr_t src_idx, uintptr_t len);
403
404 /* Pins the MonoArray using a gchandle and returns a pointer to the
405  * element with the given index (where each element is of the given
406  * size.  Call mono_gchandle_free to unpin.
407  */
408 gpointer
409 mono_array_handle_pin_with_size (MonoArrayHandle handle, int size, uintptr_t index, uint32_t *gchandle);
410
411 #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))
412
413 void
414 mono_error_set_exception_handle (MonoError *error, MonoExceptionHandle exc);
415
416 G_END_DECLS
417
418 #endif /* __MONO_HANDLE_H__ */