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