*
* Authors:
* - Ludovic Henry <ludovic@xamarin.com>
+ * - Aleksey Klieger <aleksey.klieger@xamarin.com>
+ * - Rodrigo Kumpera <kumpera@xamarin.com>
*
- * Copyright 2015 Xamarin, Inc. (www.xamarin.com)
+ * Copyright 2016 Dot net foundation.
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <mono/utils/atomic.h>
#include <mono/utils/mono-lazy-init.h>
#include <mono/utils/mono-threads.h>
+/* TODO (missing pieces)
-#define HANDLES_PER_CHUNK (16 - 2)
+Add counters for:
+ number of stack marks
+ stack marks per icall
+ mix/max/avg size of stack marks
+ handle stack wastage
-typedef struct _MonoHandleArenaChunk MonoHandleArenaChunk;
-struct _MonoHandleArenaChunk {
- /* if next is NULL, this is the first chunk.
- *
- * The first chunk is special - it was allocated together with
- * its owning arena and must not be deallocated unless the
- * arena is being deallocated. N.B: Arenas are
- * stack-allocated.
- */
- MonoHandleArenaChunk *next;
- gsize handles_size;
- MonoHandleStorage handles [HANDLES_PER_CHUNK];
-};
+Actually do something in mono_handle_verify
-struct _MonoHandleArena {
- MonoHandleArenaChunk *chunk;
- MonoHandleArena *prev;
-};
+Shrink the handles stack in mono_handle_stack_scan
+Properly report it to the profiler.
+Add a boehm implementation
-static mono_lazy_init_t arena_status = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
+TODO (things to explore):
-static MonoGCDescriptor arena_desc = MONO_GC_DESCRIPTOR_NULL;
+There's no convenient way to wrap the object allocation function.
+Right now we do this:
+ MonoCultureInfoHandle culture = MONO_HANDLE_NEW (MonoCultureInfo, mono_object_new_checked (domain, klass, &error));
-static MonoHandleArenaChunk *chunk_free_list = NULL;
+Maybe what we need is a round of cleanup around all exposed types in the runtime to unify all helpers under the same hoof.
+Combine: MonoDefaults, GENERATE_GET_CLASS_WITH_CACHE, TYPED_HANDLE_DECL and friends.
+ This would solve the age old issue of making it clear which types are optional and tell that to the linker.
+ We could then generate neat type safe wrappers.
+*/
-static inline MonoHandleArenaChunk*
-chunk_alloc (void)
-{
- MonoHandleArenaChunk *old, *new;
-
- do {
- old = chunk_free_list;
- if (!old) {
- MonoHandleArenaChunk *chunk;
-
- chunk = g_malloc0 (sizeof (MonoHandleArenaChunk));
- g_assert (chunk);
+const MonoObject *null_cell = { NULL };
+const MonoObjectHandle mono_null_value_handle = { (MonoObject**)&null_cell };
- return chunk;
- }
-
- new = old->next;
- } while (InterlockedCompareExchangePointer ((gpointer*) &chunk_free_list, new, old) != old);
-
- memset (old, 0, sizeof (MonoHandleArenaChunk));
- return old;
-}
+#define THIS_IS_AN_OK_NUMBER_OF_HANDLES 100
-static inline void
-chunk_free (MonoHandleArenaChunk *chunk)
+/* Actual handles implementation */
+MonoRawHandle
+mono_handle_new (MonoObject *object)
{
- if (chunk == NULL)
- return;
- while (chunk->next != NULL) {
- MonoHandleArenaChunk *next = chunk->next;
- chunk->next = NULL;
- do {
- chunk->next = chunk_free_list;
- } while (InterlockedCompareExchangePointer ((gpointer*) &chunk_free_list, chunk, chunk->next) != chunk->next);
- chunk = next;
+ MonoThreadInfo *info = mono_thread_info_current ();
+ HandleStack *handles = (HandleStack *)info->handle_stack;
+ HandleChunk *top = handles->top;
+
+retry:
+ if (G_LIKELY (top->size < OBJECTS_PER_HANDLES_CHUNK)) {
+ MonoObject **h = &top->objects [top->size++];
+ *h = object;
+ return h;
}
-}
-
-static MonoHandle
-handle_new (MonoHandleArena *arena, MonoObject *obj)
-{
- MonoHandleArenaChunk *chunk;
-
- g_assert (arena->chunk);
-
- chunk = arena->chunk;
-
- if (chunk->handles_size < HANDLES_PER_CHUNK) {
- chunk->handles [chunk->handles_size].__private_obj = obj;
- chunk->handles_size += 1;
-
- return &chunk->handles [chunk->handles_size - 1];
- } else {
-
- MonoHandleArenaChunk *new_chunk = chunk_alloc ();
- new_chunk->next = chunk;
- arena->chunk = chunk = new_chunk;
-
- chunk->handles [0].__private_obj = obj;
- chunk->handles_size = 1;
-
- return &chunk->handles [0];
+ if (G_LIKELY (top->next)) {
+ top = top->next;
+ top->size = 0;
+ handles->top = top;
+ goto retry;
}
+ HandleChunk *new_chunk = g_new (HandleChunk, 1);
+ new_chunk->size = 0;
+ new_chunk->prev = top;
+ new_chunk->next = NULL;
+ top->next = new_chunk;
+ handles->top = new_chunk;
+ goto retry;
}
-MonoHandle
-mono_handle_arena_new (MonoHandleArena *arena, MonoObject *obj)
-{
- g_assert (arena);
- return handle_new (arena, obj);
-}
-
-/*
- * Elevate the handle to the parent arena
- */
-MonoHandle
-mono_handle_arena_elevate (MonoHandleArena *arena, MonoHandle handle)
-{
- g_assert (handle);
- g_assert (arena);
- g_assert (arena->prev);
- return handle_new (arena->prev, handle->__private_obj);
-}
-gsize
-mono_handle_arena_size (void)
+HandleStack*
+mono_handle_stack_alloc (void)
{
- return sizeof (MonoHandleArena) + sizeof (MonoHandleArenaChunk);
+ HandleStack *stack = g_new (HandleStack, 1);
+ HandleChunk *chunk = g_new (HandleChunk, 1);
+
+ stack->top = stack->bottom = chunk;
+ chunk->size = 0;
+ chunk->prev = chunk->next = NULL;
+ return stack;
}
void
-mono_handle_arena_stack_push(MonoHandleArena **arena_stack, MonoHandleArena *arena)
+mono_handle_stack_free (HandleStack *stack)
{
- g_assert (arena_stack);
- g_assert (arena);
-
- arena->prev = *arena_stack;
- arena->chunk = (MonoHandleArenaChunk*) (((char*) arena) + sizeof (MonoHandleArena));
-
- arena->chunk->next = NULL;
- arena->chunk->handles_size = 0;
- memset (&arena->chunk->handles [0], 0, sizeof (MonoHandleStorage) * HANDLES_PER_CHUNK);
-
- *arena_stack = arena;
+ if (!stack)
+ return;
+ HandleChunk *c = stack->bottom;
+ while (c) {
+ HandleChunk *next = c->next;
+ g_free (c);
+ c = next;
+ }
+ g_free (c);
}
void
-mono_handle_arena_stack_pop(MonoHandleArena **arena_stack, MonoHandleArena *arena)
+mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data)
{
- MonoHandleArenaChunk *chunk, *next;
+ HandleChunk *cur = stack->bottom;
+ HandleChunk *last = stack->top;
- g_assert (arena);
- g_assert (arena->chunk);
- g_assert (arena_stack);
-
- *arena_stack = arena->prev;
+ if (!cur)
+ return;
- for (chunk = arena->chunk; chunk; chunk = next) {
- next = chunk->next;
- memset (&chunk->handles [0], 0, sizeof (MonoHandleStorage) * HANDLES_PER_CHUNK);
- if (next != NULL)
- chunk_free (chunk);
+ while (cur) {
+ int i;
+ for (i = 0; i < cur->size; ++i)
+ func ((gpointer*)&cur->objects [i], gc_data);
+ if (cur == last)
+ break;
+ cur = cur->next;
}
}
-static void
-arena_scan (gpointer addr, MonoGCMarkFunc mark_func, gpointer gc_data)
+void
+mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name)
{
- MonoHandleArena *arena;
- MonoHandleArenaChunk *chunk;
- int i;
-
- for (arena = *(MonoHandleArena**) addr; arena; arena = arena->prev) {
- for (chunk = arena->chunk; chunk; chunk = chunk->next) {
- for (i = 0; i < chunk->handles_size; ++i) {
- if (chunk->handles [i].__private_obj != NULL)
- mark_func (&chunk->handles [i].__private_obj, gc_data);
- }
- }
+ HandleStack *handles = (HandleStack *)info->handle_stack;
+ HandleChunk *cur = stackmark->chunk;
+ int size = -stackmark->size; //discard the starting point of the stack
+ while (cur) {
+ size += cur->size;
+ if (cur == handles->top)
+ break;
+ cur = cur->next;
}
-}
-static void
-initialize (void)
-{
- arena_desc = mono_gc_make_root_descr_user (arena_scan);
+ if (size > THIS_IS_AN_OK_NUMBER_OF_HANDLES)
+ printf ("%s USED %d handles\n", func_name, size);
}
-void
-mono_handle_arena_init (MonoHandleArena **arena_stack)
+/*
+ * Pop the stack until @stackmark and make @value the top value.
+ *
+ * @return the new handle for what @value points to
+ */
+MonoRawHandle
+mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value)
{
- mono_lazy_initialize (&arena_status, initialize);
- mono_gc_register_root ((char*) arena_stack, sizeof (MonoHandleArena*), arena_desc, MONO_ROOT_SOURCE_HANDLE, "runtime threads handle arena");
+ g_error ("impl me");
}
-void
-mono_handle_arena_cleanup (MonoHandleArena **arena_stack)
+/* Temporary place for some of the handle enabled wrapper functions*/
+
+MonoStringHandle
+mono_string_new_handle (MonoDomain *domain, const char *data)
{
- mono_gc_deregister_root ((char*) arena_stack);
+ return MONO_HANDLE_NEW (MonoString, mono_string_new (domain, data));
}
-MonoHandleArena*
-mono_handle_arena_current (void)
+MonoArrayHandle
+mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error)
{
- return (MonoHandleArena*) mono_thread_info_current ()->handle_arena;
+ return MONO_HANDLE_NEW (MonoArray, mono_array_new_checked (domain, eclass, n, error));
}
-MonoHandleArena**
-mono_handle_arena_current_addr (void)
+#ifdef ENABLE_CHECKED_BUILD
+/* Checked build helpers */
+void
+mono_handle_verify (MonoRawHandle raw_handle)
{
- return (MonoHandleArena**) &mono_thread_info_current ()->handle_arena;
+
}
+#endif
*
* Authors:
* - Ludovic Henry <ludovic@xamarin.com>
+ * - Aleksey Klieger <aleksey.klieger@xamarin.com>
+ * - Rodrigo Kumpera <kumpera@xamarin.com>
*
- * Copyright 2015 Xamarin, Inc. (www.xamarin.com)
+ * Copyright 2016 Dot net foundation.
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <mono/metadata/object.h>
#include <mono/metadata/class.h>
-#include <mono/utils/mono-error.h>
+#include <mono/utils/mono-error-internals.h>
+#include <mono/utils/mono-threads.h>
#include <mono/utils/checked-build.h>
G_BEGIN_DECLS
-/*
- * DO NOT ACCESS DIRECTLY
- * USE mono_handle_obj BELOW TO ACCESS OBJ
- *
- * The field obj is not private as there is no way to do that
- * in C, but using a C++ template would simplify that a lot
- */
-typedef struct {
- MonoObject *__private_obj;
-} MonoHandleStorage;
-
-typedef MonoHandleStorage* MonoHandle;
-typedef struct _MonoHandleArena MonoHandleArena;
+/*
+Handle stack.
-gsize
-mono_handle_arena_size (void);
+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.
-MonoHandle
-mono_handle_arena_new (MonoHandleArena *arena, MonoObject *obj);
+To do bulk operations you use a stack mark.
+
+*/
-MonoHandle
-mono_handle_arena_elevate (MonoHandleArena *arena, MonoHandle handle);
+/*
+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)
-void
-mono_handle_arena_stack_push (MonoHandleArena **arena_stack, MonoHandleArena *arena);
+/*
+Whether this config needs stack watermark recording to know where to start scanning from.
+*/
+#ifdef HOST_WATCHOS
+#define MONO_NEEDS_STACK_WATERMARK 1
+#endif
-void
-mono_handle_arena_stack_pop (MonoHandleArena **arena_stack, MonoHandleArena *arena);
+typedef struct _HandleChunk HandleChunk;
-void
-mono_handle_arena_init (MonoHandleArena **arena_stack);
+struct _HandleChunk {
+ int size; //number of bytes
+ HandleChunk *prev, *next;
+ MonoObject *objects [OBJECTS_PER_HANDLES_CHUNK];
+};
-void
-mono_handle_arena_cleanup (MonoHandleArena **arena_stack);
+typedef struct {
+ HandleChunk *top; //alloc from here
+ HandleChunk *bottom; //scan from here
+} HandleStack;
-MonoHandleArena*
-mono_handle_arena_current (void);
+typedef struct {
+ int size;
+ HandleChunk *chunk;
+} HandleStackMark;
-MonoHandleArena**
-mono_handle_arena_current_addr (void);
+typedef void *MonoRawHandle;
-#define MONO_HANDLE_ARENA_PUSH() \
- do { \
- MonoHandleArena **__arena_stack = mono_handle_arena_current_addr (); \
- MonoHandleArena *__arena = (MonoHandleArena*) g_alloca (mono_handle_arena_size ()); \
- mono_handle_arena_stack_push (__arena_stack, __arena)
+typedef void (*GcScanFunc) (gpointer*, gpointer);
-#define MONO_HANDLE_ARENA_POP() \
- mono_handle_arena_stack_pop (__arena_stack, __arena); \
- } while (0)
-#define MONO_HANDLE_ARENA_POP_RETURN_UNSAFE(handle,ret) \
- (ret) = (handle)->__private_obj; \
- mono_handle_arena_stack_pop (__arena_stack, __arena); \
- } while (0)
+MonoRawHandle mono_handle_new (MonoObject *object);
-#define MONO_HANDLE_ARENA_POP_RETURN(handle,ret_handle) \
- *((MonoHandle**)(&(ret_handle))) = mono_handle_elevate ((MonoHandle*)(handle)); \
- mono_handle_arena_stack_pop(__arena_stack, __arena); \
- } while (0)
+void mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data);
+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);
-static inline MonoHandle
-mono_handle_new (MonoObject *obj)
+static void
+mono_stack_mark_init (MonoThreadInfo *info, HandleStackMark *stackmark)
{
- return mono_handle_arena_new (mono_handle_arena_current (), obj);
+ HandleStack *handles = (HandleStack *)info->handle_stack;
+ stackmark->size = handles->top->size;
+ stackmark->chunk = handles->top;
}
-static inline MonoHandle
-mono_handle_elevate (MonoHandle handle)
+static void
+mono_stack_mark_pop (MonoThreadInfo *info, HandleStackMark *stackmark)
{
- return mono_handle_arena_elevate (mono_handle_arena_current (), handle);
+ HandleStack *handles = (HandleStack *)info->handle_stack;
+ handles->top = stackmark->chunk;
+ handles->top->size = stackmark->size;
}
-#ifndef ENABLE_CHECKED_BUILD
+/*
+Icall macros
+*/
+#define SETUP_ICALL_COMMON \
+ do { \
+ MonoError error; \
+ MonoThreadInfo *__info = mono_thread_info_current (); \
+ error_init (&error); \
-#define mono_handle_obj(handle) ((handle)->__private_obj)
+#define CLEAR_ICALL_COMMON \
+ mono_error_set_pending_exception (&error);
-#define mono_handle_assign(handle,rawptr) do { (handle)->__private_obj = (rawptr); } while(0)
+#define SETUP_ICALL_FRAME \
+ HandleStackMark __mark; \
+ mono_stack_mark_init (__info, &__mark);
-#else
+#define CLEAR_ICALL_FRAME \
+ mono_stack_mark_record_size (__info, &__mark, __FUNCTION__); \
+ mono_stack_mark_pop (__info, &__mark);
+
+#ifdef MONO_NEEDS_STACK_WATERMARK
-static inline void
-mono_handle_check_in_critical_section ()
+static void
+mono_thread_info_pop_stack_mark (MonoThreadInfo *info, void *old_mark)
{
- MONO_REQ_GC_CRITICAL;
+ info->stack_mark = old_mark;
}
-#define mono_handle_obj(handle) (mono_handle_check_in_critical_section (), (handle)->__private_obj)
+static void*
+mono_thread_info_push_stack_mark (MonoThreadInfo *info, void *mark)
+{
+ void *old = info->stack_mark;
+ info->stack_mark = mark;
+ return old;
+}
-#define mono_handle_assign(handle,rawptr) do { mono_handle_check_in_critical_section (); (handle)->__private_obj = (rawptr); } while (0)
+#define SETUP_STACK_WATERMARK \
+ int __dummy; \
+ __builtin_unwind_init (); \
+ void *__old_stack_mark = mono_thread_info_push_stack_mark (__info, &__dummy);
-#endif
+#define CLEAR_STACK_WATERMARK \
+ mono_thread_info_pop_stack_mark (__info, __old_stack_mark);
-static inline MonoClass*
-mono_handle_class (MonoHandle handle)
-{
- return mono_object_get_class (handle->__private_obj);
-}
+#else
+#define SETUP_STACK_WATERMARK
+#define CLEAR_STACK_WATERMARK
+#endif
-static inline MonoDomain*
-mono_handle_domain (MonoHandle handle)
-{
- return mono_object_get_domain (handle->__private_obj);
-}
+#define ICALL_ENTRY() \
+ SETUP_ICALL_COMMON \
+ SETUP_ICALL_FRAME \
+ SETUP_STACK_WATERMARK
-#define mono_handle_obj_is_null(handle) ((handle)->__private_obj == NULL)
+#define ICALL_RETURN() \
+ do { \
+ CLEAR_STACK_WATERMARK \
+ CLEAR_ICALL_COMMON \
+ CLEAR_ICALL_FRAME \
+ return; \
+ } while (0); } while (0)
-#define MONO_HANDLE_TYPE_DECL(type) typedef struct { type *__private_obj; } type ## HandleStorage ; \
- typedef type ## HandleStorage * type ## Handle
-#define MONO_HANDLE_TYPE(type) type ## Handle
-#define MONO_HANDLE_NEW(type,obj) ((type ## Handle) mono_handle_new ((MonoObject*) (obj)))
-#define MONO_HANDLE_ELEVATE(type,handle) ((type ## Handle) mono_handle_elevate ((MonoObject*) (handle)->__private_obj))
+#define ICALL_RETURN_VAL(VAL) \
+ do { \
+ CLEAR_STACK_WATERMARK \
+ CLEAR_ICALL_COMMON \
+ CLEAR_ICALL_FRAME \
+ return VAL; \
+ } while (0); } while (0)
-#define MONO_HANDLE_ASSIGN(handle,rawptr) \
+#define ICALL_RETURN_OBJ(HANDLE) \
do { \
- mono_handle_assign ((handle), (rawptr)); \
- } while (0)
+ CLEAR_STACK_WATERMARK \
+ CLEAR_ICALL_COMMON \
+ void* __ret = MONO_HANDLE_RAW (HANDLE); \
+ CLEAR_ICALL_FRAME \
+ return __ret; \
+ } while (0); } while (0)
-#define MONO_HANDLE_SETREF(handle,fieldname,value) \
- do { \
- MonoHandle __value = (MonoHandle) (value); \
- MONO_PREPARE_GC_CRITICAL_REGION; \
- MONO_OBJECT_SETREF (mono_handle_obj ((handle)), fieldname, mono_handle_obj (__value)); \
- MONO_FINISH_GC_CRITICAL_REGION; \
- } while (0)
+/*
+Handle macros/functions
+*/
-#define MONO_HANDLE_SETREF_NULL(handle,fieldname) \
- do { \
- MONO_PREPARE_GC_CRITICAL_REGION; \
- MONO_OBJECT_SETREF (mono_handle_obj ((handle)), fieldname, NULL); \
- MONO_FINISH_GC_CRITICAL_REGION; \
- } while (0)
+#ifdef ENABLE_CHECKED_BUILD
+void mono_handle_verify (MonoRawHandle handle);
+#define HANDLE_INVARIANTS(H) mono_handle_verify((void*)(H).__obj)
+#else
+#define HANDLE_INVARIANTS(H) (0)
+#endif
+#define TYPED_HANDLE_NAME(TYPE) TYPE ## Handle
+#define TYPED_HANDLE_DECL(TYPE) typedef struct { TYPE **__obj; } TYPED_HANDLE_NAME (TYPE) ;
-#define MONO_HANDLE_SET(handle,fieldname,value) \
- do { \
- MONO_PREPARE_GC_CRITICAL_REGION; \
- mono_handle_obj ((handle))->fieldname = (value); \
- MONO_FINISH_GC_CRITICAL_REGION; \
- } while (0)
+#define MONO_HANDLE_INIT { (void*)mono_null_value_handle.__obj }
+#define NULL_HANDLE mono_null_value_handle
-#define MONO_HANDLE_ARRAY_SETREF(handle,index,value) \
- do { \
- MonoHandle __value = (MonoHandle) (value); \
- MONO_PREPARE_GC_CRITICAL_REGION; \
- mono_array_setref (mono_handle_obj ((handle)), (index), mono_handle_obj (__value)); \
- MONO_FINISH_GC_CRITICAL_REGION; \
- } while (0)
+//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).__obj))
+#define MONO_HANDLE_DCL(TYPE, NAME) TYPED_HANDLE_NAME(TYPE) NAME = { mono_handle_new ((MonoObject*)(NAME ## _raw)) }
+#define MONO_HANDLE_NEW(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE)){ mono_handle_new ((MonoObject*)(VALUE)) }
+#define MONO_HANDLE_CAST(TYPE, VALUE) (TYPED_HANDLE_NAME(TYPE)){ (TYPE**)((VALUE).__obj) }
-#define MONO_HANDLE_ARRAY_SETREF_NULL(handle,index) \
- do { \
- MONO_PREPARE_GC_CRITICAL_REGION; \
- mono_array_setref (mono_handle_obj ((handle)), (index), NULL); \
- MONO_FINISH_GC_CRITICAL_REGION; \
+/*
+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 { \
+ MonoObject *__val = (MonoObject*)(VALUE); \
+ MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, __val); \
+ } while (0);
+
+#define MONO_HANDLE_SET(HANDLE, FIELD, VALUE) do { \
+ MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE); \
+ MONO_OBJECT_SETREF (MONO_HANDLE_RAW (HANDLE), FIELD, MONO_HANDLE_RAW (__val)); \
+ } while (0);
+
+/* VS doesn't support typeof :( :( :( */
+#define MONO_HANDLE_SETVAL(HANDLE, FIELD, TYPE, VALUE) do { \
+ TYPE __val = (VALUE); \
+ MONO_HANDLE_RAW (HANDLE)->FIELD = __val; \
+ } while (0)
+
+#define MONO_HANDLE_ARRAY_SETREF(HANDLE, IDX, VALUE) do { \
+ int __idx = (IDX); \
+ MonoObjectHandle __val = MONO_HANDLE_CAST (MonoObject, VALUE); \
+ mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, MONO_HANDLE_RAW (__val)); \
} while (0)
-
-#define MONO_HANDLE_ARRAY_SET(handle,type,index,value) \
- do { \
- MONO_PREPARE_GC_CRITICAL_REGION; \
- mono_array_set (mono_handle_obj ((handle)), type, (index), (value)); \
- MONO_FINISH_GC_CRITICAL_REGION; \
+#define MONO_HANDLE_ARRAY_SETRAW(HANDLE, IDX, VALUE) do { \
+ int __idx = (IDX); \
+ MonoObject *__val = (MonoObject*)(VALUE); \
+ mono_array_setref_fast (MONO_HANDLE_RAW (HANDLE), __idx, __val); \
} while (0)
+/* Baked typed handles we all want */
+TYPED_HANDLE_DECL (MonoString)
+TYPED_HANDLE_DECL (MonoArray)
+TYPED_HANDLE_DECL (MonoObject)
+/*
+This is the constant for a handle that points nowhere.
+Init values to it.
+*/
+extern const MonoObjectHandle mono_null_value_handle;
-/* Some common handle types */
-MONO_HANDLE_TYPE_DECL (MonoArray);
-MONO_HANDLE_TYPE_DECL (MonoString);
+//FIXME this should go somewhere else
+MonoStringHandle mono_string_new_handle (MonoDomain *domain, const char *data);
+MonoArrayHandle mono_array_new_handle (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error);
G_END_DECLS