Apply changes from https://github.com/dotnet/runtime/commit/eb1756e97d23df13bc6fe798e...
[mono-project.git] / mono / metadata / handle.h
blob0be5c18d206f5491906aec9464b6c242452da55b
1 /**
2 * \file
3 * Handle to object in native code
5 * Authors:
6 * - Ludovic Henry <ludovic@xamarin.com>
7 * - Aleksey Klieger <aleksey.klieger@xamarin.com>
8 * - Rodrigo Kumpera <kumpera@xamarin.com>
10 * Copyright 2016 Dot net foundation.
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
14 #ifndef __MONO_HANDLE_H__
15 #define __MONO_HANDLE_H__
17 #include <config.h>
18 #include <glib.h>
20 #include <mono/metadata/handle-decl.h>
21 #include <mono/metadata/object.h>
22 #include <mono/metadata/class.h>
23 #include <mono/utils/mono-error-internals.h>
24 #include <mono/utils/mono-threads.h>
25 #include <mono/utils/checked-build.h>
26 #include <mono/metadata/class-internals.h>
29 Handle stack.
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.
47 #ifdef HOST_WATCHOS
48 #define MONO_NEEDS_STACK_WATERMARK 1
49 #endif
51 typedef struct _HandleChunk HandleChunk;
54 * Define MONO_HANDLE_TRACK_OWNER to store the file and line number of each call to MONO_HANDLE_NEW
55 * in the handle stack. (This doubles the amount of memory used for handles, so it's only useful for debugging).
57 /*#define MONO_HANDLE_TRACK_OWNER*/
60 * Define MONO_HANDLE_TRACK_SP to record the C stack pointer at the time of each HANDLE_FUNCTION_ENTER and
61 * to ensure that when a new handle is allocated the previous newest handle is not lower in the stack.
62 * This is useful to catch missing HANDLE_FUNCTION_ENTER / HANDLE_FUNCTION_RETURN pairs which could cause
63 * handle leaks.
65 /*#define MONO_HANDLE_TRACK_SP*/
67 typedef struct {
68 gpointer o; /* MonoObject ptr */
69 #ifdef MONO_HANDLE_TRACK_OWNER
70 const char *owner;
71 gpointer backtrace_ips[7]; /* result of backtrace () at time of allocation */
72 #endif
73 #ifdef MONO_HANDLE_TRACK_SP
74 gpointer alloc_sp; /* sp from HandleStack:stackmark_sp at time of allocation */
75 #endif
76 } HandleChunkElem;
78 struct _HandleChunk {
79 int size; //number of handles
80 HandleChunk *prev, *next;
81 HandleChunkElem elems [OBJECTS_PER_HANDLES_CHUNK];
84 typedef struct MonoHandleStack {
85 HandleChunk *top; //alloc from here
86 HandleChunk *bottom; //scan from here
87 #ifdef MONO_HANDLE_TRACK_SP
88 gpointer stackmark_sp; // C stack pointer top when from most recent mono_stack_mark_init
89 #endif
90 } HandleStack;
92 // Keep this in sync with RuntimeStructs.cs
93 typedef struct {
94 int size;
95 HandleChunk *chunk;
96 #ifdef MONO_HANDLE_TRACK_SP
97 gpointer prev_sp; // C stack pointer from prior mono_stack_mark_init
98 #endif
99 } HandleStackMark;
101 // There are two types of handles.
102 // Pointers to volatile pointers in managed frames.
103 // These are allocated by icall wrappers in marshal-ilgen.c.
104 // Pointers to non-volatile pointers in TLS.
105 // These are allocated by MONO_HANDLE_NEW.
106 typedef void volatile * MonoRawHandle;
108 typedef void (*GcScanFunc) (gpointer*, gpointer);
111 /* If Centrinel is analyzing Mono, use the SUPPRESS macros to mark the bodies
112 * of the handle macros as allowed to perform operations on raw pointers to
113 * managed objects. Take care to UNSUPPRESS the _arguments_ to the macros - we
114 * want warnings if the argument uses pointers unsafely.
116 #ifdef __CENTRINEL__
117 #define MONO_HANDLE_SUPPRESS_SCOPE(b) __CENTRINEL_SUPPRESS_SCOPE(b)
118 #define MONO_HANDLE_SUPPRESS(expr) __CENTRINEL_SUPPRESS(expr)
119 #define MONO_HANDLE_UNSUPPRESS(expr) __CENTRINEL_UNSUPPRESS(expr)
120 #else
121 #define MONO_HANDLE_SUPPRESS_SCOPE(b) ;
122 #define MONO_HANDLE_SUPPRESS(expr) (expr)
123 #define MONO_HANDLE_UNSUPPRESS(expr) (expr)
124 #endif
126 #ifndef MONO_HANDLE_TRACK_OWNER
127 MonoRawHandle mono_handle_new (MonoObject *object, MonoThreadInfo *info);
128 #else
129 MonoRawHandle mono_handle_new (MonoObject *object, MonoThreadInfo *info, const char* owner);
130 #endif
132 void mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data, gboolean precise, gboolean check);
133 gboolean mono_handle_stack_is_empty (HandleStack *stack);
134 HandleStack* mono_handle_stack_alloc (void);
135 void mono_handle_stack_free (HandleStack *handlestack);
136 MonoRawHandle mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value);
137 MonoThreadInfo* mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name);
138 void mono_handle_stack_free_domain (HandleStack *stack, MonoDomain *domain);
140 #ifdef MONO_HANDLE_TRACK_SP
141 void mono_handle_chunk_leak_check (HandleStack *handles);
142 #endif
144 static inline void
145 mono_stack_mark_init (MonoThreadInfo *info, HandleStackMark *stackmark)
147 #ifdef MONO_HANDLE_TRACK_SP
148 gpointer sptop = &stackmark;
149 #endif
150 HandleStack *handles = info->handle_stack;
151 stackmark->size = handles->top->size;
152 stackmark->chunk = handles->top;
153 #ifdef MONO_HANDLE_TRACK_SP
154 stackmark->prev_sp = handles->stackmark_sp;
155 handles->stackmark_sp = sptop;
156 #endif
159 static inline void
160 mono_stack_mark_pop (MonoThreadInfo *info, HandleStackMark *stackmark)
162 HandleStack *handles = info->handle_stack;
163 HandleChunk *old_top = stackmark->chunk;
164 old_top->size = stackmark->size;
165 mono_memory_write_barrier ();
166 handles->top = old_top;
167 #ifdef MONO_HANDLE_TRACK_SP
168 mono_memory_write_barrier (); /* write to top before prev_sp */
169 handles->stackmark_sp = stackmark->prev_sp;
170 #endif
173 // There are deliberately locals and a constant NULL global with this same name.
174 extern MonoThreadInfo * const mono_thread_info_current_var;
177 Icall macros
179 #define SETUP_ICALL_COMMON \
180 do { \
181 MONO_DISABLE_WARNING(4459) /* declaration of 'identifier' hides global declaration */ \
182 ERROR_DECL (error); \
183 /* There are deliberately locals and a constant NULL global with this same name. */ \
184 MonoThreadInfo *mono_thread_info_current_var = mono_thread_info_current (); \
185 MONO_RESTORE_WARNING \
187 #define CLEAR_ICALL_COMMON \
188 mono_error_set_pending_exception (error);
190 // FIXME There should be fast and slow versions of this, i.e. with and without local variable.
191 #define SETUP_ICALL_FRAME \
192 HandleStackMark __mark; \
193 mono_stack_mark_init (mono_thread_info_current_var ? mono_thread_info_current_var : mono_thread_info_current (), &__mark);
195 #ifdef ENABLE_CHECKED_BUILD
196 /* __FUNCTION__ creates a C string for every icall */
197 // FIXME This should be one function call since it is not fully inlined.
198 #define CLEAR_ICALL_FRAME \
199 mono_stack_mark_pop (mono_stack_mark_record_size (mono_thread_info_current_var, &__mark, __FUNCTION__), &__mark);
200 // FIXME This should be one function call since it is not fully inlined.
201 #define CLEAR_ICALL_FRAME_VALUE(RESULT, HANDLE) \
202 (RESULT) = g_cast (mono_stack_mark_pop_value (mono_stack_mark_record_size (mono_thread_info_current_var, &__mark, __FUNCTION__), &__mark, (HANDLE)));
203 #else
204 #define CLEAR_ICALL_FRAME \
205 mono_stack_mark_pop (mono_thread_info_current_var ? mono_thread_info_current_var : mono_thread_info_current (), &__mark);
206 #define CLEAR_ICALL_FRAME_VALUE(RESULT, HANDLE) \
207 (RESULT) = g_cast (mono_stack_mark_pop_value (mono_thread_info_current_var ? mono_thread_info_current_var : mono_thread_info_current (), &__mark, (HANDLE)));
208 #endif
210 #define HANDLE_FUNCTION_ENTER() do { \
211 MONO_DISABLE_WARNING(4459) /* declaration of 'identifier' hides global declaration */ \
212 /* There are deliberately locals and a constant NULL global with this same name. */ \
213 MonoThreadInfo *mono_thread_info_current_var = mono_thread_info_current (); \
214 MONO_RESTORE_WARNING \
215 SETUP_ICALL_FRAME \
217 #define HANDLE_FUNCTION_RETURN() \
218 CLEAR_ICALL_FRAME; \
219 } while (0)
221 // Do not do this often, but icall state can be manually managed.
223 // SETUP_ICALL_FUNCTION
224 // loop { // Does not have to be a loop.
225 // SETUP_ICALL_FRAME
226 // ..
227 // CLEAR_ICALL_FRAME
228 // }
230 // As with HANDLE_FUNCTION_RETURN, you must not
231 // skip CLEAR_ICALL_FRAME -- no break, continue, return, or goto (goto label at CLEAR_ICALL_FRAME is idiom).
233 #define SETUP_ICALL_FUNCTION \
234 MONO_DISABLE_WARNING(4459) /* declaration of 'identifier' hides global declaration */ \
235 /* There are deliberately locals and a constant NULL global with this same name. */ \
236 MonoThreadInfo *mono_thread_info_current_var = mono_thread_info_current () \
237 MONO_RESTORE_WARNING
239 // A common use of manual icall frame management is for loop.
240 // It can also be used for conditionality, where only some paths
241 // through a function allocate handles and frame teardown does
242 // coincide with function return. For example: emit_invoke_call.
244 #define HANDLE_LOOP_PREPARE SETUP_ICALL_FUNCTION
246 // Return a non-pointer or non-managed pointer, e.g. gboolean.
247 // VAL should be a local variable or at least not use handles in the current frame.
248 // i.e. it is "val", not "expr".
249 #define HANDLE_FUNCTION_RETURN_VAL(VAL) \
250 CLEAR_ICALL_FRAME; \
251 return (VAL); \
252 } while (0)
254 // Return a raw pointer from coop handle.
255 #define HANDLE_FUNCTION_RETURN_OBJ(HANDLE) \
256 do { \
257 void* __result = MONO_HANDLE_RAW (HANDLE); \
258 CLEAR_ICALL_FRAME; \
259 return g_cast (__result); \
260 } while (0); } while (0);
262 // Return a coop handle from coop handle.
263 #define HANDLE_FUNCTION_RETURN_REF(TYPE, HANDLE) \
264 do { \
265 MonoObjectHandle __result; \
266 CLEAR_ICALL_FRAME_VALUE (__result.__raw, (HANDLE).__raw); \
267 return MONO_HANDLE_CAST (TYPE, __result); \
268 } while (0); } while (0);
270 #ifdef MONO_NEEDS_STACK_WATERMARK
272 static void
273 mono_thread_info_pop_stack_mark (MonoThreadInfo *info, void *old_mark)
275 info->stack_mark = old_mark;
278 static void*
279 mono_thread_info_push_stack_mark (MonoThreadInfo *info, void *mark)
281 void *old = info->stack_mark;
282 info->stack_mark = mark;
283 return old;
286 #define SETUP_STACK_WATERMARK \
287 int __dummy; \
288 __builtin_unwind_init (); \
289 void *__old_stack_mark = mono_thread_info_push_stack_mark (mono_thread_info_current_var, &__dummy);
291 #define CLEAR_STACK_WATERMARK \
292 mono_thread_info_pop_stack_mark (mono_thread_info_current_var, __old_stack_mark);
294 #else
295 #define SETUP_STACK_WATERMARK
296 #define CLEAR_STACK_WATERMARK
297 #endif
299 #define ICALL_ENTRY() \
300 SETUP_ICALL_COMMON \
301 SETUP_ICALL_FRAME \
302 SETUP_STACK_WATERMARK
304 #define ICALL_RETURN() \
305 do { \
306 CLEAR_STACK_WATERMARK \
307 CLEAR_ICALL_COMMON \
308 CLEAR_ICALL_FRAME \
309 return; \
310 } while (0); } while (0)
312 #define ICALL_RETURN_VAL(VAL) \
313 do { \
314 CLEAR_STACK_WATERMARK \
315 CLEAR_ICALL_COMMON \
316 CLEAR_ICALL_FRAME \
317 return VAL; \
318 } while (0); } while (0)
320 #define ICALL_RETURN_OBJ(HANDLE) \
321 do { \
322 CLEAR_STACK_WATERMARK \
323 CLEAR_ICALL_COMMON \
324 void* __ret = MONO_HANDLE_RAW (HANDLE); \
325 CLEAR_ICALL_FRAME \
326 return g_cast (__ret); \
327 } while (0); } while (0)
330 Handle macros/functions
332 #ifdef MONO_HANDLE_TRACK_OWNER
333 #define STRINGIFY_(x) #x
334 #define STRINGIFY(x) STRINGIFY_(x)
335 #define HANDLE_OWNER (__FILE__ ":" STRINGIFY (__LINE__))
336 #endif
338 //XXX add functions to get/set raw, set field, set field to null, set array, set array to null
339 #define MONO_HANDLE_DCL(TYPE, NAME) TYPED_HANDLE_NAME(TYPE) NAME = MONO_HANDLE_NEW (TYPE, (NAME ## _raw))
341 // With Visual C++ compiling as C, the type of a ternary expression
342 // yielding two unrelated non-void pointers is the type of the first, plus a warning.
343 // This can be used to simulate gcc typeof extension.
344 // Otherwise we are forced to evaluate twice, or use C++.
345 #ifdef _MSC_VER
346 typedef struct _MonoTypeofCastHelper *MonoTypeofCastHelper; // a pointer type unrelated to anything else
347 #define MONO_TYPEOF_CAST(typeexpr, expr) __pragma(warning(suppress:4133))(0 ? (typeexpr) : (MonoTypeofCastHelper)(expr))
348 #else
349 #define MONO_TYPEOF_CAST(typeexpr, expr) ((__typeof__ (typeexpr))(expr))
350 #endif
353 * Create handle for the object OBJECT.
354 * The handle will keep the object alive and pinned.
356 #ifndef MONO_HANDLE_TRACK_OWNER
358 #define MONO_HANDLE_NEW(type, object) \
359 (MONO_HANDLE_CAST_FOR (type) (mono_handle_new (MONO_HANDLE_TYPECHECK_FOR (type) (object), mono_thread_info_current_var)))
361 #else
363 #define MONO_HANDLE_NEW(type, object) \
364 (MONO_HANDLE_CAST_FOR (type) (mono_handle_new (MONO_HANDLE_TYPECHECK_FOR (type) (object), mono_thread_info_current_var, HANDLE_OWNER)))
366 #endif
368 #define MONO_HANDLE_CAST(type, value) (MONO_HANDLE_CAST_FOR (type) ((value).__raw))
371 * Return the raw object reference stored in the handle.
372 * The objref is valid while the handle is alive and
373 * points to it.
375 #ifdef __cplusplus
376 #define MONO_HANDLE_RAW(handle) ((handle).GetRaw())
377 #else
378 #define MONO_HANDLE_RAW(handle) (MONO_TYPEOF_CAST (*(handle).__raw, mono_handle_raw ((handle).__raw)))
379 #endif
380 #define MONO_HANDLE_IS_NULL(handle) (mono_handle_is_null ((handle).__raw))
382 #define MONO_BOOL(x) (!!MONO_HANDLE_SUPPRESS (x))
383 #define MONO_HANDLE_BOOL(handle) (MONO_BOOL (!MONO_HANDLE_IS_NULL (handle)))
386 WARNING WARNING WARNING
388 The following functions require a particular evaluation ordering to ensure correctness.
389 We must not have exposed handles while any sort of evaluation is happening as that very evaluation might trigger
390 a safepoint and break us.
392 This is why we evaluate index and value before any call to MONO_HANDLE_RAW or other functions that deal with naked objects.
394 #define MONO_HANDLE_SETRAW(HANDLE, FIELD, VALUE) do { \
395 MONO_HANDLE_SUPPRESS_SCOPE(1); \
396 MonoObject *__val = MONO_HANDLE_SUPPRESS ((MonoObject*)(MONO_HANDLE_UNSUPPRESS (VALUE))); \
397 MONO_OBJECT_SETREF_INTERNAL (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE)), FIELD, __val); \
398 } while (0)
400 // handle->field = value for managed pointer
401 #define MONO_HANDLE_SET(HANDLE, FIELD, VALUE) do { \
402 MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE); \
403 do { \
404 MONO_HANDLE_SUPPRESS_SCOPE(1); \
405 MONO_OBJECT_SETREF_INTERNAL (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE)), FIELD, MONO_HANDLE_RAW (__val)); \
406 } while (0); \
407 } while (0)
409 // resultHandle = handle->field
410 /* N.B. RESULT is evaluated before HANDLE */
411 #define MONO_HANDLE_GET(RESULT, HANDLE, FIELD) do { \
412 MonoObjectHandle __dest = MONO_HANDLE_CAST (MonoObject, RESULT); \
413 MONO_HANDLE_SUPPRESS (*(gpointer*)__dest.__raw = (gpointer)MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE))->FIELD); \
414 } while (0)
416 // Get handle->field as a type-handle.
417 #define MONO_HANDLE_NEW_GET(TYPE,HANDLE,FIELD) (MONO_HANDLE_NEW(TYPE,MONO_HANDLE_SUPPRESS (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE))->FIELD)))
419 // Get handle->field, where field is not a pointer (an integer or non-managed pointer).
420 #define MONO_HANDLE_GETVAL(HANDLE, FIELD) MONO_HANDLE_SUPPRESS (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE))->FIELD)
422 // Get handle->field as a boolean, i.e. typically compare managed pointer to NULL,
423 // though any type is ok.
424 #define MONO_HANDLE_GET_BOOL(handle, field) (MONO_BOOL (MONO_HANDLE_GETVAL (handle, field)))
426 // handle->field = (type)value, for non-managed pointers
427 // This would be easier to write with the gcc extension typeof,
428 // but it is not widely enough implemented (i.e. Microsoft C).
429 // The value copy is needed in cases computing value causes a GC
430 #define MONO_HANDLE_SETVAL(HANDLE, FIELD, TYPE, VALUE) do { \
431 TYPE __val = (VALUE); \
432 if (0) { TYPE * typecheck G_GNUC_UNUSED = &MONO_HANDLE_SUPPRESS (MONO_HANDLE_RAW (HANDLE)->FIELD); } \
433 MONO_HANDLE_SUPPRESS (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE))->FIELD = __val); \
434 } while (0)
436 // handle [idx] = value (for managed pointers)
437 #define MONO_HANDLE_ARRAY_SETREF(HANDLE, IDX, VALUE) do { \
438 uintptr_t __idx = (IDX); \
439 MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE); \
440 { /* FIXME scope needed by Centrinel */ \
441 /* FIXME mono_array_setref_fast is not an expression. */ \
442 MONO_HANDLE_SUPPRESS_SCOPE(1); \
443 mono_array_setref_fast (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE)), __idx, MONO_HANDLE_RAW (__val)); \
445 } while (0)
447 // handle [idx] = (type)value (for non-managed types)
448 #define MONO_HANDLE_ARRAY_SETVAL(HANDLE, TYPE, IDX, VALUE) do { \
449 uintptr_t __idx = (IDX); \
450 TYPE __val = (VALUE); \
451 { /* FIXME scope needed by Centrinel */ \
452 /* FIXME mono_array_set is not an expression. */ \
453 MONO_HANDLE_SUPPRESS_SCOPE(1); \
454 mono_array_set_internal (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE)), TYPE, __idx, __val); \
456 } while (0)
458 #if 0 // This is never used.
459 // handle [idx] = value
460 #define MONO_HANDLE_ARRAY_SETRAW(HANDLE, IDX, VALUE) do { \
461 MONO_HANDLE_SUPPRESS_SCOPE(1); \
462 uintptr_t __idx = MONO_HANDLE_UNSUPPRESS(IDX); \
463 MonoObject *__val = (MonoObject*)(VALUE); \
464 mono_array_setref_fast (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE)), __idx, __val); \
465 } while (0)
466 #endif
468 /* N.B. DEST is evaluated AFTER all the other arguments */
469 #define MONO_HANDLE_ARRAY_GETVAL(DEST, HANDLE, TYPE, IDX) do { \
470 MonoArrayHandle __arr = (HANDLE); \
471 uintptr_t __idx = (IDX); \
472 TYPE __result = MONO_HANDLE_SUPPRESS (mono_array_get_internal (MONO_HANDLE_RAW(__arr), TYPE, __idx)); \
473 (DEST) = __result; \
474 } while (0)
476 // dest = handle [idx] (for managed pointers)
477 #define MONO_HANDLE_ARRAY_GETREF(DEST, HANDLE, IDX) do { \
478 mono_handle_array_getref (MONO_HANDLE_CAST(MonoObject, (DEST)), (HANDLE), (IDX)); \
479 } while (0)
481 #define MONO_HANDLE_ASSIGN_RAW(DESTH, SRCP) (mono_handle_assign_raw (MONO_HANDLE_CAST (MonoObject, (DESTH)), (SRCP)))
482 #define MONO_HANDLE_ASSIGN(DESTH, SRCH) (MONO_HANDLE_ASSIGN_RAW ((DESTH), MONO_HANDLE_RAW (SRCH)))
484 #define MONO_HANDLE_DOMAIN(HANDLE) MONO_HANDLE_SUPPRESS (mono_object_domain (MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject, MONO_HANDLE_UNSUPPRESS (HANDLE)))))
486 #define mono_handle_domain(handle) MONO_HANDLE_DOMAIN ((handle))
488 /* Given an object and a MonoClassField, return the value (must be non-object)
489 * of the field. It's the caller's responsibility to check that the object is
490 * of the correct class. */
491 #define MONO_HANDLE_GET_FIELD_VAL(HANDLE,TYPE,FIELD) (*(TYPE *)(mono_handle_unsafe_field_addr (MONO_HANDLE_CAST (MonoObject, (HANDLE)), (FIELD))))
492 #define MONO_HANDLE_GET_FIELD_BOOL(handle, type, field) (MONO_BOOL (MONO_HANDLE_GET_FIELD_VAL ((handle), type, (field))))
494 #define MONO_HANDLE_NEW_GET_FIELD(HANDLE,TYPE,FIELD) MONO_HANDLE_NEW (TYPE, MONO_HANDLE_SUPPRESS (*(TYPE**)(mono_handle_unsafe_field_addr (MONO_HANDLE_CAST (MonoObject, MONO_HANDLE_UNSUPPRESS (HANDLE)), (FIELD)))))
496 #define MONO_HANDLE_SET_FIELD_VAL(HANDLE,TYPE,FIELD,VAL) do { \
497 MonoObjectHandle __obj = (HANDLE); \
498 MonoClassField *__field = (FIELD); \
499 TYPE __value = (VAL); \
500 *(TYPE*)(mono_handle_unsafe_field_addr (__obj, __field)) = __value; \
501 } while (0)
503 #define MONO_HANDLE_SET_FIELD_REF(HANDLE,FIELD,VALH) do { \
504 MonoObjectHandle __obj = MONO_HANDLE_CAST (MonoObject, (HANDLE)); \
505 MonoClassField *__field = (FIELD); \
506 MonoObjectHandle __value = MONO_HANDLE_CAST (MonoObject, (VALH)); \
507 MONO_HANDLE_SUPPRESS (mono_gc_wbarrier_generic_store_internal (mono_handle_unsafe_field_addr (__obj, __field), MONO_HANDLE_RAW (__value))); \
508 } while (0)
510 #define MONO_HANDLE_GET_CLASS(handle) (MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoObject, (handle)), vtable)->klass)
512 /* Baked typed handles we all want */
513 TYPED_HANDLE_DECL (MonoString);
514 TYPED_HANDLE_DECL (MonoArray);
515 TYPED_HANDLE_DECL (MonoObject);
516 TYPED_HANDLE_DECL (MonoException);
517 TYPED_HANDLE_DECL (MonoAppContext);
519 /* Simpler version of MONO_HANDLE_NEW if the handle is not used */
520 #define MONO_HANDLE_PIN(object) do { \
521 if ((object) != NULL) \
522 MONO_HANDLE_NEW (MonoObject, (MonoObject*)(object)); \
523 } while (0)
525 // Structs cannot be cast to structs.
526 // As well, a function is needed because an anonymous struct cannot be initialized in C.
527 static inline MonoObjectHandle
528 mono_handle_cast (gpointer a)
530 return *(MonoObjectHandle*)&a;
533 static inline MONO_ALWAYS_INLINE gboolean
534 mono_handle_is_null (MonoRawHandle raw_handle)
536 MONO_HANDLE_SUPPRESS_SCOPE (1);
537 MonoObjectHandle *handle = (MonoObjectHandle*)&raw_handle;
538 return !handle->__raw || !*handle->__raw;
541 static inline MONO_ALWAYS_INLINE gpointer
542 mono_handle_raw (MonoRawHandle raw_handle)
544 MONO_HANDLE_SUPPRESS_SCOPE (1);
545 MonoObjectHandle *handle = (MonoObjectHandle*)&raw_handle;
546 return handle->__raw ? *handle->__raw : NULL;
549 /* Unfortunately MonoThreadHandle is already a typedef used for something unrelated. So
550 * the coop handle for MonoThread* is MonoThreadObjectHandle.
552 typedef MonoThread MonoThreadObject;
553 TYPED_HANDLE_DECL (MonoThreadObject);
556 This is the constant for a handle that points nowhere.
557 Constant handles may be initialized to it, but non-constant
558 handles must be NEW'ed. Uses of these are suspicious and should
559 be reviewed and probably changed FIXME.
561 #define NULL_HANDLE (mono_null_value_handle ())
562 #define NULL_HANDLE_INIT { 0 }
563 static inline MonoObjectHandle
564 mono_null_value_handle (void)
566 MonoObjectHandle result = NULL_HANDLE_INIT;
567 return result;
569 #define NULL_HANDLE_STRING (MONO_HANDLE_CAST (MonoString, NULL_HANDLE))
570 #define NULL_HANDLE_ARRAY (MONO_HANDLE_CAST (MonoArray, NULL_HANDLE))
571 #define NULL_HANDLE_STRING_BUILDER (MONO_HANDLE_CAST (MonoStringBuilder, NULL_HANDLE))
573 #if __cplusplus
575 // Use this to convert a THandle to a raw T** such as for a ref or out parameter, without
576 // copying back and forth through an intermediate. The handle must already be allocated,
577 // such as icall marshaling does for out and ref parameters.
578 #define MONO_HANDLE_REF(h) (h.Ref ())
580 #else
582 static inline void volatile*
583 mono_handle_ref (void volatile* p)
585 g_assert (p);
586 return p;
589 // Use this to convert a THandle to a raw T** such as for a ref or out parameter, without
590 // copying back and forth through an intermediate. The handle must already be allocated,
591 // such as icall marshaling does for out and ref parameters.
592 #define MONO_HANDLE_REF(handle) (MONO_TYPEOF_CAST ((handle).__raw, mono_handle_ref ((handle).__raw)))
594 #endif
596 static inline MonoObjectHandle
597 mono_handle_assign_raw (MonoObjectHandleOut dest, void *src)
599 g_assert (dest.__raw);
600 MONO_HANDLE_SUPPRESS (*dest.__raw = (MonoObject*)src);
601 return dest;
604 /* It is unsafe to call this function directly - it does not pin the handle! Use MONO_HANDLE_GET_FIELD_VAL(). */
605 static inline gpointer
606 mono_handle_unsafe_field_addr (MonoObjectHandle h, MonoClassField *field)
608 return MONO_HANDLE_SUPPRESS (((gchar *)MONO_HANDLE_RAW (h)) + field->offset);
611 //FIXME this should go somewhere else
612 MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data, MonoError *error);
613 MonoArrayHandle mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error);
614 MonoArrayHandle
615 mono_array_new_full_handle (MonoDomain *domain, MonoClass *array_class, uintptr_t *lengths, intptr_t *lower_bounds, MonoError *error);
617 #define mono_array_handle_setref(array,index,value) MONO_HANDLE_ARRAY_SETREF ((array), (index), (value))
619 void
620 mono_handle_array_getref (MonoObjectHandleOut dest, MonoArrayHandle array, uintptr_t index);
622 #define mono_handle_class(o) MONO_HANDLE_SUPPRESS (mono_object_class (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (o))))
624 #define mono_handle_vtable(o) MONO_HANDLE_GETVAL (o, vtable)
626 /* Local handles to global GC handles and back */
628 MonoGCHandle
629 mono_gchandle_from_handle (MonoObjectHandle handle, mono_bool pinned);
631 MonoObjectHandle
632 mono_gchandle_get_target_handle (MonoGCHandle gchandle);
634 gboolean
635 mono_gchandle_target_equal (MonoGCHandle gchandle, MonoObjectHandle equal);
637 void
638 mono_gchandle_target_is_null_or_equal (MonoGCHandle gchandle, MonoObjectHandle equal, gboolean *is_null,
639 gboolean *is_equal);
641 void
642 mono_gchandle_set_target_handle (MonoGCHandle gchandle, MonoObjectHandle obj);
644 void
645 mono_array_handle_memcpy_refs (MonoArrayHandle dest, uintptr_t dest_idx, MonoArrayHandle src, uintptr_t src_idx, uintptr_t len);
647 /* Pins the MonoArray using a gchandle and returns a pointer to the
648 * element with the given index (where each element is of the given
649 * size. Call mono_gchandle_free to unpin.
651 gpointer
652 mono_array_handle_pin_with_size (MonoArrayHandle handle, int size, uintptr_t index, MonoGCHandle *gchandle);
654 #define MONO_ARRAY_HANDLE_PIN(handle,type,index,gchandle_out) ((type*)mono_array_handle_pin_with_size (MONO_HANDLE_CAST(MonoArray,(handle)), sizeof (type), (index), (gchandle_out)))
656 void
657 mono_value_copy_array_handle (MonoArrayHandle dest, int dest_idx, gconstpointer src, int count);
659 gunichar2 *
660 mono_string_handle_pin_chars (MonoStringHandle s, MonoGCHandle *gchandle_out);
662 gpointer
663 mono_object_handle_pin_unbox (MonoObjectHandle boxed_valuetype_obj, MonoGCHandle *gchandle_out);
665 static inline gpointer
666 mono_handle_unbox_unsafe (MonoObjectHandle handle)
668 g_assert (m_class_is_valuetype (MONO_HANDLE_GETVAL (handle, vtable)->klass));
669 return MONO_HANDLE_SUPPRESS (MONO_HANDLE_RAW (handle) + 1);
672 void
673 mono_error_set_exception_handle (MonoError *error, MonoExceptionHandle exc);
675 MonoAppContextHandle
676 mono_context_get_handle (void);
678 void
679 mono_context_set_handle (MonoAppContextHandle new_context);
681 MonoGCHandle
682 mono_gchandle_new_weakref_from_handle (MonoObjectHandle handle);
685 mono_handle_hash (MonoObjectHandle object);
687 MonoGCHandle
688 mono_gchandle_new_weakref_from_handle_track_resurrection (MonoObjectHandle handle);
690 #endif /* __MONO_HANDLE_H__ */