Merge pull request #3686 from lambdageek/dev-format-printf
[mono.git] / mono / metadata / object.c
index 18f9bbf017ca2c196c4963bd87ee1db3cbdd32e6..3ab92326b1b388bfdf002a7bc1074694047887c4 100644 (file)
@@ -41,6 +41,7 @@
 #include <mono/metadata/gc-internals.h>
 #include <mono/metadata/verify-internals.h>
 #include <mono/metadata/reflection-internals.h>
+#include <mono/metadata/w32event.h>
 #include <mono/utils/strenc.h>
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-error-internals.h>
@@ -329,6 +330,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
        MonoNativeThreadId tid;
        int do_initialization = 0;
        MonoDomain *last_domain = NULL;
+       MonoException * pending_tae = NULL;
 
        mono_error_init (error);
 
@@ -431,14 +433,22 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
 
        if (do_initialization) {
                MonoException *exc = NULL;
+
+               mono_threads_begin_abort_protected_block ();
                mono_runtime_try_invoke (method, NULL, NULL, (MonoObject**) &exc, error);
-               if (exc != NULL && mono_error_ok (error)) {
-                       mono_error_set_exception_instance (error, exc);
-               }
+               mono_threads_end_abort_protected_block ();
+
+               //exception extracted, error will be set to the right value later
+               if (exc == NULL && !mono_error_ok (error))//invoking failed but exc was not set
+                       exc = mono_error_convert_to_exception (error);
+               else
+                       mono_error_cleanup (error);
+
+               mono_error_init (error);
 
                /* If the initialization failed, mark the class as unusable. */
                /* Avoid infinite loops */
-               if (!(mono_error_ok(error) ||
+               if (!(!exc ||
                          (klass->image == mono_defaults.corlib &&
                           !strcmp (klass->name_space, "System") &&
                           !strcmp (klass->name, "TypeInitializationException")))) {
@@ -451,15 +461,9 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
 
                        MonoException *exc_to_throw = mono_get_exception_type_initialization_checked (full_name, exc, error);
                        g_free (full_name);
-                       return_val_if_nok (error, FALSE);
 
-                       mono_error_set_exception_instance (error, exc_to_throw);
+                       mono_error_assert_ok (error); //We can't recover from this, no way to fail a type we can't alloc a failure.
 
-                       MonoException *exc_to_store = mono_error_convert_to_exception (error);
-                       /* What we really want to do here is clone the error object and store one copy in the
-                        * domain's exception hash and use the other one to error out here. */
-                       mono_error_init (error);
-                       mono_error_set_exception_instance (error, exc_to_store);
                        /*
                         * Store the exception object so it could be thrown on subsequent
                         * accesses.
@@ -467,7 +471,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
                        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_store);
+                       mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_throw);
                        mono_domain_unlock (domain);
                }
 
@@ -475,6 +479,11 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
                        mono_domain_set (last_domain, TRUE);
                lock->done = TRUE;
                mono_type_init_unlock (lock);
+               if (exc && mono_object_class (exc) == mono_defaults.threadabortexception_class)
+                       pending_tae = exc;
+               //TAEs are blocked around .cctors, they must escape as soon as no cctor is left to run.
+               if (!pending_tae)
+                       pending_tae = mono_thread_try_resume_interruption ();
        } else {
                /* this just blocks until the initializing thread is done */
                mono_type_init_lock (lock);
@@ -495,7 +504,10 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
                vtable->initialized = 1;
        mono_type_initialization_unlock ();
 
-       if (vtable->init_failed) {
+       //TAE wins over TIE
+       if (pending_tae)
+               mono_error_set_exception_instance (error, pending_tae);
+       else if (vtable->init_failed) {
                /* Either we were the initializing thread or we waited for the initialization */
                mono_error_set_exception_instance (error, get_type_init_exception_for_vtable (vtable));
                return FALSE;
@@ -560,8 +572,8 @@ default_delegate_trampoline (MonoDomain *domain, MonoClass *klass)
 }
 
 static MonoDelegateTrampoline arch_create_delegate_trampoline = default_delegate_trampoline;
-static MonoImtThunkBuilder imt_thunk_builder;
-static gboolean always_build_imt_thunks;
+static MonoImtTrampolineBuilder imt_trampoline_builder;
+static gboolean always_build_imt_trampolines;
 
 #if (MONO_IMT_SIZE > 32)
 #error "MONO_IMT_SIZE cannot be larger than 32"
@@ -594,14 +606,15 @@ mono_install_delegate_trampoline (MonoDelegateTrampoline func)
 }
 
 void
-mono_install_imt_thunk_builder (MonoImtThunkBuilder func) {
-       imt_thunk_builder = func;
+mono_install_imt_trampoline_builder (MonoImtTrampolineBuilder func)
+{
+       imt_trampoline_builder = func;
 }
 
 void
-mono_set_always_build_imt_thunks (gboolean value)
+mono_set_always_build_imt_trampolines (gboolean value)
 {
-       always_build_imt_thunks = value;
+       always_build_imt_trampolines = value;
 }
 
 /**
@@ -1195,7 +1208,7 @@ mono_method_get_imt_slot (MonoMethod *method)
                break;
        }
        
-       free (hashes_start);
+       g_free (hashes_start);
        /* Report the result */
        return c % MONO_IMT_SIZE;
 }
@@ -1323,7 +1336,7 @@ imt_sort_slot_entries (MonoImtBuilderEntry *entries) {
 
        imt_emit_ir (sorted_array, 0, number_of_entries, result);
 
-       free (sorted_array);
+       g_free (sorted_array);
        return result;
 }
 
@@ -1333,15 +1346,15 @@ initialize_imt_slot (MonoVTable *vtable, MonoDomain *domain, MonoImtBuilderEntry
        MONO_REQ_GC_NEUTRAL_MODE;
 
        if (imt_builder_entry != NULL) {
-               if (imt_builder_entry->children == 0 && !fail_tramp && !always_build_imt_thunks) {
+               if (imt_builder_entry->children == 0 && !fail_tramp && !always_build_imt_trampolines) {
                        /* No collision, return the vtable slot contents */
                        return vtable->vtable [imt_builder_entry->value.vtable_slot];
                } else {
-                       /* Collision, build the thunk */
+                       /* Collision, build the trampoline */
                        GPtrArray *imt_ir = imt_sort_slot_entries (imt_builder_entry);
                        gpointer result;
                        int i;
-                       result = imt_thunk_builder (vtable, domain,
+                       result = imt_trampoline_builder (vtable, domain,
                                (MonoIMTCheckItem**)imt_ir->pdata, imt_ir->len, fail_tramp);
                        for (i = 0; i < imt_ir->len; ++i)
                                g_free (g_ptr_array_index (imt_ir, i));
@@ -1463,12 +1476,12 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
 
                        if (has_generic_virtual || has_variant_iface) {
                                /*
-                                * There might be collisions later when the the thunk is expanded.
+                                * There might be collisions later when the the trampoline is expanded.
                                 */
                                imt_collisions_bitmap |= (1 << i);
 
                                /* 
-                                * The IMT thunk might be called with an instance of one of the 
+                                * The IMT trampoline might be called with an instance of one of the 
                                 * generic virtual methods, so has to fallback to the IMT trampoline.
                                 */
                                imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], callbacks.get_imt_trampoline (vt, i));
@@ -1503,7 +1516,7 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
                        entry = next;
                }
        }
-       free (imt_builder);
+       g_free (imt_builder);
        /* we OR the bitmap since we may build just a single imt slot at a time */
        vt->imt_collisions_bitmap |= imt_collisions_bitmap;
 }
@@ -1521,7 +1534,7 @@ build_imt (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer* imt,
  * @imt_slot: slot in the IMT table
  *
  * Fill the given @imt_slot in the IMT table of @vtable with
- * a trampoline or a thunk for the case of collisions.
+ * a trampoline or a trampoline for the case of collisions.
  * This is part of the internal mono API.
  *
  * LOCKING: Take the domain lock.
@@ -1549,167 +1562,35 @@ mono_vtable_build_imt_slot (MonoVTable* vtable, int imt_slot)
        mono_loader_unlock ();
 }
 
-
-/*
- * The first two free list entries both belong to the wait list: The
- * first entry is the pointer to the head of the list and the second
- * entry points to the last element.  That way appending and removing
- * the first element are both O(1) operations.
- */
-#ifdef MONO_SMALL_CONFIG
-#define NUM_FREE_LISTS         6
-#else
-#define NUM_FREE_LISTS         12
-#endif
-#define FIRST_FREE_LIST_SIZE   64
-#define MAX_WAIT_LENGTH        50
 #define THUNK_THRESHOLD                10
 
-/*
- * LOCKING: The domain lock must be held.
- */
-static void
-init_thunk_free_lists (MonoDomain *domain)
-{
-       MONO_REQ_GC_NEUTRAL_MODE;
-
-       if (domain->thunk_free_lists)
-               return;
-       domain->thunk_free_lists = (MonoThunkFreeList **)mono_domain_alloc0 (domain, sizeof (gpointer) * NUM_FREE_LISTS);
-}
-
-static int
-list_index_for_size (int item_size)
-{
-       int i = 2;
-       int size = FIRST_FREE_LIST_SIZE;
-
-       while (item_size > size && i < NUM_FREE_LISTS - 1) {
-               i++;
-               size <<= 1;
-       }
-
-       return i;
-}
-
 /**
- * mono_method_alloc_generic_virtual_thunk:
+ * mono_method_alloc_generic_virtual_trampoline:
  * @domain: a domain
  * @size: size in bytes
  *
  * Allocs size bytes to be used for the code of a generic virtual
- * thunk.  It's either allocated from the domain's code manager or
+ * trampoline.  It's either allocated from the domain's code manager or
  * reused from a previously invalidated piece.
  *
  * LOCKING: The domain lock must be held.
  */
 gpointer
-mono_method_alloc_generic_virtual_thunk (MonoDomain *domain, int size)
+mono_method_alloc_generic_virtual_trampoline (MonoDomain *domain, int size)
 {
        MONO_REQ_GC_NEUTRAL_MODE;
 
        static gboolean inited = FALSE;
-       static int generic_virtual_thunks_size = 0;
+       static int generic_virtual_trampolines_size = 0;
 
-       guint32 *p;
-       int i;
-       MonoThunkFreeList **l;
-
-       init_thunk_free_lists (domain);
-
-       size += sizeof (guint32);
-       if (size < sizeof (MonoThunkFreeList))
-               size = sizeof (MonoThunkFreeList);
-
-       i = list_index_for_size (size);
-       for (l = &domain->thunk_free_lists [i]; *l; l = &(*l)->next) {
-               if ((*l)->size >= size) {
-                       MonoThunkFreeList *item = *l;
-                       *l = item->next;
-                       return ((guint32*)item) + 1;
-               }
-       }
-
-       /* no suitable item found - search lists of larger sizes */
-       while (++i < NUM_FREE_LISTS) {
-               MonoThunkFreeList *item = domain->thunk_free_lists [i];
-               if (!item)
-                       continue;
-               g_assert (item->size > size);
-               domain->thunk_free_lists [i] = item->next;
-               return ((guint32*)item) + 1;
-       }
-
-       /* still nothing found - allocate it */
        if (!inited) {
-               mono_counters_register ("Generic virtual thunk bytes",
-                               MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &generic_virtual_thunks_size);
+               mono_counters_register ("Generic virtual trampoline bytes",
+                               MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &generic_virtual_trampolines_size);
                inited = TRUE;
        }
-       generic_virtual_thunks_size += size;
+       generic_virtual_trampolines_size += size;
 
-       p = (guint32 *)mono_domain_code_reserve (domain, size);
-       *p = size;
-
-       mono_domain_lock (domain);
-       if (!domain->generic_virtual_thunks)
-               domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL);
-       g_hash_table_insert (domain->generic_virtual_thunks, p, p);
-       mono_domain_unlock (domain);
-
-       return p + 1;
-}
-
-/*
- * LOCKING: The domain lock must be held.
- */
-static void
-invalidate_generic_virtual_thunk (MonoDomain *domain, gpointer code)
-{
-       MONO_REQ_GC_NEUTRAL_MODE;
-
-       guint32 *p = (guint32 *)code;
-       MonoThunkFreeList *l = (MonoThunkFreeList*)(p - 1);
-       gboolean found = FALSE;
-
-       mono_domain_lock (domain);
-       if (!domain->generic_virtual_thunks)
-               domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL);
-       if (g_hash_table_lookup (domain->generic_virtual_thunks, l))
-               found = TRUE;
-       mono_domain_unlock (domain);
-
-       if (!found)
-               /* Not allocated by mono_method_alloc_generic_virtual_thunk (), i.e. AOT */
-               return;
-       init_thunk_free_lists (domain);
-
-       while (domain->thunk_free_lists [0] && domain->thunk_free_lists [0]->length >= MAX_WAIT_LENGTH) {
-               MonoThunkFreeList *item = domain->thunk_free_lists [0];
-               int length = item->length;
-               int i;
-
-               /* unlink the first item from the wait list */
-               domain->thunk_free_lists [0] = item->next;
-               domain->thunk_free_lists [0]->length = length - 1;
-
-               i = list_index_for_size (item->size);
-
-               /* put it in the free list */
-               item->next = domain->thunk_free_lists [i];
-               domain->thunk_free_lists [i] = item;
-       }
-
-       l->next = NULL;
-       if (domain->thunk_free_lists [1]) {
-               domain->thunk_free_lists [1] = domain->thunk_free_lists [1]->next = l;
-               domain->thunk_free_lists [0]->length++;
-       } else {
-               g_assert (!domain->thunk_free_lists [0]);
-
-               domain->thunk_free_lists [0] = domain->thunk_free_lists [1] = l;
-               domain->thunk_free_lists [0]->length = 1;
-       }
+       return mono_domain_code_reserve (domain, size);
 }
 
 typedef struct _GenericVirtualCase {
@@ -1773,7 +1654,7 @@ get_generic_virtual_entries (MonoDomain *domain, gpointer *vtable_slot)
  * Registers a call via unmanaged code to a generic virtual method
  * instantiation or variant interface method.  If the number of calls reaches a threshold
  * (THUNK_THRESHOLD), the method is added to the vtable slot's generic
- * virtual method thunk.
+ * virtual method trampoline.
  */
 void
 mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtable,
@@ -1784,6 +1665,7 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
 
        static gboolean inited = FALSE;
        static int num_added = 0;
+       static int num_freed = 0;
 
        GenericVirtualCase *gvc, *list;
        MonoImtBuilderEntry *entries;
@@ -1794,6 +1676,12 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
        if (!domain->generic_virtual_cases)
                domain->generic_virtual_cases = g_hash_table_new (mono_aligned_addr_hash, NULL);
 
+       if (!inited) {
+               mono_counters_register ("Generic virtual cases", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_added);
+               mono_counters_register ("Freed IMT trampolines", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_freed);
+               inited = TRUE;
+       }
+
        /* Check whether the case was already added */
        list = (GenericVirtualCase *)g_hash_table_lookup (domain->generic_virtual_cases, vtable_slot);
        gvc = list;
@@ -1813,10 +1701,6 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
 
                g_hash_table_insert (domain->generic_virtual_cases, vtable_slot, gvc);
 
-               if (!inited) {
-                       mono_counters_register ("Generic virtual cases", MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_added);
-                       inited = TRUE;
-               }
                num_added++;
        }
 
@@ -1829,7 +1713,7 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
                        int displacement = (gpointer*)vtable_slot - (gpointer*)vtable;
                        int imt_slot = MONO_IMT_SIZE + displacement;
 
-                       /* Force the rebuild of the thunk at the next call */
+                       /* Force the rebuild of the trampoline at the next call */
                        imt_trampoline = callbacks.get_imt_trampoline (vtable, imt_slot);
                        *vtable_slot = imt_trampoline;
                } else {
@@ -1839,8 +1723,8 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
 
                        sorted = imt_sort_slot_entries (entries);
 
-                       *vtable_slot = imt_thunk_builder (NULL, domain, (MonoIMTCheckItem**)sorted->pdata, sorted->len,
-                                                                                         vtable_trampoline);
+                       *vtable_slot = imt_trampoline_builder (NULL, domain, (MonoIMTCheckItem**)sorted->pdata, sorted->len,
+                                                                                                  vtable_trampoline);
 
                        while (entries) {
                                MonoImtBuilderEntry *next = entries->next;
@@ -1851,14 +1735,10 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
                        for (i = 0; i < sorted->len; ++i)
                                g_free (g_ptr_array_index (sorted, i));
                        g_ptr_array_free (sorted, TRUE);
-               }
 
-#ifndef __native_client__
-               /* We don't re-use any thunks as there is a lot of overhead */
-               /* to deleting and re-using code in Native Client.          */
-               if (old_thunk != vtable_trampoline && old_thunk != imt_trampoline)
-                       invalidate_generic_virtual_thunk (domain, old_thunk);
-#endif
+                       if (old_thunk != vtable_trampoline && old_thunk != imt_trampoline)
+                               num_freed ++;
+               }
        }
 
        mono_domain_unlock (domain);
@@ -4165,22 +4045,14 @@ mono_runtime_set_main_args (int argc, char* argv[])
        return 0;
 }
 
-/**
- * mono_runtime_run_main:
- * @method: the method to start the application with (usually Main)
- * @argc: number of arguments from the command line
- * @argv: array of strings from the command line
- * @exc: excetption results
- *
- * Execute a standard Main() method (argc/argv contains the
- * executable name). This method also sets the command line argument value
- * needed by System.Environment.
- *
+/*
+ * Prepare an array of arguments in order to execute a standard Main()
+ * method (argc/argv contains the executable name). This method also
+ * sets the command line argument value needed by System.Environment.
  * 
  */
-int
-mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
-                      MonoObject **exc)
+static MonoArray*
+prepare_run_main (MonoMethod *method, int argc, char *argv[])
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -4271,9 +4143,87 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
        
        mono_assembly_set_main (method->klass->image->assembly);
 
-       return mono_runtime_exec_main (method, args, exc);
+       return args;
+}
+
+/**
+ * mono_runtime_run_main:
+ * @method: the method to start the application with (usually Main)
+ * @argc: number of arguments from the command line
+ * @argv: array of strings from the command line
+ * @exc: excetption results
+ *
+ * Execute a standard Main() method (argc/argv contains the
+ * executable name). This method also sets the command line argument value
+ * needed by System.Environment.
+ *
+ * 
+ */
+int
+mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
+                      MonoObject **exc)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       MonoError error;
+       MonoArray *args = prepare_run_main (method, argc, argv);
+       int res;
+       if (exc) {
+               res = mono_runtime_try_exec_main (method, args, exc);
+       } else {
+               res = mono_runtime_exec_main_checked (method, args, &error);
+               mono_error_raise_exception (&error); /* OK to throw, external only without a better alternative */
+       }
+       return res;
+}
+
+/**
+ * mono_runtime_run_main_checked:
+ * @method: the method to start the application with (usually Main)
+ * @argc: number of arguments from the command line
+ * @argv: array of strings from the command line
+ * @error: set on error
+ *
+ * Execute a standard Main() method (argc/argv contains the
+ * executable name). This method also sets the command line argument value
+ * needed by System.Environment.  On failure sets @error.
+ *
+ * 
+ */
+int
+mono_runtime_run_main_checked (MonoMethod *method, int argc, char* argv[],
+                              MonoError *error)
+{
+       mono_error_init (error);
+       MonoArray *args = prepare_run_main (method, argc, argv);
+       return mono_runtime_exec_main_checked (method, args, error);
+}
+
+/**
+ * mono_runtime_try_run_main:
+ * @method: the method to start the application with (usually Main)
+ * @argc: number of arguments from the command line
+ * @argv: array of strings from the command line
+ * @exc: set if Main throws an exception
+ * @error: set if Main can't be executed
+ *
+ * Execute a standard Main() method (argc/argv contains the executable
+ * name). This method also sets the command line argument value needed
+ * by System.Environment.  On failure sets @error if Main can't be
+ * executed or @exc if it threw and exception.
+ *
+ * 
+ */
+int
+mono_runtime_try_run_main (MonoMethod *method, int argc, char* argv[],
+                          MonoObject **exc)
+{
+       g_assert (exc);
+       MonoArray *args = prepare_run_main (method, argc, argv);
+       return mono_runtime_try_exec_main (method, args, exc);
 }
 
+
 static MonoObject*
 serialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 {
@@ -4590,10 +4540,13 @@ mono_unhandled_exception (MonoObject *exc)
        if (!current_appdomain_delegate && !root_appdomain_delegate) {
                mono_print_unhandled_exception (exc);
        } else {
+               /* unhandled exception callbacks must not be aborted */
+               mono_threads_begin_abort_protected_block ();
                if (root_appdomain_delegate)
                        call_unhandled_exception_delegate (root_domain, root_appdomain_delegate, exc);
                if (current_appdomain_delegate)
                        call_unhandled_exception_delegate (current_domain, current_appdomain_delegate, exc);
+               mono_threads_end_abort_protected_block ();
        }
 
        /* set exitcode only if we will abort the process */
@@ -4632,28 +4585,13 @@ mono_runtime_exec_managed_code (MonoDomain *domain,
        mono_thread_manage ();
 }
 
-/*
- * Execute a standard Main() method (args doesn't contain the
- * executable name).
- */
-int
-mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
+static void
+prepare_thread_to_exec_main (MonoDomain *domain, MonoMethod *method)
 {
-       MONO_REQ_GC_UNSAFE_MODE;
-
-       MonoError error;
-       MonoDomain *domain;
-       gpointer pa [1];
-       int rval;
+       MonoInternalThread* thread = mono_thread_internal_current ();
        MonoCustomAttrInfo* cinfo;
        gboolean has_stathread_attribute;
-       MonoInternalThread* thread = mono_thread_internal_current ();
-
-       g_assert (args);
-
-       pa [0] = args;
 
-       domain = mono_object_domain (args);
        if (!domain->entry_assembly) {
                gchar *str;
                MonoAssembly *assembly;
@@ -4673,8 +4611,9 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
                }
        }
 
-       cinfo = mono_custom_attrs_from_method_checked (method, &error);
-       mono_error_cleanup (&error); /* FIXME warn here? */
+       MonoError cattr_error;
+       cinfo = mono_custom_attrs_from_method_checked (method, &cattr_error);
+       mono_error_cleanup (&cattr_error); /* FIXME warn here? */
        if (cinfo) {
                has_stathread_attribute = mono_custom_attrs_has_attr (cinfo, mono_class_get_sta_thread_attribute_class ());
                if (!cinfo->cached)
@@ -4689,39 +4628,80 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
        }
        mono_thread_init_apartment_state ();
 
+}
+
+static int
+do_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       gpointer pa [1];
+       int rval;
+
+       mono_error_init (error);
+       g_assert (args);
+
+       pa [0] = args;
+
        /* FIXME: check signature of method */
        if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
                MonoObject *res;
-               if (exc) {
-                       res = mono_runtime_try_invoke (method, NULL, pa, exc, &error);
-                       if (*exc == NULL && !mono_error_ok (&error))
-                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
-                       else
-                               mono_error_cleanup (&error);
-               } else {
-                       res = mono_runtime_invoke_checked (method, NULL, pa, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               res = mono_runtime_invoke_checked (method, NULL, pa, error);
+               if (is_ok (error))
+                       rval = *(guint32 *)((char *)res + sizeof (MonoObject));
+               else
+                       rval = -1;
+               mono_environment_exitcode_set (rval);
+       } else {
+               mono_runtime_invoke_checked (method, NULL, pa, error);
+
+               if (is_ok (error))
+                       rval = 0;
+               else {
+                       rval = -1;
                }
+       }
+       return rval;
+}
+
+static int
+do_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       gpointer pa [1];
+       int rval;
+
+       g_assert (args);
+       g_assert (exc);
+
+       pa [0] = args;
 
-               if (!exc || !*exc)
+       /* FIXME: check signature of method */
+       if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
+               MonoError inner_error;
+               MonoObject *res;
+               res = mono_runtime_try_invoke (method, NULL, pa, exc, &inner_error);
+               if (*exc == NULL && !mono_error_ok (&inner_error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (&inner_error);
+               else
+                       mono_error_cleanup (&inner_error);
+
+               if (*exc == NULL)
                        rval = *(guint32 *)((char *)res + sizeof (MonoObject));
                else
                        rval = -1;
 
                mono_environment_exitcode_set (rval);
        } else {
-               if (exc) {
-                       mono_runtime_try_invoke (method, NULL, pa, exc, &error);
-                       if (*exc == NULL && !mono_error_ok (&error))
-                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
-                       else
-                               mono_error_cleanup (&error);
-               } else {
-                       mono_runtime_invoke_checked (method, NULL, pa, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
-               }
+               MonoError inner_error;
+               mono_runtime_try_invoke (method, NULL, pa, exc, &inner_error);
+               if (*exc == NULL && !mono_error_ok (&inner_error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (&inner_error);
+               else
+                       mono_error_cleanup (&inner_error);
 
-               if (!exc || !*exc)
+               if (*exc == NULL)
                        rval = 0;
                else {
                        /* If the return type of Main is void, only
@@ -4737,6 +4717,54 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
        return rval;
 }
 
+/*
+ * Execute a standard Main() method (args doesn't contain the
+ * executable name).
+ */
+int
+mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
+{
+       MonoError error;
+       prepare_thread_to_exec_main (mono_object_domain (args), method);
+       if (exc) {
+               int rval = do_try_exec_main (method, args, exc);
+               return rval;
+       } else {
+               int rval = do_exec_main_checked (method, args, &error);
+               mono_error_raise_exception (&error); /* OK to throw, external only with no better option */
+               return rval;
+       }
+}
+
+/*
+ * Execute a standard Main() method (args doesn't contain the
+ * executable name).
+ *
+ * On failure sets @error
+ */
+int
+mono_runtime_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError *error)
+{
+       mono_error_init (error);
+       prepare_thread_to_exec_main (mono_object_domain (args), method);
+       return do_exec_main_checked (method, args, error);
+}
+
+/*
+ * Execute a standard Main() method (args doesn't contain the
+ * executable name).
+ *
+ * On failure sets @error if Main couldn't be executed, or @exc if it threw an exception.
+ */
+int
+mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
+{
+       prepare_thread_to_exec_main (mono_object_domain (args), method);
+       return do_try_exec_main (method, args, exc);
+}
+
+
+
 /** invoke_array_extract_argument:
  * @params: array of arguments to the method.
  * @i: the index of the argument to extract.
@@ -4891,7 +4919,7 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                }
        } else {
                MonoObject *result = mono_runtime_try_invoke_array (method, obj, params, NULL, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
                return result;
        }
 }
@@ -5429,7 +5457,7 @@ mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *p
 
        *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))
+       if (mono_class_has_finalizer (vtable->klass) || mono_class_is_marshalbyref (vtable->klass))
                return ves_icall_object_new_specific;
 
        if (vtable->gc_descr != MONO_GC_DESCRIPTOR_NULL) {
@@ -5794,7 +5822,7 @@ mono_array_new_full_checked (MonoDomain *domain, MonoClass *array_class, uintptr
                o = (MonoObject *)mono_gc_alloc_vector (vtable, byte_len, len);
 
        if (G_UNLIKELY (!o)) {
-               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", byte_len);
+               mono_error_set_out_of_memory (error, "Could not allocate %zd bytes", (gsize) byte_len);
                return NULL;
        }
 
@@ -5908,7 +5936,7 @@ mono_array_new_specific_checked (MonoVTable *vtable, uintptr_t n, MonoError *err
        o = (MonoObject *)mono_gc_alloc_vector (vtable, byte_len, n);
 
        if (G_UNLIKELY (!o)) {
-               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", byte_len);
+               mono_error_set_out_of_memory (error, "Could not allocate %zd bytes", (gsize) byte_len);
                return NULL;
        }
 
@@ -6066,7 +6094,7 @@ mono_string_new_size_checked (MonoDomain *domain, gint32 len, MonoError *error)
        s = (MonoString *)mono_gc_alloc_string (vtable, size, len);
 
        if (G_UNLIKELY (!s)) {
-               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", size);
+               mono_error_set_out_of_memory (error, "Could not allocate %zd bytes", size);
                return NULL;
        }
 
@@ -6813,6 +6841,48 @@ mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig, MonoError *error)
        return interned;
 }
 
+/*
+ * mono_ldstr_utf8:
+ *
+ *   Same as mono_ldstr, but return a NULL terminated utf8 string instead
+ * of an object.
+ */
+char*
+mono_ldstr_utf8 (MonoImage *image, guint32 idx, MonoError *error)
+{
+       const char *str;
+       size_t len2;
+       long written = 0;
+       char *as;
+       GError *gerror = NULL;
+
+       mono_error_init (error);
+
+       if (!mono_verifier_verify_string_signature (image, idx, NULL))
+               return NULL; /*FIXME we should probably be raising an exception here*/
+       str = mono_metadata_user_string (image, idx);
+
+       len2 = mono_metadata_decode_blob_size (str, &str);
+       len2 >>= 1;
+
+       as = g_utf16_to_utf8 ((guint16*)str, len2, NULL, &written, &gerror);
+       if (gerror) {
+               mono_error_set_argument (error, "string", "%s", gerror->message);
+               g_error_free (gerror);
+               return NULL;
+       }
+       /* g_utf16_to_utf8  may not be able to complete the convertion (e.g. NULL values were found, #335488) */
+       if (len2 > written) {
+               /* allocate the total length and copy the part of the string that has been converted */
+               char *as2 = (char *)g_malloc0 (len2);
+               memcpy (as2, as, written);
+               g_free (as);
+               as = as2;
+       }
+
+       return as;
+}
+
 /**
  * mono_string_to_utf8:
  * @s: a System.String
@@ -7345,9 +7415,19 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
                gpointer wait_event = NULL;
 
                ac->msg->exc = NULL;
+
                res = mono_message_invoke (ares->async_delegate, ac->msg, &ac->msg->exc, &ac->out_args, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return NULL;
+
+               /* The exit side of the invoke must not be aborted as it would leave the runtime in an undefined state */
+               mono_threads_begin_abort_protected_block ();
+
+               if (!ac->msg->exc) {
+                       MonoException *ex = mono_error_convert_to_exception (&error);
+                       ac->msg->exc = (MonoObject *)ex;
+               } else {
+                       mono_error_cleanup (&error);
+               }
+
                MONO_OBJECT_SETREF (ac, res, res);
 
                mono_monitor_enter ((MonoObject*) ares);
@@ -7357,13 +7437,16 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
                mono_monitor_exit ((MonoObject*) ares);
 
                if (wait_event != NULL)
-                       SetEvent (wait_event);
+                       mono_w32event_set (wait_event);
 
-               if (ac->cb_method) {
+               mono_error_init (&error); //the else branch would leave it in an undefined state
+               if (ac->cb_method)
                        mono_runtime_invoke_checked (ac->cb_method, ac->cb_target, (gpointer*) &ares, &error);
-                       if (mono_error_set_pending_exception (&error))
-                               return NULL;
-               }
+
+               mono_threads_end_abort_protected_block ();
+
+               if (mono_error_set_pending_exception (&error))
+                       return NULL;
        }
 
        return res;
@@ -7378,88 +7461,24 @@ mono_message_init (MonoDomain *domain,
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       static MonoClass *object_array_klass;
-       static MonoClass *byte_array_klass;
-       static MonoClass *string_array_klass;
-       mono_error_init (error);
-       MonoMethodSignature *sig = mono_method_signature (method->method);
-       MonoString *name;
-       MonoArray *arr;
-       int i, j;
-       char **names;
-       guint8 arg_type;
-
-       if (!object_array_klass) {
-               MonoClass *klass;
-
-               klass = mono_array_class_get (mono_defaults.byte_class, 1);
-               g_assert (klass);
-               byte_array_klass = klass;
-
-               klass = mono_array_class_get (mono_defaults.string_class, 1);
-               g_assert (klass);
-               string_array_klass = klass;
-
-               klass = mono_array_class_get (mono_defaults.object_class, 1);
-               g_assert (klass);
+       static MonoMethod *init_message_method = NULL;
 
-               mono_atomic_store_release (&object_array_klass, klass);
+       if (!init_message_method) {
+               init_message_method = mono_class_get_method_from_name (mono_defaults.mono_method_message_class, "InitMessage", 2);
+               g_assert (init_message_method != NULL);
        }
 
-       MONO_OBJECT_SETREF (this_obj, method, method);
-
-       arr = mono_array_new_specific_checked (mono_class_vtable (domain, object_array_klass), sig->param_count, error);
-       return_val_if_nok (error, FALSE);
-
-       MONO_OBJECT_SETREF (this_obj, args, arr);
-
-       arr = mono_array_new_specific_checked (mono_class_vtable (domain, byte_array_klass), sig->param_count, error);
-       return_val_if_nok (error, FALSE);
-
-       MONO_OBJECT_SETREF (this_obj, arg_types, arr);
-
-       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);
-
-       arr = mono_array_new_specific_checked (mono_class_vtable (domain, string_array_klass), sig->param_count, error);
-       if (!is_ok (error))
-               goto fail;
-
-       MONO_OBJECT_SETREF (this_obj, names, arr);
+       mono_error_init (error);
+       /* FIXME set domain instead? */
+       g_assert (domain == mono_domain_get ());
        
-       for (i = 0; i < sig->param_count; i++) {
-               name = mono_string_new_checked (domain, names [i], error);
-               if (!is_ok (error))
-                       goto fail;
-               mono_array_setref (this_obj->names, i, name);   
-       }
+       gpointer args[2];
 
-       g_free (names);
-       for (i = 0, j = 0; i < sig->param_count; i++) {
-               if (sig->params [i]->byref) {
-                       if (out_args) {
-                               MonoObject* arg = (MonoObject *)mono_array_get (out_args, gpointer, j);
-                               mono_array_setref (this_obj->args, i, arg);
-                               j++;
-                       }
-                       arg_type = 2;
-                       if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
-                               arg_type |= 1;
-               } else {
-                       arg_type = 1;
-                       if (sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT)
-                               arg_type |= 4;
-               }
-               mono_array_set (this_obj->arg_types, guint8, i, arg_type);
-       }
+       args[0] = method;
+       args[1] = out_args;
 
-       return TRUE;
-fail:
-       g_free (names);
-       return FALSE;
+       mono_runtime_invoke_checked (init_message_method, this_obj, args, error);
+       return is_ok (error);
 }
 
 #ifndef DISABLE_REMOTING
@@ -8085,28 +8104,6 @@ mono_load_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFie
        return result;
 }
 
-/**
- * mono_load_remote_field_new_icall:
- * @this: pointer to an object
- * @klass: klass of the object containing @field
- * @field: the field to load
- *
- * This method is called by the runtime on attempts to load fields of
- * transparent proxy objects. @this points to such TP, @klass is the class of
- * the object containing @field.
- * 
- * Returns: a freshly allocated object containing the value of the
- * field.  On failure returns NULL and throws an exception.
- */
-MonoObject *
-mono_load_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field)
-{
-       MonoError error;
-       MonoObject *result = mono_load_remote_field_new_checked (this_obj, klass, field, &error);
-       mono_error_set_pending_exception (&error);
-       return result;
-}
-
 /**
  * mono_load_remote_field_new_checked:
  * @this: pointer to an object
@@ -8127,69 +8124,25 @@ mono_load_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, Mono
 
        mono_error_init (error);
 
-       static MonoMethod *getter = NULL;
-       MonoDomain *domain = mono_domain_get ();
-       MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
-       MonoClass *field_class;
-       MonoMethodMessage *msg;
-       MonoArray *out_args;
-       MonoObject *exc, *res;
-       char* full_name;
+       static MonoMethod *tp_load = NULL;
 
        g_assert (mono_object_is_transparent_proxy (this_obj));
 
-       field_class = mono_class_from_mono_type (field->type);
-
-       if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
-               gpointer val;
-               if (field_class->valuetype) {
-                       res = mono_object_new_checked (domain, field_class, error);
-                       return_val_if_nok (error, NULL);
-                       val = ((gchar *) res) + sizeof (MonoObject);
-               } else {
-                       val = &res;
-               }
-               mono_field_get_value (tp->rp->unwrapped_server, field, val);
-               return res;
-       }
-
-       if (!getter) {
-               getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
-               if (!getter) {
+       if (!tp_load) {
+               tp_load = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "LoadRemoteFieldNew", -1);
+               if (!tp_load) {
                        mono_error_set_not_supported (error, "Linked away.");
                        return NULL;
                }
        }
        
-       msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error);
-       return_val_if_nok (error, NULL);
-       out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, error);
-       return_val_if_nok (error, NULL);
-
-       MonoReflectionMethod *rm = mono_method_get_object_checked (domain, getter, NULL, error);
-       return_val_if_nok (error, NULL);
-       mono_message_init (domain, msg, rm, out_args, error);
-       return_val_if_nok (error, NULL);
-
-       full_name = mono_type_get_full_name (klass);
-       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
-       mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field)));
-       g_free (full_name);
+       /* MonoType *type = mono_class_get_type (klass); */
 
-       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
-       return_val_if_nok (error, NULL);
+       gpointer args[2];
+       args [0] = &klass;
+       args [1] = &field;
 
-       if (exc) {
-               mono_error_set_exception_instance (error, (MonoException *)exc);
-               return NULL;
-       }
-
-       if (mono_array_length (out_args) == 0)
-               res = NULL;
-       else
-               res = mono_array_get (out_args, MonoObject *, 0);
-
-       return res;
+       return mono_runtime_invoke_checked (tp_load, this_obj, args, error);
 }
 
 /**
@@ -8231,65 +8184,24 @@ mono_store_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoCla
        
        MONO_REQ_GC_UNSAFE_MODE;
 
-       static MonoMethod *setter = NULL;
+       mono_error_init (error);
 
        MonoDomain *domain = mono_domain_get ();
-       MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
        MonoClass *field_class;
-       MonoMethodMessage *msg;
-       MonoArray *out_args;
-       MonoObject *exc;
        MonoObject *arg;
-       char* full_name;
-
-       mono_error_init (error);
 
        g_assert (mono_object_is_transparent_proxy (this_obj));
 
        field_class = mono_class_from_mono_type (field->type);
 
-       if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
-               if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
-               else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
-               return TRUE;
-       }
-
-       if (!setter) {
-               setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
-               if (!setter) {
-                       mono_error_set_not_supported (error, "Linked away.");
-                       return FALSE;
-               }
-       }
-
        if (field_class->valuetype) {
                arg = mono_value_box_checked (domain, field_class, val, error);
                return_val_if_nok (error, FALSE);
-       } else 
-               arg = *((MonoObject **)val);
-               
-
-       msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error);
-       return_val_if_nok (error, FALSE);
-       MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, error);
-       return_val_if_nok (error, FALSE);
-       mono_message_init (domain, msg, rm, NULL, error);
-       return_val_if_nok (error, FALSE);
-
-       full_name = mono_type_get_full_name (klass);
-       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
-       mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field)));
-       mono_array_setref (msg->args, 2, arg);
-       g_free (full_name);
-
-       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
-       return_val_if_nok (error, FALSE);
-
-       if (exc) {
-               mono_error_set_exception_instance (error, (MonoException *)exc);
-               return FALSE;
+       } else {
+               arg = *((MonoObject**)val);
        }
-       return TRUE;
+
+       return mono_store_remote_field_new_checked (this_obj, klass, field, arg, error);
 }
 
 /**
@@ -8309,23 +8221,6 @@ mono_store_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFi
        mono_error_cleanup (&error);
 }
 
-/**
- * mono_store_remote_field_new_icall:
- * @this_obj:
- * @klass:
- * @field:
- * @arg:
- *
- * Missing documentation
- */
-void
-mono_store_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg)
-{
-       MonoError error;
-       (void) mono_store_remote_field_new_checked (this_obj, klass, field, arg, &error);
-       mono_error_set_pending_exception (&error);
-}
-
 /**
  * mono_store_remote_field_new_checked:
  * @this_obj:
@@ -8341,56 +8236,27 @@ mono_store_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, Mon
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       static MonoMethod *setter = NULL;
-       MonoDomain *domain = mono_domain_get ();
-       MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
-       MonoClass *field_class;
-       MonoMethodMessage *msg;
-       MonoArray *out_args;
-       MonoObject *exc;
-       char* full_name;
+       static MonoMethod *tp_store = NULL;
 
        mono_error_init (error);
 
        g_assert (mono_object_is_transparent_proxy (this_obj));
 
-       field_class = mono_class_from_mono_type (field->type);
-
-       if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
-               if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
-               else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
-               return TRUE;
-       }
-
-       if (!setter) {
-               setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
-               if (!setter) {
+       if (!tp_store) {
+               tp_store = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "StoreRemoteField", -1);
+               if (!tp_store) {
                        mono_error_set_not_supported (error, "Linked away.");
                        return FALSE;
                }
        }
 
-       msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error);
-       return_val_if_nok (error, FALSE);
-       MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, error);
-       return_val_if_nok (error, FALSE);
-       mono_message_init (domain, msg, rm, NULL, error);
-       return_val_if_nok (error, FALSE);
-
-       full_name = mono_type_get_full_name (klass);
-       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
-       mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field)));
-       mono_array_setref (msg->args, 2, arg);
-       g_free (full_name);
-
-       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
-       return_val_if_nok (error, FALSE);
+       gpointer args[3];
+       args [0] = &klass;
+       args [1] = &field;
+       args [2] = arg;
 
-       if (exc) {
-               mono_error_set_exception_instance (error, (MonoException *)exc);
-               return FALSE;
-       }
-       return TRUE;
+       mono_runtime_invoke_checked (tp_store, this_obj, args, error);
+       return is_ok (error);
 }
 #endif