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