2 * handle.h: Handle to object in native code
5 * - Ludovic Henry <ludovic@xamarin.com>
6 * - Aleksey Klieger <aleksey.klieger@xamarin.com>
7 * - Rodrigo Kumpera <kumpera@xamarin.com>
9 * Copyright 2016 Dot net foundation.
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
13 #ifndef __MONO_HANDLE_H__
14 #define __MONO_HANDLE_H__
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>
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.
34 To do bulk operations you use a stack mark.
39 3 is the number of fields besides the data in the struct;
40 128 words makes each chunk 512 or 1024 bytes each
42 #define OBJECTS_PER_HANDLES_CHUNK (128 - 3)
45 Whether this config needs stack watermark recording to know where to start scanning from.
48 #define MONO_NEEDS_STACK_WATERMARK 1
51 typedef struct _HandleChunk HandleChunk;
54 int size; //number of bytes
55 HandleChunk *prev, *next;
56 MonoObject *objects [OBJECTS_PER_HANDLES_CHUNK];
60 HandleChunk *top; //alloc from here
61 HandleChunk *bottom; //scan from here
69 typedef void *MonoRawHandle;
71 typedef void (*GcScanFunc) (gpointer*, gpointer);
74 MonoRawHandle mono_handle_new (MonoObject *object);
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);
83 mono_stack_mark_init (MonoThreadInfo *info, HandleStackMark *stackmark)
85 HandleStack *handles = (HandleStack *)info->handle_stack;
86 stackmark->size = handles->top->size;
87 stackmark->chunk = handles->top;
91 mono_stack_mark_pop (MonoThreadInfo *info, HandleStackMark *stackmark)
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;
103 #define SETUP_ICALL_COMMON \
106 MonoThreadInfo *__info = mono_thread_info_current (); \
107 error_init (&error); \
109 #define CLEAR_ICALL_COMMON \
110 mono_error_set_pending_exception (&error);
112 #define SETUP_ICALL_FRAME \
113 HandleStackMark __mark; \
114 mono_stack_mark_init (__info, &__mark);
116 #define CLEAR_ICALL_FRAME \
117 mono_stack_mark_record_size (__info, &__mark, __FUNCTION__); \
118 mono_stack_mark_pop (__info, &__mark);
120 #define HANDLE_FUNCTION_ENTER() do { \
121 MonoThreadInfo *__info = mono_thread_info_current (); \
124 #define HANDLE_FUNCTION_RETURN() \
128 #define HANDLE_FUNCTION_RETURN_VAL(VAL) \
133 #define HANDLE_FUNCTION_RETURN_OBJ(HANDLE) \
135 void* __result = (MONO_HANDLE_RAW (HANDLE)); \
138 } while (0); } while (0);
140 #ifdef MONO_NEEDS_STACK_WATERMARK
143 mono_thread_info_pop_stack_mark (MonoThreadInfo *info, void *old_mark)
145 info->stack_mark = old_mark;
149 mono_thread_info_push_stack_mark (MonoThreadInfo *info, void *mark)
151 void *old = info->stack_mark;
152 info->stack_mark = mark;
156 #define SETUP_STACK_WATERMARK \
158 __builtin_unwind_init (); \
159 void *__old_stack_mark = mono_thread_info_push_stack_mark (__info, &__dummy);
161 #define CLEAR_STACK_WATERMARK \
162 mono_thread_info_pop_stack_mark (__info, __old_stack_mark);
165 #define SETUP_STACK_WATERMARK
166 #define CLEAR_STACK_WATERMARK
169 #define ICALL_ENTRY() \
172 SETUP_STACK_WATERMARK
174 #define ICALL_RETURN() \
176 CLEAR_STACK_WATERMARK \
180 } while (0); } while (0)
182 #define ICALL_RETURN_VAL(VAL) \
184 CLEAR_STACK_WATERMARK \
188 } while (0); } while (0)
190 #define ICALL_RETURN_OBJ(HANDLE) \
192 CLEAR_STACK_WATERMARK \
194 void* __ret = MONO_HANDLE_RAW (HANDLE); \
197 } while (0); } while (0)
200 Handle macros/functions
203 #ifdef ENABLE_CHECKED_BUILD
204 void mono_handle_verify (MonoRawHandle handle);
205 #define HANDLE_INVARIANTS(H) mono_handle_verify((void*)(H))
207 #define HANDLE_INVARIANTS(H) (0)
210 #define TYPED_HANDLE_PAYLOAD_NAME(TYPE) TYPE ## HandlePayload
211 #define TYPED_HANDLE_NAME(TYPE) TYPE ## Handle
212 #define TYPED_OUT_HANDLE_NAME(TYPE) TYPE ## HandleOut
216 * TYPED_HANDLE_DECL(SomeType):
217 * Expands to a decl for handles to SomeType and to an internal payload struct.
219 * For example, TYPED_HANDLE_DECL(MonoObject) (see below) expands to:
223 * } MonoObjectHandlePayload;
225 * typedef MonoObjectHandlePayload* MonoObjectHandle;
226 * typedef MonoObjectHandlePayload* MonoObjectHandleOut;
228 #define TYPED_HANDLE_DECL(TYPE) \
229 typedef struct { TYPE *__obj; } TYPED_HANDLE_PAYLOAD_NAME (TYPE) ; \
230 typedef TYPED_HANDLE_PAYLOAD_NAME (TYPE) * TYPED_HANDLE_NAME (TYPE); \
231 typedef TYPED_HANDLE_PAYLOAD_NAME (TYPE) * TYPED_OUT_HANDLE_NAME (TYPE)
232 /* Have to double expand because MONO_STRUCT_OFFSET is doing token pasting on cross-compilers. */
233 #define MONO_HANDLE_PAYLOAD_OFFSET_(PayloadType) MONO_STRUCT_OFFSET(PayloadType, __obj)
234 #define MONO_HANDLE_PAYLOAD_OFFSET(TYPE) MONO_HANDLE_PAYLOAD_OFFSET_(TYPED_HANDLE_PAYLOAD_NAME (TYPE))
236 #define MONO_HANDLE_INIT ((void*) mono_null_value_handle)
237 #define NULL_HANDLE mono_null_value_handle
239 //XXX add functions to get/set raw, set field, set field to null, set array, set array to null
240 #define MONO_HANDLE_RAW(HANDLE) (HANDLE_INVARIANTS (HANDLE), ((HANDLE)->__obj))
241 #define MONO_HANDLE_DCL(TYPE, NAME) TYPED_HANDLE_NAME(TYPE) NAME = (TYPED_HANDLE_NAME(TYPE))(mono_handle_new ((MonoObject*)(NAME ## _raw)))
242 #define MONO_HANDLE_NEW(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( mono_handle_new ((MonoObject*)(VALUE)) )
243 #define MONO_HANDLE_CAST(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( VALUE )
245 #define MONO_HANDLE_IS_NULL(HANDLE) (MONO_HANDLE_RAW(HANDLE) == NULL)
249 WARNING WARNING WARNING
251 The following functions require a particular evaluation ordering to ensure correctness.
252 We must not have exposed handles while any sort of evaluation is happening as that very evaluation might trigger
253 a safepoint and break us.
255 This is why we evaluate index and value before any call to MONO_HANDLE_RAW or other functions that deal with naked objects.
257 #define MONO_HANDLE_SETRAW(HANDLE, FIELD, VALUE) do { \
258 MonoObject *__val = (MonoObject*)(VALUE); \
259 MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, __val); \
262 #define MONO_HANDLE_SET(HANDLE, FIELD, VALUE) do { \
263 MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE); \
264 MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, MONO_HANDLE_RAW (__val)); \
267 /* N.B. RESULT is evaluated before HANDLE */
268 #define MONO_HANDLE_GET(RESULT, HANDLE, FIELD) do { \
269 MonoObjectHandle __dest = MONO_HANDLE_CAST(MonoObject, RESULT); \
270 mono_gc_wbarrier_generic_store (&__dest->__obj, (MonoObject*)(MONO_HANDLE_RAW(HANDLE)->FIELD)); \
273 #define MONO_HANDLE_GETVAL(HANDLE, FIELD) (MONO_HANDLE_RAW(HANDLE)->FIELD)
275 /* VS doesn't support typeof :( :( :( */
276 #define MONO_HANDLE_SETVAL(HANDLE, FIELD, TYPE, VALUE) do { \
277 TYPE __val = (VALUE); \
278 MONO_HANDLE_RAW (HANDLE)->FIELD = __val; \
281 #define MONO_HANDLE_ARRAY_SETREF(HANDLE, IDX, VALUE) do { \
283 MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE); \
284 mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, MONO_HANDLE_RAW (__val)); \
287 #define MONO_HANDLE_ARRAY_SETVAL(HANDLE, TYPE, IDX, VALUE) do { \
289 TYPE __val = (VALUE); \
290 mono_array_set (MONO_HANDLE_RAW (HANDLE), TYPE, __idx, __val); \
293 #define MONO_HANDLE_ARRAY_SETRAW(HANDLE, IDX, VALUE) do { \
295 MonoObject *__val = (MonoObject*)(VALUE); \
296 mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, __val); \
299 /* N.B. DEST is evaluated AFTER all the other arguments */
300 #define MONO_HANDLE_ARRAY_GETVAL(DEST, HANDLE, TYPE, IDX) do { \
301 MonoArrayHandle __arr = (HANDLE); \
303 TYPE __result = mono_array_get (MONO_HANDLE_RAW(__arr), TYPE, __idx); \
307 #define MONO_HANDLE_ARRAY_GETREF(DEST, HANDLE, IDX) do { \
308 mono_handle_array_getref (MONO_HANDLE_CAST(MonoObject, (DEST)), (HANDLE), (IDX)); \
311 #define MONO_HANDLE_ASSIGN(DESTH, SRCH) \
312 mono_handle_assign (MONO_HANDLE_CAST (MonoObject, (DESTH)), MONO_HANDLE_CAST(MonoObject, (SRCH)))
314 #define MONO_HANDLE_DOMAIN(HANDLE) (mono_object_domain (MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject, HANDLE))))
316 /* Baked typed handles we all want */
317 TYPED_HANDLE_DECL (MonoString);
318 TYPED_HANDLE_DECL (MonoArray);
319 TYPED_HANDLE_DECL (MonoObject);
320 TYPED_HANDLE_DECL (MonoException);
322 #define NULL_HANDLE_STRING MONO_HANDLE_CAST(MonoString, NULL_HANDLE)
325 This is the constant for a handle that points nowhere.
328 extern const MonoObjectHandle mono_null_value_handle;
331 mono_handle_assign (MonoObjectHandleOut dest, MonoObjectHandle src)
333 mono_gc_wbarrier_generic_store (&dest->__obj, MONO_HANDLE_RAW(src));
336 //FIXME this should go somewhere else
337 MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data, MonoError *error);
338 MonoArrayHandle mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error);
340 uintptr_t mono_array_handle_length (MonoArrayHandle arr);
343 mono_handle_array_getref (MonoObjectHandleOut dest, MonoArrayHandle array, uintptr_t index)
345 mono_gc_wbarrier_generic_store (&dest->__obj, mono_array_get (MONO_HANDLE_RAW (array),gpointer, index));
348 #define mono_handle_class(o) mono_object_class (MONO_HANDLE_RAW (o))
350 /* Local handles to global GC handles and back */
353 mono_gchandle_from_handle (MonoObjectHandle handle, mono_bool pinned);
356 mono_gchandle_get_target_handle (uint32_t gchandle);
359 mono_array_handle_memcpy_refs (MonoArrayHandle dest, uintptr_t dest_idx, MonoArrayHandle src, uintptr_t src_idx, uintptr_t len);
361 /* Pins the MonoArray using a gchandle and returns a pointer to the
362 * element with the given index (where each element is of the given
363 * size. Call mono_gchandle_free to unpin.
366 mono_array_handle_pin_with_size (MonoArrayHandle handle, int size, uintptr_t index, uint32_t *gchandle);
368 #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))
371 mono_error_set_exception_handle (MonoError *error, MonoExceptionHandle exc);
375 #endif /* __MONO_HANDLE_H__ */