Merge pull request #2040 from esdrubal/monoman
[mono.git] / mono / metadata / object.c
index 822f901902e28d6ef39addc835807edf7eadfe61..31746e2308d5456ba833573d8af534c65edf838d 100644 (file)
@@ -27,7 +27,6 @@
 #include "mono/metadata/metadata-internals.h"
 #include "mono/metadata/class-internals.h"
 #include <mono/metadata/assembly.h>
-#include <mono/metadata/threadpool.h>
 #include <mono/metadata/marshal.h>
 #include "mono/metadata/debug-helpers.h"
 #include "mono/metadata/marshal.h"
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-error-internals.h>
 #include <mono/utils/mono-memory-model.h>
+#include <mono/utils/checked-build.h>
 #include "cominterop.h"
 
-#ifdef HAVE_BOEHM_GC
-#define NEED_TO_ZERO_PTRFREE 1
-#define ALLOC_PTRFREE(obj,vt,size) do { (obj) = GC_MALLOC_ATOMIC ((size)); (obj)->vtable = (vt); (obj)->synchronisation = NULL;} while (0)
-#define ALLOC_OBJECT(obj,vt,size) do { (obj) = GC_MALLOC ((size)); (obj)->vtable = (vt);} while (0)
-#ifdef HAVE_GC_GCJ_MALLOC
-#define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
-#define ALLOC_TYPED(dest,size,type) do { (dest) = GC_GCJ_MALLOC ((size),(type)); } while (0)
-#else
-#define GC_NO_DESCRIPTOR (NULL)
-#define ALLOC_TYPED(dest,size,type) do { (dest) = GC_MALLOC ((size)); *(gpointer*)dest = (type);} while (0)
-#endif
-#else
-#ifdef HAVE_SGEN_GC
-#define GC_NO_DESCRIPTOR (NULL)
-#define ALLOC_PTRFREE(obj,vt,size) do { (obj) = mono_gc_alloc_obj (vt, size);} while (0)
-#define ALLOC_OBJECT(obj,vt,size) do { (obj) = mono_gc_alloc_obj (vt, size);} while (0)
-#define ALLOC_TYPED(dest,size,type) do { (dest) = mono_gc_alloc_obj (type, size);} while (0)
-#else
-#define NEED_TO_ZERO_PTRFREE 1
-#define GC_NO_DESCRIPTOR (NULL)
-#define ALLOC_PTRFREE(obj,vt,size) do { (obj) = malloc ((size)); (obj)->vtable = (vt); (obj)->synchronisation = NULL;} while (0)
-#define ALLOC_OBJECT(obj,vt,size) do { (obj) = calloc (1, (size)); (obj)->vtable = (vt);} while (0)
-#define ALLOC_TYPED(dest,size,type) do { (dest) = calloc (1, (size)); *(gpointer*)dest = (type);} while (0)
-#endif
-#endif
-
-static MonoObject* mono_object_new_ptrfree (MonoVTable *vtable);
-static MonoObject* mono_object_new_ptrfree_box (MonoVTable *vtable);
-
 static void
 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value);
 
@@ -91,11 +62,11 @@ mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s,
 #define ldstr_unlock() mono_mutex_unlock (&ldstr_section)
 static mono_mutex_t ldstr_section;
 
-static gboolean profile_allocs = TRUE;
-
 void
 mono_runtime_object_init (MonoObject *this)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoMethod *method = NULL;
        MonoClass *klass = this->vtable->klass;
 
@@ -140,17 +111,31 @@ typedef struct
 } TypeInitializationLock;
 
 /* for locking access to type_initialization_hash and blocked_thread_hash */
-#define mono_type_initialization_lock() mono_mutex_lock (&type_initialization_section)
-#define mono_type_initialization_unlock() mono_mutex_unlock (&type_initialization_section)
 static mono_mutex_t type_initialization_section;
 
+static inline void
+mono_type_initialization_lock (void)
+{
+       /* The critical sections protected by this lock in mono_runtime_class_init_full () can block */
+       MONO_PREPARE_BLOCKING;
+       mono_mutex_lock (&type_initialization_section);
+       MONO_FINISH_BLOCKING;
+}
+
+static inline void
+mono_type_initialization_unlock (void)
+{
+       mono_mutex_unlock (&type_initialization_section);
+}
 
 static void
 mono_type_init_lock (TypeInitializationLock *lock)
 {
-       MONO_TRY_BLOCKING
+       MONO_REQ_GC_NEUTRAL_MODE;
+
+       MONO_TRY_BLOCKING;
        mono_mutex_lock (&lock->initialization_section);
-       MONO_FINISH_TRY_BLOCKING
+       MONO_FINISH_TRY_BLOCKING;
 }
 
 static void
@@ -183,10 +168,12 @@ static MonoRuntimeCallbacks callbacks;
 void
 mono_thread_set_main (MonoThread *thread)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        static gboolean registered = FALSE;
 
        if (!registered) {
-               MONO_GC_REGISTER_ROOT_SINGLE (main_thread);
+               MONO_GC_REGISTER_ROOT_SINGLE (main_thread, MONO_ROOT_SOURCE_THREADING, "main thread object");
                registered = TRUE;
        }
 
@@ -196,6 +183,8 @@ mono_thread_set_main (MonoThread *thread)
 MonoThread*
 mono_thread_get_main (void)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return main_thread;
 }
 
@@ -234,6 +223,8 @@ mono_type_initialization_cleanup (void)
 static MonoException*
 get_type_init_exception_for_vtable (MonoVTable *vtable)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoDomain *domain = vtable->domain;
        MonoClass *klass = vtable->klass;
        MonoException *ex;
@@ -272,6 +263,8 @@ get_type_init_exception_for_vtable (MonoVTable *vtable)
 void
 mono_runtime_class_init (MonoVTable *vtable)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        mono_runtime_class_init_full (vtable, TRUE);
 }
 
@@ -284,11 +277,18 @@ mono_runtime_class_init (MonoVTable *vtable)
 MonoException *
 mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoException *exc;
        MonoException *exc_to_throw;
        MonoMethod *method = NULL;
        MonoClass *klass;
        gchar *full_name;
+       MonoDomain *domain = vtable->domain;
+       TypeInitializationLock *lock;
+       guint32 tid;
+       int do_initialization = 0;
+       MonoDomain *last_domain = NULL;
 
        if (vtable->initialized)
                return NULL;
@@ -320,143 +320,139 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                }
        }
        method = mono_class_get_cctor (klass);
+       if (!method) {
+               vtable->initialized = 1;
+               return NULL;
+       }
 
-       if (method) {
-               MonoDomain *domain = vtable->domain;
-               TypeInitializationLock *lock;
-               guint32 tid = GetCurrentThreadId();
-               int do_initialization = 0;
-               MonoDomain *last_domain = NULL;
+       tid = GetCurrentThreadId ();
 
-               mono_type_initialization_lock ();
-               /* double check... */
-               if (vtable->initialized) {
+       mono_type_initialization_lock ();
+       /* double check... */
+       if (vtable->initialized) {
+               mono_type_initialization_unlock ();
+               return NULL;
+       }
+       if (vtable->init_failed) {
+               mono_type_initialization_unlock ();
+
+               /* The type initialization already failed once, rethrow the same exception */
+               if (raise_exception)
+                       mono_raise_exception (get_type_init_exception_for_vtable (vtable));
+               return get_type_init_exception_for_vtable (vtable);
+       }
+       lock = g_hash_table_lookup (type_initialization_hash, vtable);
+       if (lock == NULL) {
+               /* This thread will get to do the initialization */
+               if (mono_domain_get () != domain) {
+                       /* Transfer into the target domain */
+                       last_domain = mono_domain_get ();
+                       if (!mono_domain_set (domain, FALSE)) {
+                               vtable->initialized = 1;
+                               mono_type_initialization_unlock ();
+                               if (raise_exception)
+                                       mono_raise_exception (mono_get_exception_appdomain_unloaded ());
+                               return mono_get_exception_appdomain_unloaded ();
+                       }
+               }
+               lock = g_malloc (sizeof(TypeInitializationLock));
+               mono_mutex_init_recursive (&lock->initialization_section);
+               lock->initializing_tid = tid;
+               lock->waiting_count = 1;
+               lock->done = FALSE;
+               /* grab the vtable lock while this thread still owns type_initialization_section */
+               /* This is why type_initialization_lock needs to enter blocking mode */
+               mono_type_init_lock (lock);
+               g_hash_table_insert (type_initialization_hash, vtable, lock);
+               do_initialization = 1;
+       } else {
+               gpointer blocked;
+               TypeInitializationLock *pending_lock;
+
+               if (lock->initializing_tid == tid || lock->done) {
                        mono_type_initialization_unlock ();
                        return NULL;
                }
-               if (vtable->init_failed) {
-                       mono_type_initialization_unlock ();
-
-                       /* The type initialization already failed once, rethrow the same exception */
-                       if (raise_exception)
-                               mono_raise_exception (get_type_init_exception_for_vtable (vtable));
-                       return get_type_init_exception_for_vtable (vtable);
-               }                       
-               lock = g_hash_table_lookup (type_initialization_hash, vtable);
-               if (lock == NULL) {
-                       /* This thread will get to do the initialization */
-                       if (mono_domain_get () != domain) {
-                               /* Transfer into the target domain */
-                               last_domain = mono_domain_get ();
-                               if (!mono_domain_set (domain, FALSE)) {
-                                       vtable->initialized = 1;
+               /* see if the thread doing the initialization is already blocked on this thread */
+               blocked = GUINT_TO_POINTER (lock->initializing_tid);
+               while ((pending_lock = (TypeInitializationLock*) g_hash_table_lookup (blocked_thread_hash, blocked))) {
+                       if (pending_lock->initializing_tid == tid) {
+                               if (!pending_lock->done) {
                                        mono_type_initialization_unlock ();
-                                       if (raise_exception)
-                                               mono_raise_exception (mono_get_exception_appdomain_unloaded ());
-                                       return mono_get_exception_appdomain_unloaded ();
-                               }
-                       }
-                       lock = g_malloc (sizeof(TypeInitializationLock));
-                       mono_mutex_init_recursive (&lock->initialization_section);
-                       lock->initializing_tid = tid;
-                       lock->waiting_count = 1;
-                       lock->done = FALSE;
-                       /* grab the vtable lock while this thread still owns type_initialization_section */
-                       mono_type_init_lock (lock);
-                       g_hash_table_insert (type_initialization_hash, vtable, lock);
-                       do_initialization = 1;
-               } else {
-                       gpointer blocked;
-                       TypeInitializationLock *pending_lock;
-
-                       if (lock->initializing_tid == tid || lock->done) {
-                               mono_type_initialization_unlock ();
-                               return NULL;
-                       }
-                       /* see if the thread doing the initialization is already blocked on this thread */
-                       blocked = GUINT_TO_POINTER (lock->initializing_tid);
-                       while ((pending_lock = (TypeInitializationLock*) g_hash_table_lookup (blocked_thread_hash, blocked))) {
-                               if (pending_lock->initializing_tid == tid) {
-                                       if (!pending_lock->done) {
-                                               mono_type_initialization_unlock ();
-                                               return NULL;
-                                       } else {
-                                               /* the thread doing the initialization is blocked on this thread,
-                                                  but on a lock that has already been freed. It just hasn't got
-                                                  time to awake */
-                                               break;
-                                       }
+                                       return NULL;
+                               } else {
+                                       /* the thread doing the initialization is blocked on this thread,
+                                          but on a lock that has already been freed. It just hasn't got
+                                          time to awake */
+                                       break;
                                }
-                               blocked = GUINT_TO_POINTER (pending_lock->initializing_tid);
                        }
-                       ++lock->waiting_count;
-                       /* record the fact that we are waiting on the initializing thread */
-                       g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock);
+                       blocked = GUINT_TO_POINTER (pending_lock->initializing_tid);
                }
-               mono_type_initialization_unlock ();
-
-               if (do_initialization) {
-                       mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
+               ++lock->waiting_count;
+               /* record the fact that we are waiting on the initializing thread */
+               g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock);
+       }
+       mono_type_initialization_unlock ();
 
-                       /* If the initialization failed, mark the class as unusable. */
-                       /* Avoid infinite loops */
-                       if (!(exc == NULL ||
-                                 (klass->image == mono_defaults.corlib &&              
-                                  !strcmp (klass->name_space, "System") &&
-                                  !strcmp (klass->name, "TypeInitializationException")))) {
-                               vtable->init_failed = 1;
+       if (do_initialization) {
+               mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
 
-                               if (klass->name_space && *klass->name_space)
-                                       full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
-                               else
-                                       full_name = g_strdup (klass->name);
-                               exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
-                               g_free (full_name);
-
-                               /* 
-                                * Store the exception object so it could be thrown on subsequent 
-                                * accesses.
-                                */
-                               mono_domain_lock (domain);
-                               if (!domain->type_init_exception_hash)
-                                       domain->type_init_exception_hash = mono_g_hash_table_new_type (mono_aligned_addr_hash, NULL, MONO_HASH_VALUE_GC);
-                               mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_throw);
-                               mono_domain_unlock (domain);
-                       }
+               /* If the initialization failed, mark the class as unusable. */
+               /* Avoid infinite loops */
+               if (!(exc == NULL ||
+                         (klass->image == mono_defaults.corlib &&
+                          !strcmp (klass->name_space, "System") &&
+                          !strcmp (klass->name, "TypeInitializationException")))) {
+                       vtable->init_failed = 1;
 
-                       if (last_domain)
-                               mono_domain_set (last_domain, TRUE);
-                       lock->done = TRUE;
-                       mono_type_init_unlock (lock);
-               } else {
-                       /* this just blocks until the initializing thread is done */
-                       mono_type_init_lock (lock);
-                       mono_type_init_unlock (lock);
-               }
+                       if (klass->name_space && *klass->name_space)
+                               full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
+                       else
+                               full_name = g_strdup (klass->name);
+                       exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
+                       g_free (full_name);
 
-               mono_type_initialization_lock ();
-               if (lock->initializing_tid != tid)
-                       g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
-               --lock->waiting_count;
-               if (lock->waiting_count == 0) {
-                       mono_mutex_destroy (&lock->initialization_section);
-                       g_hash_table_remove (type_initialization_hash, vtable);
-                       g_free (lock);
+                       /*
+                        * Store the exception object so it could be thrown on subsequent
+                        * accesses.
+                        */
+                       mono_domain_lock (domain);
+                       if (!domain->type_init_exception_hash)
+                               domain->type_init_exception_hash = mono_g_hash_table_new_type (mono_aligned_addr_hash, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "type initialization exceptions table");
+                       mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_throw);
+                       mono_domain_unlock (domain);
                }
-               mono_memory_barrier ();
-               if (!vtable->init_failed)
-                       vtable->initialized = 1;
-               mono_type_initialization_unlock ();
 
-               if (vtable->init_failed) {
-                       /* Either we were the initializing thread or we waited for the initialization */
-                       if (raise_exception)
-                               mono_raise_exception (get_type_init_exception_for_vtable (vtable));
-                       return get_type_init_exception_for_vtable (vtable);
-               }
+               if (last_domain)
+                       mono_domain_set (last_domain, TRUE);
+               lock->done = TRUE;
+               mono_type_init_unlock (lock);
        } else {
+               /* this just blocks until the initializing thread is done */
+               mono_type_init_lock (lock);
+               mono_type_init_unlock (lock);
+       }
+
+       mono_type_initialization_lock ();
+       if (lock->initializing_tid != tid)
+               g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
+       --lock->waiting_count;
+       if (lock->waiting_count == 0) {
+               mono_mutex_destroy (&lock->initialization_section);
+               g_hash_table_remove (type_initialization_hash, vtable);
+               g_free (lock);
+       }
+       mono_memory_barrier ();
+       if (!vtable->init_failed)
                vtable->initialized = 1;
-               return NULL;
+       mono_type_initialization_unlock ();
+
+       if (vtable->init_failed) {
+               /* Either we were the initializing thread or we waited for the initialization */
+               if (raise_exception)
+                       mono_raise_exception (get_type_init_exception_for_vtable (vtable));
+               return get_type_init_exception_for_vtable (vtable);
        }
        return NULL;
 }
@@ -464,6 +460,8 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
 static
 gboolean release_type_locks (gpointer key, gpointer value, gpointer user)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        MonoVTable *vtable = (MonoVTable*)key;
 
        TypeInitializationLock *lock = (TypeInitializationLock*) value;
@@ -489,6 +487,8 @@ gboolean release_type_locks (gpointer key, gpointer value, gpointer user)
 void
 mono_release_type_locks (MonoInternalThread *thread)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        mono_type_initialization_lock ();
        g_hash_table_foreach_remove (type_initialization_hash, release_type_locks, (gpointer)(gsize)(thread->tid));
        mono_type_initialization_unlock ();
@@ -602,6 +602,8 @@ mono_install_compile_method (MonoCompileFunc func)
 gpointer 
 mono_compile_method (MonoMethod *method)
 {
+       MONO_REQ_GC_NEUTRAL_MODE
+
        if (!default_mono_compile_method) {
                g_error ("compile method called on uninitialized runtime");
                return NULL;
@@ -612,12 +614,16 @@ mono_compile_method (MonoMethod *method)
 gpointer
 mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper)
 {
+       MONO_REQ_GC_NEUTRAL_MODE
+
        return arch_create_jump_trampoline (domain, method, add_sync_wrapper);
 }
 
 gpointer
 mono_runtime_create_delegate_trampoline (MonoClass *klass)
 {
+       MONO_REQ_GC_NEUTRAL_MODE
+
        return arch_create_delegate_trampoline (mono_domain_get (), klass);
 }
 
@@ -652,6 +658,8 @@ mono_install_free_method (MonoFreeMethodFunc func)
 void
 mono_runtime_free_method (MonoDomain *domain, MonoMethod *method)
 {
+       MONO_REQ_GC_NEUTRAL_MODE
+
        if (default_mono_free_method != NULL)
                default_mono_free_method (domain, method);
 
@@ -673,6 +681,8 @@ mono_runtime_free_method (MonoDomain *domain, MonoMethod *method)
 static gsize*
 compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int *max_set, gboolean static_fields)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        MonoClassField *field;
        MonoClass *p;
        guint32 pos;
@@ -715,8 +725,8 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                        if (field->type->byref)
                                break;
 
-                       if (static_fields && field->offset == -1)
-                               /* special static */
+                       // Special static fields do not have a domain-level static slot
+                       if (static_fields && mono_class_field_is_special_static (field))
                                continue;
 
                        pos = field->offset / sizeof (gpointer);
@@ -797,6 +807,8 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
 gsize*
 mono_class_compute_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int *max_set, gboolean static_fields)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        return compute_class_bitmap (class, bitmap, size, offset, max_set, static_fields);
 }
 
@@ -945,12 +957,15 @@ mono_class_insecure_overlapping (MonoClass *klass)
 MonoString*
 mono_string_alloc (int length)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
        return mono_string_new_size (mono_domain_get (), length);
 }
 
 void
 mono_class_compute_gc_descriptor (MonoClass *class)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        int max_set = 0;
        gsize *bitmap;
        gsize default_bitmap [4] = {0};
@@ -959,26 +974,9 @@ mono_class_compute_gc_descriptor (MonoClass *class)
        if (!gcj_inited) {
                mono_loader_lock ();
 
-               mono_register_jit_icall (mono_object_new_ptrfree, "mono_object_new_ptrfree", mono_create_icall_signature ("object ptr"), FALSE);
-               mono_register_jit_icall (mono_object_new_ptrfree_box, "mono_object_new_ptrfree_box", mono_create_icall_signature ("object ptr"), FALSE);
                mono_register_jit_icall (mono_object_new_fast, "mono_object_new_fast", mono_create_icall_signature ("object ptr"), FALSE);
                mono_register_jit_icall (mono_string_alloc, "mono_string_alloc", mono_create_icall_signature ("object int"), FALSE);
 
-#ifdef HAVE_GC_GCJ_MALLOC
-               /* 
-                * This is not needed unless the relevant code in mono_get_allocation_ftn () is 
-                * turned on.
-                */
-#if 0
-#ifdef GC_REDIRECT_TO_LOCAL
-               mono_register_jit_icall (GC_local_gcj_malloc, "GC_local_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
-               mono_register_jit_icall (GC_local_gcj_fast_malloc, "GC_local_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
-#endif
-               mono_register_jit_icall (GC_gcj_malloc, "GC_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
-               mono_register_jit_icall (GC_gcj_fast_malloc, "GC_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
-#endif
-
-#endif
                gcj_inited = TRUE;
                mono_loader_unlock ();
        }
@@ -990,11 +988,11 @@ mono_class_compute_gc_descriptor (MonoClass *class)
                return;
 
        class->gc_descr_inited = TRUE;
-       class->gc_descr = GC_NO_DESCRIPTOR;
+       class->gc_descr = MONO_GC_DESCRIPTOR_NULL;
 
        bitmap = default_bitmap;
        if (class == mono_defaults.string_class) {
-               class->gc_descr = (gpointer)mono_gc_make_descr_for_string (bitmap, 2);
+               class->gc_descr = mono_gc_make_descr_for_string (bitmap, 2);
        } else if (class->rank) {
                mono_class_compute_gc_descriptor (class->element_class);
                if (MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg)) {
@@ -1016,9 +1014,9 @@ mono_class_compute_gc_descriptor (MonoClass *class)
                if (count++ > 58)
                        return;*/
                bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, FALSE);
-               class->gc_descr = (gpointer)mono_gc_make_descr_for_object (bitmap, max_set + 1, class->instance_size);
+               class->gc_descr = mono_gc_make_descr_for_object (bitmap, max_set + 1, class->instance_size);
                /*
-               if (class->gc_descr == GC_NO_DESCRIPTOR)
+               if (class->gc_descr == MONO_GC_DESCRIPTOR_NULL)
                        g_print ("disabling typed alloc (%d) for %s.%s\n", max_set, class->name_space, class->name);
                */
                /*printf ("new descriptor: %p 0x%x for %s.%s\n", class->gc_descr, bitmap [0], class->name_space, class->name);*/
@@ -1038,6 +1036,8 @@ mono_class_compute_gc_descriptor (MonoClass *class)
 static gint32
 field_is_special_static (MonoClass *fklass, MonoClassField *field)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        MonoCustomAttrInfo *ainfo;
        int i;
        ainfo = mono_custom_attrs_from_field (fklass, field);
@@ -1090,6 +1090,8 @@ field_is_special_static (MonoClass *fklass, MonoClassField *field)
 guint32
 mono_method_get_imt_slot (MonoMethod *method)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        MonoMethodSignature *sig;
        int hashes_count;
        guint32 *hashes_start, *hashes;
@@ -1162,6 +1164,8 @@ mono_method_get_imt_slot (MonoMethod *method)
 
 static void
 add_imt_builder_entry (MonoImtBuilderEntry **imt_builder, MonoMethod *method, guint32 *imt_collisions_bitmap, int vtable_slot, int slot_num) {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        guint32 imt_slot = mono_method_get_imt_slot (method);
        MonoImtBuilderEntry *entry;
 
@@ -1224,6 +1228,8 @@ compare_imt_builder_entries (const void *p1, const void *p2) {
 static int
 imt_emit_ir (MonoImtBuilderEntry **sorted_array, int start, int end, GPtrArray *out_array)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        int count = end - start;
        int chunk_start = out_array->len;
        if (count < 4) {
@@ -1255,6 +1261,8 @@ imt_emit_ir (MonoImtBuilderEntry **sorted_array, int start, int end, GPtrArray *
 
 static GPtrArray*
 imt_sort_slot_entries (MonoImtBuilderEntry *entries) {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        int number_of_entries = entries->children + 1;
        MonoImtBuilderEntry **sorted_array = malloc (sizeof (MonoImtBuilderEntry*) * number_of_entries);
        GPtrArray *result = g_ptr_array_new ();
@@ -1279,6 +1287,8 @@ imt_sort_slot_entries (MonoImtBuilderEntry *entries) {
 static gpointer
 initialize_imt_slot (MonoVTable *vtable, MonoDomain *domain, MonoImtBuilderEntry *imt_builder_entry, gpointer fail_tramp)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        if (imt_builder_entry != NULL) {
                if (imt_builder_entry->children == 0 && !fail_tramp) {
                        /* No collision, return the vtable slot contents */
@@ -1314,6 +1324,8 @@ get_generic_virtual_entries (MonoDomain *domain, gpointer *vtable_slot);
 static void
 build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer* imt, GSList *extra_interfaces, int slot_num)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        int i;
        GSList *list_item;
        guint32 imt_collisions_bitmap = 0;
@@ -1455,6 +1467,8 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
 
 static void
 build_imt (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer* imt, GSList *extra_interfaces) {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        build_imt_slots (klass, vt, domain, imt, extra_interfaces, -1);
 }
 
@@ -1472,6 +1486,8 @@ build_imt (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer* imt,
 void
 mono_vtable_build_imt_slot (MonoVTable* vtable, int imt_slot)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        gpointer *imt = (gpointer*)vtable;
        imt -= MONO_IMT_SIZE;
        g_assert (imt_slot >= 0 && imt_slot < MONO_IMT_SIZE);
@@ -1512,6 +1528,8 @@ mono_vtable_build_imt_slot (MonoVTable* vtable, int imt_slot)
 static void
 init_thunk_free_lists (MonoDomain *domain)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        if (domain->thunk_free_lists)
                return;
        domain->thunk_free_lists = mono_domain_alloc0 (domain, sizeof (gpointer) * NUM_FREE_LISTS);
@@ -1545,6 +1563,8 @@ list_index_for_size (int item_size)
 gpointer
 mono_method_alloc_generic_virtual_thunk (MonoDomain *domain, int size)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        static gboolean inited = FALSE;
        static int generic_virtual_thunks_size = 0;
 
@@ -1603,6 +1623,8 @@ mono_method_alloc_generic_virtual_thunk (MonoDomain *domain, int size)
 static void
 invalidate_generic_virtual_thunk (MonoDomain *domain, gpointer code)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        guint32 *p = code;
        MonoThunkFreeList *l = (MonoThunkFreeList*)(p - 1);
        gboolean found = FALSE;
@@ -1664,6 +1686,8 @@ typedef struct _GenericVirtualCase {
 static MonoImtBuilderEntry*
 get_generic_virtual_entries (MonoDomain *domain, gpointer *vtable_slot)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        GenericVirtualCase *list;
        MonoImtBuilderEntry *entries;
   
@@ -1713,6 +1737,8 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
                                                                                        gpointer *vtable_slot,
                                                                                        MonoMethod *method, gpointer code)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        static gboolean inited = FALSE;
        static int num_added = 0;
 
@@ -1824,6 +1850,8 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
 MonoVTable *
 mono_class_vtable_full (MonoDomain *domain, MonoClass *class, gboolean raise_on_error)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoClassRuntimeInfo *runtime_info;
 
        g_assert (class);
@@ -1852,6 +1880,8 @@ mono_class_vtable_full (MonoDomain *domain, MonoClass *class, gboolean raise_on_
 MonoVTable *
 mono_class_try_get_vtable (MonoDomain *domain, MonoClass *class)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        MonoClassRuntimeInfo *runtime_info;
 
        g_assert (class);
@@ -1865,6 +1895,8 @@ mono_class_try_get_vtable (MonoDomain *domain, MonoClass *class)
 static gpointer*
 alloc_vtable (MonoDomain *domain, size_t vtable_size, size_t imt_table_bytes)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        size_t alloc_offset;
 
        /*
@@ -1886,6 +1918,8 @@ alloc_vtable (MonoDomain *domain, size_t vtable_size, size_t imt_table_bytes)
 static MonoVTable *
 mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean raise_on_error)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoVTable *vt;
        MonoClassRuntimeInfo *runtime_info, *old_info;
        MonoClassField *field;
@@ -2000,7 +2034,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                 */
 #ifdef HAVE_BOEHM_GC
        if (domain != mono_get_root_domain () && !mono_dont_free_domains)
-               vt->gc_descr = GC_NO_DESCRIPTOR;
+               vt->gc_descr = MONO_GC_DESCRIPTOR_NULL;
        else
 #endif
                vt->gc_descr = class->gc_descr;
@@ -2013,7 +2047,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
        if (class_size) {
                /* we store the static field pointer at the end of the vtable: vt->vtable [class->vtable_size] */
                if (class->has_static_refs) {
-                       gpointer statics_gc_descr;
+                       MonoGCDescriptor statics_gc_descr;
                        int max_set = 0;
                        gsize default_bitmap [4] = {0};
                        gsize *bitmap;
@@ -2021,7 +2055,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                        bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, TRUE);
                        /*g_print ("bitmap 0x%x for %s.%s (size: %d)\n", bitmap [0], class->name_space, class->name, class_size);*/
                        statics_gc_descr = mono_gc_make_descr_from_bitmap (bitmap, max_set + 1);
-                       vt->vtable [class->vtable_size] = mono_gc_alloc_fixed (class_size, statics_gc_descr);
+                       vt->vtable [class->vtable_size] = mono_gc_alloc_fixed (class_size, statics_gc_descr, MONO_ROOT_SOURCE_STATIC, "managed static variables");
                        mono_domain_add_class_static_data (domain, class, vt->vtable [class->vtable_size], NULL);
                        if (bitmap != default_bitmap)
                                g_free (bitmap);
@@ -2137,7 +2171,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                        /* This is unregistered in
                           unregister_vtable_reflection_type() in
                           domain.c. */
-                       MONO_GC_REGISTER_ROOT_IF_MOVING(vt->type);
+                       MONO_GC_REGISTER_ROOT_IF_MOVING(vt->type, MONO_ROOT_SOURCE_REFLECTION, "vtable reflection type");
        }
 
        mono_vtable_set_is_remote (vt, mono_class_is_contextbound (class));
@@ -2191,16 +2225,12 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                        /* This is unregistered in
                           unregister_vtable_reflection_type() in
                           domain.c. */
-                       MONO_GC_REGISTER_ROOT_IF_MOVING(vt->type);
+                       MONO_GC_REGISTER_ROOT_IF_MOVING(vt->type, MONO_ROOT_SOURCE_REFLECTION, "vtable reflection type");
        }
 
        mono_domain_unlock (domain);
        mono_loader_unlock ();
 
-       /* Initialization is now complete, we can throw if the InheritanceDemand aren't satisfied */
-       if (mono_security_enabled () && (class->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) && raise_on_error)
-               mono_raise_exception (mono_class_get_exception_for_failure (class));
-
        /* make sure the parent is initialized */
        /*FIXME shouldn't this fail the current type?*/
        if (class->parent)
@@ -2223,6 +2253,8 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
 static MonoVTable *
 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRemotingTarget target_type)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoError error;
        MonoVTable *vt, *pvt;
        int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
@@ -2380,11 +2412,15 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
 gboolean
 mono_class_field_is_special_static (MonoClassField *field)
 {
+       MONO_REQ_GC_NEUTRAL_MODE
+
        if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
                return FALSE;
        if (mono_field_is_deleted (field))
                return FALSE;
        if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
+               if (field->offset == -1)
+                       return TRUE;
                if (field_is_special_static (field->parent, field) != SPECIAL_STATIC_NONE)
                        return TRUE;
        }
@@ -2401,6 +2437,8 @@ mono_class_field_is_special_static (MonoClassField *field)
 guint32
 mono_class_field_get_special_static_type (MonoClassField *field)
 {
+       MONO_REQ_GC_NEUTRAL_MODE
+
        if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
                return SPECIAL_STATIC_NONE;
        if (mono_field_is_deleted (field))
@@ -2418,6 +2456,8 @@ mono_class_field_get_special_static_type (MonoClassField *field)
 gboolean
 mono_class_has_special_static_fields (MonoClass *klass)
 {
+       MONO_REQ_GC_NEUTRAL_MODE
+
        MonoClassField *field;
        gpointer iter;
 
@@ -2440,6 +2480,8 @@ mono_class_has_special_static_fields (MonoClass *klass)
 static gpointer*
 create_remote_class_key (MonoRemoteClass *remote_class, MonoClass *extra_class)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        gpointer *key;
        int i, j;
        
@@ -2491,6 +2533,8 @@ create_remote_class_key (MonoRemoteClass *remote_class, MonoClass *extra_class)
 static gpointer*
 copy_remote_class_key (MonoDomain *domain, gpointer *key)
 {
+       MONO_REQ_GC_NEUTRAL_MODE
+
        int key_size = (GPOINTER_TO_UINT (key [0]) + 1) * sizeof (gpointer);
        gpointer *mp_key = mono_domain_alloc (domain, key_size);
 
@@ -2511,6 +2555,8 @@ copy_remote_class_key (MonoDomain *domain, gpointer *key)
 MonoRemoteClass*
 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoError error;
        MonoRemoteClass *rc;
        gpointer* key, *mp_key;
@@ -2569,6 +2615,8 @@ mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_
 static MonoRemoteClass*
 clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass *extra_class)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        MonoRemoteClass *rc;
        gpointer* key, *mp_key;
        
@@ -2619,6 +2667,8 @@ clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass
 gpointer
 mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *rp)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        mono_loader_lock (); /*FIXME mono_class_from_mono_type and mono_class_proxy_vtable take it*/
        mono_domain_lock (domain);
        if (rp->target_domain_id != -1) {
@@ -2659,6 +2709,8 @@ mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mon
 void
 mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoClass *klass)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoTransparentProxy *tproxy;
        MonoRemoteClass *remote_class;
        gboolean redo_vtable;
@@ -2702,6 +2754,8 @@ mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoCla
 MonoMethod*
 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoClass *klass;
        MonoMethod **vtable;
        gboolean is_proxy = FALSE;
@@ -2825,6 +2879,8 @@ static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
 MonoObject*
 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoObject *result;
 
        if (mono_runtime_get_no_exec ())
@@ -2894,13 +2950,24 @@ mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **
 gpointer
 mono_method_get_unmanaged_thunk (MonoMethod *method)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+       MONO_REQ_API_ENTRYPOINT;
+
+       gpointer res;
+
+       MONO_PREPARE_RESET_BLOCKING
        method = mono_marshal_get_thunk_invoke_wrapper (method);
-       return mono_compile_method (method);
+       res = mono_compile_method (method);
+       MONO_FINISH_RESET_BLOCKING
+
+       return res;
 }
 
 void
 mono_copy_value (MonoType *type, void *dest, void *value, int deref_pointer)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        int t;
        if (type->byref) {
                /* object fields cannot be byref, so we don't need a
@@ -3006,6 +3073,8 @@ handle_enum:
 void
 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        void *dest;
 
        g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
@@ -3027,6 +3096,8 @@ mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
 void
 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        void *dest;
 
        g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
@@ -3057,6 +3128,8 @@ mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
 void *
 mono_vtable_get_static_field_data (MonoVTable *vt)
 {
+       MONO_REQ_GC_NEUTRAL_MODE
+
        if (!vt->has_static_fields)
                return NULL;
        return vt->vtable [vt->klass->vtable_size];
@@ -3065,6 +3138,8 @@ mono_vtable_get_static_field_data (MonoVTable *vt)
 static guint8*
 mono_field_get_addr (MonoObject *obj, MonoVTable *vt, MonoClassField *field)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        guint8 *src;
 
        if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
@@ -3106,6 +3181,8 @@ mono_field_get_addr (MonoObject *obj, MonoVTable *vt, MonoClassField *field)
 void
 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        void *src;
 
        g_assert (obj);
@@ -3129,6 +3206,8 @@ mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
 MonoObject *
 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
 {      
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoObject *o;
        MonoClass *klass;
        MonoVTable *vtable = NULL;
@@ -3257,6 +3336,8 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
 int
 mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, const char *blob, void *value)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        int retval = 0;
        const char *p = blob;
        mono_metadata_decode_blob_size (p, &p);
@@ -3302,6 +3383,8 @@ mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, const
 static void
 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        MonoTypeEnum def_type;
        const char* data;
        
@@ -3312,6 +3395,8 @@ get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
 void
 mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *vt, MonoClassField *field, void *value)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        void *src;
 
        g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
@@ -3350,6 +3435,8 @@ mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *
 void
 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        mono_field_static_get_value_for_thread (mono_thread_internal_current (), vt, field, value);
 }
 
@@ -3371,6 +3458,8 @@ mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
 void
 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        default_mono_runtime_invoke (prop->set, obj, params, exc);
 }
 
@@ -3394,6 +3483,8 @@ mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObjec
 MonoObject*
 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return default_mono_runtime_invoke (prop->get, obj, params, exc);
 }
 
@@ -3414,6 +3505,8 @@ mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObjec
 void
 mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoClass *param_class = klass->cast_class;
 
        mono_class_setup_fields_locking (klass);
@@ -3444,6 +3537,8 @@ mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
 MonoObject*
 mono_nullable_box (guint8 *buf, MonoClass *klass)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoClass *param_class = klass->cast_class;
 
        mono_class_setup_fields_locking (klass);
@@ -3473,6 +3568,8 @@ mono_nullable_box (guint8 *buf, MonoClass *klass)
 MonoMethod *
 mono_get_delegate_invoke (MonoClass *klass)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        MonoMethod *im;
 
        /* This is called at runtime, so avoid the slower search in metadata */
@@ -3492,6 +3589,8 @@ mono_get_delegate_invoke (MonoClass *klass)
 MonoMethod *
 mono_get_delegate_begin_invoke (MonoClass *klass)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        MonoMethod *im;
 
        /* This is called at runtime, so avoid the slower search in metadata */
@@ -3511,6 +3610,8 @@ mono_get_delegate_begin_invoke (MonoClass *klass)
 MonoMethod *
 mono_get_delegate_end_invoke (MonoClass *klass)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        MonoMethod *im;
 
        /* This is called at runtime, so avoid the slower search in metadata */
@@ -3537,6 +3638,8 @@ mono_get_delegate_end_invoke (MonoClass *klass)
 MonoObject*
 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoMethod *im;
        MonoClass *klass = delegate->vtable->klass;
 
@@ -3558,6 +3661,8 @@ static int num_main_args = 0;
 MonoArray*
 mono_runtime_get_main_args (void)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoArray *res;
        int i;
        MonoDomain *domain = mono_domain_get ();
@@ -3573,6 +3678,8 @@ mono_runtime_get_main_args (void)
 static void
 free_main_args (void)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        int i;
 
        for (i = 0; i < num_main_args; ++i)
@@ -3593,6 +3700,8 @@ free_main_args (void)
 int
 mono_runtime_set_main_args (int argc, char* argv[])
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        int i;
 
        free_main_args ();
@@ -3632,6 +3741,8 @@ int
 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
                       MonoObject **exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        int i;
        MonoArray *args = NULL;
        MonoDomain *domain = mono_domain_get ();
@@ -3751,6 +3862,8 @@ serialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 static MonoObject*
 deserialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        static MonoMethod *deserialize_method;
 
        void *params [1];
@@ -3778,6 +3891,8 @@ deserialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 static MonoObject*
 make_transparent_proxy (MonoObject *obj, gboolean *failure, MonoObject **exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        static MonoMethod *get_proxy_method;
 
        MonoDomain *domain = mono_domain_get ();
@@ -3822,6 +3937,8 @@ make_transparent_proxy (MonoObject *obj, gboolean *failure, MonoObject **exc)
 MonoObject*
 mono_object_xdomain_representation (MonoObject *obj, MonoDomain *target_domain, MonoObject **exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoObject *deserialized = NULL;
        gboolean failure = FALSE;
 
@@ -3853,6 +3970,8 @@ mono_object_xdomain_representation (MonoObject *obj, MonoDomain *target_domain,
 static MonoObject *
 create_unhandled_exception_eventargs (MonoObject *exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoClass *klass;
        gpointer args [2];
        MonoMethod *method = NULL;
@@ -3880,6 +3999,8 @@ create_unhandled_exception_eventargs (MonoObject *exc)
 /* Used in mono_unhandled_exception */
 static void
 call_unhandled_exception_delegate (MonoDomain *domain, MonoObject *delegate, MonoObject *exc) {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoObject *e = NULL;
        gpointer pa [2];
        MonoDomain *current_domain = mono_domain_get ();
@@ -3969,6 +4090,8 @@ mono_runtime_unhandled_exception_policy_get (void) {
 void
 mono_unhandled_exception (MonoObject *exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoDomain *current_domain = mono_domain_get ();
        MonoDomain *root_domain = mono_get_root_domain ();
        MonoClassField *field;
@@ -4038,6 +4161,8 @@ mono_runtime_exec_managed_code (MonoDomain *domain,
 int
 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoDomain *domain;
        gpointer pa [1];
        int rval;
@@ -4169,6 +4294,8 @@ MonoObject*
 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                           MonoObject **exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoMethodSignature *sig = mono_method_signature (method);
        gpointer *pa = NULL;
        MonoObject *res;
@@ -4346,51 +4473,9 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
 static void
 arith_overflow (void)
 {
-       mono_raise_exception (mono_get_exception_overflow ());
-}
-
-/**
- * mono_object_allocate:
- * @size: number of bytes to allocate
- *
- * This is a very simplistic routine until we have our GC-aware
- * memory allocator. 
- *
- * Returns: an allocated object of size @size, or NULL on failure.
- */
-static inline void *
-mono_object_allocate (size_t size, MonoVTable *vtable)
-{
-       MonoObject *o;
-       ALLOC_OBJECT (o, vtable, size);
-
-       return o;
-}
-
-#ifndef HAVE_SGEN_GC
-/**
- * mono_object_allocate_ptrfree:
- * @size: number of bytes to allocate
- *
- * Note that the memory allocated is not zeroed.
- * Returns: an allocated object of size @size, or NULL on failure.
- */
-static inline void *
-mono_object_allocate_ptrfree (size_t size, MonoVTable *vtable)
-{
-       MonoObject *o;
-       ALLOC_PTRFREE (o, vtable, size);
-       return o;
-}
-#endif
-
-static inline void *
-mono_object_allocate_spec (size_t size, MonoVTable *vtable)
-{
-       void *o;
-       ALLOC_TYPED (o, size, vtable);
+       MONO_REQ_GC_UNSAFE_MODE;
 
-       return o;
+       mono_raise_exception (mono_get_exception_overflow ());
 }
 
 /**
@@ -4407,6 +4492,8 @@ mono_object_allocate_spec (size_t size, MonoVTable *vtable)
 MonoObject *
 mono_object_new (MonoDomain *domain, MonoClass *klass)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoVTable *vtable;
 
        vtable = mono_class_vtable (domain, klass);
@@ -4424,6 +4511,8 @@ mono_object_new (MonoDomain *domain, MonoClass *klass)
 MonoObject *
 mono_object_new_pinned (MonoDomain *domain, MonoClass *klass)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoVTable *vtable;
 
        vtable = mono_class_vtable (domain, klass);
@@ -4447,6 +4536,8 @@ mono_object_new_pinned (MonoDomain *domain, MonoClass *klass)
 MonoObject *
 mono_object_new_specific (MonoVTable *vtable)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoObject *o;
 
        /* check for is_com_object for COM Interop */
@@ -4462,7 +4553,8 @@ mono_object_new_specific (MonoVTable *vtable)
                                mono_class_init (klass);
 
                        im = mono_class_get_method_from_name (klass, "CreateProxyForType", 1);
-                       g_assert (im);
+                       if (!im)
+                               mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
                        vtable->domain->create_proxy_for_type_method = im;
                }
        
@@ -4478,63 +4570,22 @@ mono_object_new_specific (MonoVTable *vtable)
 MonoObject *
 mono_object_new_alloc_specific (MonoVTable *vtable)
 {
-       MonoObject *o;
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       MonoObject *o = mono_gc_alloc_obj (vtable, vtable->klass->instance_size);
 
-       if (!vtable->klass->has_references) {
-               o = mono_object_new_ptrfree (vtable);
-       } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
-               o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
-       } else {
-/*             printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
-               o = mono_object_allocate (vtable->klass->instance_size, vtable);
-       }
        if (G_UNLIKELY (vtable->klass->has_finalize))
                mono_object_register_finalizer (o);
-       
-       if (G_UNLIKELY (profile_allocs))
-               mono_profiler_allocation (o, vtable->klass);
+
        return o;
 }
 
 MonoObject*
 mono_object_new_fast (MonoVTable *vtable)
 {
-       MonoObject *o;
-       ALLOC_TYPED (o, vtable->klass->instance_size, vtable);
-       return o;
-}
+       MONO_REQ_GC_UNSAFE_MODE;
 
-static MonoObject*
-mono_object_new_ptrfree (MonoVTable *vtable)
-{
-       MonoObject *obj;
-       ALLOC_PTRFREE (obj, vtable, vtable->klass->instance_size);
-#if NEED_TO_ZERO_PTRFREE
-       /* an inline memset is much faster for the common vcase of small objects
-        * note we assume the allocated size is a multiple of sizeof (void*).
-        */
-       if (vtable->klass->instance_size < 128) {
-               gpointer *p, *end;
-               end = (gpointer*)((char*)obj + vtable->klass->instance_size);
-               p = (gpointer*)((char*)obj + sizeof (MonoObject));
-               while (p < end) {
-                       *p = NULL;
-                       ++p;
-               }
-       } else {
-               memset ((char*)obj + sizeof (MonoObject), 0, vtable->klass->instance_size - sizeof (MonoObject));
-       }
-#endif
-       return obj;
-}
-
-static MonoObject*
-mono_object_new_ptrfree_box (MonoVTable *vtable)
-{
-       MonoObject *obj;
-       ALLOC_PTRFREE (obj, vtable, vtable->klass->instance_size);
-       /* the object will be boxed right away, no need to memzero it */
-       return obj;
+       return mono_gc_alloc_obj (vtable, vtable->klass->instance_size);
 }
 
 /**
@@ -4549,22 +4600,14 @@ mono_object_new_ptrfree_box (MonoVTable *vtable)
 void*
 mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *pass_size_in_words)
 {
-       *pass_size_in_words = FALSE;
+       MONO_REQ_GC_NEUTRAL_MODE;
 
-       if (!(mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
-               profile_allocs = FALSE;
+       *pass_size_in_words = FALSE;
 
        if (mono_class_has_finalizer (vtable->klass) || mono_class_is_marshalbyref (vtable->klass) || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
                return mono_object_new_specific;
 
-       if (!vtable->klass->has_references) {
-               //g_print ("ptrfree for %s.%s\n", vtable->klass->name_space, vtable->klass->name);
-               if (for_box)
-                       return mono_object_new_ptrfree_box;
-               return mono_object_new_ptrfree;
-       }
-
-       if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
+       if (vtable->gc_descr != MONO_GC_DESCRIPTOR_NULL) {
 
                return mono_object_new_fast;
 
@@ -4596,6 +4639,8 @@ mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *p
 MonoObject *
 mono_object_new_from_token  (MonoDomain *domain, MonoImage *image, guint32 token)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoError error;
        MonoClass *class;
 
@@ -4615,23 +4660,18 @@ mono_object_new_from_token  (MonoDomain *domain, MonoImage *image, guint32 token
 MonoObject *
 mono_object_clone (MonoObject *obj)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoObject *o;
        int size = obj->vtable->klass->instance_size;
 
        if (obj->vtable->klass->rank)
                return (MonoObject*)mono_array_clone ((MonoArray*)obj);
 
-       o = mono_object_allocate (size, obj->vtable);
+       o = mono_gc_alloc_obj (obj->vtable, size);
 
-       if (obj->vtable->klass->has_references) {
-               mono_gc_wbarrier_object_copy (o, obj);
-       } else {
-               int size = obj->vtable->klass->instance_size;
-               /* do not copy the sync state */
-               mono_gc_memmove_atomic ((char*)o + sizeof (MonoObject), (char*)obj + sizeof (MonoObject), size - sizeof (MonoObject));
-       }
-       if (G_UNLIKELY (profile_allocs))
-               mono_profiler_allocation (o, obj->vtable->klass);
+       /* If the object doesn't contain references this will do a simple memmove. */
+       mono_gc_wbarrier_object_copy (o, obj);
 
        if (obj->vtable->klass->has_finalize)
                mono_object_register_finalizer (o);
@@ -4648,6 +4688,8 @@ mono_object_clone (MonoObject *obj)
 void
 mono_array_full_copy (MonoArray *src, MonoArray *dest)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        uintptr_t size;
        MonoClass *klass = src->obj.vtable->klass;
 
@@ -4681,6 +4723,8 @@ mono_array_full_copy (MonoArray *src, MonoArray *dest)
 MonoArray*
 mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoArray *o;
        uintptr_t size, i;
        uintptr_t *sizes;
@@ -4739,6 +4783,8 @@ mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
 MonoArray*
 mono_array_clone (MonoArray *array)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return mono_array_clone_in_domain (((MonoObject *)array)->vtable->domain, array);
 }
 
@@ -4764,6 +4810,8 @@ mono_array_clone (MonoArray *array)
 gboolean
 mono_array_calc_byte_len (MonoClass *class, uintptr_t len, uintptr_t *res)
 {
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        uintptr_t byte_len;
 
        byte_len = mono_array_element_size (class);
@@ -4792,6 +4840,8 @@ mono_array_calc_byte_len (MonoClass *class, uintptr_t len, uintptr_t *res)
 MonoArray*
 mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *lengths, intptr_t *lower_bounds)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        uintptr_t byte_len = 0, len, bounds_size;
        MonoObject *o;
        MonoArray *array;
@@ -4839,26 +4889,6 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *leng
         * they need to be kept in sync.
         */
        vtable = mono_class_vtable_full (domain, array_class, TRUE);
-#ifndef HAVE_SGEN_GC
-       if (!array_class->has_references) {
-               o = mono_object_allocate_ptrfree (byte_len, vtable);
-#if NEED_TO_ZERO_PTRFREE
-               memset ((char*)o + sizeof (MonoObject), 0, byte_len - sizeof (MonoObject));
-#endif
-       } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
-               o = mono_object_allocate_spec (byte_len, vtable);
-       }else {
-               o = mono_object_allocate (byte_len, vtable);
-       }
-
-       array = (MonoArray*)o;
-       array->max_length = len;
-
-       if (bounds_size) {
-               bounds = (MonoArrayBounds*)((char*)array + byte_len - bounds_size);
-               array->bounds = bounds;
-       }
-#else
        if (bounds_size)
                o = mono_gc_alloc_array (vtable, byte_len, len, bounds_size);
        else
@@ -4866,7 +4896,6 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *leng
        array = (MonoArray*)o;
 
        bounds = array->bounds;
-#endif
 
        if (bounds_size) {
                for (i = 0; i < array_class->rank; ++i) {
@@ -4876,9 +4905,6 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *leng
                }
        }
 
-       if (G_UNLIKELY (profile_allocs))
-               mono_profiler_allocation (o, array_class);
-
        return array;
 }
 
@@ -4893,6 +4919,8 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *leng
 MonoArray *
 mono_array_new (MonoDomain *domain, MonoClass *eclass, uintptr_t n)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoClass *ac;
 
        ac = mono_array_class_get (eclass, 1);
@@ -4912,6 +4940,8 @@ mono_array_new (MonoDomain *domain, MonoClass *eclass, uintptr_t n)
 MonoArray *
 mono_array_new_specific (MonoVTable *vtable, uintptr_t n)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoObject *o;
        MonoArray *ao;
        uintptr_t byte_len;
@@ -4925,29 +4955,8 @@ mono_array_new_specific (MonoVTable *vtable, uintptr_t n)
                mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE);
                return NULL;
        }
-#ifndef HAVE_SGEN_GC
-       if (!vtable->klass->has_references) {
-               o = mono_object_allocate_ptrfree (byte_len, vtable);
-#if NEED_TO_ZERO_PTRFREE
-               ((MonoArray*)o)->bounds = NULL;
-               memset ((char*)o + sizeof (MonoObject), 0, byte_len - sizeof (MonoObject));
-#endif
-       } else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
-               o = mono_object_allocate_spec (byte_len, vtable);
-       } else {
-/*             printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
-               o = mono_object_allocate (byte_len, vtable);
-       }
-
-       ao = (MonoArray *)o;
-       ao->max_length = n;
-#else
        o = mono_gc_alloc_vector (vtable, byte_len, n);
        ao = (MonoArray*)o;
-#endif
-
-       if (G_UNLIKELY (profile_allocs))
-               mono_profiler_allocation (o, vtable->klass);
 
        return ao;
 }
@@ -4962,6 +4971,8 @@ mono_array_new_specific (MonoVTable *vtable, uintptr_t n)
 MonoString *
 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoString *s;
        
        s = mono_string_new_size (domain, len);
@@ -4982,6 +4993,8 @@ mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
 MonoString *
 mono_string_new_utf32 (MonoDomain *domain, const mono_unichar4 *text, gint32 len)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoString *s;
        mono_unichar2 *utf16_output = NULL;
        gint32 utf16_len = 0;
@@ -5015,6 +5028,8 @@ mono_string_new_utf32 (MonoDomain *domain, const mono_unichar4 *text, gint32 len
 MonoString *
 mono_string_new_size (MonoDomain *domain, gint32 len)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoString *s;
        MonoVTable *vtable;
        size_t size;
@@ -5029,18 +5044,7 @@ mono_string_new_size (MonoDomain *domain, gint32 len)
        vtable = mono_class_vtable (domain, mono_defaults.string_class);
        g_assert (vtable);
 
-#ifndef HAVE_SGEN_GC
-       s = mono_object_allocate_ptrfree (size, vtable);
-
-       s->length = len;
-#else
        s = mono_gc_alloc_string (vtable, size, len);
-#endif
-#if NEED_TO_ZERO_PTRFREE
-       s->chars [len] = 0;
-#endif
-       if (G_UNLIKELY (profile_allocs))
-               mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
 
        return s;
 }
@@ -5055,6 +5059,8 @@ mono_string_new_size (MonoDomain *domain, gint32 len)
 MonoString*
 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        GError *error = NULL;
        MonoString *o = NULL;
        guint16 *ut;
@@ -5081,6 +5087,8 @@ mono_string_new_len (MonoDomain *domain, const char *text, guint length)
 MonoString*
 mono_string_new (MonoDomain *domain, const char *text)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
     GError *error = NULL;
     MonoString *o = NULL;
     guint16 *ut;
@@ -5128,6 +5136,8 @@ mono_string_new (MonoDomain *domain, const char *text)
 MonoString*
 mono_string_new_wrapper (const char *text)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoDomain *domain = mono_domain_get ();
 
        if (text)
@@ -5146,6 +5156,8 @@ mono_string_new_wrapper (const char *text)
 MonoObject *
 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoObject *res;
        int size;
        MonoVTable *vtable;
@@ -5159,8 +5171,6 @@ mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
                return NULL;
        size = mono_class_instance_size (class);
        res = mono_object_new_alloc_specific (vtable);
-       if (G_UNLIKELY (profile_allocs))
-               mono_profiler_allocation (res, class);
 
        size = size - sizeof (MonoObject);
 
@@ -5206,6 +5216,8 @@ mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
 void
 mono_value_copy (gpointer dest, gpointer src, MonoClass *klass)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        mono_gc_wbarrier_value_copy (dest, src, 1, klass);
 }
 
@@ -5223,6 +5235,8 @@ mono_value_copy (gpointer dest, gpointer src, MonoClass *klass)
 void
 mono_value_copy_array (MonoArray *dest, int dest_idx, gpointer src, int count)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        int size = mono_array_element_size (dest->obj.vtable->klass);
        char *d = mono_array_addr_with_size_fast (dest, size, dest_idx);
        g_assert (size == mono_class_value_size (mono_object_class (dest)->element_class, NULL));
@@ -5238,6 +5252,8 @@ mono_value_copy_array (MonoArray *dest, int dest_idx, gpointer src, int count)
 MonoDomain*
 mono_object_get_domain (MonoObject *obj)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return mono_object_domain (obj);
 }
 
@@ -5250,6 +5266,8 @@ mono_object_get_domain (MonoObject *obj)
 MonoClass*
 mono_object_get_class (MonoObject *obj)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return mono_object_class (obj);
 }
 /**
@@ -5261,6 +5279,8 @@ mono_object_get_class (MonoObject *obj)
 guint
 mono_object_get_size (MonoObject* o)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoClass* klass = mono_object_class (o);
        if (klass == mono_defaults.string_class) {
                return sizeof (MonoString) + 2 * mono_string_length ((MonoString*) o) + 2;
@@ -5290,6 +5310,8 @@ mono_object_get_size (MonoObject* o)
 gpointer
 mono_object_unbox (MonoObject *obj)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        /* add assert for valuetypes? */
        g_assert (obj->vtable->klass->valuetype);
        return ((char*)obj) + sizeof (MonoObject);
@@ -5305,6 +5327,8 @@ mono_object_unbox (MonoObject *obj)
 MonoObject *
 mono_object_isinst (MonoObject *obj, MonoClass *klass)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        if (!klass->inited)
                mono_class_init (klass);
 
@@ -5320,6 +5344,8 @@ mono_object_isinst (MonoObject *obj, MonoClass *klass)
 MonoObject *
 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoVTable *vt;
 
        if (!obj)
@@ -5355,6 +5381,8 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
                gpointer pa [2];
 
                im = mono_class_get_method_from_name (rpklass, "CanCastTo", -1);
+               if (!im)
+                       mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
                im = mono_object_get_virtual_method (rp, im);
                g_assert (im);
        
@@ -5383,6 +5411,8 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
 MonoObject *
 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        if (!obj) return NULL;
        if (mono_object_isinst_mbyref (obj, klass)) return obj;
                
@@ -5401,6 +5431,8 @@ typedef struct {
 static void
 str_lookup (MonoDomain *domain, gpointer user_data)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        LDStrInfo *info = user_data;
        if (info->res || domain == info->orig_domain)
                return;
@@ -5412,6 +5444,8 @@ str_lookup (MonoDomain *domain, gpointer user_data)
 static MonoString*
 mono_string_get_pinned (MonoString *str)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        int size;
        MonoString *news;
        size = sizeof (MonoString) + 2 * (mono_string_length (str) + 1);
@@ -5430,6 +5464,8 @@ mono_string_get_pinned (MonoString *str)
 static MonoString*
 mono_string_is_interned_lookup (MonoString *str, int insert)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoGHashTable *ldstr_table;
        MonoString *s, *res;
        MonoDomain *domain;
@@ -5487,6 +5523,8 @@ mono_string_is_interned_lookup (MonoString *str, int insert)
 MonoString*
 mono_string_is_interned (MonoString *o)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return mono_string_is_interned_lookup (o, FALSE);
 }
 
@@ -5500,6 +5538,8 @@ mono_string_is_interned (MonoString *o)
 MonoString*
 mono_string_intern (MonoString *str)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return mono_string_is_interned_lookup (str, TRUE);
 }
 
@@ -5515,6 +5555,8 @@ mono_string_intern (MonoString *str)
 MonoString*
 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        if (image->dynamic) {
                MonoString *str = mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL);
                return str;
@@ -5535,6 +5577,8 @@ mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
 static MonoString*
 mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        const char *str = sig;
        MonoString *o, *interned;
        size_t len2;
@@ -5585,6 +5629,8 @@ mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig)
 char *
 mono_string_to_utf8 (MonoString *s)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoError error;
        char *result = mono_string_to_utf8_checked (s, &error);
        
@@ -5605,6 +5651,8 @@ mono_string_to_utf8 (MonoString *s)
 char *
 mono_string_to_utf8_checked (MonoString *s, MonoError *error)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        long written = 0;
        char *as;
        GError *gerror = NULL;
@@ -5647,6 +5695,8 @@ mono_string_to_utf8_checked (MonoString *s, MonoError *error)
 char *
 mono_string_to_utf8_ignore (MonoString *s)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        long written = 0;
        char *as;
 
@@ -5679,6 +5729,8 @@ mono_string_to_utf8_ignore (MonoString *s)
 char *
 mono_string_to_utf8_image_ignore (MonoImage *image, MonoString *s)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return mono_string_to_utf8_internal (NULL, image, s, TRUE, NULL);
 }
 
@@ -5691,6 +5743,8 @@ mono_string_to_utf8_image_ignore (MonoImage *image, MonoString *s)
 char *
 mono_string_to_utf8_mp_ignore (MonoMemPool *mp, MonoString *s)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return mono_string_to_utf8_internal (mp, NULL, s, TRUE, NULL);
 }
 
@@ -5707,6 +5761,8 @@ mono_string_to_utf8_mp_ignore (MonoMemPool *mp, MonoString *s)
 mono_unichar2*
 mono_string_to_utf16 (MonoString *s)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        char *as;
 
        if (s == NULL)
@@ -5734,6 +5790,8 @@ mono_string_to_utf16 (MonoString *s)
 mono_unichar4*
 mono_string_to_utf32 (MonoString *s)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        mono_unichar4 *utf32_output = NULL; 
        GError *error = NULL;
        glong items_written;
@@ -5760,6 +5818,8 @@ mono_string_to_utf32 (MonoString *s)
 MonoString *
 mono_string_from_utf16 (gunichar2 *data)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoDomain *domain = mono_domain_get ();
        int len = 0;
 
@@ -5782,6 +5842,8 @@ mono_string_from_utf16 (gunichar2 *data)
 MonoString *
 mono_string_from_utf32 (mono_unichar4 *data)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoString* result = NULL;
        mono_unichar2 *utf16_output = NULL;
        GError *error = NULL;
@@ -5806,6 +5868,8 @@ mono_string_from_utf32 (mono_unichar4 *data)
 static char *
 mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, gboolean ignore_error, MonoError *error)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        char *r;
        char *mp_s;
        int len;
@@ -5843,6 +5907,8 @@ mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s,
 char *
 mono_string_to_utf8_image (MonoImage *image, MonoString *s, MonoError *error)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return mono_string_to_utf8_internal (NULL, image, s, FALSE, error);
 }
 
@@ -5855,6 +5921,8 @@ mono_string_to_utf8_image (MonoImage *image, MonoString *s, MonoError *error)
 char *
 mono_string_to_utf8_mp (MonoMemPool *mp, MonoString *s, MonoError *error)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return mono_string_to_utf8_internal (mp, NULL, s, FALSE, error);
 }
 
@@ -5882,6 +5950,8 @@ mono_get_eh_callbacks (void)
 void
 mono_raise_exception (MonoException *ex) 
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        /*
         * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
         * that will cause gcc to omit the function epilog, causing problems when
@@ -5894,6 +5964,8 @@ mono_raise_exception (MonoException *ex)
 void
 mono_raise_exception_with_context (MonoException *ex, MonoContext *ctx) 
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        eh_callbacks.mono_raise_exception_with_ctx (ex, ctx);
 }
 
@@ -5907,6 +5979,8 @@ mono_raise_exception_with_context (MonoException *ex, MonoContext *ctx)
 MonoWaitHandle *
 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoWaitHandle *res;
        gpointer params [1];
        static MonoMethod *handle_set;
@@ -5926,6 +6000,8 @@ mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
 HANDLE
 mono_wait_handle_get_handle (MonoWaitHandle *handle)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        static MonoClassField *f_os_handle;
        static MonoClassField *f_safe_handle;
 
@@ -5949,6 +6025,8 @@ mono_wait_handle_get_handle (MonoWaitHandle *handle)
 static MonoObject*
 mono_runtime_capture_context (MonoDomain *domain)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        RuntimeInvokeFunction runtime_invoke;
 
        if (!domain->capture_context_runtime_invoke || !domain->capture_context_method) {
@@ -5979,6 +6057,8 @@ mono_runtime_capture_context (MonoDomain *domain)
 MonoAsyncResult *
 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data, MonoObject *object_data)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
        MonoObject *context = mono_runtime_capture_context (domain);
        /* we must capture the execution context from the original thread */
@@ -6000,39 +6080,25 @@ mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpo
 }
 
 MonoObject *
-mono_async_result_invoke (MonoAsyncResult *ares, MonoObject **exc)
+ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult *ares)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoAsyncCall *ac;
        MonoObject *res;
-       MonoInternalThread *thread;
 
        g_assert (ares);
        g_assert (ares->async_delegate);
 
-       thread = mono_thread_internal_current ();
-
-       if (!ares->execution_context) {
-               ares->original_context = NULL;
-       } else {
-               /* use captured ExecutionContext (if available) */
-               MONO_OBJECT_SETREF (ares, original_context, mono_thread_get_execution_context ());
-               mono_thread_set_execution_context (ares->execution_context);
-       }
-
        ac = (MonoAsyncCall*) ares->object_data;
        if (!ac) {
-               thread->async_invoke_method = ((MonoDelegate*) ares->async_delegate)->method;
-               res = mono_runtime_delegate_invoke (ares->async_delegate, (void**) &ares->async_state, exc);
-               thread->async_invoke_method = NULL;
+               res = mono_runtime_delegate_invoke (ares->async_delegate, (void**) &ares->async_state, NULL);
        } else {
-               MonoArray *out_args = NULL;
                gpointer wait_event = NULL;
 
                ac->msg->exc = NULL;
-               res = mono_message_invoke (ares->async_delegate, ac->msg, exc, &out_args);
-               MONO_OBJECT_SETREF (ac->msg, exc, *exc);
+               res = mono_message_invoke (ares->async_delegate, ac->msg, &ac->msg->exc, &ac->out_args);
                MONO_OBJECT_SETREF (ac, res, res);
-               MONO_OBJECT_SETREF (ac, out_args, out_args);
 
                mono_monitor_enter ((MonoObject*) ares);
                ares->completed = 1;
@@ -6043,40 +6109,26 @@ mono_async_result_invoke (MonoAsyncResult *ares, MonoObject **exc)
                if (wait_event != NULL)
                        SetEvent (wait_event);
 
-               if (!ac->cb_method) {
-                       *exc = NULL;
-               } else {
-                       thread->async_invoke_method = ac->cb_method;
-                       mono_runtime_invoke (ac->cb_method, ac->cb_target, (gpointer*) &ares, exc);
-                       thread->async_invoke_method = NULL;
+               if (ac->cb_method) {
+                       /* we swallow the excepton as it is the behavior on .NET */
+                       MonoObject *exc = NULL;
+                       mono_runtime_invoke (ac->cb_method, ac->cb_target, (gpointer*) &ares, &exc);
+                       if (exc)
+                               mono_unhandled_exception (exc);
                }
        }
 
-       /* restore original thread execution context if flow isn't suppressed, i.e. non null */
-       if (ares->original_context) {
-               mono_thread_set_execution_context (ares->original_context);
-               ares->original_context = NULL;
-       }
-
-       return res;
-}
-
-MonoObject *
-ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult *this)
-{
-       MonoObject *exc = NULL;
-       MonoObject *res = mono_async_result_invoke (this, &exc);
-       if (exc)
-               mono_raise_exception ((MonoException*) exc);
        return res;
 }
 
 void
 mono_message_init (MonoDomain *domain,
-                  MonoMethodMessage *this, 
+                  MonoMethodMessage *this_obj
                   MonoReflectionMethod *method,
                   MonoArray *out_args)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        static MonoClass *object_array_klass;
        static MonoClass *byte_array_klass;
        static MonoClass *string_array_klass;
@@ -6103,20 +6155,20 @@ mono_message_init (MonoDomain *domain,
                mono_atomic_store_release (&object_array_klass, klass);
        }
 
-       MONO_OBJECT_SETREF (this, method, method);
+       MONO_OBJECT_SETREF (this_obj, method, method);
 
-       MONO_OBJECT_SETREF (this, args, mono_array_new_specific (mono_class_vtable (domain, object_array_klass), sig->param_count));
-       MONO_OBJECT_SETREF (this, arg_types, mono_array_new_specific (mono_class_vtable (domain, byte_array_klass), sig->param_count));
-       this->async_result = NULL;
-       this->call_type = CallType_Sync;
+       MONO_OBJECT_SETREF (this_obj, args, mono_array_new_specific (mono_class_vtable (domain, object_array_klass), sig->param_count));
+       MONO_OBJECT_SETREF (this_obj, arg_types, mono_array_new_specific (mono_class_vtable (domain, byte_array_klass), sig->param_count));
+       this_obj->async_result = NULL;
+       this_obj->call_type = CallType_Sync;
 
        names = g_new (char *, sig->param_count);
        mono_method_get_param_names (method->method, (const char **) names);
-       MONO_OBJECT_SETREF (this, names, mono_array_new_specific (mono_class_vtable (domain, string_array_klass), sig->param_count));
+       MONO_OBJECT_SETREF (this_obj, names, mono_array_new_specific (mono_class_vtable (domain, string_array_klass), sig->param_count));
        
        for (i = 0; i < sig->param_count; i++) {
                name = mono_string_new (domain, names [i]);
-               mono_array_setref (this->names, i, name);       
+               mono_array_setref (this_obj->names, i, name);   
        }
 
        g_free (names);
@@ -6124,7 +6176,7 @@ mono_message_init (MonoDomain *domain,
                if (sig->params [i]->byref) {
                        if (out_args) {
                                MonoObject* arg = mono_array_get (out_args, gpointer, j);
-                               mono_array_setref (this->args, i, arg);
+                               mono_array_setref (this_obj->args, i, arg);
                                j++;
                        }
                        arg_type = 2;
@@ -6135,7 +6187,7 @@ mono_message_init (MonoDomain *domain,
                        if (sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT)
                                arg_type |= 4;
                }
-               mono_array_set (this->arg_types, guint8, i, arg_type);
+               mono_array_set (this_obj->arg_types, guint8, i, arg_type);
        }
 }
 
@@ -6158,6 +6210,8 @@ MonoObject *
 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, 
                      MonoObject **exc, MonoArray **out_args)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
        gpointer pa [4];
 
@@ -6165,7 +6219,8 @@ mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
 
        if (!im) {
                im = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "PrivateInvoke", 4);
-               g_assert (im);
+               if (!im)
+                       mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
                real_proxy->vtable->domain->private_invoke_method = im;
        }
 
@@ -6182,6 +6237,8 @@ MonoObject *
 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, 
                     MonoObject **exc, MonoArray **out_args) 
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        static MonoClass *object_array_klass;
        MonoDomain *domain; 
        MonoMethod *method;
@@ -6219,8 +6276,7 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
                object_array_klass = klass;
        }
 
-       /* FIXME: GC ensure we insert a write barrier for out_args, maybe in the caller? */
-       *out_args = mono_array_new_specific (mono_class_vtable (domain, object_array_klass), outarg_count);
+       mono_gc_wbarrier_generic_store (out_args, (MonoObject*) mono_array_new_specific (mono_class_vtable (domain, object_array_klass), outarg_count));
        *exc = NULL;
 
        ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
@@ -6247,6 +6303,8 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
 MonoString *
 mono_object_to_string (MonoObject *obj, MonoObject **exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        static MonoMethod *to_string = NULL;
        MonoMethod *method;
        void *target = obj;
@@ -6275,6 +6333,8 @@ mono_object_to_string (MonoObject *obj, MonoObject **exc)
 void
 mono_print_unhandled_exception (MonoObject *exc)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoString * str;
        char *message = (char*)"";
        gboolean free_message = FALSE;
@@ -6283,6 +6343,9 @@ mono_print_unhandled_exception (MonoObject *exc)
        if (exc == (MonoObject*)mono_object_domain (exc)->out_of_memory_ex) {
                message = g_strdup ("OutOfMemoryException");
                free_message = TRUE;
+       } else if (exc == (MonoObject*)mono_object_domain (exc)->stack_overflow_ex) {
+               message = g_strdup ("StackOverflowException"); //if we OVF, we can't expect to have stack space to JIT Exception::ToString.
+               free_message = TRUE;
        } else {
                
                if (((MonoException*)exc)->native_trace_ips) {
@@ -6336,13 +6399,17 @@ mono_print_unhandled_exception (MonoObject *exc)
  * correct instantiation of the method.
  */
 void
-mono_delegate_ctor_with_method (MonoObject *this, MonoObject *target, gpointer addr, MonoMethod *method)
+mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoMethod *method)
 {
-       MonoDelegate *delegate = (MonoDelegate *)this;
+       MONO_REQ_GC_UNSAFE_MODE;
 
-       g_assert (this);
+       MonoDelegate *delegate = (MonoDelegate *)this_obj;
+
+       g_assert (this_obj);
        g_assert (addr);
 
+       g_assert (mono_class_has_parent (mono_object_class (this_obj), mono_defaults.multicastdelegate_class));
+
        if (method)
                delegate->method = method;
 
@@ -6373,8 +6440,10 @@ mono_delegate_ctor_with_method (MonoObject *this, MonoObject *target, gpointer a
  * This is used to initialize a delegate.
  */
 void
-mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
+mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoDomain *domain = mono_domain_get ();
        MonoJitInfo *ji;
        MonoMethod *method = NULL;
@@ -6390,7 +6459,7 @@ mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
                g_assert (!method->klass->generic_container);
        }
 
-       mono_delegate_ctor_with_method (this, target, addr, method);
+       mono_delegate_ctor_with_method (this_obj, target, addr, method);
 }
 
 /**
@@ -6407,6 +6476,8 @@ MonoMethodMessage *
 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke, 
                              MonoDelegate **cb, MonoObject **state)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoDomain *domain = mono_domain_get ();
        MonoMethodSignature *sig = mono_method_signature (method);
        MonoMethodMessage *msg;
@@ -6459,6 +6530,8 @@ mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *
 void
 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoMethodSignature *sig = mono_method_signature (method);
        int i, j, type, size, out_len;
        
@@ -6519,18 +6592,20 @@ mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoAr
  * Returns: an address pointing to the value of field.
  */
 gpointer
-mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
+mono_load_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, gpointer *res)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        static MonoMethod *getter = NULL;
        MonoDomain *domain = mono_domain_get ();
-       MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
+       MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
        MonoClass *field_class;
        MonoMethodMessage *msg;
        MonoArray *out_args;
        MonoObject *exc;
        char* full_name;
 
-       g_assert (mono_object_is_transparent_proxy (this));
+       g_assert (mono_object_is_transparent_proxy (this_obj));
        g_assert (res != NULL);
 
        if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
@@ -6540,7 +6615,8 @@ mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fiel
        
        if (!getter) {
                getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
-               g_assert (getter);
+               if (!getter)
+                       mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
        }
        
        field_class = mono_class_from_mono_type (field->type);
@@ -6578,18 +6654,20 @@ mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fiel
  * Missing documentation.
  */
 MonoObject *
-mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
+mono_load_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassField *field)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        static MonoMethod *getter = NULL;
        MonoDomain *domain = mono_domain_get ();
-       MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
+       MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
        MonoClass *field_class;
        MonoMethodMessage *msg;
        MonoArray *out_args;
        MonoObject *exc, *res;
        char* full_name;
 
-       g_assert (mono_object_is_transparent_proxy (this));
+       g_assert (mono_object_is_transparent_proxy (this_obj));
 
        field_class = mono_class_from_mono_type (field->type);
 
@@ -6607,7 +6685,8 @@ mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *
 
        if (!getter) {
                getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
-               g_assert (getter);
+               if (!getter)
+                       mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
        }
        
        msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
@@ -6634,21 +6713,23 @@ mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *
 
 /**
  * mono_store_remote_field:
- * @this: pointer to an object
+ * @this_obj: pointer to an object
  * @klass: klass of the object containing @field
  * @field: the field to load
  * @val: the value/object to store
  *
  * This method is called by the runtime on attempts to store fields of
- * transparent proxy objects. @this points to such TP, @klass is the class of
+ * transparent proxy objects. @this_obj points to such TP, @klass is the class of
  * the object containing @field. @val is the new value to store in @field.
  */
 void
-mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
+mono_store_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, gpointer val)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        static MonoMethod *setter = NULL;
        MonoDomain *domain = mono_domain_get ();
-       MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
+       MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
        MonoClass *field_class;
        MonoMethodMessage *msg;
        MonoArray *out_args;
@@ -6656,7 +6737,7 @@ mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fie
        MonoObject *arg;
        char* full_name;
 
-       g_assert (mono_object_is_transparent_proxy (this));
+       g_assert (mono_object_is_transparent_proxy (this_obj));
 
        field_class = mono_class_from_mono_type (field->type);
 
@@ -6668,7 +6749,8 @@ mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fie
 
        if (!setter) {
                setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
-               g_assert (setter);
+               if (!setter)
+                       mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
        }
 
        if (field_class->valuetype)
@@ -6693,7 +6775,7 @@ mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fie
 
 /**
  * mono_store_remote_field_new:
- * @this:
+ * @this_obj:
  * @klass:
  * @field:
  * @arg:
@@ -6701,18 +6783,20 @@ mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fie
  * Missing documentation
  */
 void
-mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
+mono_store_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        static MonoMethod *setter = NULL;
        MonoDomain *domain = mono_domain_get ();
-       MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
+       MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
        MonoClass *field_class;
        MonoMethodMessage *msg;
        MonoArray *out_args;
        MonoObject *exc;
        char* full_name;
 
-       g_assert (mono_object_is_transparent_proxy (this));
+       g_assert (mono_object_is_transparent_proxy (this_obj));
 
        field_class = mono_class_from_mono_type (field->type);
 
@@ -6724,7 +6808,8 @@ mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField
 
        if (!setter) {
                setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
-               g_assert (setter);
+               if (!setter)
+                       mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
        }
 
        msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
@@ -6775,6 +6860,8 @@ mono_get_addr_from_ftnptr (gpointer descr)
 gunichar2 *
 mono_string_chars (MonoString *s)
 {
+       // MONO_REQ_GC_UNSAFE_MODE; //FIXME too much trouble for now
+
        return s->chars;
 }
 
@@ -6787,6 +6874,8 @@ mono_string_chars (MonoString *s)
 int
 mono_string_length (MonoString *s)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return s->length;
 }
 
@@ -6800,6 +6889,8 @@ mono_string_length (MonoString *s)
 uintptr_t
 mono_array_length (MonoArray *array)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return array->max_length;
 }
 
@@ -6814,6 +6905,8 @@ mono_array_length (MonoArray *array)
 char*
 mono_array_addr_with_size (MonoArray *array, int size, uintptr_t idx)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        return ((char*)(array)->vector) + size * idx;
 }