1 /**
2  * \file
3  * Handle to object in native code
4  *
5  * Authors:
6  *  - Ludovic Henry <ludovic@xamarin.com>
7  *  - Aleksey Klieger <aleksey.klieger@xamarin.com>
8  *  - Rodrigo Kumpera <kumpera@xamarin.com>
9  *
10  * Copyright 2016 Dot net foundation.
11  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13 
14 #ifndef __MONO_HANDLE_H__
15 #define __MONO_HANDLE_H__
16 
17 #include <config.h>
18 #include <glib.h>
19 
20 #include <mono/metadata/object.h>
21 #include <mono/metadata/class.h>
22 #include <mono/utils/mono-error-internals.h>
23 #include <mono/utils/mono-threads.h>
24 #include <mono/utils/checked-build.h>
25 
26 G_BEGIN_DECLS
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 /*
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).
56  */
57 /*#define MONO_HANDLE_TRACK_OWNER*/
58 
59 /*
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.
64  *
65  * If defined, keep HandleStackMark in sync in RuntimeStructs.cs
66  */
67 /*#define MONO_HANDLE_TRACK_SP*/
68 
69 typedef struct {
70 	gpointer o; /* MonoObject ptr or interior ptr */
71 #ifdef MONO_HANDLE_TRACK_OWNER
72 	const char *owner;
73 	gpointer backtrace_ips[7]; /* result of backtrace () at time of allocation */
74 #endif
75 #ifdef MONO_HANDLE_TRACK_SP
76 	gpointer alloc_sp; /* sp from HandleStack:stackmark_sp at time of allocation */
77 #endif
78 } HandleChunkElem;
79 
80 struct _HandleChunk {
81 	int size; //number of handles
82 	HandleChunk *prev, *next;
83 	HandleChunkElem elems [OBJECTS_PER_HANDLES_CHUNK];
84 };
85 
86 typedef struct {
87 	HandleChunk *top; //alloc from here
88 	HandleChunk *bottom; //scan from here
89 #ifdef MONO_HANDLE_TRACK_SP
90 	gpointer stackmark_sp; // C stack pointer top when from most recent mono_stack_mark_init
91 #endif
92 	/* Chunk for storing interior pointers. Not extended right now */
93 	HandleChunk *interior;
94 } HandleStack;
95 
96 // Keep this in sync with RuntimeStructs.cs
97 typedef struct {
98 	int size, interior_size;
99 	HandleChunk *chunk;
100 #ifdef MONO_HANDLE_TRACK_SP
101 	gpointer prev_sp; // C stack pointer from prior mono_stack_mark_init
102 #endif
103 } HandleStackMark;
104 
105 typedef void *MonoRawHandle;
106 
107 typedef void (*GcScanFunc) (gpointer*, gpointer);
108 
109 
110 /* If Centrinel is analyzing Mono, use the SUPPRESS macros to mark the bodies
111  * of the handle macros as allowed to perform operations on raw pointers to
112  * managed objects.  Take care to UNSUPPRESS the _arguments_ to the macros - we
113  * want warnings if the argument uses pointers unsafely.
114  */
115 #ifdef __CENTRINEL__
116 #define MONO_HANDLE_SUPPRESS_SCOPE(b) __CENTRINEL_SUPPRESS_SCOPE(b)
117 #define MONO_HANDLE_SUPPRESS(expr) __CENTRINEL_SUPPRESS(expr)
118 #define MONO_HANDLE_UNSUPPRESS(expr) __CENTRINEL_UNSUPPRESS(expr)
119 #else
120 #define MONO_HANDLE_SUPPRESS_SCOPE(b) ;
121 #define MONO_HANDLE_SUPPRESS(expr) (expr)
122 #define MONO_HANDLE_UNSUPPRESS(expr) (expr)
123 #endif
124 
125 #ifndef MONO_HANDLE_TRACK_OWNER
126 MonoRawHandle mono_handle_new (MonoObject *object);
127 MonoRawHandle mono_handle_new_full (gpointer rawptr, gboolean interior);
128 MonoRawHandle mono_handle_new_interior (gpointer rawptr);
129 #else
130 MonoRawHandle mono_handle_new (MonoObject *object, const char* owner);
131 MonoRawHandle mono_handle_new_full (gpointer rawptr, gboolean interior, const char *owner);
132 MonoRawHandle mono_handle_new_interior (gpointer rawptr, const char *owner);
133 #endif
134 
135 void mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data, gboolean precise);
136 gboolean mono_handle_stack_is_empty (HandleStack *stack);
137 HandleStack* mono_handle_stack_alloc (void);
138 void mono_handle_stack_free (HandleStack *handlestack);
139 MonoRawHandle mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value);
140 void mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name);
141 void mono_handle_stack_free_domain (HandleStack *stack, MonoDomain *domain);
142 
143 #ifdef MONO_HANDLE_TRACK_SP
144 void mono_handle_chunk_leak_check (HandleStack *handles);
145 #endif
146 
147 static inline void
mono_stack_mark_init(MonoThreadInfo * info,HandleStackMark * stackmark)148 mono_stack_mark_init (MonoThreadInfo *info, HandleStackMark *stackmark)
149 {
150 #ifdef MONO_HANDLE_TRACK_SP
151 	gpointer sptop = (gpointer)(intptr_t)&stackmark;
152 #endif
153 	HandleStack *handles = (HandleStack *)info->handle_stack;
154 	stackmark->size = handles->top->size;
155 	stackmark->chunk = handles->top;
156 	stackmark->interior_size = handles->interior->size;
157 #ifdef MONO_HANDLE_TRACK_SP
158 	stackmark->prev_sp = handles->stackmark_sp;
159 	handles->stackmark_sp = sptop;
160 #endif
161 }
162 
163 static inline void
mono_stack_mark_pop(MonoThreadInfo * info,HandleStackMark * stackmark)164 mono_stack_mark_pop (MonoThreadInfo *info, HandleStackMark *stackmark)
165 {
166 	HandleStack *handles = (HandleStack *)info->handle_stack;
167 	HandleChunk *old_top = stackmark->chunk;
168 	old_top->size = stackmark->size;
169 	mono_memory_write_barrier ();
170 	handles->top = old_top;
171 	handles->interior->size = stackmark->interior_size;
172 #ifdef MONO_HANDLE_TRACK_SP
173 	mono_memory_write_barrier (); /* write to top before prev_sp */
174 	handles->stackmark_sp = stackmark->prev_sp;
175 #endif
176 }
177 
178 /*
179 Icall macros
180 */
181 #define SETUP_ICALL_COMMON	\
182 	do { \
183 		MonoError error;	\
184 		MonoThreadInfo *__info = mono_thread_info_current ();	\
185 		error_init (&error);	\
186 
187 #define CLEAR_ICALL_COMMON	\
188 	mono_error_set_pending_exception (&error);
189 
190 #define SETUP_ICALL_FRAME	\
191 	HandleStackMark __mark;	\
192 	mono_stack_mark_init (__info, &__mark);
193 
194 #define CLEAR_ICALL_FRAME	\
195 	mono_stack_mark_record_size (__info, &__mark, __FUNCTION__);	\
196 	mono_stack_mark_pop (__info, &__mark);
197 
198 #define CLEAR_ICALL_FRAME_VALUE(RESULT, HANDLE)				\
199 	mono_stack_mark_record_size (__info, &__mark, __FUNCTION__);	\
200 	(RESULT) = mono_stack_mark_pop_value (__info, &__mark, (HANDLE));
201 
202 
203 #define HANDLE_FUNCTION_ENTER() do {				\
204 	MonoThreadInfo *__info = mono_thread_info_current ();	\
205 	SETUP_ICALL_FRAME					\
206 
207 #define HANDLE_FUNCTION_RETURN()		\
208 	CLEAR_ICALL_FRAME;			\
209 	} while (0)
210 
211 #define HANDLE_FUNCTION_RETURN_VAL(VAL)		\
212 	CLEAR_ICALL_FRAME;			\
213 	return (VAL);				\
214 	} while (0)
215 
216 #define HANDLE_FUNCTION_RETURN_OBJ(HANDLE)			\
217 	do {							\
218 		void* __result = (MONO_HANDLE_RAW (HANDLE));	\
219 		CLEAR_ICALL_FRAME;				\
220 		return __result;				\
221 	} while (0); } while (0);
222 
223 #define HANDLE_FUNCTION_RETURN_REF(TYPE, HANDLE)			\
224 	do {								\
225 		MonoRawHandle __result;					\
226 		CLEAR_ICALL_FRAME_VALUE (__result, ((MonoRawHandle) (HANDLE))); \
227 		return MONO_HANDLE_CAST (TYPE, __result);		\
228 	} while (0); } while (0);
229 
230 #ifdef MONO_NEEDS_STACK_WATERMARK
231 
232 static void
mono_thread_info_pop_stack_mark(MonoThreadInfo * info,void * old_mark)233 mono_thread_info_pop_stack_mark (MonoThreadInfo *info, void *old_mark)
234 {
235 	info->stack_mark = old_mark;
236 }
237 
238 static void*
mono_thread_info_push_stack_mark(MonoThreadInfo * info,void * mark)239 mono_thread_info_push_stack_mark (MonoThreadInfo *info, void *mark)
240 {
241 	void *old = info->stack_mark;
242 	info->stack_mark = mark;
243 	return old;
244 }
245 
246 #define SETUP_STACK_WATERMARK	\
247 	int __dummy;	\
248 	__builtin_unwind_init ();	\
249 	void *__old_stack_mark = mono_thread_info_push_stack_mark (__info, &__dummy);
250 
251 #define CLEAR_STACK_WATERMARK	\
252 	mono_thread_info_pop_stack_mark (__info, __old_stack_mark);
253 
254 #else
255 #define SETUP_STACK_WATERMARK
256 #define CLEAR_STACK_WATERMARK
257 #endif
258 
259 #define ICALL_ENTRY()	\
260 	SETUP_ICALL_COMMON	\
261 	SETUP_ICALL_FRAME	\
262 	SETUP_STACK_WATERMARK
263 
264 #define ICALL_RETURN()	\
265 	do {	\
266 		CLEAR_STACK_WATERMARK	\
267 		CLEAR_ICALL_COMMON	\
268 		CLEAR_ICALL_FRAME	\
269 		return;	\
270 	} while (0); } while (0)
271 
272 #define ICALL_RETURN_VAL(VAL)	\
273 	do {	\
274 		CLEAR_STACK_WATERMARK	\
275 		CLEAR_ICALL_COMMON	\
276 		CLEAR_ICALL_FRAME	\
277 		return VAL;	\
278 	} while (0); } while (0)
279 
280 #define ICALL_RETURN_OBJ(HANDLE)	\
281 	do {	\
282 		CLEAR_STACK_WATERMARK	\
283 		CLEAR_ICALL_COMMON	\
284 		void* __ret = MONO_HANDLE_RAW (HANDLE);	\
285 		CLEAR_ICALL_FRAME	\
286 		return __ret;	\
287 	} while (0); } while (0)
288 
289 /*
290 Handle macros/functions
291 */
292 
293 #ifdef ENABLE_CHECKED_BUILD
294 void mono_handle_verify (MonoRawHandle handle);
295 #define HANDLE_INVARIANTS(H) mono_handle_verify((void*)(H))
296 #else
297 #define HANDLE_INVARIANTS(H) (0)
298 #endif
299 
300 #define TYPED_HANDLE_PAYLOAD_NAME(TYPE) TYPE ## HandlePayload
301 #define TYPED_HANDLE_NAME(TYPE) TYPE ## Handle
302 #define TYPED_OUT_HANDLE_NAME(TYPE) TYPE ## HandleOut
303 
304 #ifdef MONO_HANDLE_TRACK_OWNER
305 #define STRINGIFY_(x) #x
306 #define STRINGIFY(x) STRINGIFY_(x)
307 #define HANDLE_OWNER_STRINGIFY(file,lineno) (const char*) (file ":" STRINGIFY(lineno))
308 #endif
309 
310 
311 /*
312  * TYPED_HANDLE_DECL(SomeType):
313  *   Expands to a decl for handles to SomeType and to an internal payload struct.
314  *
315  * For example, TYPED_HANDLE_DECL(MonoObject) (see below) expands to:
316  *
317  * typedef struct {
318  *   MonoObject *__raw;
319  * } MonoObjectHandlePayload;
320  *
321  * typedef MonoObjectHandlePayload* MonoObjectHandle;
322  * typedef MonoObjectHandlePayload* MonoObjectHandleOut;
323  */
324 #define TYPED_HANDLE_DECL(TYPE)						\
325 	typedef struct { TYPE *__raw; } TYPED_HANDLE_PAYLOAD_NAME (TYPE) ; \
326 	typedef TYPED_HANDLE_PAYLOAD_NAME (TYPE) * TYPED_HANDLE_NAME (TYPE); \
327 	typedef TYPED_HANDLE_PAYLOAD_NAME (TYPE) * TYPED_OUT_HANDLE_NAME (TYPE)
328 /*
329  * TYPED_VALUE_HANDLE_DECL(SomeType):
330  *   Expands to a decl for handles to SomeType (which is a managed valuetype (likely a struct) of some sort) and to an internal payload struct.
331  * For example TYPED_HANDLE_DECL(MonoMethodInfo) expands to:
332  *
333  * typedef struct {
334  *   MonoMethodInfo *__raw;
335  * } MonoMethodInfoHandlePayload;
336  * typedef MonoMethodInfoHandlePayload* MonoMethodInfoHandle;
337  */
338 #define TYPED_VALUE_HANDLE_DECL(TYPE) TYPED_HANDLE_DECL(TYPE)
339 
340 /* Have to double expand because MONO_STRUCT_OFFSET is doing token pasting on cross-compilers. */
341 #define MONO_HANDLE_PAYLOAD_OFFSET_(PayloadType) MONO_STRUCT_OFFSET(PayloadType, __raw)
342 #define MONO_HANDLE_PAYLOAD_OFFSET(TYPE) MONO_HANDLE_PAYLOAD_OFFSET_(TYPED_HANDLE_PAYLOAD_NAME (TYPE))
343 
344 #define MONO_HANDLE_INIT ((void*) mono_null_value_handle)
345 #define NULL_HANDLE mono_null_value_handle
346 
347 //XXX add functions to get/set raw, set field, set field to null, set array, set array to null
348 #define MONO_HANDLE_RAW(HANDLE) (HANDLE_INVARIANTS (HANDLE), ((HANDLE)->__raw))
349 #define MONO_HANDLE_DCL(TYPE, NAME) TYPED_HANDLE_NAME(TYPE) NAME = MONO_HANDLE_NEW (TYPE, (NAME ## _raw))
350 
351 #ifndef MONO_HANDLE_TRACK_OWNER
352 #define MONO_HANDLE_NEW(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( mono_handle_new ((MonoObject*)(VALUE)) )
353 #else
354 #define MONO_HANDLE_NEW(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( mono_handle_new ((MonoObject*)(VALUE), HANDLE_OWNER_STRINGIFY(__FILE__, __LINE__)))
355 #endif
356 
357 #define MONO_HANDLE_CAST(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( VALUE )
358 
359 #define MONO_HANDLE_IS_NULL(HANDLE) (MONO_HANDLE_SUPPRESS (MONO_HANDLE_RAW(HANDLE) == NULL))
360 
361 
362 /*
363 WARNING WARNING WARNING
364 
365 The following functions require a particular evaluation ordering to ensure correctness.
366 We must not have exposed handles while any sort of evaluation is happening as that very evaluation might trigger
367 a safepoint and break us.
368 
369 This is why we evaluate index and value before any call to MONO_HANDLE_RAW or other functions that deal with naked objects.
370 */
371 #define MONO_HANDLE_SETRAW(HANDLE, FIELD, VALUE) do {			\
372 		MONO_HANDLE_SUPPRESS_SCOPE(1);				\
373 		MonoObject *__val = MONO_HANDLE_SUPPRESS ((MonoObject*)(MONO_HANDLE_UNSUPPRESS (VALUE))); \
374 		MONO_OBJECT_SETREF (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE)), FIELD, __val); \
375 	} while (0)
376 
377 #define MONO_HANDLE_SET(HANDLE, FIELD, VALUE) do {			\
378 		MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE);	\
379 		do {							\
380 			MONO_HANDLE_SUPPRESS_SCOPE(1);			\
381 			MONO_OBJECT_SETREF (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE)), FIELD, MONO_HANDLE_RAW (__val)); \
382 		} while (0);						\
383 	} while (0)
384 
385 /* N.B. RESULT is evaluated before HANDLE */
386 #define MONO_HANDLE_GET(RESULT, HANDLE, FIELD) do {			\
387 		MonoObjectHandle __dest = MONO_HANDLE_CAST(MonoObject, RESULT);	\
388 		MONO_HANDLE_SUPPRESS (mono_gc_wbarrier_generic_store (&__dest->__raw,  (MonoObject*)(MONO_HANDLE_RAW(MONO_HANDLE_UNSUPPRESS (HANDLE))->FIELD))); \
389 	} while (0)
390 
391 #define MONO_HANDLE_NEW_GET(TYPE,HANDLE,FIELD) (MONO_HANDLE_NEW(TYPE,MONO_HANDLE_SUPPRESS (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE))->FIELD)))
392 
393 #define MONO_HANDLE_GETVAL(HANDLE, FIELD) MONO_HANDLE_SUPPRESS (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE))->FIELD)
394 
395 /* VS doesn't support typeof :( :( :( */
396 #define MONO_HANDLE_SETVAL(HANDLE, FIELD, TYPE, VALUE) do {	\
397 		TYPE __val = (VALUE);	\
398 		MONO_HANDLE_SUPPRESS (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE))->FIELD = __val); \
399 	 } while (0)
400 
401 #define MONO_HANDLE_ARRAY_SETREF(HANDLE, IDX, VALUE) do {	\
402 		int __idx = (IDX);	\
403    		MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE);		\
404 		do {							\
405 			MONO_HANDLE_SUPPRESS_SCOPE(1);			\
406 			mono_array_setref_fast (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE)), __idx, MONO_HANDLE_RAW (__val)); \
407 		} while (0);						\
408 	} while (0)
409 
410 #define MONO_HANDLE_ARRAY_SETVAL(HANDLE, TYPE, IDX, VALUE) do {		\
411 		int __idx = (IDX);					\
412    		TYPE __val = (VALUE);					\
413 		do {							\
414 			MONO_HANDLE_SUPPRESS_SCOPE(1);			\
415 			mono_array_set (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE)), TYPE, __idx, __val); \
416 		} while (0);						\
417 	} while (0)
418 
419 #define MONO_HANDLE_ARRAY_SETRAW(HANDLE, IDX, VALUE) do {	\
420 		MONO_HANDLE_SUPPRESS_SCOPE(1);			\
421 		int __idx = MONO_HANDLE_UNSUPPRESS(IDX);	\
422 		MonoObject *__val = (MonoObject*)(VALUE);	\
423 		mono_array_setref_fast (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (HANDLE)), __idx, __val); \
424 	} while (0)
425 
426 /* N.B. DEST is evaluated AFTER all the other arguments */
427 #define MONO_HANDLE_ARRAY_GETVAL(DEST, HANDLE, TYPE, IDX) do {		\
428 		MonoArrayHandle __arr = (HANDLE);			\
429 		int __idx = (IDX);					\
430 		TYPE __result = MONO_HANDLE_SUPPRESS (mono_array_get (MONO_HANDLE_RAW(__arr), TYPE, __idx)); \
431 		(DEST) =  __result;					\
432 	} while (0)
433 
434 #define MONO_HANDLE_ARRAY_GETREF(DEST, HANDLE, IDX) do {		\
435 		mono_handle_array_getref (MONO_HANDLE_CAST(MonoObject, (DEST)), (HANDLE), (IDX)); \
436 	} while (0)
437 
438 #define MONO_HANDLE_ASSIGN(DESTH, SRCH)				\
439 	mono_handle_assign (MONO_HANDLE_CAST (MonoObject, (DESTH)), MONO_HANDLE_CAST(MonoObject, (SRCH)))
440 
441 #define MONO_HANDLE_DOMAIN(HANDLE) MONO_HANDLE_SUPPRESS (mono_object_domain (MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject, MONO_HANDLE_UNSUPPRESS (HANDLE)))))
442 
443 /* Given an object and a MonoClassField, return the value (must be non-object)
444  * of the field.  It's the caller's responsibility to check that the object is
445  * of the correct class. */
446 #define MONO_HANDLE_GET_FIELD_VAL(HANDLE,TYPE,FIELD) *(TYPE *)(mono_handle_unsafe_field_addr (MONO_HANDLE_CAST (MonoObject, (HANDLE)), (FIELD)))
447 
448 #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)))))
449 
450 #define MONO_HANDLE_SET_FIELD_VAL(HANDLE,TYPE,FIELD,VAL) do {		\
451 		MonoObjectHandle __obj = (HANDLE);			\
452 		MonoClassField *__field = (FIELD);			\
453 		TYPE __value = (VAL);					\
454 		*(TYPE*)(mono_handle_unsafe_field_addr (__obj, __field)) = __value; \
455 	} while (0)
456 
457 #define MONO_HANDLE_SET_FIELD_REF(HANDLE,FIELD,VALH) do {		\
458 		MonoObjectHandle __obj = MONO_HANDLE_CAST (MonoObject, (HANDLE)); \
459 		MonoClassField *__field = (FIELD);			\
460 		MonoObjectHandle __value = MONO_HANDLE_CAST (MonoObject, (VALH)); \
461 		MONO_HANDLE_SUPPRESS (mono_gc_wbarrier_generic_store (mono_handle_unsafe_field_addr (__obj, __field), MONO_HANDLE_RAW (__value))); \
462 	} while (0)
463 
464 /* Baked typed handles we all want */
465 TYPED_HANDLE_DECL (MonoString);
466 TYPED_HANDLE_DECL (MonoArray);
467 TYPED_HANDLE_DECL (MonoObject);
468 TYPED_HANDLE_DECL (MonoException);
469 TYPED_HANDLE_DECL (MonoAppContext);
470 
471 /* Unfortunately MonoThreadHandle is already a typedef used for something unrelated.  So
472  * the coop handle for MonoThread* is MonoThreadObjectHandle.
473  */
474 typedef MonoThread MonoThreadObject;
475 TYPED_HANDLE_DECL (MonoThreadObject);
476 
477 #define NULL_HANDLE_STRING MONO_HANDLE_CAST(MonoString, NULL_HANDLE)
478 
479 /*
480 This is the constant for a handle that points nowhere.
481 Init values to it.
482 */
483 extern const MonoObjectHandle mono_null_value_handle;
484 
485 static inline void
mono_handle_assign(MonoObjectHandleOut dest,MonoObjectHandle src)486 mono_handle_assign (MonoObjectHandleOut dest, MonoObjectHandle src)
487 {
488 	MONO_HANDLE_SUPPRESS (mono_gc_wbarrier_generic_store (&dest->__raw, src ? MONO_HANDLE_RAW(src) : NULL));
489 }
490 
491 /* It is unsafe to call this function directly - it does not pin the handle!  Use MONO_HANDLE_GET_FIELD_VAL(). */
492 static inline gchar*
mono_handle_unsafe_field_addr(MonoObjectHandle h,MonoClassField * field)493 mono_handle_unsafe_field_addr (MonoObjectHandle h, MonoClassField *field)
494 {
495 	return MONO_HANDLE_SUPPRESS (((gchar *)MONO_HANDLE_RAW (h)) + field->offset);
496 }
497 
498 //FIXME this should go somewhere else
499 MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data, MonoError *error);
500 MonoArrayHandle mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error);
501 MonoArrayHandle
502 mono_array_new_full_handle (MonoDomain *domain, MonoClass *array_class, uintptr_t *lengths, intptr_t *lower_bounds, MonoError *error);
503 
504 
505 uintptr_t mono_array_handle_length (MonoArrayHandle arr);
506 
507 static inline void
mono_handle_array_getref(MonoObjectHandleOut dest,MonoArrayHandle array,uintptr_t index)508 mono_handle_array_getref (MonoObjectHandleOut dest, MonoArrayHandle array, uintptr_t index)
509 {
510 	MONO_HANDLE_SUPPRESS (mono_gc_wbarrier_generic_store (&dest->__raw, mono_array_get (MONO_HANDLE_RAW (array),gpointer, index)));
511 }
512 
513 #define mono_handle_class(o) MONO_HANDLE_SUPPRESS (mono_object_class (MONO_HANDLE_RAW (MONO_HANDLE_UNSUPPRESS (o))))
514 
515 /* Local handles to global GC handles and back */
516 
517 uint32_t
518 mono_gchandle_from_handle (MonoObjectHandle handle, mono_bool pinned);
519 
520 MonoObjectHandle
521 mono_gchandle_get_target_handle (uint32_t gchandle);
522 
523 void
524 mono_array_handle_memcpy_refs (MonoArrayHandle dest, uintptr_t dest_idx, MonoArrayHandle src, uintptr_t src_idx, uintptr_t len);
525 
526 /* Pins the MonoArray using a gchandle and returns a pointer to the
527  * element with the given index (where each element is of the given
528  * size.  Call mono_gchandle_free to unpin.
529  */
530 gpointer
531 mono_array_handle_pin_with_size (MonoArrayHandle handle, int size, uintptr_t index, uint32_t *gchandle);
532 
533 #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))
534 
535 gunichar2 *
536 mono_string_handle_pin_chars (MonoStringHandle s, uint32_t *gchandle_out);
537 
538 gpointer
539 mono_object_handle_pin_unbox (MonoObjectHandle boxed_valuetype_obj, uint32_t *gchandle_out);
540 
541 void
542 mono_error_set_exception_handle (MonoError *error, MonoExceptionHandle exc);
543 
544 MonoAppContextHandle
545 mono_context_get_handle (void);
546 
547 void
548 mono_context_set_handle (MonoAppContextHandle new_context);
549 
550 G_END_DECLS
551 
552 #endif /* __MONO_HANDLE_H__ */
553