[coop] Change handles to be pointers (#3249)
[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 struct _HandleChunk {
54         int size; //number of bytes
55         HandleChunk *prev, *next;
56         MonoObject *objects [OBJECTS_PER_HANDLES_CHUNK];
57 };
58
59 typedef struct {
60         HandleChunk *top; //alloc from here
61         HandleChunk *bottom; //scan from here
62 } HandleStack;
63
64 typedef struct {
65         int size;
66         HandleChunk *chunk;
67 } HandleStackMark;
68
69 typedef void *MonoRawHandle;
70
71 typedef void (*GcScanFunc) (gpointer*, gpointer);
72
73
74 MonoRawHandle mono_handle_new (MonoObject *object);
75
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);
81
82 static void
83 mono_stack_mark_init (MonoThreadInfo *info, HandleStackMark *stackmark)
84 {
85         HandleStack *handles = (HandleStack *)info->handle_stack;
86         stackmark->size = handles->top->size;
87         stackmark->chunk = handles->top;
88 }
89
90 static void
91 mono_stack_mark_pop (MonoThreadInfo *info, HandleStackMark *stackmark)
92 {
93         HandleStack *handles = (HandleStack *)info->handle_stack;
94         handles->top = stackmark->chunk;
95         handles->top->size = stackmark->size;
96 }
97
98 /*
99 Icall macros
100 */
101 #define SETUP_ICALL_COMMON      \
102         do { \
103                 MonoError error;        \
104                 MonoThreadInfo *__info = mono_thread_info_current ();   \
105                 error_init (&error);    \
106
107 #define CLEAR_ICALL_COMMON      \
108         mono_error_set_pending_exception (&error);
109
110 #define SETUP_ICALL_FRAME       \
111         HandleStackMark __mark; \
112         mono_stack_mark_init (__info, &__mark);
113
114 #define CLEAR_ICALL_FRAME       \
115         mono_stack_mark_record_size (__info, &__mark, __FUNCTION__);    \
116         mono_stack_mark_pop (__info, &__mark);
117
118 #ifdef MONO_NEEDS_STACK_WATERMARK
119
120 static void
121 mono_thread_info_pop_stack_mark (MonoThreadInfo *info, void *old_mark)
122 {
123         info->stack_mark = old_mark;
124 }
125
126 static void*
127 mono_thread_info_push_stack_mark (MonoThreadInfo *info, void *mark)
128 {
129         void *old = info->stack_mark;
130         info->stack_mark = mark;
131         return old;
132 }
133
134 #define SETUP_STACK_WATERMARK   \
135         int __dummy;    \
136         __builtin_unwind_init ();       \
137         void *__old_stack_mark = mono_thread_info_push_stack_mark (__info, &__dummy);
138
139 #define CLEAR_STACK_WATERMARK   \
140         mono_thread_info_pop_stack_mark (__info, __old_stack_mark);
141
142 #else
143 #define SETUP_STACK_WATERMARK
144 #define CLEAR_STACK_WATERMARK
145 #endif
146
147 #define ICALL_ENTRY()   \
148         SETUP_ICALL_COMMON      \
149         SETUP_ICALL_FRAME       \
150         SETUP_STACK_WATERMARK
151
152 #define ICALL_RETURN()  \
153         do {    \
154                 CLEAR_STACK_WATERMARK   \
155                 CLEAR_ICALL_COMMON      \
156                 CLEAR_ICALL_FRAME       \
157                 return; \
158         } while (0); } while (0)
159
160 #define ICALL_RETURN_VAL(VAL)   \
161         do {    \
162                 CLEAR_STACK_WATERMARK   \
163                 CLEAR_ICALL_COMMON      \
164                 CLEAR_ICALL_FRAME       \
165                 return VAL;     \
166         } while (0); } while (0)
167
168 #define ICALL_RETURN_OBJ(HANDLE)        \
169         do {    \
170                 CLEAR_STACK_WATERMARK   \
171                 CLEAR_ICALL_COMMON      \
172                 void* __ret = MONO_HANDLE_RAW (HANDLE); \
173                 CLEAR_ICALL_FRAME       \
174                 return __ret;   \
175         } while (0); } while (0)
176
177 /*
178 Handle macros/functions
179 */
180
181 #ifdef ENABLE_CHECKED_BUILD
182 void mono_handle_verify (MonoRawHandle handle);
183 #define HANDLE_INVARIANTS(H) mono_handle_verify((void*)(H))
184 #else
185 #define HANDLE_INVARIANTS(H) (0)
186 #endif
187
188 #define TYPED_HANDLE_PAYLOAD_NAME(TYPE) TYPE ## HandlePayload
189 #define TYPED_HANDLE_NAME(TYPE) TYPE ## Handle
190 /*
191  * typedef struct {
192  *   MonoObject *__obj;
193  * } MonoObjectHandlePayload;
194  *
195  * typedef MonoObjectHandlePayload* MonoObjectHandle;
196  */
197 #define TYPED_HANDLE_DECL(TYPE) typedef struct { TYPE *__obj; } TYPED_HANDLE_PAYLOAD_NAME (TYPE) ; typedef TYPED_HANDLE_PAYLOAD_NAME (TYPE) * TYPED_HANDLE_NAME (TYPE);
198
199 #define MONO_HANDLE_INIT ((void*) mono_null_value_handle)
200 #define NULL_HANDLE mono_null_value_handle
201
202 //XXX add functions to get/set raw, set field, set field to null, set array, set array to null
203 #define MONO_HANDLE_RAW(HANDLE) (HANDLE_INVARIANTS (HANDLE), ((HANDLE)->__obj))
204 #define MONO_HANDLE_DCL(TYPE, NAME) TYPED_HANDLE_NAME(TYPE) NAME = (TYPED_HANDLE_NAME(TYPE))(mono_handle_new ((MonoObject*)(NAME ## _raw)))
205 #define MONO_HANDLE_NEW(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( mono_handle_new ((MonoObject*)(VALUE)) )
206 #define MONO_HANDLE_CAST(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE))( VALUE )
207
208 /*
209 WARNING WARNING WARNING
210
211 The following functions require a particular evaluation ordering to ensure correctness.
212 We must not have exposed handles while any sort of evaluation is happening as that very evaluation might trigger
213 a safepoint and break us.
214
215 This is why we evaluate index and value before any call to MONO_HANDLE_RAW or other functions that deal with naked objects.
216 */
217 #define MONO_HANDLE_SETRAW(HANDLE, FIELD, VALUE) do {   \
218                 MonoObject *__val = (MonoObject*)(VALUE);       \
219                 MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, __val);    \
220         } while (0);
221
222 #define MONO_HANDLE_SET(HANDLE, FIELD, VALUE) do {      \
223                 MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE);  \
224                 MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, MONO_HANDLE_RAW (__val));  \
225         } while (0);
226
227 /* VS doesn't support typeof :( :( :( */
228 #define MONO_HANDLE_SETVAL(HANDLE, FIELD, TYPE, VALUE) do {     \
229                 TYPE __val = (VALUE);   \
230                 MONO_HANDLE_RAW (HANDLE)->FIELD = __val;        \
231          } while (0)
232
233 #define MONO_HANDLE_ARRAY_SETREF(HANDLE, IDX, VALUE) do {       \
234                 int __idx = (IDX);      \
235                 MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE);          \
236                 mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, MONO_HANDLE_RAW (__val));      \
237         } while (0)
238
239 #define MONO_HANDLE_ARRAY_SETRAW(HANDLE, IDX, VALUE) do {       \
240                 int __idx = (IDX);      \
241                 MonoObject *__val = (MonoObject*)(VALUE);       \
242                 mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, __val);        \
243         } while (0)
244
245
246 /* Baked typed handles we all want */
247 TYPED_HANDLE_DECL (MonoString)
248 TYPED_HANDLE_DECL (MonoArray)
249 TYPED_HANDLE_DECL (MonoObject)
250
251 /*
252 This is the constant for a handle that points nowhere.
253 Init values to it.
254 */
255 extern const MonoObjectHandle mono_null_value_handle;
256
257
258 //FIXME this should go somewhere else
259 MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data);
260 MonoArrayHandle mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error);
261
262 G_END_DECLS
263
264 #endif /* __MONO_HANDLE_H__ */