Merge pull request #2408 from tastywheattasteslikechicken/MoreInterfaceSupport
[mono.git] / mono / metadata / object.c
index db0047db6484424c6597c6505aef2821a9420789..c25a107fdeb502712987c0c7b5671e8258b1f49d 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2011 Novell, Inc (http://www.novell.com)
  * Copyright 2001 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #ifdef HAVE_ALLOCA_H
@@ -23,6 +24,7 @@
 #include <mono/metadata/object.h>
 #include <mono/metadata/gc-internals.h>
 #include <mono/metadata/exception.h>
+#include <mono/metadata/exception-internals.h>
 #include <mono/metadata/domain-internals.h>
 #include "mono/metadata/metadata-internals.h"
 #include "mono/metadata/class-internals.h"
 #include "mono/metadata/mono-debug-debugger.h"
 #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>
 #include <mono/utils/mono-memory-model.h>
 #include <mono/utils/checked-build.h>
 #include <mono/utils/mono-threads.h>
+#include <mono/utils/mono-threads-coop.h>
 #include "cominterop.h"
 
 static void
-get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value);
+get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value, MonoError *error);
 
 static MonoString*
-mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig);
+mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig, MonoError *error);
 
 static void
 free_main_args (void);
@@ -58,26 +63,60 @@ free_main_args (void);
 static char *
 mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, gboolean ignore_error, MonoError *error);
 
+/* Class lazy loading functions */
+static GENERATE_GET_CLASS_WITH_CACHE (pointer, System.Reflection, Pointer)
+static GENERATE_GET_CLASS_WITH_CACHE (remoting_services, System.Runtime.Remoting, RemotingServices)
+static GENERATE_GET_CLASS_WITH_CACHE (unhandled_exception_event_args, System, UnhandledExceptionEventArgs)
+static GENERATE_GET_CLASS_WITH_CACHE (sta_thread_attribute, System, STAThreadAttribute)
+static GENERATE_GET_CLASS_WITH_CACHE (activation_services, System.Runtime.Remoting.Activation, ActivationServices)
+
 
 #define ldstr_lock() mono_os_mutex_lock (&ldstr_section)
 #define ldstr_unlock() mono_os_mutex_unlock (&ldstr_section)
 static mono_mutex_t ldstr_section;
 
+/**
+ * mono_runtime_object_init:
+ * @this_obj: the object to initialize
+ *
+ * This function calls the zero-argument constructor (which must
+ * exist) for the given object.
+ */
 void
 mono_runtime_object_init (MonoObject *this_obj)
+{
+       MonoError error;
+       mono_runtime_object_init_checked (this_obj, &error);
+       mono_error_assert_ok (&error);
+}
+
+/**
+ * mono_runtime_object_init_checked:
+ * @this_obj: the object to initialize
+ * @error: set on error.
+ *
+ * This function calls the zero-argument constructor (which must
+ * exist) for the given object and returns TRUE on success, or FALSE
+ * on error and sets @error.
+ */
+gboolean
+mono_runtime_object_init_checked (MonoObject *this_obj, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        MonoMethod *method = NULL;
        MonoClass *klass = this_obj->vtable->klass;
 
+       mono_error_init (error);
        method = mono_class_get_method_from_name (klass, ".ctor", 0);
        if (!method)
                g_error ("Could not lookup zero argument constructor for class %s", mono_type_get_full_name (klass));
 
        if (method->klass->valuetype)
                this_obj = (MonoObject *)mono_object_unbox (this_obj);
-       mono_runtime_invoke (method, this_obj, NULL, NULL);
+
+       mono_runtime_invoke_checked (method, this_obj, NULL, error);
+       return is_ok (error);
 }
 
 /* The pseudo algorithm for type initialization from the spec
@@ -222,6 +261,7 @@ get_type_init_exception_for_vtable (MonoVTable *vtable)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoDomain *domain = vtable->domain;
        MonoClass *klass = vtable->klass;
        MonoException *ex;
@@ -245,12 +285,14 @@ get_type_init_exception_for_vtable (MonoVTable *vtable)
                        full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
                else
                        full_name = g_strdup (klass->name);
-               ex = mono_get_exception_type_initialization (full_name, NULL);
+               ex = mono_get_exception_type_initialization_checked (full_name, NULL, &error);
                g_free (full_name);
+               return_val_if_nok (&error, NULL);
        }
 
        return ex;
 }
+
 /*
  * mono_runtime_class_init:
  * @vtable: vtable that needs to be initialized
@@ -261,23 +303,25 @@ void
 mono_runtime_class_init (MonoVTable *vtable)
 {
        MONO_REQ_GC_UNSAFE_MODE;
+       MonoError error;
 
-       mono_runtime_class_init_full (vtable, TRUE);
+       mono_runtime_class_init_full (vtable, &error);
+       mono_error_assert_ok (&error);
 }
 
-/*
+/**
  * mono_runtime_class_init_full:
  * @vtable that neeeds to be initialized
- * @raise_exception is TRUE, exceptions are raised intead of returned 
+ * @error set on error
+ *
+ * returns TRUE if class constructor .cctor has been initialized successfully, or FALSE otherwise and sets @error.
  * 
  */
-MonoException *
-mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
+gboolean
+mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoException *exc;
-       MonoException *exc_to_throw;
        MonoMethod *method = NULL;
        MonoClass *klass;
        gchar *full_name;
@@ -286,40 +330,37 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
        MonoNativeThreadId tid;
        int do_initialization = 0;
        MonoDomain *last_domain = NULL;
+       MonoException * pending_tae = NULL;
+
+       mono_error_init (error);
 
        if (vtable->initialized)
-               return NULL;
+               return TRUE;
 
-       exc = NULL;
        klass = vtable->klass;
 
        if (!klass->image->checked_module_cctor) {
                mono_image_check_for_module_cctor (klass->image);
                if (klass->image->has_module_cctor) {
-                       MonoError error;
                        MonoClass *module_klass;
                        MonoVTable *module_vtable;
 
-                       module_klass = mono_class_get_checked (klass->image, MONO_TOKEN_TYPE_DEF | 1, &error);
+                       module_klass = mono_class_get_checked (klass->image, MONO_TOKEN_TYPE_DEF | 1, error);
                        if (!module_klass) {
-                               exc = mono_error_convert_to_exception (&error);
-                               if (raise_exception)
-                                       mono_raise_exception (exc);
-                               return exc; 
+                               return FALSE;
                        }
                                
-                       module_vtable = mono_class_vtable_full (vtable->domain, module_klass, raise_exception);
+                       module_vtable = mono_class_vtable_full (vtable->domain, module_klass, error);
                        if (!module_vtable)
-                               return NULL;
-                       exc = mono_runtime_class_init_full (module_vtable, raise_exception);
-                       if (exc)
-                               return exc;
+                               return FALSE;
+                       if (!mono_runtime_class_init_full (module_vtable, error))
+                               return FALSE;
                }
        }
        method = mono_class_get_cctor (klass);
        if (!method) {
                vtable->initialized = 1;
-               return NULL;
+               return TRUE;
        }
 
        tid = mono_native_thread_id_get ();
@@ -328,15 +369,14 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
        /* double check... */
        if (vtable->initialized) {
                mono_type_initialization_unlock ();
-               return NULL;
+               return TRUE;
        }
        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);
+               mono_error_set_exception_instance (error, get_type_init_exception_for_vtable (vtable));
+               return FALSE;
        }
        lock = (TypeInitializationLock *)g_hash_table_lookup (type_initialization_hash, vtable);
        if (lock == NULL) {
@@ -347,9 +387,8 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                        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 ();
+                               mono_error_set_exception_instance (error, mono_get_exception_appdomain_unloaded ());
+                               return FALSE;
                        }
                }
                lock = (TypeInitializationLock *)g_malloc (sizeof (TypeInitializationLock));
@@ -368,7 +407,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
 
                if (mono_native_thread_id_equals (lock->initializing_tid, tid) || lock->done) {
                        mono_type_initialization_unlock ();
-                       return NULL;
+                       return TRUE;
                }
                /* see if the thread doing the initialization is already blocked on this thread */
                blocked = GUINT_TO_POINTER (MONO_NATIVE_THREAD_ID_TO_UINT (lock->initializing_tid));
@@ -376,7 +415,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                        if (mono_native_thread_id_equals (pending_lock->initializing_tid, tid)) {
                                if (!pending_lock->done) {
                                        mono_type_initialization_unlock ();
-                                       return NULL;
+                                       return TRUE;
                                } 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
@@ -393,11 +432,23 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
        mono_type_initialization_unlock ();
 
        if (do_initialization) {
-               mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
+               MonoException *exc = NULL;
+
+               mono_threads_begin_abort_protected_block ();
+               mono_runtime_try_invoke (method, NULL, NULL, (MonoObject**) &exc, error);
+               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 (!(exc == NULL ||
+               if (!(!exc ||
                          (klass->image == mono_defaults.corlib &&
                           !strcmp (klass->name_space, "System") &&
                           !strcmp (klass->name, "TypeInitializationException")))) {
@@ -407,9 +458,12 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                                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);
+
+                       MonoException *exc_to_throw = mono_get_exception_type_initialization_checked (full_name, exc, error);
                        g_free (full_name);
 
+                       mono_error_assert_ok (error); //We can't recover from this, no way to fail a type we can't alloc a failure.
+
                        /*
                         * Store the exception object so it could be thrown on subsequent
                         * accesses.
@@ -425,6 +479,11 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                        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);
@@ -445,13 +504,15 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                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 */
-               if (raise_exception)
-                       mono_raise_exception (get_type_init_exception_for_vtable (vtable));
-               return get_type_init_exception_for_vtable (vtable);
+               mono_error_set_exception_instance (error, get_type_init_exception_for_vtable (vtable));
+               return FALSE;
        }
-       return NULL;
+       return TRUE;
 }
 
 static
@@ -491,24 +552,10 @@ mono_release_type_locks (MonoInternalThread *thread)
        mono_type_initialization_unlock ();
 }
 
-static gpointer
-default_trampoline (MonoMethod *method)
-{
-       return method;
-}
-
-static gpointer
-default_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper)
-{
-       g_assert_not_reached ();
-
-       return NULL;
-}
-
 #ifndef DISABLE_REMOTING
 
 static gpointer
-default_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target)
+default_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target, MonoError *error)
 {
        g_error ("remoting not installed");
        return NULL;
@@ -524,11 +571,9 @@ default_delegate_trampoline (MonoDomain *domain, MonoClass *klass)
        return NULL;
 }
 
-static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
-static MonoJumpTrampoline arch_create_jump_trampoline = default_jump_trampoline;
 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"
@@ -546,18 +591,6 @@ mono_get_runtime_callbacks (void)
        return &callbacks;
 }
 
-void
-mono_install_trampoline (MonoTrampoline func) 
-{
-       arch_create_jit_trampoline = func? func: default_trampoline;
-}
-
-void
-mono_install_jump_trampoline (MonoJumpTrampoline func) 
-{
-       arch_create_jump_trampoline = func? func: default_jump_trampoline;
-}
-
 #ifndef DISABLE_REMOTING
 void
 mono_install_remoting_trampoline (MonoRemotingTrampoline func) 
@@ -573,55 +606,68 @@ 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;
 }
 
-static MonoCompileFunc default_mono_compile_method = NULL;
-
 /**
- * mono_install_compile_method:
- * @func: function to install
+ * mono_compile_method:
+ * @method: The method to compile.
  *
- * This is a VM internal routine
+ * This JIT-compiles the method, and returns the pointer to the native code
+ * produced.
  */
-void        
-mono_install_compile_method (MonoCompileFunc func)
+gpointer 
+mono_compile_method (MonoMethod *method)
 {
-       default_mono_compile_method = func;
+       MonoError error;
+       gpointer result = mono_compile_method_checked (method, &error);
+       mono_error_cleanup (&error);
+       return result;
 }
 
 /**
  * mono_compile_method:
  * @method: The method to compile.
+ * @error: set on error.
  *
  * This JIT-compiles the method, and returns the pointer to the native code
- * produced.
+ * produced.  On failure returns NULL and sets @error.
  */
-gpointer 
-mono_compile_method (MonoMethod *method)
+gpointer
+mono_compile_method_checked (MonoMethod *method, MonoError *error)
 {
+       gpointer res;
+
        MONO_REQ_GC_NEUTRAL_MODE
 
-       if (!default_mono_compile_method) {
+       mono_error_init (error);
+
+       if (!callbacks.compile_method) {
                g_error ("compile method called on uninitialized runtime");
                return NULL;
        }
-       return default_mono_compile_method (method);
+       res = callbacks.compile_method (method, error);
+       return res;
 }
 
 gpointer
-mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper)
+mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper, MonoError *error)
 {
-       MONO_REQ_GC_NEUTRAL_MODE
+       gpointer res;
+
+       MONO_REQ_GC_NEUTRAL_MODE;
 
-       return arch_create_jump_trampoline (domain, method, add_sync_wrapper);
+       mono_error_init (error);
+       res = callbacks.create_jump_trampoline (domain, method, add_sync_wrapper, error);
+       return res;
 }
 
 gpointer
@@ -960,10 +1006,13 @@ mono_class_insecure_overlapping (MonoClass *klass)
 #endif
 
 MonoString*
-mono_string_alloc (int length)
+ves_icall_string_alloc (int length)
 {
-       MONO_REQ_GC_UNSAFE_MODE;
-       return mono_string_new_size (mono_domain_get (), length);
+       MonoError error;
+       MonoString *str = mono_string_new_size_checked (mono_domain_get (), length, &error);
+       mono_error_set_pending_exception (&error);
+
+       return str;
 }
 
 void
@@ -979,8 +1028,8 @@ mono_class_compute_gc_descriptor (MonoClass *klass)
        if (!gcj_inited) {
                mono_loader_lock ();
 
-               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);
+               mono_register_jit_icall (ves_icall_object_new_fast, "ves_icall_object_new_fast", mono_create_icall_signature ("object ptr"), FALSE);
+               mono_register_jit_icall (ves_icall_string_alloc, "ves_icall_string_alloc", mono_create_icall_signature ("object int"), FALSE);
 
                gcj_inited = TRUE;
                mono_loader_unlock ();
@@ -1043,9 +1092,11 @@ field_is_special_static (MonoClass *fklass, MonoClassField *field)
 {
        MONO_REQ_GC_NEUTRAL_MODE;
 
+       MonoError error;
        MonoCustomAttrInfo *ainfo;
        int i;
-       ainfo = mono_custom_attrs_from_field (fklass, field);
+       ainfo = mono_custom_attrs_from_field_checked (fklass, field, &error);
+       mono_error_cleanup (&error); /* FIXME don't swallow the error? */
        if (!ainfo)
                return FALSE;
        for (i = 0; i < ainfo->num_attrs; ++i) {
@@ -1157,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;
 }
@@ -1285,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;
 }
 
@@ -1295,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));
@@ -1355,14 +1406,14 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
                for (method_slot_in_interface = 0; method_slot_in_interface < iface->method.count; method_slot_in_interface++) {
                        MonoMethod *method;
 
-                       if (slot_num >= 0 && iface->is_inflated) {
+                       if (slot_num >= 0 && mono_class_is_ginst (iface)) {
                                /*
                                 * The imt slot of the method is the same as for its declaring method,
                                 * see the comment in mono_method_get_imt_slot (), so we can
                                 * avoid inflating methods which will be discarded by 
                                 * add_imt_builder_entry anyway.
                                 */
-                               method = mono_class_get_method_by_index (iface->generic_class->container_class, method_slot_in_interface);
+                               method = mono_class_get_method_by_index (mono_class_get_generic_class (iface)->container_class, method_slot_in_interface);
                                if (mono_method_get_imt_slot (method) != slot_num) {
                                        vt_slot ++;
                                        continue;
@@ -1425,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));
@@ -1465,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;
 }
@@ -1483,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.
@@ -1511,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;
-
-       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;
-       }
+       static int generic_virtual_trampolines_size = 0;
 
-       /* 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;
-
-       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]);
+       generic_virtual_trampolines_size += size;
 
-               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 {
@@ -1735,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,
@@ -1746,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;
@@ -1756,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;
@@ -1775,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++;
        }
 
@@ -1791,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 {
@@ -1801,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;
@@ -1813,20 +1735,16 @@ 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);
 }
 
-static MonoVTable *mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean raise_on_error);
+static MonoVTable *mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoError *error);
 
 /**
  * mono_class_vtable:
@@ -1840,30 +1758,34 @@ static MonoVTable *mono_class_create_runtime_vtable (MonoDomain *domain, MonoCla
 MonoVTable *
 mono_class_vtable (MonoDomain *domain, MonoClass *klass)
 {
-       return mono_class_vtable_full (domain, klass, FALSE);
+       MonoError error;
+       MonoVTable* vtable = mono_class_vtable_full (domain, klass, &error);
+       mono_error_cleanup (&error);
+       return vtable;
 }
 
 /**
  * mono_class_vtable_full:
  * @domain: the application domain
  * @class: the class to initialize
- * @raise_on_error if an exception should be raised on failure or not
+ * @error set on failure.
  *
  * VTables are domain specific because we create domain specific code, and 
  * they contain the domain specific static class data.
  */
 MonoVTable *
-mono_class_vtable_full (MonoDomain *domain, MonoClass *klass, gboolean raise_on_error)
+mono_class_vtable_full (MonoDomain *domain, MonoClass *klass, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        MonoClassRuntimeInfo *runtime_info;
 
+       mono_error_init (error);
+
        g_assert (klass);
 
-       if (klass->exception_type) {
-               if (raise_on_error)
-                       mono_raise_exception (mono_class_get_exception_for_failure (klass));
+       if (mono_class_has_failure (klass)) {
+               mono_error_set_for_class_failure (error, klass);
                return NULL;
        }
 
@@ -1871,7 +1793,7 @@ mono_class_vtable_full (MonoDomain *domain, MonoClass *klass, gboolean raise_on_
        runtime_info = klass->runtime_info;
        if (runtime_info && runtime_info->max_domain >= domain->domain_id && runtime_info->domain_vtables [domain->domain_id])
                return runtime_info->domain_vtables [domain->domain_id];
-       return mono_class_create_runtime_vtable (domain, klass, raise_on_error);
+       return mono_class_create_runtime_vtable (domain, klass, error);
 }
 
 /**
@@ -1921,7 +1843,7 @@ alloc_vtable (MonoDomain *domain, size_t vtable_size, size_t imt_table_bytes)
 }
 
 static MonoVTable *
-mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean raise_on_error)
+mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -1936,6 +1858,8 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
        gpointer iter;
        gpointer *interface_offsets;
 
+       mono_error_init (error);
+
        mono_loader_lock (); /*FIXME mono_class_init acquires it*/
        mono_domain_lock (domain);
        runtime_info = klass->runtime_info;
@@ -1944,12 +1868,11 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
                mono_loader_unlock ();
                return runtime_info->domain_vtables [domain->domain_id];
        }
-       if (!klass->inited || klass->exception_type) {
-               if (!mono_class_init (klass) || klass->exception_type) {
+       if (!klass->inited || mono_class_has_failure (klass)) {
+               if (!mono_class_init (klass) || mono_class_has_failure (klass)) {
                        mono_domain_unlock (domain);
                        mono_loader_unlock ();
-                       if (raise_on_error)
-                               mono_raise_exception (mono_class_get_exception_for_failure (klass));
+                       mono_error_set_for_class_failure (error, klass);
                        return NULL;
                }
        }
@@ -1961,17 +1884,16 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
                        mono_class_init (element_class);
 
                /*mono_class_init can leave the vtable layout to be lazily done and we can't afford this here*/
-               if (element_class->exception_type == MONO_EXCEPTION_NONE && !element_class->vtable_size)
+               if (!mono_class_has_failure (element_class) && !element_class->vtable_size)
                        mono_class_setup_vtable (element_class);
                
-               if (element_class->exception_type != MONO_EXCEPTION_NONE) {
+               if (mono_class_has_failure (element_class)) {
                        /*Can happen if element_class only got bad after mono_class_setup_vtable*/
-                       if (klass->exception_type == MONO_EXCEPTION_NONE)
-                               mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       if (!mono_class_has_failure (klass))
+                               mono_class_set_type_load_failure (klass, "");
                        mono_domain_unlock (domain);
                        mono_loader_unlock ();
-                       if (raise_on_error)
-                               mono_raise_exception (mono_class_get_exception_for_failure (klass));
+                       mono_error_set_for_class_failure (error, klass);
                        return NULL;
                }
        }
@@ -1983,17 +1905,16 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
        if (!klass->vtable_size)
                mono_class_setup_vtable (klass);
 
-       if (klass->generic_class && !klass->vtable)
+       if (mono_class_is_ginst (klass) && !klass->vtable)
                mono_class_check_vtable_constraints (klass, NULL);
 
        /* Initialize klass->has_finalize */
        mono_class_has_finalizer (klass);
 
-       if (klass->exception_type) {
+       if (mono_class_has_failure (klass)) {
                mono_domain_unlock (domain);
                mono_loader_unlock ();
-               if (raise_on_error)
-                       mono_raise_exception (mono_class_get_exception_for_failure (klass));
+               mono_error_set_for_class_failure (error, klass);
                return NULL;
        }
 
@@ -2153,8 +2074,15 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
                for (i = 0; i < klass->vtable_size; ++i) {
                        MonoMethod *cm;
 
-                       if ((cm = klass->vtable [i]))
-                               vt->vtable [i] = arch_create_jit_trampoline (cm);
+                       cm = klass->vtable [i];
+                       if (cm) {
+                               vt->vtable [i] = callbacks.create_jit_trampoline (domain, cm, error);
+                               if (!is_ok (error)) {
+                                       mono_domain_unlock (domain);
+                                       mono_loader_unlock ();
+                                       return NULL;
+                               }
+                       }
                }
        }
 
@@ -2169,10 +2097,15 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
         * re-acquire them and check if another thread has created the vtable in the meantime.
         */
        /* Special case System.MonoType to avoid infinite recursion */
-       if (klass != mono_defaults.monotype_class) {
-               /*FIXME check for OOM*/
-               vt->type = mono_type_get_object (domain, &klass->byval_arg);
-               if (mono_object_get_class ((MonoObject *)vt->type) != mono_defaults.monotype_class)
+       if (klass != mono_defaults.runtimetype_class) {
+               vt->type = mono_type_get_object_checked (domain, &klass->byval_arg, error);
+               if (!is_ok (error)) {
+                       mono_domain_unlock (domain);
+                       mono_loader_unlock ();
+                       return NULL;
+               }
+
+               if (mono_object_get_class ((MonoObject *)vt->type) != mono_defaults.runtimetype_class)
                        /* This is unregistered in
                           unregister_vtable_reflection_type() in
                           domain.c. */
@@ -2223,10 +2156,15 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
                klass->runtime_info = runtime_info;
        }
 
-       if (klass == mono_defaults.monotype_class) {
-               /*FIXME check for OOM*/
-               vt->type = mono_type_get_object (domain, &klass->byval_arg);
-               if (mono_object_get_class ((MonoObject *)vt->type) != mono_defaults.monotype_class)
+       if (klass == mono_defaults.runtimetype_class) {
+               vt->type = mono_type_get_object_checked (domain, &klass->byval_arg, error);
+               if (!is_ok (error)) {
+                       mono_domain_unlock (domain);
+                       mono_loader_unlock ();
+                       return NULL;
+               }
+
+               if (mono_object_get_class ((MonoObject *)vt->type) != mono_defaults.runtimetype_class)
                        /* This is unregistered in
                           unregister_vtable_reflection_type() in
                           domain.c. */
@@ -2239,7 +2177,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
        /* make sure the parent is initialized */
        /*FIXME shouldn't this fail the current type?*/
        if (klass->parent)
-               mono_class_vtable_full (domain, klass->parent, raise_on_error);
+               mono_class_vtable_full (domain, klass->parent, error);
 
        return vt;
 }
@@ -2249,18 +2187,20 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
  * mono_class_proxy_vtable:
  * @domain: the application domain
  * @remove_class: the remote class
+ * @error: set on error
  *
  * Creates a vtable for transparent proxies. It is basically
  * a copy of the real vtable of the class wrapped in @remote_class,
  * but all function pointers invoke the remoting functions, and
  * vtable->klass points to the transparent proxy class, and not to @class.
+ *
+ * On failure returns NULL and sets @error
  */
 static MonoVTable *
-mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRemotingTarget target_type)
+mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRemotingTarget target_type, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoError error;
        MonoVTable *vt, *pvt;
        int i, j, vtsize, extra_interface_vtsize = 0;
        guint32 max_interface_id;
@@ -2268,7 +2208,7 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        GSList *extra_interfaces = NULL;
        MonoClass *klass = remote_class->proxy_class;
        gpointer *interface_offsets;
-       uint8_t *bitmap;
+       uint8_t *bitmap = NULL;
        int bsize;
        size_t imt_table_bytes;
        
@@ -2276,6 +2216,8 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        int bcsize;
 #endif
 
+       mono_error_init (error);
+
        vt = mono_class_vtable (domain, klass);
        g_assert (vt); /*FIXME property handle failure*/
        max_interface_id = vt->max_interface_id;
@@ -2296,8 +2238,9 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
                
                method_count = mono_class_num_methods (iclass);
        
-               ifaces = mono_class_get_implemented_interfaces (iclass, &error);
-               g_assert (mono_error_ok (&error)); /*FIXME do proper error handling*/
+               ifaces = mono_class_get_implemented_interfaces (iclass, error);
+               if (!is_ok (error))
+                       goto failure;
                if (ifaces) {
                        for (i = 0; i < ifaces->len; ++i) {
                                MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
@@ -2310,6 +2253,7 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
                                method_count += mono_class_num_methods (ic);
                        }
                        g_ptr_array_free (ifaces, TRUE);
+                       ifaces = NULL;
                }
 
                extra_interface_vtsize += method_count * sizeof (gpointer);
@@ -2339,20 +2283,25 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        for (i = 0; i < klass->vtable_size; ++i) {
                MonoMethod *cm;
                    
-               if ((cm = klass->vtable [i]))
-                       pvt->vtable [i] = arch_create_remoting_trampoline (domain, cm, target_type);
-               else
+               if ((cm = klass->vtable [i])) {
+                       pvt->vtable [i] = arch_create_remoting_trampoline (domain, cm, target_type, error);
+                       if (!is_ok (error))
+                               goto failure;
+               } else
                        pvt->vtable [i] = NULL;
        }
 
-       if (klass->flags & TYPE_ATTRIBUTE_ABSTRACT) {
+       if (mono_class_is_abstract (klass)) {
                /* create trampolines for abstract methods */
                for (k = klass; k; k = k->parent) {
                        MonoMethod* m;
                        gpointer iter = NULL;
                        while ((m = mono_class_get_methods (k, &iter)))
-                               if (!pvt->vtable [m->slot])
-                                       pvt->vtable [m->slot] = arch_create_remoting_trampoline (domain, m, target_type);
+                               if (!pvt->vtable [m->slot]) {
+                                       pvt->vtable [m->slot] = arch_create_remoting_trampoline (domain, m, target_type, error);
+                                       if (!is_ok (error))
+                                               goto failure;
+                               }
                }
        }
 
@@ -2384,8 +2333,11 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
 
                        iter = NULL;
                        j = 0;
-                       while ((cm = mono_class_get_methods (interf, &iter)))
-                               pvt->vtable [slot + j++] = arch_create_remoting_trampoline (domain, cm, target_type);
+                       while ((cm = mono_class_get_methods (interf, &iter))) {
+                               pvt->vtable [slot + j++] = arch_create_remoting_trampoline (domain, cm, target_type, error);
+                               if (!is_ok (error))
+                                       goto failure;
+                       }
                        
                        slot += mono_class_num_methods (interf);
                }
@@ -2406,6 +2358,13 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        pvt->interface_bitmap = bitmap;
 #endif
        return pvt;
+failure:
+       if (extra_interfaces)
+               g_slist_free (extra_interfaces);
+#ifdef COMPRESSED_INTERFACE_BITMAP
+       g_free (bitmap);
+#endif
+       return NULL;
 }
 
 #endif /* DISABLE_REMOTING */
@@ -2490,7 +2449,7 @@ create_remote_class_key (MonoRemoteClass *remote_class, MonoClass *extra_class)
        int i, j;
        
        if (remote_class == NULL) {
-               if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+               if (mono_class_is_interface (extra_class)) {
                        key = (void **)g_malloc (sizeof(gpointer) * 3);
                        key [0] = GINT_TO_POINTER (2);
                        key [1] = mono_defaults.marshalbyrefobject_class;
@@ -2501,7 +2460,7 @@ create_remote_class_key (MonoRemoteClass *remote_class, MonoClass *extra_class)
                        key [1] = extra_class;
                }
        } else {
-               if (extra_class != NULL && (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+               if (extra_class != NULL && mono_class_is_interface (extra_class)) {
                        key = (void **)g_malloc (sizeof(gpointer) * (remote_class->interface_count + 3));
                        key [0] = GINT_TO_POINTER (remote_class->interface_count + 2);
                        key [1] = remote_class->proxy_class;
@@ -2551,21 +2510,23 @@ copy_remote_class_key (MonoDomain *domain, gpointer *key)
  * mono_remote_class:
  * @domain: the application domain
  * @class_name: name of the remote class
+ * @error: set on error
  *
  * Creates and initializes a MonoRemoteClass object for a remote type. 
  *
- * Can raise an exception on failure. 
+ * On failure returns NULL and sets @error
  */
 MonoRemoteClass*
-mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
+mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoError error;
        MonoRemoteClass *rc;
        gpointer* key, *mp_key;
        char *name;
        
+       mono_error_init (error);
+
        key = create_remote_class_key (NULL, proxy_class);
        
        mono_domain_lock (domain);
@@ -2577,18 +2538,18 @@ mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_
                return rc;
        }
 
-       name = mono_string_to_utf8_mp (domain->mp, class_name, &error);
-       if (!mono_error_ok (&error)) {
+       name = mono_string_to_utf8_mp (domain->mp, class_name, error);
+       if (!is_ok (error)) {
                g_free (key);
                mono_domain_unlock (domain);
-               mono_error_raise_exception (&error);
+               return NULL;
        }
 
        mp_key = copy_remote_class_key (domain, key);
        g_free (key);
        key = mp_key;
 
-       if (proxy_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+       if (mono_class_is_interface (proxy_class)) {
                rc = (MonoRemoteClass *)mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*));
                rc->interface_count = 1;
                rc->interfaces [0] = proxy_class;
@@ -2635,7 +2596,7 @@ clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass
        g_free (key);
        key = mp_key;
 
-       if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+       if (mono_class_is_interface (extra_class)) {
                int i,j;
                rc = (MonoRemoteClass *)mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*) * (remote_class->interface_count + 1));
                rc->proxy_class = remote_class->proxy_class;
@@ -2669,17 +2630,20 @@ clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass
 }
 
 gpointer
-mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *rp)
+mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *rp, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
+
        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) {
                if (remote_class->xdomain_vtable == NULL)
-                       remote_class->xdomain_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_APPDOMAIN);
+                       remote_class->xdomain_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_APPDOMAIN, error);
                mono_domain_unlock (domain);
                mono_loader_unlock ();
+               return_val_if_nok (error, NULL);
                return remote_class->xdomain_vtable;
        }
        if (remote_class->default_vtable == NULL) {
@@ -2689,10 +2653,16 @@ mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mon
                klass = mono_class_from_mono_type (type);
 #ifndef DISABLE_COM
                if ((mono_class_is_com_object (klass) || (mono_class_get_com_object_class () && klass == mono_class_get_com_object_class ())) && !mono_vtable_is_remote (mono_class_vtable (mono_domain_get (), klass)))
-                       remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_COMINTEROP);
+                       remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_COMINTEROP, error);
                else
 #endif
-                       remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN);
+                       remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN, error);
+               /* N.B. both branches of the if modify error */
+               if (!is_ok (error)) {
+                       mono_domain_unlock (domain);
+                       mono_loader_unlock ();
+                       return NULL;
+               }
        }
        
        mono_domain_unlock (domain);
@@ -2705,13 +2675,14 @@ mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mon
  * @domain: the application domain
  * @tproxy: the proxy whose remote class has to be upgraded.
  * @klass: class to which the remote class can be casted.
+ * @error: set on error
  *
  * Updates the vtable of the remote class by adding the necessary method slots
  * and interface offsets so it can be safely casted to klass. klass can be a
- * class or an interface.
+ * class or an interface.  On success returns TRUE, on failure returns FALSE and sets @error.
  */
-void
-mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoClass *klass)
+gboolean
+mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoClass *klass, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -2719,13 +2690,14 @@ mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoCla
        MonoRemoteClass *remote_class;
        gboolean redo_vtable;
 
+       mono_error_init (error);
        mono_loader_lock (); /*FIXME mono_remote_class_vtable requires it.*/
        mono_domain_lock (domain);
 
        tproxy = (MonoTransparentProxy*) proxy_object;
        remote_class = tproxy->remote_class;
        
-       if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+       if (mono_class_is_interface (klass)) {
                int i;
                redo_vtable = TRUE;
                for (i = 0; i < remote_class->interface_count && redo_vtable; i++)
@@ -2738,11 +2710,15 @@ mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoCla
 
        if (redo_vtable) {
                tproxy->remote_class = clone_remote_class (domain, remote_class, klass);
-               proxy_object->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tproxy->remote_class, tproxy->rp);
+               proxy_object->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tproxy->remote_class, tproxy->rp, error);
+               if (!is_ok (error))
+                       goto leave;
        }
        
+leave:
        mono_domain_unlock (domain);
        mono_loader_unlock ();
+       return is_ok (error);
 }
 #endif /* DISABLE_REMOTING */
 
@@ -2792,7 +2768,7 @@ mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method)
 
        /* check method->slot is a valid index: perform isinstance? */
        if (method->slot != -1) {
-               if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+               if (mono_class_is_interface (method->klass)) {
                        if (!is_proxy) {
                                gboolean variance_used = FALSE;
                                int iface_offset = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
@@ -2838,13 +2814,29 @@ mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method)
 }
 
 static MonoObject*
-dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
+do_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
 {
-       g_error ("runtime invoke called on uninitialized runtime");
-       return NULL;
-}
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       MonoObject *result = NULL;
+
+       g_assert (callbacks.runtime_invoke);
 
-static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
+       mono_error_init (error);
+       
+       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
+               mono_profiler_method_start_invoke (method);
+
+       result = callbacks.runtime_invoke (method, obj, params, exc, error);
+
+       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
+               mono_profiler_method_end_invoke (method);
+
+       if (!mono_error_ok (error))
+               return NULL;
+
+       return result;
+}
 
 /**
  * mono_runtime_invoke:
@@ -2883,34 +2875,129 @@ 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 ())
-               g_warning ("Invoking method '%s' when running in no-exec mode.\n", mono_method_full_name (method, TRUE));
-
-       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
-               mono_profiler_method_start_invoke (method);
-
-       result = default_mono_runtime_invoke (method, obj, params, exc);
-
-       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
-               mono_profiler_method_end_invoke (method);
-
-       return result;
+       MonoError error;
+       MonoObject *res;
+       if (exc) {
+               res = mono_runtime_try_invoke (method, obj, params, 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, obj, params, &error);
+               mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
+       }
+       return res;
 }
 
 /**
- * mono_method_get_unmanaged_thunk:
- * @method: method to generate a thunk for.
+ * mono_runtime_try_invoke:
+ * @method: method to invoke
+ * @obJ: object instance
+ * @params: arguments to the method
+ * @exc: exception information.
+ * @error: set on error
  *
- * Returns an unmanaged->managed thunk that can be used to call
- * a managed method directly from C.
+ * Invokes the method represented by @method on the object @obj.
  *
- * The thunk's C signature closely matches the managed signature:
+ * obj is the 'this' pointer, it should be NULL for static
+ * methods, a MonoObject* for object instances and a pointer to
+ * the value type for value types.
  *
- * C#: public bool Equals (object obj);
+ * The params array contains the arguments to the method with the
+ * same convention: MonoObject* pointers for object instances and
+ * pointers to the value type otherwise. 
+ * 
+ * From unmanaged code you'll usually use the
+ * mono_runtime_invoke() variant.
+ *
+ * Note that this function doesn't handle virtual methods for
+ * you, it will exec the exact method you pass: we still need to
+ * expose a function to lookup the derived class implementation
+ * of a virtual method (there are examples of this in the code,
+ * though).
+ * 
+ * For this function, you must not pass NULL as the exc argument if
+ * you don't want to catch exceptions, use
+ * mono_runtime_invoke_checked().  If an exception is thrown, you
+ * can't use the MonoObject* result from the function.
+ * 
+ * If this method cannot be invoked, @error will be set and @exc and
+ * the return value must not be used.
+ *
+ * If the method returns a value type, it is boxed in an object
+ * reference.
+ */
+MonoObject*
+mono_runtime_try_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError* error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       g_assert (exc != NULL);
+
+       if (mono_runtime_get_no_exec ())
+               g_warning ("Invoking method '%s' when running in no-exec mode.\n", mono_method_full_name (method, TRUE));
+
+       return do_runtime_invoke (method, obj, params, exc, error);
+}
+
+/**
+ * mono_runtime_invoke_checked:
+ * @method: method to invoke
+ * @obJ: object instance
+ * @params: arguments to the method
+ * @error: set on error
+ *
+ * Invokes the method represented by @method on the object @obj.
+ *
+ * obj is the 'this' pointer, it should be NULL for static
+ * methods, a MonoObject* for object instances and a pointer to
+ * the value type for value types.
+ *
+ * The params array contains the arguments to the method with the
+ * same convention: MonoObject* pointers for object instances and
+ * pointers to the value type otherwise. 
+ * 
+ * From unmanaged code you'll usually use the
+ * mono_runtime_invoke() variant.
+ *
+ * Note that this function doesn't handle virtual methods for
+ * you, it will exec the exact method you pass: we still need to
+ * expose a function to lookup the derived class implementation
+ * of a virtual method (there are examples of this in the code,
+ * though).
+ * 
+ * If an exception is thrown, you can't use the MonoObject* result
+ * from the function.
+ * 
+ * If this method cannot be invoked, @error will be set.  If the
+ * method throws an exception (and we're in coop mode) the exception
+ * will be set in @error.
+ *
+ * If the method returns a value type, it is boxed in an object
+ * reference.
+ */
+MonoObject*
+mono_runtime_invoke_checked (MonoMethod *method, void *obj, void **params, MonoError* error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       if (mono_runtime_get_no_exec ())
+               g_warning ("Invoking method '%s' when running in no-exec mode.\n", mono_method_full_name (method, TRUE));
+
+       return do_runtime_invoke (method, obj, params, NULL, error);
+}
+
+/**
+ * mono_method_get_unmanaged_thunk:
+ * @method: method to generate a thunk for.
+ *
+ * Returns an unmanaged->managed thunk that can be used to call
+ * a managed method directly from C.
+ *
+ * The thunk's C signature closely matches the managed signature:
+ *
+ * C#: public bool Equals (object obj);
  * C:  typedef MonoBoolean (*Equals)(MonoObject*,
  *             MonoObject*, MonoException**);
  *
@@ -2957,12 +3044,16 @@ mono_method_get_unmanaged_thunk (MonoMethod *method)
        MONO_REQ_GC_NEUTRAL_MODE;
        MONO_REQ_API_ENTRYPOINT;
 
+       MonoError error;
        gpointer res;
 
-       MONO_PREPARE_RESET_BLOCKING;
+       g_assert (!mono_threads_is_coop_enabled ());
+
+       MONO_ENTER_GC_UNSAFE;
        method = mono_marshal_get_thunk_invoke_wrapper (method);
-       res = mono_compile_method (method);
-       MONO_FINISH_RESET_BLOCKING;
+       res = mono_compile_method_checked (method, &error);
+       mono_error_cleanup (&error);
+       MONO_EXIT_GC_UNSAFE;
 
        return res;
 }
@@ -3210,8 +3301,30 @@ mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
 MonoObject *
 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
 {      
+       MonoError error;
+       MonoObject* result = mono_field_get_value_object_checked (domain, field, obj, &error);
+       mono_error_assert_ok (&error);
+       return result;
+}
+
+/**
+ * mono_field_get_value_object_checked:
+ * @domain: domain where the object will be created (if boxing)
+ * @field: MonoClassField describing the field to fetch information from
+ * @obj: The object instance for the field.
+ * @error: Set on error.
+ *
+ * Returns: a new MonoObject with the value from the given field.  If the
+ * field represents a value type, the value is boxed.  On error returns NULL and sets @error.
+ *
+ */
+MonoObject *
+mono_field_get_value_object_checked (MonoDomain *domain, MonoClassField *field, MonoObject *obj, MonoError *error)
+{
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
+
        MonoObject *o;
        MonoClass *klass;
        MonoVTable *vtable = NULL;
@@ -3220,11 +3333,9 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
        gboolean is_ref = FALSE;
        gboolean is_literal = FALSE;
        gboolean is_ptr = FALSE;
-       MonoError error;
-       MonoType *type = mono_field_get_type_checked (field, &error);
+       MonoType *type = mono_field_get_type_checked (field, error);
 
-       if (!mono_error_ok (&error))
-               mono_error_raise_exception (&error);
+       return_val_if_nok (error, NULL);
 
        switch (type->type) {
        case MONO_TYPE_STRING:
@@ -3270,9 +3381,13 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
                is_static = TRUE;
 
                if (!is_literal) {
-                       vtable = mono_class_vtable_full (domain, field->parent, TRUE);
-                       if (!vtable->initialized)
-                               mono_runtime_class_init (vtable);
+                       vtable = mono_class_vtable_full (domain, field->parent, error);
+                       return_val_if_nok (error, NULL);
+
+                       if (!vtable->initialized) {
+                               mono_runtime_class_init_full (vtable, error);
+                               return_val_if_nok (error, NULL);
+                       }
                }
        } else {
                g_assert (obj);
@@ -3280,9 +3395,11 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
        
        if (is_ref) {
                if (is_literal) {
-                       get_default_field_value (domain, field, &o);
+                       get_default_field_value (domain, field, &o, error);
+                       return_val_if_nok (error, NULL);
                } else if (is_static) {
-                       mono_field_static_get_value (vtable, field, &o);
+                       mono_field_static_get_value_checked (vtable, field, &o, error);
+                       return_val_if_nok (error, NULL);
                } else {
                        mono_field_get_value (obj, field, &o);
                }
@@ -3296,40 +3413,49 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
                gpointer v;
 
                if (!m) {
-                       MonoClass *ptr_klass = mono_class_from_name_cached (mono_defaults.corlib, "System.Reflection", "Pointer");
+                       MonoClass *ptr_klass = mono_class_get_pointer_class ();
                        m = mono_class_get_method_from_name_flags (ptr_klass, "Box", 2, METHOD_ATTRIBUTE_STATIC);
                        g_assert (m);
                }
 
                v = &ptr;
                if (is_literal) {
-                       get_default_field_value (domain, field, v);
+                       get_default_field_value (domain, field, v, error);
+                       return_val_if_nok (error, NULL);
                } else if (is_static) {
-                       mono_field_static_get_value (vtable, field, v);
+                       mono_field_static_get_value_checked (vtable, field, v, error);
+                       return_val_if_nok (error, NULL);
                } else {
                        mono_field_get_value (obj, field, v);
                }
 
                /* MONO_TYPE_PTR is passed by value to runtime_invoke () */
                args [0] = ptr ? *ptr : NULL;
-               args [1] = mono_type_get_object (mono_domain_get (), type);
+               args [1] = mono_type_get_object_checked (mono_domain_get (), type, error);
+               return_val_if_nok (error, NULL);
+
+               o = mono_runtime_invoke_checked (m, NULL, args, error);
+               return_val_if_nok (error, NULL);
 
-               return mono_runtime_invoke (m, NULL, args, NULL);
+               return o;
        }
 
        /* boxed value type */
        klass = mono_class_from_mono_type (type);
 
        if (mono_class_is_nullable (klass))
-               return mono_nullable_box (mono_field_get_addr (obj, vtable, field), klass);
+               return mono_nullable_box (mono_field_get_addr (obj, vtable, field), klass, error);
 
-       o = mono_object_new (domain, klass);
+       o = mono_object_new_checked (domain, klass, error);
+       return_val_if_nok (error, NULL);
        v = ((gchar *) o) + sizeof (MonoObject);
 
        if (is_literal) {
-               get_default_field_value (domain, field, v);
+               get_default_field_value (domain, field, v, error);
+               return_val_if_nok (error, NULL);
        } else if (is_static) {
-               mono_field_static_get_value (vtable, field, v);
+               mono_field_static_get_value_checked (vtable, field, v, error);
+               return_val_if_nok (error, NULL);
        } else {
                mono_field_get_value (obj, field, v);
        }
@@ -3338,10 +3464,11 @@ 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_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, const char *blob, void *value, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
        int retval = 0;
        const char *p = blob;
        mono_metadata_decode_blob_size (p, &p);
@@ -3372,7 +3499,7 @@ mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, const
                readr8 (p, (double*) value);
                break;
        case MONO_TYPE_STRING:
-               *(gpointer*) value = mono_ldstr_metadata_sig (domain, blob);
+               *(gpointer*) value = mono_ldstr_metadata_sig (domain, blob, error);
                break;
        case MONO_TYPE_CLASS:
                *(gpointer*) value = NULL;
@@ -3385,28 +3512,32 @@ mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, const
 }
 
 static void
-get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
+get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value, MonoError *error)
 {
        MONO_REQ_GC_NEUTRAL_MODE;
 
        MonoTypeEnum def_type;
        const char* data;
+
+       mono_error_init (error);
        
        data = mono_class_get_field_default_value (field, &def_type);
-       mono_get_constant_value_from_blob (domain, def_type, data, value);
+       mono_get_constant_value_from_blob (domain, def_type, data, value, error);
 }
 
 void
-mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *vt, MonoClassField *field, void *value)
+mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *vt, MonoClassField *field, void *value, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        void *src;
 
+       mono_error_init (error);
+
        g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
        
        if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
-               get_default_field_value (vt->domain, field, value);
+               get_default_field_value (vt->domain, field, value, error);
                return;
        }
 
@@ -3441,7 +3572,37 @@ 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);
+       MonoError error;
+       mono_field_static_get_value_checked (vt, field, value, &error);
+       mono_error_cleanup (&error);
+}
+
+/**
+ * mono_field_static_get_value_checked:
+ * @vt: vtable to the object
+ * @field: MonoClassField describing the field to fetch information from
+ * @value: where the value is returned
+ * @error: set on error
+ *
+ * Use this routine to get the value of the static field @field value.
+ *
+ * The pointer provided by value must be of the field type, for reference
+ * types this is a MonoObject*, for value types its the actual pointer to
+ * the value type.
+ *
+ * For example:
+ *     int i;
+ *     mono_field_static_get_value_checked (vt, int_field, &i, error);
+ *     if (!is_ok (error)) { ... }
+ *
+ * On failure sets @error.
+ */
+void
+mono_field_static_get_value_checked (MonoVTable *vt, MonoClassField *field, void *value, MonoError *error)
+{
+       MONO_REQ_GC_NEUTRAL_MODE;
+
+       mono_field_static_get_value_for_thread (mono_thread_internal_current (), vt, field, value, error);
 }
 
 /**
@@ -3464,7 +3625,40 @@ mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObjec
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       default_mono_runtime_invoke (prop->set, obj, params, exc);
+       MonoError error;
+       do_runtime_invoke (prop->set, obj, params, exc, &error);
+       if (exc && *exc == NULL && !mono_error_ok (&error)) {
+               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+       } else {
+               mono_error_cleanup (&error);
+       }
+}
+
+/**
+ * mono_property_set_value_checked:
+ * @prop: MonoProperty to set
+ * @obj: instance object on which to act
+ * @params: parameters to pass to the propery
+ * @error: set on error
+ *
+ * Invokes the property's set method with the given arguments on the
+ * object instance obj (or NULL for static properties). 
+ * 
+ * Returns: TRUE on success.  On failure returns FALSE and sets @error.
+ * If an exception is thrown, it will be caught and returned via @error.
+ */
+gboolean
+mono_property_set_value_checked (MonoProperty *prop, void *obj, void **params, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       MonoObject *exc;
+
+       mono_error_init (error);
+       do_runtime_invoke (prop->set, obj, params, &exc, error);
+       if (exc != NULL && is_ok (error))
+               mono_error_set_exception_instance (error, (MonoException*)exc);
+       return is_ok (error);
 }
 
 /**
@@ -3489,9 +3683,48 @@ mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObjec
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       return default_mono_runtime_invoke (prop->get, obj, params, exc);
+       MonoError error;
+       MonoObject *val = do_runtime_invoke (prop->get, obj, params, exc, &error);
+       if (exc && *exc == NULL && !mono_error_ok (&error)) {
+               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+       } else {
+               mono_error_cleanup (&error); /* FIXME don't raise here */
+       }
+
+       return val;
+}
+
+/**
+ * mono_property_get_value_checked:
+ * @prop: MonoProperty to fetch
+ * @obj: instance object on which to act
+ * @params: parameters to pass to the propery
+ * @error: set on error
+ *
+ * Invokes the property's get method with the given arguments on the
+ * object instance obj (or NULL for static properties). 
+ * 
+ * If an exception is thrown, you can't use the
+ * MonoObject* result from the function.  The exception will be propagated via @error.
+ *
+ * Returns: the value from invoking the get method on the property. On
+ * failure returns NULL and sets @error.
+ */
+MonoObject*
+mono_property_get_value_checked (MonoProperty *prop, void *obj, void **params, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       MonoObject *exc;
+       MonoObject *val = do_runtime_invoke (prop->get, obj, params, &exc, error);
+       if (exc != NULL && !is_ok (error))
+               mono_error_set_exception_instance (error, (MonoException*) exc);
+       if (!is_ok (error))
+               val = NULL;
+       return val;
 }
 
+
 /*
  * mono_nullable_init:
  * @buf: The nullable structure to initialize.
@@ -3513,7 +3746,7 @@ mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
 
        MonoClass *param_class = klass->cast_class;
 
-       mono_class_setup_fields_locking (klass);
+       mono_class_setup_fields (klass);
        g_assert (klass->fields_inited);
                                
        g_assert (mono_class_from_mono_type (klass->fields [0].type) == param_class);
@@ -3534,25 +3767,28 @@ mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
  * mono_nullable_box:
  * @buf: The buffer representing the data to be boxed
  * @klass: the type to box it as.
+ * @error: set on oerr
  *
  * Creates a boxed vtype or NULL from the Nullable structure pointed to by
- * @buf.
+ * @buf.  On failure returns NULL and sets @error
  */
 MonoObject*
-mono_nullable_box (guint8 *buf, MonoClass *klass)
+mono_nullable_box (guint8 *buf, MonoClass *klass, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
        MonoClass *param_class = klass->cast_class;
 
-       mono_class_setup_fields_locking (klass);
+       mono_class_setup_fields (klass);
        g_assert (klass->fields_inited);
 
        g_assert (mono_class_from_mono_type (klass->fields [0].type) == param_class);
        g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class);
 
        if (*(guint8*)(buf + klass->fields [1].offset - sizeof (MonoObject))) {
-               MonoObject *o = mono_object_new (mono_domain_get (), param_class);
+               MonoObject *o = mono_object_new_checked (mono_domain_get (), param_class, error);
+               return_val_if_nok (error, NULL);
                if (param_class->has_references)
                        mono_gc_wbarrier_value_copy (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), 1, param_class);
                else
@@ -3578,7 +3814,7 @@ mono_get_delegate_invoke (MonoClass *klass)
 
        /* This is called at runtime, so avoid the slower search in metadata */
        mono_class_setup_methods (klass);
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return NULL;
        im = mono_class_get_method_from_name (klass, "Invoke", -1);
        return im;
@@ -3599,7 +3835,7 @@ mono_get_delegate_begin_invoke (MonoClass *klass)
 
        /* This is called at runtime, so avoid the slower search in metadata */
        mono_class_setup_methods (klass);
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return NULL;
        im = mono_class_get_method_from_name (klass, "BeginInvoke", -1);
        return im;
@@ -3620,7 +3856,7 @@ mono_get_delegate_end_invoke (MonoClass *klass)
 
        /* This is called at runtime, so avoid the slower search in metadata */
        mono_class_setup_methods (klass);
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return NULL;
        im = mono_class_get_method_from_name (klass, "EndInvoke", -1);
        return im;
@@ -3644,14 +3880,78 @@ mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+       if (exc) {
+               MonoObject *result = mono_runtime_delegate_try_invoke (delegate, params, exc, &error);
+               if (*exc) {
+                       mono_error_cleanup (&error);
+                       return NULL;
+               } else {
+                       if (!is_ok (&error))
+                               *exc = (MonoObject*)mono_error_convert_to_exception (&error);
+                       return result;
+               }
+       } else {
+               MonoObject *result = mono_runtime_delegate_invoke_checked (delegate, params, &error);
+               mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
+               return result;
+       }
+}
+
+/**
+ * mono_runtime_delegate_try_invoke:
+ * @delegate: pointer to a delegate object.
+ * @params: parameters for the delegate.
+ * @exc: Pointer to the exception result.
+ * @error: set on error
+ *
+ * Invokes the delegate method @delegate with the parameters provided.
+ *
+ * You can pass NULL as the exc argument if you don't want to
+ * catch exceptions, otherwise, *exc will be set to the exception
+ * thrown, if any.  On failure to execute, @error will be set.
+ * if an exception is thrown, you can't use the
+ * MonoObject* result from the function.
+ */
+MonoObject*
+mono_runtime_delegate_try_invoke (MonoObject *delegate, void **params, MonoObject **exc, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       mono_error_init (error);
        MonoMethod *im;
        MonoClass *klass = delegate->vtable->klass;
+       MonoObject *o;
 
        im = mono_get_delegate_invoke (klass);
        if (!im)
                g_error ("Could not lookup delegate invoke method for delegate %s", mono_type_get_full_name (klass));
 
-       return mono_runtime_invoke (im, delegate, params, exc);
+       if (exc) {
+               o = mono_runtime_try_invoke (im, delegate, params, exc, error);
+       } else {
+               o = mono_runtime_invoke_checked (im, delegate, params, error);
+       }
+
+       return o;
+}
+
+/**
+ * mono_runtime_delegate_invoke_checked:
+ * @delegate: pointer to a delegate object.
+ * @params: parameters for the delegate.
+ * @error: set on error
+ *
+ * Invokes the delegate method @delegate with the parameters provided.
+ *
+ * On failure @error will be set and you can't use the MonoObject*
+ * result from the function.
+ */
+MonoObject*
+mono_runtime_delegate_invoke_checked (MonoObject *delegate, void **params, MonoError *error)
+{
+       mono_error_init (error);
+       return mono_runtime_delegate_try_invoke (delegate, params, NULL, error);
 }
 
 static char **main_args = NULL;
@@ -3666,12 +3966,30 @@ MonoArray*
 mono_runtime_get_main_args (void)
 {
        MONO_REQ_GC_UNSAFE_MODE;
+       MonoError error;
+       MonoArray *result = mono_runtime_get_main_args_checked (&error);
+       mono_error_assert_ok (&error);
+       return result;
+}
 
+/**
+ * mono_runtime_get_main_args:
+ * @error: set on error
+ *
+ * Returns: a MonoArray with the arguments passed to the main
+ * program. On failure returns NULL and sets @error.
+ */
+MonoArray*
+mono_runtime_get_main_args_checked (MonoError *error)
+{
        MonoArray *res;
        int i;
        MonoDomain *domain = mono_domain_get ();
 
-       res = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, num_main_args);
+       mono_error_init (error);
+
+       res = (MonoArray*)mono_array_new_checked (domain, mono_defaults.string_class, num_main_args, error);
+       return_val_if_nok (error, NULL);
 
        for (i = 0; i < num_main_args; ++i)
                mono_array_setref (res, i, mono_string_new (domain, main_args [i]));
@@ -3728,25 +4046,18 @@ 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;
 
+       MonoError error;
        int i;
        MonoArray *args = NULL;
        MonoDomain *domain = mono_domain_get ();
@@ -3814,7 +4125,8 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
        }
 
        if (sig->param_count) {
-               args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
+               args = (MonoArray*)mono_array_new_checked (domain, mono_defaults.string_class, argc, &error);
+               mono_error_assert_ok (&error);
                for (i = 0; i < argc; ++i) {
                        /* The encodings should all work, given that
                         * we've checked all these args for the
@@ -3826,37 +4138,123 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
                        g_free (str);
                }
        } else {
-               args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
+               args = (MonoArray*)mono_array_new_checked (domain, mono_defaults.string_class, 0, &error);
+               mono_error_assert_ok (&error);
        }
        
        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)
-{
-       static MonoMethod *serialize_method;
-
-       void *params [1];
-       MonoObject *array;
-
-       if (!serialize_method) {
-               MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting", "RemotingServices");
-               serialize_method = mono_class_get_method_from_name (klass, "SerializeCallData", -1);
-       }
-
-       if (!serialize_method) {
-               *failure = TRUE;
-               return NULL;
-       }
+
+static MonoObject*
+serialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
+{
+       static MonoMethod *serialize_method;
+
+       MonoError error;
+       void *params [1];
+       MonoObject *array;
+
+       if (!serialize_method) {
+               MonoClass *klass = mono_class_get_remoting_services_class ();
+               serialize_method = mono_class_get_method_from_name (klass, "SerializeCallData", -1);
+       }
+
+       if (!serialize_method) {
+               *failure = TRUE;
+               return NULL;
+       }
 
        g_assert (!mono_class_is_marshalbyref (mono_object_class (obj)));
 
        params [0] = obj;
        *exc = NULL;
-       array = mono_runtime_invoke (serialize_method, NULL, params, exc);
+
+       array = mono_runtime_try_invoke (serialize_method, NULL, params, exc, &error);
+       if (*exc == NULL && !mono_error_ok (&error))
+               *exc = (MonoObject*) mono_error_convert_to_exception (&error); /* FIXME convert serialize_object to MonoError */
+       else
+               mono_error_cleanup (&error);
+
        if (*exc)
                *failure = TRUE;
 
@@ -3870,11 +4268,12 @@ deserialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 
        static MonoMethod *deserialize_method;
 
+       MonoError error;
        void *params [1];
        MonoObject *result;
 
        if (!deserialize_method) {
-               MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting", "RemotingServices");
+               MonoClass *klass = mono_class_get_remoting_services_class ();
                deserialize_method = mono_class_get_method_from_name (klass, "DeserializeCallData", -1);
        }
        if (!deserialize_method) {
@@ -3884,7 +4283,13 @@ deserialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 
        params [0] = obj;
        *exc = NULL;
-       result = mono_runtime_invoke (deserialize_method, NULL, params, exc);
+
+       result = mono_runtime_try_invoke (deserialize_method, NULL, params, exc, &error);
+       if (*exc == NULL && !mono_error_ok (&error))
+               *exc = (MonoObject*) mono_error_convert_to_exception (&error); /* FIXME convert deserialize_object to MonoError */
+       else
+               mono_error_cleanup (&error);
+
        if (*exc)
                *failure = TRUE;
 
@@ -3893,7 +4298,7 @@ deserialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 
 #ifndef DISABLE_REMOTING
 static MonoObject*
-make_transparent_proxy (MonoObject *obj, gboolean *failure, MonoObject **exc)
+make_transparent_proxy (MonoObject *obj, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -3904,21 +4309,26 @@ make_transparent_proxy (MonoObject *obj, gboolean *failure, MonoObject **exc)
        MonoReflectionType *reflection_type;
        MonoTransparentProxy *transparent_proxy;
 
+       mono_error_init (error);
+
        if (!get_proxy_method)
                get_proxy_method = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "GetTransparentProxy", 0);
 
        g_assert (mono_class_is_marshalbyref (obj->vtable->klass));
 
-       real_proxy = (MonoRealProxy*) mono_object_new (domain, mono_defaults.real_proxy_class);
-       reflection_type = mono_type_get_object (domain, &obj->vtable->klass->byval_arg);
+       real_proxy = (MonoRealProxy*) mono_object_new_checked (domain, mono_defaults.real_proxy_class, error);
+       return_val_if_nok (error, NULL);
+       reflection_type = mono_type_get_object_checked (domain, &obj->vtable->klass->byval_arg, error);
+       return_val_if_nok (error, NULL);
 
        MONO_OBJECT_SETREF (real_proxy, class_to_proxy, reflection_type);
        MONO_OBJECT_SETREF (real_proxy, unwrapped_server, obj);
 
-       *exc = NULL;
-       transparent_proxy = (MonoTransparentProxy*) mono_runtime_invoke (get_proxy_method, real_proxy, NULL, exc);
-       if (*exc)
-               *failure = TRUE;
+       MonoObject *exc = NULL;
+
+       transparent_proxy = (MonoTransparentProxy*) mono_runtime_try_invoke (get_proxy_method, real_proxy, NULL, &exc, error);
+       if (exc != NULL && is_ok (error))
+               mono_error_set_exception_instance (error, (MonoException*)exc);
 
        return (MonoObject*) transparent_proxy;
 }
@@ -3928,7 +4338,7 @@ make_transparent_proxy (MonoObject *obj, gboolean *failure, MonoObject **exc)
  * mono_object_xdomain_representation
  * @obj: an object
  * @target_domain: a domain
- * @exc: pointer to a MonoObject*
+ * @error: set on error.
  *
  * Creates a representation of obj in the domain target_domain.  This
  * is either a copy of obj arrived through via serialization and
@@ -3936,35 +4346,37 @@ make_transparent_proxy (MonoObject *obj, gboolean *failure, MonoObject **exc)
  * serializable or marshal by ref.  obj must not be in target_domain.
  *
  * If the object cannot be represented in target_domain, NULL is
- * returned and *exc is set to an appropriate exception.
+ * returned and @error is set appropriately.
  */
 MonoObject*
-mono_object_xdomain_representation (MonoObject *obj, MonoDomain *target_domain, MonoObject **exc)
+mono_object_xdomain_representation (MonoObject *obj, MonoDomain *target_domain, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
        MonoObject *deserialized = NULL;
-       gboolean failure = FALSE;
-
-       *exc = NULL;
 
 #ifndef DISABLE_REMOTING
        if (mono_class_is_marshalbyref (mono_object_class (obj))) {
-               deserialized = make_transparent_proxy (obj, &failure, exc);
+               deserialized = make_transparent_proxy (obj, error);
        } 
        else
 #endif
        {
+               gboolean failure = FALSE;
                MonoDomain *domain = mono_domain_get ();
                MonoObject *serialized;
+               MonoObject *exc = NULL;
 
                mono_domain_set_internal_with_options (mono_object_domain (obj), FALSE);
-               serialized = serialize_object (obj, &failure, exc);
+               serialized = serialize_object (obj, &failure, &exc);
                mono_domain_set_internal_with_options (target_domain, FALSE);
                if (!failure)
-                       deserialized = deserialize_object (serialized, &failure, exc);
+                       deserialized = deserialize_object (serialized, &failure, &exc);
                if (domain != target_domain)
                        mono_domain_set_internal_with_options (domain, FALSE);
+               if (failure)
+                       mono_error_set_exception_instance (error, (MonoException*)exc);
        }
 
        return deserialized;
@@ -3972,19 +4384,18 @@ mono_object_xdomain_representation (MonoObject *obj, MonoDomain *target_domain,
 
 /* Used in call_unhandled_exception_delegate */
 static MonoObject *
-create_unhandled_exception_eventargs (MonoObject *exc)
+create_unhandled_exception_eventargs (MonoObject *exc, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
        MonoClass *klass;
        gpointer args [2];
        MonoMethod *method = NULL;
        MonoBoolean is_terminating = TRUE;
        MonoObject *obj;
 
-       klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
-       g_assert (klass);
-
+       klass = mono_class_get_unhandled_exception_event_args_class ();
        mono_class_init (klass);
 
        /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
@@ -3994,8 +4405,11 @@ create_unhandled_exception_eventargs (MonoObject *exc)
        args [0] = exc;
        args [1] = &is_terminating;
 
-       obj = mono_object_new (mono_domain_get (), klass);
-       mono_runtime_invoke (method, obj, args, NULL);
+       obj = mono_object_new_checked (mono_domain_get (), klass, error);
+       return_val_if_nok (error, NULL);
+
+       mono_runtime_invoke_checked (method, obj, args, error);
+       return_val_if_nok (error, NULL);
 
        return obj;
 }
@@ -4005,6 +4419,7 @@ static void
 call_unhandled_exception_delegate (MonoDomain *domain, MonoObject *delegate, MonoObject *exc) {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoObject *e = NULL;
        gpointer pa [2];
        MonoDomain *current_domain = mono_domain_get ();
@@ -4015,14 +4430,14 @@ call_unhandled_exception_delegate (MonoDomain *domain, MonoObject *delegate, Mon
        g_assert (domain == mono_object_domain (domain->domain));
 
        if (mono_object_domain (exc) != domain) {
-               MonoObject *serialization_exc;
 
-               exc = mono_object_xdomain_representation (exc, domain, &serialization_exc);
+               exc = mono_object_xdomain_representation (exc, domain, &error);
                if (!exc) {
-                       if (serialization_exc) {
-                               MonoObject *dummy;
-                               exc = mono_object_xdomain_representation (serialization_exc, domain, &dummy);
-                               g_assert (exc);
+                       if (!is_ok (&error)) {
+                               MonoError inner_error;
+                               MonoException *serialization_exc = mono_error_convert_to_exception (&error);
+                               exc = mono_object_xdomain_representation ((MonoObject*)serialization_exc, domain, &inner_error);
+                               mono_error_assert_ok (&inner_error);
                        } else {
                                exc = (MonoObject*) mono_exception_from_name_msg (mono_get_corlib (),
                                                "System.Runtime.Serialization", "SerializationException",
@@ -4033,14 +4448,20 @@ call_unhandled_exception_delegate (MonoDomain *domain, MonoObject *delegate, Mon
        g_assert (mono_object_domain (exc) == domain);
 
        pa [0] = domain->domain;
-       pa [1] = create_unhandled_exception_eventargs (exc);
-       mono_runtime_delegate_invoke (delegate, pa, &e);
+       pa [1] = create_unhandled_exception_eventargs (exc, &error);
+       mono_error_assert_ok (&error);
+       mono_runtime_delegate_try_invoke (delegate, pa, &e, &error);
+       if (!is_ok (&error)) {
+               if (e == NULL)
+                       e = (MonoObject*)mono_error_convert_to_exception (&error);
+               else
+                       mono_error_cleanup (&error);
+       }
 
        if (domain != current_domain)
                mono_domain_set_internal_with_options (current_domain, FALSE);
 
        if (e) {
-               MonoError error;
                gchar *msg = mono_string_to_utf8_checked (((MonoException *) e)->message, &error);
                if (!mono_error_ok (&error)) {
                        g_warning ("Exception inside UnhandledException handler with invalid message (Invalid characters)\n");
@@ -4096,6 +4517,7 @@ mono_unhandled_exception (MonoObject *exc)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoClassField *field;
        MonoDomain *current_domain, *root_domain;
        MonoObject *current_appdomain_delegate = NULL, *root_appdomain_delegate = NULL;
@@ -4109,24 +4531,30 @@ mono_unhandled_exception (MonoObject *exc)
        current_domain = mono_domain_get ();
        root_domain = mono_get_root_domain ();
 
-       root_appdomain_delegate = mono_field_get_value_object (root_domain, field, (MonoObject*) root_domain->domain);
-       if (current_domain != root_domain)
-               current_appdomain_delegate = mono_field_get_value_object (current_domain, field, (MonoObject*) current_domain->domain);
+       root_appdomain_delegate = mono_field_get_value_object_checked (root_domain, field, (MonoObject*) root_domain->domain, &error);
+       mono_error_assert_ok (&error);
+       if (current_domain != root_domain) {
+               current_appdomain_delegate = mono_field_get_value_object_checked (current_domain, field, (MonoObject*) current_domain->domain, &error);
+               mono_error_assert_ok (&error);
+       }
 
-       /* set exitcode only if we will abort the process */
        if (!current_appdomain_delegate && !root_appdomain_delegate) {
-               if ((main_thread && mono_thread_internal_current () == main_thread->internal_thread)
-                    || mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_CURRENT)
-               {
-                       mono_environment_exitcode_set (1);
-               }
-
                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 */
+       if ((main_thread && mono_thread_internal_current () == main_thread->internal_thread)
+                || mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_CURRENT)
+       {
+               mono_environment_exitcode_set (1);
        }
 }
 
@@ -4151,32 +4579,20 @@ mono_runtime_exec_managed_code (MonoDomain *domain,
                                MonoMainThreadFunc main_func,
                                gpointer main_args)
 {
-       mono_thread_create (domain, main_func, main_args);
+       MonoError error;
+       mono_thread_create_checked (domain, main_func, main_args, &error);
+       mono_error_assert_ok (&error);
 
        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;
-
-       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;
@@ -4192,16 +4608,15 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
                        str = g_strconcat (assembly->image->name, ".config", NULL);
                        MONO_OBJECT_SETREF (domain->setup, configuration_file, mono_string_new (domain, str));
                        g_free (str);
-                       mono_set_private_bin_path_from_config (domain);
+                       mono_domain_set_options_from_config (domain);
                }
        }
 
-       cinfo = mono_custom_attrs_from_method (method);
+       MonoError cattr_error;
+       cinfo = mono_custom_attrs_from_method_checked (method, &cattr_error);
+       mono_error_cleanup (&cattr_error); /* FIXME warn here? */
        if (cinfo) {
-               static MonoClass *stathread_attribute = NULL;
-               if (!stathread_attribute)
-                       stathread_attribute = mono_class_from_name (mono_defaults.corlib, "System", "STAThreadAttribute");
-               has_stathread_attribute = mono_custom_attrs_has_attr (cinfo, stathread_attribute);
+               has_stathread_attribute = mono_custom_attrs_has_attr (cinfo, mono_class_get_sta_thread_attribute_class ());
                if (!cinfo->cached)
                        mono_custom_attrs_free (cinfo);
        } else {
@@ -4214,19 +4629,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;
+               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;
+
        /* FIXME: check signature of method */
        if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
+               MonoError inner_error;
                MonoObject *res;
-               res = mono_runtime_invoke (method, NULL, pa, exc);
-               if (!exc || !*exc)
+               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 {
-               mono_runtime_invoke (method, NULL, pa, exc);
-               if (!exc || !*exc)
+               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 == NULL)
                        rval = 0;
                else {
                        /* If the return type of Main is void, only
@@ -4242,73 +4718,72 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
        return rval;
 }
 
-/**
- * mono_install_runtime_invoke:
- * @func: Function to install
- *
- * This is a VM internal routine
+/*
+ * Execute a standard Main() method (args doesn't contain the
+ * executable name).
  */
-void
-mono_install_runtime_invoke (MonoInvokeFunc func)
+int
+mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
 {
-       default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
+       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;
+       }
 }
 
-
-/**
- * mono_runtime_invoke_array:
- * @method: method to invoke
- * @obJ: object instance
- * @params: arguments to the method
- * @exc: exception information.
- *
- * Invokes the method represented by @method on the object @obj.
- *
- * obj is the 'this' pointer, it should be NULL for static
- * methods, a MonoObject* for object instances and a pointer to
- * the value type for value types.
+/*
+ * Execute a standard Main() method (args doesn't contain the
+ * executable name).
  *
- * The params array contains the arguments to the method with the
- * same convention: MonoObject* pointers for object instances and
- * pointers to the value type otherwise. The _invoke_array
- * variant takes a C# object[] as the params argument (MonoArray
- * *params): in this case the value types are boxed inside the
- * respective reference representation.
- * 
- * From unmanaged code you'll usually use the
- * mono_runtime_invoke() variant.
+ * 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).
  *
- * Note that this function doesn't handle virtual methods for
- * you, it will exec the exact method you pass: we still need to
- * expose a function to lookup the derived class implementation
- * of a virtual method (there are examples of this in the code,
- * though).
- * 
- * You can pass NULL as the exc argument if you don't want to
- * catch exceptions, otherwise, *exc will be set to the exception
- * thrown, if any.  if an exception is thrown, you can't use the
- * MonoObject* result from the function.
- * 
- * If the method returns a value type, it is boxed in an object
- * reference.
+ * On failure sets @error if Main couldn't be executed, or @exc if it threw an exception.
  */
-MonoObject*
-mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
-                          MonoObject **exc)
+int
+mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
 {
-       MONO_REQ_GC_UNSAFE_MODE;
+       prepare_thread_to_exec_main (mono_object_domain (args), method);
+       return do_try_exec_main (method, args, exc);
+}
 
-       MonoMethodSignature *sig = mono_method_signature (method);
-       gpointer *pa = NULL;
-       MonoObject *res;
-       int i;
-       gboolean has_byref_nullables = FALSE;
 
-       if (NULL != params) {
-               pa = (void **)alloca (sizeof (gpointer) * mono_array_length (params));
-               for (i = 0; i < mono_array_length (params); i++) {
-                       MonoType *t = sig->params [i];
 
+/** invoke_array_extract_argument:
+ * @params: array of arguments to the method.
+ * @i: the index of the argument to extract.
+ * @t: ith type from the method signature.
+ * @has_byref_nullables: outarg - TRUE if method expects a byref nullable argument
+ * @error: set on error.
+ *
+ * Given an array of method arguments, return the ith one using the corresponding type
+ * to perform necessary unboxing.  If method expects a ref nullable argument, writes TRUE to @has_byref_nullables.
+ *
+ * On failure sets @error and returns NULL.
+ */
+static gpointer
+invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, gboolean* has_byref_nullables, MonoError *error)
+{
+       MonoType *t_orig = t;
+       gpointer result = NULL;
+       mono_error_init (error);
                again:
                        switch (t->type) {
                        case MONO_TYPE_U1:
@@ -4326,15 +4801,18 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                        case MONO_TYPE_R4:
                        case MONO_TYPE_R8:
                        case MONO_TYPE_VALUETYPE:
-                               if (t->type == MONO_TYPE_VALUETYPE && mono_class_is_nullable (mono_class_from_mono_type (sig->params [i]))) {
+                               if (t->type == MONO_TYPE_VALUETYPE && mono_class_is_nullable (mono_class_from_mono_type (t_orig))) {
                                        /* The runtime invoke wrapper needs the original boxed vtype, it does handle byref values as well. */
-                                       pa [i] = mono_array_get (params, MonoObject*, i);
+                                       result = mono_array_get (params, MonoObject*, i);
                                        if (t->byref)
-                                               has_byref_nullables = TRUE;
+                                               *has_byref_nullables = TRUE;
                                } else {
                                        /* MS seems to create the objects if a null is passed in */
-                                       if (!mono_array_get (params, MonoObject*, i))
-                                               mono_array_setref (params, i, mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]))); 
+                                       if (!mono_array_get (params, MonoObject*, i)) {
+                                               MonoObject *o = mono_object_new_checked (mono_domain_get (), mono_class_from_mono_type (t_orig), error);
+                                               return_val_if_nok (error, NULL);
+                                               mono_array_setref (params, i, o); 
+                                       }
 
                                        if (t->byref) {
                                                /*
@@ -4345,11 +4823,12 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                                                 * boxed object in the arg array with the copy.
                                                 */
                                                MonoObject *orig = mono_array_get (params, MonoObject*, i);
-                                               MonoObject *copy = mono_value_box (mono_domain_get (), orig->vtable->klass, mono_object_unbox (orig));
+                                               MonoObject *copy = mono_value_box_checked (mono_domain_get (), orig->vtable->klass, mono_object_unbox (orig), error);
+                                               return_val_if_nok (error, NULL);
                                                mono_array_setref (params, i, copy);
                                        }
                                                
-                                       pa [i] = mono_object_unbox (mono_array_get (params, MonoObject*, i));
+                                       result = mono_object_unbox (mono_array_get (params, MonoObject*, i));
                                }
                                break;
                        case MONO_TYPE_STRING:
@@ -4358,10 +4837,10 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                        case MONO_TYPE_ARRAY:
                        case MONO_TYPE_SZARRAY:
                                if (t->byref)
-                                       pa [i] = mono_array_addr (params, MonoObject*, i);
+                                       result = mono_array_addr (params, MonoObject*, i);
                                        // FIXME: I need to check this code path
                                else
-                                       pa [i] = mono_array_get (params, MonoObject*, i);
+                                       result = mono_array_get (params, MonoObject*, i);
                                break;
                        case MONO_TYPE_GENERICINST:
                                if (t->byref)
@@ -4375,16 +4854,179 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                                /* The argument should be an IntPtr */
                                arg = mono_array_get (params, MonoObject*, i);
                                if (arg == NULL) {
-                                       pa [i] = NULL;
+                                       result = NULL;
                                } else {
                                        g_assert (arg->vtable->klass == mono_defaults.int_class);
-                                       pa [i] = ((MonoIntPtr*)arg)->m_value;
+                                       result = ((MonoIntPtr*)arg)->m_value;
                                }
                                break;
                        }
                        default:
-                               g_error ("type 0x%x not handled in mono_runtime_invoke_array", sig->params [i]->type);
+                               g_error ("type 0x%x not handled in mono_runtime_invoke_array", t_orig->type);
                        }
+       return result;
+}
+/**
+ * mono_runtime_invoke_array:
+ * @method: method to invoke
+ * @obJ: object instance
+ * @params: arguments to the method
+ * @exc: exception information.
+ *
+ * Invokes the method represented by @method on the object @obj.
+ *
+ * obj is the 'this' pointer, it should be NULL for static
+ * methods, a MonoObject* for object instances and a pointer to
+ * the value type for value types.
+ *
+ * The params array contains the arguments to the method with the
+ * same convention: MonoObject* pointers for object instances and
+ * pointers to the value type otherwise. The _invoke_array
+ * variant takes a C# object[] as the params argument (MonoArray
+ * *params): in this case the value types are boxed inside the
+ * respective reference representation.
+ * 
+ * From unmanaged code you'll usually use the
+ * mono_runtime_invoke_checked() variant.
+ *
+ * Note that this function doesn't handle virtual methods for
+ * you, it will exec the exact method you pass: we still need to
+ * expose a function to lookup the derived class implementation
+ * of a virtual method (there are examples of this in the code,
+ * though).
+ * 
+ * You can pass NULL as the exc argument if you don't want to
+ * catch exceptions, otherwise, *exc will be set to the exception
+ * thrown, if any.  if an exception is thrown, you can't use the
+ * MonoObject* result from the function.
+ * 
+ * If the method returns a value type, it is boxed in an object
+ * reference.
+ */
+MonoObject*
+mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
+                          MonoObject **exc)
+{
+       MonoError error;
+       if (exc) {
+               MonoObject *result = mono_runtime_try_invoke_array (method, obj, params, exc, &error);
+               if (*exc) {
+                       mono_error_cleanup (&error);
+                       return NULL;
+               } else {
+                       if (!is_ok (&error))
+                               *exc = (MonoObject*)mono_error_convert_to_exception (&error);
+                       return result;
+               }
+       } else {
+               MonoObject *result = mono_runtime_try_invoke_array (method, obj, params, NULL, &error);
+               mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
+               return result;
+       }
+}
+
+/**
+ * mono_runtime_invoke_array_checked:
+ * @method: method to invoke
+ * @obJ: object instance
+ * @params: arguments to the method
+ * @error: set on failure.
+ *
+ * Invokes the method represented by @method on the object @obj.
+ *
+ * obj is the 'this' pointer, it should be NULL for static
+ * methods, a MonoObject* for object instances and a pointer to
+ * the value type for value types.
+ *
+ * The params array contains the arguments to the method with the
+ * same convention: MonoObject* pointers for object instances and
+ * pointers to the value type otherwise. The _invoke_array
+ * variant takes a C# object[] as the params argument (MonoArray
+ * *params): in this case the value types are boxed inside the
+ * respective reference representation.
+ *
+ * From unmanaged code you'll usually use the
+ * mono_runtime_invoke_checked() variant.
+ *
+ * Note that this function doesn't handle virtual methods for
+ * you, it will exec the exact method you pass: we still need to
+ * expose a function to lookup the derived class implementation
+ * of a virtual method (there are examples of this in the code,
+ * though).
+ *
+ * On failure or exception, @error will be set. In that case, you
+ * can't use the MonoObject* result from the function.
+ *
+ * If the method returns a value type, it is boxed in an object
+ * reference.
+ */
+MonoObject*
+mono_runtime_invoke_array_checked (MonoMethod *method, void *obj, MonoArray *params,
+                                  MonoError *error)
+{
+       mono_error_init (error);
+       return mono_runtime_try_invoke_array (method, obj, params, NULL, error);
+}
+
+/**
+ * mono_runtime_try_invoke_array:
+ * @method: method to invoke
+ * @obJ: object instance
+ * @params: arguments to the method
+ * @exc: exception information.
+ * @error: set on failure.
+ *
+ * Invokes the method represented by @method on the object @obj.
+ *
+ * obj is the 'this' pointer, it should be NULL for static
+ * methods, a MonoObject* for object instances and a pointer to
+ * the value type for value types.
+ *
+ * The params array contains the arguments to the method with the
+ * same convention: MonoObject* pointers for object instances and
+ * pointers to the value type otherwise. The _invoke_array
+ * variant takes a C# object[] as the params argument (MonoArray
+ * *params): in this case the value types are boxed inside the
+ * respective reference representation.
+ *
+ * From unmanaged code you'll usually use the
+ * mono_runtime_invoke_checked() variant.
+ *
+ * Note that this function doesn't handle virtual methods for
+ * you, it will exec the exact method you pass: we still need to
+ * expose a function to lookup the derived class implementation
+ * of a virtual method (there are examples of this in the code,
+ * though).
+ *
+ * You can pass NULL as the exc argument if you don't want to catch
+ * exceptions, otherwise, *exc will be set to the exception thrown, if
+ * any.  On other failures, @error will be set. If an exception is
+ * thrown or there's an error, you can't use the MonoObject* result
+ * from the function.
+ *
+ * If the method returns a value type, it is boxed in an object
+ * reference.
+ */
+MonoObject*
+mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
+                              MonoObject **exc, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       mono_error_init (error);
+
+       MonoMethodSignature *sig = mono_method_signature (method);
+       gpointer *pa = NULL;
+       MonoObject *res;
+       int i;
+       gboolean has_byref_nullables = FALSE;
+
+       if (NULL != params) {
+               pa = (void **)alloca (sizeof (gpointer) * mono_array_length (params));
+               for (i = 0; i < mono_array_length (params); i++) {
+                       MonoType *t = sig->params [i];
+                       pa [i] = invoke_array_extract_argument (params, i, t, &has_byref_nullables, error);
+                       return_val_if_nok (error, NULL);
                }
        }
 
@@ -4397,12 +5039,14 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
 
                        if (!params)
                                return NULL;
-                       else
-                               return mono_value_box (mono_domain_get (), method->klass->cast_class, pa [0]);
+                       else {
+                               return mono_value_box_checked (mono_domain_get (), method->klass->cast_class, pa [0], error);
+                       }
                }
 
                if (!obj) {
-                       obj = mono_object_new (mono_domain_get (), method->klass);
+                       obj = mono_object_new_checked (mono_domain_get (), method->klass, error);
+                       mono_error_assert_ok (error);
                        g_assert (obj); /*maybe we should raise a TLE instead?*/
 #ifndef DISABLE_REMOTING
                        if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
@@ -4414,24 +5058,38 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                        else
                                o = obj;
                } else if (method->klass->valuetype) {
-                       obj = mono_value_box (mono_domain_get (), method->klass, obj);
+                       obj = mono_value_box_checked (mono_domain_get (), method->klass, obj, error);
+                       return_val_if_nok (error, NULL);
+               }
+
+               if (exc) {
+                       mono_runtime_try_invoke (method, o, pa, exc, error);
+               } else {
+                       mono_runtime_invoke_checked (method, o, pa, error);
                }
 
-               mono_runtime_invoke (method, o, pa, exc);
                return (MonoObject *)obj;
        } else {
                if (mono_class_is_nullable (method->klass)) {
                        MonoObject *nullable;
 
                        /* Convert the unboxed vtype into a Nullable structure */
-                       nullable = mono_object_new (mono_domain_get (), method->klass);
+                       nullable = mono_object_new_checked (mono_domain_get (), method->klass, error);
+                       return_val_if_nok (error, NULL);
 
-                       mono_nullable_init ((guint8 *)mono_object_unbox (nullable), mono_value_box (mono_domain_get (), method->klass->cast_class, obj), method->klass);
+                       MonoObject *boxed = mono_value_box_checked (mono_domain_get (), method->klass->cast_class, obj, error);
+                       return_val_if_nok (error, NULL);
+                       mono_nullable_init ((guint8 *)mono_object_unbox (nullable), boxed, method->klass);
                        obj = mono_object_unbox (nullable);
                }
 
                /* obj must be already unboxed if needed */
-               res = mono_runtime_invoke (method, obj, pa, exc);
+               if (exc) {
+                       res = mono_runtime_try_invoke (method, obj, pa, exc, error);
+               } else {
+                       res = mono_runtime_invoke_checked (method, obj, pa, error);
+               }
+               return_val_if_nok (error, NULL);
 
                if (sig->ret->type == MONO_TYPE_PTR) {
                        MonoClass *pointer_class;
@@ -4443,15 +5101,18 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                         * The runtime-invoke wrapper returns a boxed IntPtr, need to 
                         * convert it to a Pointer object.
                         */
-                       pointer_class = mono_class_from_name_cached (mono_defaults.corlib, "System.Reflection", "Pointer");
+                       pointer_class = mono_class_get_pointer_class ();
                        if (!box_method)
                                box_method = mono_class_get_method_from_name (pointer_class, "Box", -1);
 
                        g_assert (res->vtable->klass == mono_defaults.int_class);
                        box_args [0] = ((MonoIntPtr*)res)->m_value;
-                       box_args [1] = mono_type_get_object (mono_domain_get (), sig->ret);
-                       res = mono_runtime_invoke (box_method, NULL, box_args, &box_exc);
-                       g_assert (!box_exc);
+                       box_args [1] = mono_type_get_object_checked (mono_domain_get (), sig->ret, error);
+                       return_val_if_nok (error, NULL);
+
+                       res = mono_runtime_try_invoke (box_method, NULL, box_args, &box_exc, error);
+                       g_assert (box_exc == NULL);
+                       mono_error_assert_ok (error);
                }
 
                if (has_byref_nullables) {
@@ -4472,36 +5133,67 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
        }
 }
 
-static void
-arith_overflow (void)
+/**
+ * mono_object_new:
+ * @klass: the class of the object that we want to create
+ *
+ * Returns: a newly created object whose definition is
+ * looked up using @klass.   This will not invoke any constructors, 
+ * so the consumer of this routine has to invoke any constructors on
+ * its own to initialize the object.
+ * 
+ * It returns NULL on failure.
+ */
+MonoObject *
+mono_object_new (MonoDomain *domain, MonoClass *klass)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       mono_raise_exception (mono_get_exception_overflow ());
+       MonoError error;
+
+       MonoObject * result = mono_object_new_checked (domain, klass, &error);
+
+       mono_error_cleanup (&error);
+       return result;
+}
+
+MonoObject *
+ves_icall_object_new (MonoDomain *domain, MonoClass *klass)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       MonoError error;
+
+       MonoObject * result = mono_object_new_checked (domain, klass, &error);
+
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 /**
- * mono_object_new:
+ * mono_object_new_checked:
  * @klass: the class of the object that we want to create
+ * @error: set on error
  *
  * Returns: a newly created object whose definition is
- * looked up using @klass.   This will not invoke any constructors, 
+ * looked up using @klass.   This will not invoke any constructors,
  * so the consumer of this routine has to invoke any constructors on
  * its own to initialize the object.
- * 
- * It returns NULL on failure.
+ *
+ * It returns NULL on failure and sets @error.
  */
 MonoObject *
-mono_object_new (MonoDomain *domain, MonoClass *klass)
+mono_object_new_checked (MonoDomain *domain, MonoClass *klass, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        MonoVTable *vtable;
 
        vtable = mono_class_vtable (domain, klass);
-       if (!vtable)
-               return NULL;
-       return mono_object_new_specific (vtable);
+       g_assert (vtable); /* FIXME don't swallow the error */
+
+       MonoObject *o = mono_object_new_specific_checked (vtable, error);
+       return o;
 }
 
 /**
@@ -4511,21 +5203,25 @@ mono_object_new (MonoDomain *domain, MonoClass *klass)
  * For SGEN, these objects will only be freed at appdomain unload.
  */
 MonoObject *
-mono_object_new_pinned (MonoDomain *domain, MonoClass *klass)
+mono_object_new_pinned (MonoDomain *domain, MonoClass *klass, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        MonoVTable *vtable;
 
+       mono_error_init (error);
+
        vtable = mono_class_vtable (domain, klass);
-       if (!vtable)
-               return NULL;
+       g_assert (vtable); /* FIXME don't swallow the error */
 
-#ifdef HAVE_SGEN_GC
-       return (MonoObject *)mono_gc_alloc_pinned_obj (vtable, mono_class_instance_size (klass));
-#else
-       return mono_object_new_specific (vtable);
-#endif
+       MonoObject *o = (MonoObject *)mono_gc_alloc_pinned_obj (vtable, mono_class_instance_size (klass));
+
+       if (G_UNLIKELY (!o))
+               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", mono_class_instance_size (klass));
+       else if (G_UNLIKELY (vtable->klass->has_finalize))
+               mono_object_register_finalizer (o);
+
+       return o;
 }
 
 /**
@@ -4537,11 +5233,23 @@ mono_object_new_pinned (MonoDomain *domain, MonoClass *klass)
  */
 MonoObject *
 mono_object_new_specific (MonoVTable *vtable)
+{
+       MonoError error;
+       MonoObject *o = mono_object_new_specific_checked (vtable, &error);
+       mono_error_cleanup (&error);
+
+       return o;
+}
+
+MonoObject *
+mono_object_new_specific_checked (MonoVTable *vtable, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        MonoObject *o;
 
+       mono_error_init (error);
+
        /* check for is_com_object for COM Interop */
        if (mono_vtable_is_remote (vtable) || mono_class_is_com_object (vtable->klass))
        {
@@ -4549,45 +5257,189 @@ mono_object_new_specific (MonoVTable *vtable)
                MonoMethod *im = vtable->domain->create_proxy_for_type_method;
 
                if (im == NULL) {
-                       MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
+                       MonoClass *klass = mono_class_get_activation_services_class ();
 
                        if (!klass->inited)
                                mono_class_init (klass);
 
                        im = mono_class_get_method_from_name (klass, "CreateProxyForType", 1);
-                       if (!im)
-                               mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
+                       if (!im) {
+                               mono_error_set_not_supported (error, "Linked away.");
+                               return NULL;
+                       }
                        vtable->domain->create_proxy_for_type_method = im;
                }
        
-               pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
+               pa [0] = mono_type_get_object_checked (mono_domain_get (), &vtable->klass->byval_arg, error);
+               if (!mono_error_ok (error))
+                       return NULL;
 
-               o = mono_runtime_invoke (im, NULL, pa, NULL);           
-               if (o != NULL) return o;
+               o = mono_runtime_invoke_checked (im, NULL, pa, error);
+               if (!mono_error_ok (error))
+                       return NULL;
+
+               if (o != NULL)
+                       return o;
        }
 
-       return mono_object_new_alloc_specific (vtable);
+       return mono_object_new_alloc_specific_checked (vtable, error);
+}
+
+MonoObject *
+ves_icall_object_new_specific (MonoVTable *vtable)
+{
+       MonoError error;
+       MonoObject *o = mono_object_new_specific_checked (vtable, &error);
+       mono_error_set_pending_exception (&error);
+
+       return o;
 }
 
+/**
+ * mono_object_new_alloc_specific:
+ * @vtable: virtual table for the object.
+ *
+ * This function allocates a new `MonoObject` with the type derived
+ * from the @vtable information.   If the class of this object has a 
+ * finalizer, then the object will be tracked for finalization.
+ *
+ * This method might raise an exception on errors.  Use the
+ * `mono_object_new_fast_checked` method if you want to manually raise
+ * the exception.
+ *
+ * Returns: the allocated object.   
+ */
 MonoObject *
 mono_object_new_alloc_specific (MonoVTable *vtable)
+{
+       MonoError error;
+       MonoObject *o = mono_object_new_alloc_specific_checked (vtable, &error);
+       mono_error_cleanup (&error);
+
+       return o;
+}
+
+/**
+ * mono_object_new_alloc_specific_checked:
+ * @vtable: virtual table for the object.
+ * @error: holds the error return value.  
+ *
+ * This function allocates a new `MonoObject` with the type derived
+ * from the @vtable information. If the class of this object has a 
+ * finalizer, then the object will be tracked for finalization.
+ *
+ * If there is not enough memory, the @error parameter will be set
+ * and will contain a user-visible message with the amount of bytes
+ * that were requested.
+ *
+ * Returns: the allocated object, or NULL if there is not enough memory
+ *
+ */
+MonoObject *
+mono_object_new_alloc_specific_checked (MonoVTable *vtable, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoObject *o = (MonoObject *)mono_gc_alloc_obj (vtable, vtable->klass->instance_size);
+       MonoObject *o;
+
+       mono_error_init (error);
+
+       o = (MonoObject *)mono_gc_alloc_obj (vtable, vtable->klass->instance_size);
 
-       if (G_UNLIKELY (vtable->klass->has_finalize))
+       if (G_UNLIKELY (!o))
+               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", vtable->klass->instance_size);
+       else if (G_UNLIKELY (vtable->klass->has_finalize))
                mono_object_register_finalizer (o);
 
        return o;
 }
 
+/**
+ * mono_object_new_fast:
+ * @vtable: virtual table for the object.
+ *
+ * This function allocates a new `MonoObject` with the type derived
+ * from the @vtable information.   The returned object is not tracked
+ * for finalization.   If your object implements a finalizer, you should
+ * use `mono_object_new_alloc_specific` instead.
+ *
+ * This method might raise an exception on errors.  Use the
+ * `mono_object_new_fast_checked` method if you want to manually raise
+ * the exception.
+ *
+ * Returns: the allocated object.   
+ */
 MonoObject*
 mono_object_new_fast (MonoVTable *vtable)
+{
+       MonoError error;
+       MonoObject *o = mono_object_new_fast_checked (vtable, &error);
+       mono_error_cleanup (&error);
+
+       return o;
+}
+
+/**
+ * mono_object_new_fast_checked:
+ * @vtable: virtual table for the object.
+ * @error: holds the error return value.
+ *
+ * This function allocates a new `MonoObject` with the type derived
+ * from the @vtable information. The returned object is not tracked
+ * for finalization.   If your object implements a finalizer, you should
+ * use `mono_object_new_alloc_specific_checked` instead.
+ *
+ * If there is not enough memory, the @error parameter will be set
+ * and will contain a user-visible message with the amount of bytes
+ * that were requested.
+ *
+ * Returns: the allocated object, or NULL if there is not enough memory
+ *
+ */
+MonoObject*
+mono_object_new_fast_checked (MonoVTable *vtable, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       MonoObject *o;
+
+       mono_error_init (error);
+
+       o = mono_gc_alloc_obj (vtable, vtable->klass->instance_size);
+
+       if (G_UNLIKELY (!o))
+               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", vtable->klass->instance_size);
+
+       return o;
+}
+
+MonoObject *
+ves_icall_object_new_fast (MonoVTable *vtable)
+{
+       MonoError error;
+       MonoObject *o = mono_object_new_fast_checked (vtable, &error);
+       mono_error_set_pending_exception (&error);
+
+       return o;
+}
+
+MonoObject*
+mono_object_new_mature (MonoVTable *vtable, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       return (MonoObject *)mono_gc_alloc_obj (vtable, vtable->klass->instance_size);
+       MonoObject *o;
+
+       mono_error_init (error);
+
+       o = mono_gc_alloc_mature (vtable, vtable->klass->instance_size);
+
+       if (G_UNLIKELY (!o))
+               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", vtable->klass->instance_size);
+       else if (G_UNLIKELY (vtable->klass->has_finalize))
+               mono_object_register_finalizer (o);
+
+       return o;
 }
 
 /**
@@ -4606,15 +5458,15 @@ 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))
-               return mono_object_new_specific;
+       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) {
 
-               return mono_object_new_fast;
+               return ves_icall_object_new_fast;
 
                /* 
-                * FIXME: This is actually slower than mono_object_new_fast, because
+                * FIXME: This is actually slower than ves_icall_object_new_fast, because
                 * of the overhead of parameter passing.
                 */
                /*
@@ -4627,7 +5479,7 @@ mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *p
                */
        }
 
-       return mono_object_new_specific;
+       return ves_icall_object_new_specific;
 }
 
 /**
@@ -4644,12 +5496,17 @@ mono_object_new_from_token  (MonoDomain *domain, MonoImage *image, guint32 token
        MONO_REQ_GC_UNSAFE_MODE;
 
        MonoError error;
+       MonoObject *result;
        MonoClass *klass;
 
        klass = mono_class_get_checked (image, token, &error);
-       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+       mono_error_assert_ok (&error);
+       
+       result = mono_object_new_checked (domain, klass, &error);
 
-       return mono_object_new (domain, klass);
+       mono_error_cleanup (&error);
+       return result;
+       
 }
 
 
@@ -4661,17 +5518,36 @@ mono_object_new_from_token  (MonoDomain *domain, MonoImage *image, guint32 token
  */
 MonoObject *
 mono_object_clone (MonoObject *obj)
+{
+       MonoError error;
+       MonoObject *o = mono_object_clone_checked (obj, &error);
+       mono_error_cleanup (&error);
+
+       return o;
+}
+
+MonoObject *
+mono_object_clone_checked (MonoObject *obj, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        MonoObject *o;
-       int size = obj->vtable->klass->instance_size;
+       int size;
+
+       mono_error_init (error);
+
+       size = obj->vtable->klass->instance_size;
 
        if (obj->vtable->klass->rank)
-               return (MonoObject*)mono_array_clone ((MonoArray*)obj);
+               return (MonoObject*)mono_array_clone_checked ((MonoArray*)obj, error);
 
        o = (MonoObject *)mono_gc_alloc_obj (obj->vtable, size);
 
+       if (G_UNLIKELY (!o)) {
+               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", size);
+               return NULL;
+       }
+
        /* If the object doesn't contain references this will do a simple memmove. */
        mono_gc_wbarrier_object_copy (o, obj);
 
@@ -4718,12 +5594,13 @@ mono_array_full_copy (MonoArray *src, MonoArray *dest)
  * mono_array_clone_in_domain:
  * @domain: the domain in which the array will be cloned into
  * @array: the array to clone
+ * @error: set on error
  *
  * This routine returns a copy of the array that is hosted on the
- * specified MonoDomain.
+ * specified MonoDomain.  On failure returns NULL and sets @error.
  */
 MonoArray*
-mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
+mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -4732,9 +5609,12 @@ mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
        uintptr_t *sizes;
        MonoClass *klass = array->obj.vtable->klass;
 
+       mono_error_init (error);
+
        if (array->bounds == NULL) {
                size = mono_array_length (array);
-               o = mono_array_new_full (domain, klass, &size, NULL);
+               o = mono_array_new_full_checked (domain, klass, &size, NULL, error);
+               return_val_if_nok (error, NULL);
 
                size *= mono_array_element_size (klass);
 #ifdef HAVE_SGEN_GC
@@ -4759,7 +5639,8 @@ mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
                size *= array->bounds [i].length;
                sizes [i + klass->rank] = array->bounds [i].lower_bound;
        }
-       o = mono_array_new_full (domain, klass, sizes, (intptr_t*)sizes + klass->rank);
+       o = mono_array_new_full_checked (domain, klass, sizes, (intptr_t*)sizes + klass->rank, error);
+       return_val_if_nok (error, NULL);
 #ifdef HAVE_SGEN_GC
        if (klass->element_class->valuetype) {
                if (klass->element_class->has_references)
@@ -4787,7 +5668,26 @@ mono_array_clone (MonoArray *array)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       return mono_array_clone_in_domain (((MonoObject *)array)->vtable->domain, array);
+       MonoError error;
+       MonoArray *result = mono_array_clone_checked (array, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+
+/**
+ * mono_array_clone_checked:
+ * @array: the array to clone
+ * @error: set on error
+ *
+ * Returns: A newly created array who is a shallow copy of @array.  On
+ * failure returns NULL and sets @error.
+ */
+MonoArray*
+mono_array_clone_checked (MonoArray *array, MonoError *error)
+{
+
+       MONO_REQ_GC_UNSAFE_MODE;
+       return mono_array_clone_in_domain (((MonoObject *)array)->vtable->domain, array, error);
 }
 
 /* helper macros to check for overflow when calculating the size of arrays */
@@ -4841,6 +5741,16 @@ mono_array_calc_byte_len (MonoClass *klass, uintptr_t len, uintptr_t *res)
  */
 MonoArray*
 mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *lengths, intptr_t *lower_bounds)
+{
+       MonoError error;
+       MonoArray *array = mono_array_new_full_checked (domain, array_class, lengths, lower_bounds, &error);
+       mono_error_cleanup (&error);
+
+       return array;
+}
+
+MonoArray*
+mono_array_new_full_checked (MonoDomain *domain, MonoClass *array_class, uintptr_t *lengths, intptr_t *lower_bounds, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -4851,6 +5761,8 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *leng
        MonoVTable *vtable;
        int i;
 
+       mono_error_init (error);
+
        if (!array_class->inited)
                mono_class_init (array_class);
 
@@ -4859,42 +5771,62 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *leng
        /* A single dimensional array with a 0 lower bound is the same as an szarray */
        if (array_class->rank == 1 && ((array_class->byval_arg.type == MONO_TYPE_SZARRAY) || (lower_bounds && lower_bounds [0] == 0))) {
                len = lengths [0];
-               if (len > MONO_ARRAY_MAX_INDEX)//MONO_ARRAY_MAX_INDEX
-                       arith_overflow ();
+               if (len > MONO_ARRAY_MAX_INDEX) {
+                       mono_error_set_generic_error (error, "System", "OverflowException", "");
+                       return NULL;
+               }
                bounds_size = 0;
        } else {
                bounds_size = sizeof (MonoArrayBounds) * array_class->rank;
 
                for (i = 0; i < array_class->rank; ++i) {
-                       if (lengths [i] > MONO_ARRAY_MAX_INDEX) //MONO_ARRAY_MAX_INDEX
-                               arith_overflow ();
-                       if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
-                               mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE);
+                       if (lengths [i] > MONO_ARRAY_MAX_INDEX) {
+                               mono_error_set_generic_error (error, "System", "OverflowException", "");
+                               return NULL;
+                       }
+                       if (CHECK_MUL_OVERFLOW_UN (len, lengths [i])) {
+                               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", MONO_ARRAY_MAX_SIZE);
+                               return NULL;
+                       }
                        len *= lengths [i];
                }
        }
 
-       if (!mono_array_calc_byte_len (array_class, len, &byte_len))
-               mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE);
+       if (!mono_array_calc_byte_len (array_class, len, &byte_len)) {
+               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", MONO_ARRAY_MAX_SIZE);
+               return NULL;
+       }
 
        if (bounds_size) {
                /* align */
-               if (CHECK_ADD_OVERFLOW_UN (byte_len, 3))
-                       mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE);
+               if (CHECK_ADD_OVERFLOW_UN (byte_len, 3)) {
+                       mono_error_set_out_of_memory (error, "Could not allocate %i bytes", MONO_ARRAY_MAX_SIZE);
+                       return NULL;
+               }
                byte_len = (byte_len + 3) & ~3;
-               if (CHECK_ADD_OVERFLOW_UN (byte_len, bounds_size))
-                       mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE);
+               if (CHECK_ADD_OVERFLOW_UN (byte_len, bounds_size)) {
+                       mono_error_set_out_of_memory (error, "Could not allocate %i bytes", MONO_ARRAY_MAX_SIZE);
+                       return NULL;
+               }
                byte_len += bounds_size;
        }
        /* 
         * Following three lines almost taken from mono_object_new ():
         * they need to be kept in sync.
         */
-       vtable = mono_class_vtable_full (domain, array_class, TRUE);
+       vtable = mono_class_vtable_full (domain, array_class, error);
+       return_val_if_nok (error, NULL);
+
        if (bounds_size)
                o = (MonoObject *)mono_gc_alloc_array (vtable, byte_len, len, bounds_size);
        else
                o = (MonoObject *)mono_gc_alloc_vector (vtable, byte_len, len);
+
+       if (G_UNLIKELY (!o)) {
+               mono_error_set_out_of_memory (error, "Could not allocate %zd bytes", (gsize) byte_len);
+               return NULL;
+       }
+
        array = (MonoArray*)o;
 
        bounds = array->bounds;
@@ -4923,12 +5855,46 @@ mono_array_new (MonoDomain *domain, MonoClass *eclass, uintptr_t n)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+       MonoArray *result = mono_array_new_checked (domain, eclass, n, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+
+/**
+ * mono_array_new_checked:
+ * @domain: domain where the object is created
+ * @eclass: element class
+ * @n: number of array elements
+ * @error: set on error
+ *
+ * This routine creates a new szarray with @n elements of type @eclass.
+ * On failure returns NULL and sets @error.
+ */
+MonoArray *
+mono_array_new_checked (MonoDomain *domain, MonoClass *eclass, uintptr_t n, MonoError *error)
+{
        MonoClass *ac;
 
+       mono_error_init (error);
+
        ac = mono_array_class_get (eclass, 1);
        g_assert (ac);
 
-       return mono_array_new_specific (mono_class_vtable_full (domain, ac, TRUE), n);
+       MonoVTable *vtable = mono_class_vtable_full (domain, ac, error);
+       return_val_if_nok (error, NULL);
+
+       return mono_array_new_specific_checked (vtable, n, error);
+}
+
+MonoArray*
+ves_icall_array_new (MonoDomain *domain, MonoClass *eclass, uintptr_t n)
+{
+       MonoError error;
+       MonoArray *arr = mono_array_new_checked (domain, eclass, n, &error);
+       mono_error_set_pending_exception (&error);
+
+       return arr;
 }
 
 /**
@@ -4941,26 +5907,51 @@ mono_array_new (MonoDomain *domain, MonoClass *eclass, uintptr_t n)
  */
 MonoArray *
 mono_array_new_specific (MonoVTable *vtable, uintptr_t n)
+{
+       MonoError error;
+       MonoArray *arr = mono_array_new_specific_checked (vtable, n, &error);
+       mono_error_cleanup (&error);
+
+       return arr;
+}
+
+MonoArray*
+mono_array_new_specific_checked (MonoVTable *vtable, uintptr_t n, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        MonoObject *o;
-       MonoArray *ao;
        uintptr_t byte_len;
 
+       mono_error_init (error);
+
        if (G_UNLIKELY (n > MONO_ARRAY_MAX_INDEX)) {
-               arith_overflow ();
+               mono_error_set_generic_error (error, "System", "OverflowException", "");
                return NULL;
        }
 
        if (!mono_array_calc_byte_len (vtable->klass, n, &byte_len)) {
-               mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE);
+               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", MONO_ARRAY_MAX_SIZE);
                return NULL;
        }
        o = (MonoObject *)mono_gc_alloc_vector (vtable, byte_len, n);
-       ao = (MonoArray*)o;
 
-       return ao;
+       if (G_UNLIKELY (!o)) {
+               mono_error_set_out_of_memory (error, "Could not allocate %zd bytes", (gsize) byte_len);
+               return NULL;
+       }
+
+       return (MonoArray*)o;
+}
+
+MonoArray*
+ves_icall_array_new_specific (MonoVTable *vtable, uintptr_t n)
+{
+       MonoError error;
+       MonoArray *arr = mono_array_new_specific_checked (vtable, n, &error);
+       mono_error_set_pending_exception (&error);
+
+       return arr;
 }
 
 /**
@@ -4975,12 +5966,35 @@ mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+       MonoString *res = NULL;
+       res = mono_string_new_utf16_checked (domain, text, len, &error);
+       mono_error_cleanup (&error);
+
+       return res;
+}
+
+/**
+ * mono_string_new_utf16_checked:
+ * @text: a pointer to an utf16 string
+ * @len: the length of the string
+ * @error: written on error.
+ *
+ * Returns: A newly created string object which contains @text.
+ * On error, returns NULL and sets @error.
+ */
+MonoString *
+mono_string_new_utf16_checked (MonoDomain *domain, const guint16 *text, gint32 len, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoString *s;
        
-       s = mono_string_new_size (domain, len);
-       g_assert (s != NULL);
-
-       memcpy (mono_string_chars (s), text, len * 2);
+       mono_error_init (error);
+       
+       s = mono_string_new_size_checked (domain, len, error);
+       if (s != NULL)
+               memcpy (mono_string_chars (s), text, len * 2);
 
        return s;
 }
@@ -4989,29 +6003,31 @@ mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
  * mono_string_new_utf32:
  * @text: a pointer to an utf32 string
  * @len: the length of the string
+ * @error: set on failure.
  *
- * Returns: A newly created string object which contains @text.
+ * Returns: A newly created string object which contains @text. On failure returns NULL and sets @error.
  */
-MonoString *
-mono_string_new_utf32 (MonoDomain *domain, const mono_unichar4 *text, gint32 len)
+static MonoString *
+mono_string_new_utf32_checked (MonoDomain *domain, const mono_unichar4 *text, gint32 len, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        MonoString *s;
        mono_unichar2 *utf16_output = NULL;
        gint32 utf16_len = 0;
-       GError *error = NULL;
+       GError *gerror = NULL;
        glong items_written;
        
-       utf16_output = g_ucs4_to_utf16 (text, len, NULL, &items_written, &error);
+       mono_error_init (error);
+       utf16_output = g_ucs4_to_utf16 (text, len, NULL, &items_written, &gerror);
        
-       if (error)
-               g_error_free (error);
+       if (gerror)
+               g_error_free (gerror);
 
        while (utf16_output [utf16_len]) utf16_len++;
        
-       s = mono_string_new_size (domain, utf16_len);
-       g_assert (s != NULL);
+       s = mono_string_new_size_checked (domain, utf16_len, error);
+       return_val_if_nok (error, NULL);
 
        memcpy (mono_string_chars (s), utf16_output, utf16_len * 2);
 
@@ -5020,6 +6036,22 @@ mono_string_new_utf32 (MonoDomain *domain, const mono_unichar4 *text, gint32 len
        return s;
 }
 
+/**
+ * mono_string_new_utf32:
+ * @text: a pointer to an utf32 string
+ * @len: the length of the string
+ *
+ * Returns: A newly created string object which contains @text.
+ */
+MonoString *
+mono_string_new_utf32 (MonoDomain *domain, const mono_unichar4 *text, gint32 len)
+{
+       MonoError error;
+       MonoString *result = mono_string_new_utf32_checked (domain, text, len, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+
 /**
  * mono_string_new_size:
  * @text: a pointer to an utf16 string
@@ -5028,7 +6060,17 @@ mono_string_new_utf32 (MonoDomain *domain, const mono_unichar4 *text, gint32 len
  * Returns: A newly created string object of @len
  */
 MonoString *
-mono_string_new_size (MonoDomain *domain, gint32 len)
+mono_string_new_size (MonoDomain *domain, gint32 len)
+{
+       MonoError error;
+       MonoString *str = mono_string_new_size_checked (domain, len, &error);
+       mono_error_cleanup (&error);
+
+       return str;
+}
+
+MonoString *
+mono_string_new_size_checked (MonoDomain *domain, gint32 len, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -5036,9 +6078,13 @@ mono_string_new_size (MonoDomain *domain, gint32 len)
        MonoVTable *vtable;
        size_t size;
 
+       mono_error_init (error);
+
        /* check for overflow */
-       if (len < 0 || len > ((SIZE_MAX - G_STRUCT_OFFSET (MonoString, chars) - 8) / 2))
-               mono_gc_out_of_memory (-1);
+       if (len < 0 || len > ((SIZE_MAX - G_STRUCT_OFFSET (MonoString, chars) - 8) / 2)) {
+               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", -1);
+               return NULL;
+       }
 
        size = (G_STRUCT_OFFSET (MonoString, chars) + (((size_t)len + 1) * 2));
        g_assert (size > 0);
@@ -5048,6 +6094,11 @@ mono_string_new_size (MonoDomain *domain, gint32 len)
 
        s = (MonoString *)mono_gc_alloc_string (vtable, size, len);
 
+       if (G_UNLIKELY (!s)) {
+               mono_error_set_out_of_memory (error, "Could not allocate %zd bytes", size);
+               return NULL;
+       }
+
        return s;
 }
 
@@ -5063,17 +6114,39 @@ mono_string_new_len (MonoDomain *domain, const char *text, guint length)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       GError *error = NULL;
+       MonoError error;
+       MonoString *result = mono_string_new_len_checked (domain, text, length, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+
+/**
+ * mono_string_new_len_checked:
+ * @text: a pointer to an utf8 string
+ * @length: number of bytes in @text to consider
+ * @error: set on error
+ *
+ * Returns: A newly created string object which contains @text. On
+ * failure returns NULL and sets @error.
+ */
+MonoString*
+mono_string_new_len_checked (MonoDomain *domain, const char *text, guint length, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       mono_error_init (error);
+
+       GError *eg_error = NULL;
        MonoString *o = NULL;
-       guint16 *ut;
+       guint16 *ut = NULL;
        glong items_written;
 
-       ut = eg_utf8_to_utf16_with_nuls (text, length, NULL, &items_written, &error);
+       ut = eg_utf8_to_utf16_with_nuls (text, length, NULL, &items_written, &eg_error);
 
-       if (!error)
-               o = mono_string_new_utf16 (domain, ut, items_written);
+       if (!eg_error)
+               o = mono_string_new_utf16_checked (domain, ut, items_written, error);
        else 
-               g_error_free (error);
+               g_error_free (eg_error);
 
        g_free (ut);
 
@@ -5085,28 +6158,53 @@ mono_string_new_len (MonoDomain *domain, const char *text, guint length)
  * @text: a pointer to an utf8 string
  *
  * Returns: A newly created string object which contains @text.
+ *
+ * This function asserts if it cannot allocate a new string.
+ *
+ * @deprecated Use mono_string_new_checked in new code.
  */
 MonoString*
 mono_string_new (MonoDomain *domain, const char *text)
+{
+       MonoError error;
+       MonoString *res = NULL;
+       res = mono_string_new_checked (domain, text, &error);
+       mono_error_assert_ok (&error);
+       return res;
+}
+
+/**
+ * mono_string_new_checked:
+ * @text: a pointer to an utf8 string
+ * @merror: set on error
+ *
+ * Returns: A newly created string object which contains @text.
+ * On error returns NULL and sets @merror.
+ */
+MonoString*
+mono_string_new_checked (MonoDomain *domain, const char *text, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-    GError *error = NULL;
+    GError *eg_error = NULL;
     MonoString *o = NULL;
     guint16 *ut;
     glong items_written;
     int l;
 
+    mono_error_init (error);
+
     l = strlen (text);
    
-    ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
+    ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &eg_error);
 
-    if (!error)
-        o = mono_string_new_utf16 (domain, ut, items_written);
+    if (!eg_error)
+           o = mono_string_new_utf16_checked (domain, ut, items_written, error);
     else
-        g_error_free (error);
+        g_error_free (eg_error);
 
     g_free (ut);
+    
 /*FIXME g_utf8_get_char, g_utf8_next_char and g_utf8_validate are not part of eglib.*/
 #if 0
        gunichar2 *str;
@@ -5114,17 +6212,23 @@ mono_string_new (MonoDomain *domain, const char *text)
        int len;
        MonoString *o = NULL;
 
-       if (!g_utf8_validate (text, -1, &end))
-               return NULL;
+       if (!g_utf8_validate (text, -1, &end)) {
+               mono_error_set_argument (error, "text", "Not a valid utf8 string");
+               goto leave;
+       }
 
        len = g_utf8_strlen (text, -1);
-       o = mono_string_new_size (domain, len);
+       o = mono_string_new_size_checked (domain, len, error);
+       if (!o)
+               goto leave;
        str = mono_string_chars (o);
 
        while (text < end) {
                *str++ = g_utf8_get_char (text);
                text = g_utf8_next_char (text);
        }
+
+leave:
 #endif
        return o;
 }
@@ -5158,21 +6262,42 @@ mono_string_new_wrapper (const char *text)
 MonoObject *
 mono_value_box (MonoDomain *domain, MonoClass *klass, gpointer value)
 {
-       MONO_REQ_GC_UNSAFE_MODE;
+       MonoError error;
+       MonoObject *result = mono_value_box_checked (domain, klass, value, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
 
+/**
+ * mono_value_box_checked:
+ * @domain: the domain of the new object
+ * @class: the class of the value
+ * @value: a pointer to the unboxed data
+ * @error: set on error
+ *
+ * Returns: A newly created object which contains @value. On failure
+ * returns NULL and sets @error.
+ */
+MonoObject *
+mono_value_box_checked (MonoDomain *domain, MonoClass *klass, gpointer value, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
        MonoObject *res;
        int size;
        MonoVTable *vtable;
 
+       mono_error_init (error);
+
        g_assert (klass->valuetype);
        if (mono_class_is_nullable (klass))
-               return mono_nullable_box ((guint8 *)value, klass);
+               return mono_nullable_box ((guint8 *)value, klass, error);
 
        vtable = mono_class_vtable (domain, klass);
        if (!vtable)
                return NULL;
        size = mono_class_instance_size (klass);
-       res = mono_object_new_alloc_specific (vtable);
+       res = mono_object_new_alloc_specific_checked (vtable, error);
+       return_val_if_nok (error, NULL);
 
        size = size - sizeof (MonoObject);
 
@@ -5201,12 +6326,14 @@ mono_value_box (MonoDomain *domain, MonoClass *klass, gpointer value)
        }
 #endif
 #endif
-       if (klass->has_finalize)
+       if (klass->has_finalize) {
                mono_object_register_finalizer (res);
+               return_val_if_nok (error, NULL);
+       }
        return res;
 }
 
-/*
+/**
  * mono_value_copy:
  * @dest: destination pointer
  * @src: source pointer
@@ -5223,7 +6350,7 @@ mono_value_copy (gpointer dest, gpointer src, MonoClass *klass)
        mono_gc_wbarrier_value_copy (dest, src, 1, klass);
 }
 
-/*
+/**
  * mono_value_copy_array:
  * @dest: destination array
  * @dest_idx: index in the @dest array
@@ -5262,8 +6389,10 @@ mono_object_get_domain (MonoObject *obj)
 /**
  * mono_object_get_class:
  * @obj: object to query
- * 
- * Returns: the MonOClass of the object.
+ *
+ * Use this function to obtain the `MonoClass*` for a given `MonoObject`.
+ *
+ * Returns: the MonoClass of the object.
  */
 MonoClass*
 mono_object_get_class (MonoObject *obj)
@@ -5324,18 +6453,45 @@ mono_object_unbox (MonoObject *obj)
  * @obj: an object
  * @klass: a pointer to a class 
  *
- * Returns: @obj if @obj is derived from @klass
+ * Returns: @obj if @obj is derived from @klass or NULL otherwise.
  */
 MonoObject *
 mono_object_isinst (MonoObject *obj, MonoClass *klass)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+       MonoObject *result = mono_object_isinst_checked (obj, klass, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+       
+
+/**
+ * mono_object_isinst_checked:
+ * @obj: an object
+ * @klass: a pointer to a class 
+ * @error: set on error
+ *
+ * Returns: @obj if @obj is derived from @klass or NULL if it isn't.
+ * On failure returns NULL and sets @error.
+ */
+MonoObject *
+mono_object_isinst_checked (MonoObject *obj, MonoClass *klass, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       mono_error_init (error);
+       
+       MonoObject *result = NULL;
+
        if (!klass->inited)
                mono_class_init (klass);
 
-       if (mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_INTERFACE))
-               return mono_object_isinst_mbyref (obj, klass);
+       if (mono_class_is_marshalbyref (klass) || mono_class_is_interface (klass)) {
+               result = mono_object_isinst_mbyref_checked (obj, klass, error);
+               return result;
+       }
 
        if (!obj)
                return NULL;
@@ -5348,14 +6504,27 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+       MonoObject *result = mono_object_isinst_mbyref_checked (obj, klass, &error);
+       mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
+       return result;
+}
+
+MonoObject *
+mono_object_isinst_mbyref_checked (MonoObject *obj, MonoClass *klass, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
        MonoVTable *vt;
 
+       mono_error_init (error);
+
        if (!obj)
                return NULL;
 
        vt = obj->vtable;
        
-       if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+       if (mono_class_is_interface (klass)) {
                if (MONO_VTABLE_IMPLEMENTS_INTERFACE (vt, klass->interface_id)) {
                        return obj;
                }
@@ -5383,19 +6552,24 @@ 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."));
+               if (!im) {
+                       mono_error_set_not_supported (error, "Linked away.");
+                       return NULL;
+               }
                im = mono_object_get_virtual_method (rp, im);
                g_assert (im);
        
-               pa [0] = mono_type_get_object (domain, &klass->byval_arg);
+               pa [0] = mono_type_get_object_checked (domain, &klass->byval_arg, error);
+               return_val_if_nok (error, NULL);
                pa [1] = obj;
 
-               res = mono_runtime_invoke (im, rp, pa, NULL);
-       
+               res = mono_runtime_invoke_checked (im, rp, pa, error);
+               return_val_if_nok (error, NULL);
+
                if (*(MonoBoolean *) mono_object_unbox(res)) {
                        /* Update the vtable of the remote type, so it can safely cast to this new type */
-                       mono_upgrade_remote_class (domain, obj, klass);
+                       mono_upgrade_remote_class (domain, obj, klass, error);
+                       return_val_if_nok (error, NULL);
                        return obj;
                }
        }
@@ -5408,19 +6582,17 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
  * @obj: an object
  * @klass: a pointer to a class 
  *
- * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
+ * Returns: @obj if @obj is derived from @klass, returns NULL otherwise.
  */
 MonoObject *
 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
 {
        MONO_REQ_GC_UNSAFE_MODE;
+       MonoError error;
 
        if (!obj) return NULL;
-       if (mono_object_isinst_mbyref (obj, klass)) return obj;
-               
-       mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
-                                                       "System",
-                                                       "InvalidCastException"));
+       if (mono_object_isinst_mbyref_checked (obj, klass, &error)) return obj;
+       mono_error_cleanup (&error);
        return NULL;
 }
 
@@ -5441,13 +6613,16 @@ str_lookup (MonoDomain *domain, gpointer user_data)
        info->res = (MonoString *)mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
 }
 
-#ifdef HAVE_SGEN_GC
-
 static MonoString*
-mono_string_get_pinned (MonoString *str)
+mono_string_get_pinned (MonoString *str, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
+
+       /* We only need to make a pinned version of a string if this is a moving GC */
+       if (!mono_gc_is_moving ())
+               return str;
        int size;
        MonoString *news;
        size = sizeof (MonoString) + 2 * (mono_string_length (str) + 1);
@@ -5455,16 +6630,14 @@ mono_string_get_pinned (MonoString *str)
        if (news) {
                memcpy (mono_string_chars (news), mono_string_chars (str), mono_string_length (str) * 2);
                news->length = mono_string_length (str);
+       } else {
+               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", size);
        }
        return news;
 }
 
-#else
-#define mono_string_get_pinned(str) (str)
-#endif
-
 static MonoString*
-mono_string_is_interned_lookup (MonoString *str, int insert)
+mono_string_is_interned_lookup (MonoString *str, int insert, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -5472,6 +6645,8 @@ mono_string_is_interned_lookup (MonoString *str, int insert)
        MonoString *s, *res;
        MonoDomain *domain;
        
+       mono_error_init (error);
+
        domain = ((MonoObject *)str)->vtable->domain;
        ldstr_table = domain->ldstr_table;
        ldstr_lock ();
@@ -5483,7 +6658,8 @@ mono_string_is_interned_lookup (MonoString *str, int insert)
        if (insert) {
                /* Allocate outside the lock */
                ldstr_unlock ();
-               s = mono_string_get_pinned (str);
+               s = mono_string_get_pinned (str, error);
+               return_val_if_nok (error, NULL);
                if (s) {
                        ldstr_lock ();
                        res = (MonoString *)mono_g_hash_table_lookup (ldstr_table, str);
@@ -5525,9 +6701,11 @@ 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);
+       MonoError error;
+       MonoString *result = mono_string_is_interned_lookup (o, FALSE, &error);
+       /* This function does not fail. */
+       mono_error_assert_ok (&error);
+       return result;
 }
 
 /**
@@ -5539,10 +6717,29 @@ mono_string_is_interned (MonoString *o)
  */
 MonoString*
 mono_string_intern (MonoString *str)
+{
+       MonoError error;
+       MonoString *result = mono_string_intern_checked (str, &error);
+       mono_error_assert_ok (&error);
+       return result;
+}
+
+/**
+ * mono_string_intern_checked:
+ * @o: String to intern
+ * @error: set on error.
+ *
+ * Interns the string passed.
+ * Returns: The interned string.  On failure returns NULL and sets @error
+ */
+MonoString*
+mono_string_intern_checked (MonoString *str, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       return mono_string_is_interned_lookup (str, TRUE);
+       mono_error_init (error);
+
+       return mono_string_is_interned_lookup (str, TRUE, error);
 }
 
 /**
@@ -5556,16 +6753,38 @@ mono_string_intern (MonoString *str)
  */
 MonoString*
 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
+{
+       MonoError error;
+       MonoString *result = mono_ldstr_checked (domain, image, idx, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+
+/**
+ * mono_ldstr_checked:
+ * @domain: the domain where the string will be used.
+ * @image: a metadata context
+ * @idx: index into the user string table.
+ * @error: set on error.
+ * 
+ * Implementation for the ldstr opcode.
+ * Returns: a loaded string from the @image/@idx combination.
+ * On failure returns NULL and sets @error.
+ */
+MonoString*
+mono_ldstr_checked (MonoDomain *domain, MonoImage *image, guint32 idx, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
+       mono_error_init (error);
 
        if (image->dynamic) {
-               MonoString *str = (MonoString *)mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL);
+               MonoString *str = (MonoString *)mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL, error);
                return str;
        } else {
                if (!mono_verifier_verify_string_signature (image, idx, NULL))
                        return NULL; /*FIXME we should probably be raising an exception here*/
-               return mono_ldstr_metadata_sig (domain, mono_metadata_user_string (image, idx));
+               MonoString *str = mono_ldstr_metadata_sig (domain, mono_metadata_user_string (image, idx), error);
+               return str;
        }
 }
 
@@ -5573,14 +6792,17 @@ mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
  * mono_ldstr_metadata_sig
  * @domain: the domain for the string
  * @sig: the signature of a metadata string
+ * @error: set on error
  *
- * Returns: a MonoString for a string stored in the metadata
+ * Returns: a MonoString for a string stored in the metadata. On
+ * failure returns NULL and sets @error.
  */
 static MonoString*
-mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig)
+mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
        const char *str = sig;
        MonoString *o, *interned;
        size_t len2;
@@ -5588,7 +6810,8 @@ mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig)
        len2 = mono_metadata_decode_blob_size (str, &str);
        len2 >>= 1;
 
-       o = mono_string_new_utf16 (domain, (guint16*)str, len2);
+       o = mono_string_new_utf16_checked (domain, (guint16*)str, len2, error);
+       return_val_if_nok (error, NULL);
 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
        {
                int i;
@@ -5605,7 +6828,7 @@ mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig)
        if (interned)
                return interned; /* o will get garbage collected */
 
-       o = mono_string_get_pinned (o);
+       o = mono_string_get_pinned (o, error);
        if (o) {
                ldstr_lock ();
                interned = (MonoString *)mono_g_hash_table_lookup (domain->ldstr_table, o);
@@ -5619,6 +6842,48 @@ mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig)
        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
@@ -5636,8 +6901,10 @@ mono_string_to_utf8 (MonoString *s)
        MonoError error;
        char *result = mono_string_to_utf8_checked (s, &error);
        
-       if (!mono_error_ok (&error))
-               mono_error_raise_exception (&error);
+       if (!is_ok (&error)) {
+               mono_error_cleanup (&error);
+               return NULL;
+       }
        return result;
 }
 
@@ -5820,8 +7087,28 @@ mono_string_to_utf32 (MonoString *s)
 MonoString *
 mono_string_from_utf16 (gunichar2 *data)
 {
+       MonoError error;
+       MonoString *result = mono_string_from_utf16_checked (data, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+
+/**
+ * mono_string_from_utf16_checked:
+ * @data: the UTF16 string (LPWSTR) to convert
+ * @error: set on error
+ *
+ * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString.
+ *
+ * Returns: a MonoString. On failure sets @error and returns NULL.
+ */
+MonoString *
+mono_string_from_utf16_checked (gunichar2 *data, MonoError *error)
+{
+
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
        MonoDomain *domain = mono_domain_get ();
        int len = 0;
 
@@ -5830,7 +7117,7 @@ mono_string_from_utf16 (gunichar2 *data)
 
        while (data [len]) len++;
 
-       return mono_string_new_utf16 (domain, data, len);
+       return mono_string_new_utf16_checked (domain, data, len, error);
 }
 
 /**
@@ -5843,12 +7130,31 @@ mono_string_from_utf16 (gunichar2 *data)
  */
 MonoString *
 mono_string_from_utf32 (mono_unichar4 *data)
+{
+       MonoError error;
+       MonoString *result = mono_string_from_utf32_checked (data, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+
+/**
+ * mono_string_from_utf32_checked:
+ * @data: the UTF32 string (LPWSTR) to convert
+ * @error: set on error
+ *
+ * Converts a UTF32 (UCS-4)to a MonoString.
+ *
+ * Returns: a MonoString. On failure returns NULL and sets @error.
+ */
+MonoString *
+mono_string_from_utf32_checked (mono_unichar4 *data, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
        MonoString* result = NULL;
        mono_unichar2 *utf16_output = NULL;
-       GError *error = NULL;
+       GError *gerror = NULL;
        glong items_written;
        int len = 0;
 
@@ -5857,12 +7163,12 @@ mono_string_from_utf32 (mono_unichar4 *data)
 
        while (data [len]) len++;
 
-       utf16_output = g_ucs4_to_utf16 (data, len, NULL, &items_written, &error);
+       utf16_output = g_ucs4_to_utf16 (data, len, NULL, &items_written, &gerror);
 
-       if (error)
-               g_error_free (error);
+       if (gerror)
+               g_error_free (gerror);
 
-       result = mono_string_from_utf16 (utf16_output);
+       result = mono_string_from_utf16_checked (utf16_output, error);
        g_free (utf16_output);
        return result;
 }
@@ -5975,11 +7281,13 @@ mono_raise_exception_with_context (MonoException *ex, MonoContext *ctx)
  * mono_wait_handle_new:
  * @domain: Domain where the object will be created
  * @handle: Handle for the wait handle
+ * @error: set on error.
  *
- * Returns: A new MonoWaitHandle created in the given domain for the given handle
+ * Returns: A new MonoWaitHandle created in the given domain for the
+ * given handle.  On failure returns NULL and sets @rror.
  */
 MonoWaitHandle *
-mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
+mono_wait_handle_new (MonoDomain *domain, HANDLE handle, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -5987,15 +7295,17 @@ mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
        gpointer params [1];
        static MonoMethod *handle_set;
 
-       res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.manualresetevent_class);
+       mono_error_init (error);
+       res = (MonoWaitHandle *)mono_object_new_checked (domain, mono_defaults.manualresetevent_class, error);
+       return_val_if_nok (error, NULL);
 
        /* Even though this method is virtual, it's safe to invoke directly, since the object type matches.  */
        if (!handle_set)
                handle_set = mono_class_get_property_from_name (mono_defaults.manualresetevent_class, "Handle")->set;
 
        params [0] = &handle;
-       mono_runtime_invoke (handle_set, res, params, NULL);
 
+       mono_runtime_invoke_checked (handle_set, res, params, error);
        return res;
 }
 
@@ -6004,41 +7314,38 @@ mono_wait_handle_get_handle (MonoWaitHandle *handle)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       static MonoClassField *f_os_handle;
-       static MonoClassField *f_safe_handle;
+       static MonoClassField *f_safe_handle = NULL;
+       MonoSafeHandle *sh;
 
-       if (!f_os_handle && !f_safe_handle) {
-               f_os_handle = mono_class_get_field_from_name (mono_defaults.manualresetevent_class, "os_handle");
-               f_safe_handle = mono_class_get_field_from_name (mono_defaults.manualresetevent_class, "safe_wait_handle");
+       if (!f_safe_handle) {
+               f_safe_handle = mono_class_get_field_from_name (mono_defaults.manualresetevent_class, "safeWaitHandle");
+               g_assert (f_safe_handle);
        }
 
-       if (f_os_handle) {
-               HANDLE retval;
-               mono_field_get_value ((MonoObject*)handle, f_os_handle, &retval);
-               return retval;
-       } else {
-               MonoSafeHandle *sh;
-               mono_field_get_value ((MonoObject*)handle, f_safe_handle, &sh);
-               return sh->handle;
-       }
+       mono_field_get_value ((MonoObject*)handle, f_safe_handle, &sh);
+       return sh->handle;
 }
 
 
 static MonoObject*
-mono_runtime_capture_context (MonoDomain *domain)
+mono_runtime_capture_context (MonoDomain *domain, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        RuntimeInvokeFunction runtime_invoke;
 
+       mono_error_init (error);
+
        if (!domain->capture_context_runtime_invoke || !domain->capture_context_method) {
                MonoMethod *method = mono_get_context_capture_method ();
                MonoMethod *wrapper;
                if (!method)
                        return NULL;
-               wrapper = mono_marshal_get_runtime_invoke (method, FALSE, FALSE);
-               domain->capture_context_runtime_invoke = mono_compile_method (wrapper);
-               domain->capture_context_method = mono_compile_method (method);
+               wrapper = mono_marshal_get_runtime_invoke (method, FALSE);
+               domain->capture_context_runtime_invoke = mono_compile_method_checked (wrapper, error);
+               return_val_if_nok (error, NULL);
+               domain->capture_context_method = mono_compile_method_checked (method, error);
+               return_val_if_nok (error, NULL);
        }
 
        runtime_invoke = (RuntimeInvokeFunction)domain->capture_context_runtime_invoke;
@@ -6051,18 +7358,23 @@ mono_runtime_capture_context (MonoDomain *domain)
  * @handle: wait handle.
  * @state: state to pass to AsyncResult
  * @data: C closure data.
+ * @error: set on error.
  *
  * Creates a new MonoAsyncResult (AsyncResult C# class) in the given domain.
  * If the handle is not null, the handle is initialized to a MonOWaitHandle.
+ * On failure returns NULL and sets @error.
  *
  */
 MonoAsyncResult *
-mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data, MonoObject *object_data)
+mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data, MonoObject *object_data, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
-       MonoObject *context = mono_runtime_capture_context (domain);
+       mono_error_init (error);
+       MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new_checked (domain, mono_defaults.asyncresult_class, error);
+       return_val_if_nok (error, NULL);
+       MonoObject *context = mono_runtime_capture_context (domain, error);
+       return_val_if_nok (error, NULL);
        /* we must capture the execution context from the original thread */
        if (context) {
                MONO_OBJECT_SETREF (res, execution_context, context);
@@ -6072,8 +7384,10 @@ mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpo
        res->data = (void **)data;
        MONO_OBJECT_SETREF (res, object_data, object_data);
        MONO_OBJECT_SETREF (res, async_state, state);
+       MonoWaitHandle *wait_handle = mono_wait_handle_new (domain, handle, error);
+       return_val_if_nok (error, NULL);
        if (handle != NULL)
-               MONO_OBJECT_SETREF (res, handle, (MonoObject *) mono_wait_handle_new (domain, handle));
+               MONO_OBJECT_SETREF (res, handle, (MonoObject *) wait_handle);
 
        res->sync_completed = FALSE;
        res->completed = FALSE;
@@ -6086,6 +7400,7 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoAsyncCall *ac;
        MonoObject *res;
 
@@ -6094,12 +7409,26 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
 
        ac = (MonoAsyncCall*) ares->object_data;
        if (!ac) {
-               res = mono_runtime_delegate_invoke (ares->async_delegate, (void**) &ares->async_state, NULL);
+               res = mono_runtime_delegate_invoke_checked (ares->async_delegate, (void**) &ares->async_state, &error);
+               if (mono_error_set_pending_exception (&error))
+                       return NULL;
        } else {
                gpointer wait_event = NULL;
 
                ac->msg->exc = NULL;
-               res = mono_message_invoke (ares->async_delegate, ac->msg, &ac->msg->exc, &ac->out_args);
+
+               res = mono_message_invoke (ares->async_delegate, ac->msg, &ac->msg->exc, &ac->out_args, &error);
+
+               /* 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);
@@ -6109,88 +7438,48 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
                mono_monitor_exit ((MonoObject*) ares);
 
                if (wait_event != NULL)
-                       SetEvent (wait_event);
-
-               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);
-               }
+                       mono_w32event_set (wait_event);
+
+               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);
+
+               mono_threads_end_abort_protected_block ();
+
+               if (mono_error_set_pending_exception (&error))
+                       return NULL;
        }
 
        return res;
 }
 
-void
+gboolean
 mono_message_init (MonoDomain *domain,
                   MonoMethodMessage *this_obj, 
                   MonoReflectionMethod *method,
-                  MonoArray *out_args)
+                  MonoArray *out_args,
+                  MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       static MonoClass *object_array_klass;
-       static MonoClass *byte_array_klass;
-       static MonoClass *string_array_klass;
-       MonoMethodSignature *sig = mono_method_signature (method->method);
-       MonoString *name;
-       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);
-
-               mono_atomic_store_release (&object_array_klass, klass);
-       }
-
-       MONO_OBJECT_SETREF (this_obj, method, method);
-
-       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;
+       static MonoMethod *init_message_method = NULL;
 
-       names = g_new (char *, sig->param_count);
-       mono_method_get_param_names (method->method, (const char **) names);
-       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_obj->names, i, name);   
+       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);
        }
 
-       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);
-       }
+       mono_error_init (error);
+       /* FIXME set domain instead? */
+       g_assert (domain == mono_domain_get ());
+       
+       gpointer args[2];
+
+       args[0] = method;
+       args[1] = out_args;
+
+       mono_runtime_invoke_checked (init_message_method, this_obj, args, error);
+       return is_ok (error);
 }
 
 #ifndef DISABLE_REMOTING
@@ -6209,20 +7498,26 @@ mono_message_init (MonoDomain *domain,
  * Returns: the result object.
  */
 MonoObject *
-mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, 
-                     MonoObject **exc, MonoArray **out_args)
+mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, MonoObject **exc, MonoArray **out_args, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoObject *o;
        MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
        gpointer pa [4];
 
+       g_assert (exc);
+
+       mono_error_init (error);
+
        /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
 
        if (!im) {
                im = mono_class_get_method_from_name (mono_defaults.real_proxy_class, "PrivateInvoke", 4);
-               if (!im)
-                       mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
+               if (!im) {
+                       mono_error_set_not_supported (error, "Linked away.");
+                       return NULL;
+               }
                real_proxy->vtable->domain->private_invoke_method = im;
        }
 
@@ -6231,21 +7526,26 @@ mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
        pa [2] = exc;
        pa [3] = out_args;
 
-       return mono_runtime_invoke (im, NULL, pa, exc);
+       o = mono_runtime_try_invoke (im, NULL, pa, exc, error);
+       return_val_if_nok (error, NULL);
+
+       return o;
 }
 #endif
 
 MonoObject *
 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, 
-                    MonoObject **exc, MonoArray **out_args) 
+                    MonoObject **exc, MonoArray **out_args, MonoError *error
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        static MonoClass *object_array_klass;
+       mono_error_init (error);
+
        MonoDomain *domain; 
        MonoMethod *method;
        MonoMethodSignature *sig;
-       MonoObject *ret;
+       MonoArray *arr;
        int i, j, outarg_count = 0;
 
 #ifndef DISABLE_REMOTING
@@ -6254,7 +7554,7 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
                if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
                        target = tp->rp->unwrapped_server;
                } else {
-                       return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
+                       return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args, error);
                }
        }
 #endif
@@ -6278,10 +7578,14 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
                object_array_klass = klass;
        }
 
-       mono_gc_wbarrier_generic_store (out_args, (MonoObject*) mono_array_new_specific (mono_class_vtable (domain, object_array_klass), outarg_count));
+       arr = mono_array_new_specific_checked (mono_class_vtable (domain, object_array_klass), outarg_count, error);
+       return_val_if_nok (error, NULL);
+
+       mono_gc_wbarrier_generic_store (out_args, (MonoObject*) arr);
        *exc = NULL;
 
-       ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
+       MonoObject *ret = mono_runtime_try_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc, error);
+       return_val_if_nok (error, NULL);
 
        for (i = 0, j = 0; i < sig->param_count; i++) {
                if (sig->params [i]->byref) {
@@ -6296,23 +7600,24 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
 }
 
 /**
- * mono_object_to_string:
+ * prepare_to_string_method:
  * @obj: The object
- * @exc: Any exception thrown by ToString (). May be NULL.
+ * @target: Set to @obj or unboxed value if a valuetype
  *
- * Returns: the result of calling ToString () on an object.
+ * Returns: the ToString override for @obj. If @obj is a valuetype, @target is unboxed otherwise it's @obj.
  */
-MonoString *
-mono_object_to_string (MonoObject *obj, MonoObject **exc)
+static MonoMethod *
+prepare_to_string_method (MonoObject *obj, void **target)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        static MonoMethod *to_string = NULL;
        MonoMethod *method;
-       void *target = obj;
-
+       g_assert (target);
        g_assert (obj);
 
+       *target = obj;
+
        if (!to_string)
                to_string = mono_class_get_method_from_name_flags (mono_get_object_class (), "ToString", 0, METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_PUBLIC);
 
@@ -6320,12 +7625,79 @@ mono_object_to_string (MonoObject *obj, MonoObject **exc)
 
        // Unbox value type if needed
        if (mono_class_is_valuetype (mono_method_get_class (method))) {
-               target = mono_object_unbox (obj);
+               *target = mono_object_unbox (obj);
+       }
+       return method;
+}
+
+/**
+ * mono_object_to_string:
+ * @obj: The object
+ * @exc: Any exception thrown by ToString (). May be NULL.
+ *
+ * Returns: the result of calling ToString () on an object.
+ */
+MonoString *
+mono_object_to_string (MonoObject *obj, MonoObject **exc)
+{
+       MonoError error;
+       MonoString *s = NULL;
+       void *target;
+       MonoMethod *method = prepare_to_string_method (obj, &target);
+       if (exc) {
+               s = (MonoString *) mono_runtime_try_invoke (method, target, NULL, exc, &error);
+               if (*exc == NULL && !mono_error_ok (&error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+               else
+                       mono_error_cleanup (&error);
+       } else {
+               s = (MonoString *) mono_runtime_invoke_checked (method, target, NULL, &error);
+               mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
        }
 
-       return (MonoString *) mono_runtime_invoke (method, target, NULL, exc);
+       return s;
+}
+
+/**
+ * mono_object_to_string_checked:
+ * @obj: The object
+ * @error: Set on error.
+ *
+ * Returns: the result of calling ToString () on an object. If the
+ * method cannot be invoked or if it raises an exception, sets @error
+ * and returns NULL.
+ */
+MonoString *
+mono_object_to_string_checked (MonoObject *obj, MonoError *error)
+{
+       mono_error_init (error);
+       void *target;
+       MonoMethod *method = prepare_to_string_method (obj, &target);
+       return (MonoString*) mono_runtime_invoke_checked (method, target, NULL, error);
+}
+
+/**
+ * mono_object_try_to_string:
+ * @obj: The object
+ * @exc: Any exception thrown by ToString (). Must not be NULL.
+ * @error: Set if method cannot be invoked.
+ *
+ * Returns: the result of calling ToString () on an object. If the
+ * method cannot be invoked sets @error, if it raises an exception sets @exc,
+ * and returns NULL.
+ */
+MonoString *
+mono_object_try_to_string (MonoObject *obj, MonoObject **exc, MonoError *error)
+{
+       g_assert (exc);
+       mono_error_init (error);
+       void *target;
+       MonoMethod *method = prepare_to_string_method (obj, &target);
+       return (MonoString*) mono_runtime_try_invoke (method, target, NULL, exc, error);
 }
 
+
+
 /**
  * mono_print_unhandled_exception:
  * @exc: The exception
@@ -6355,7 +7727,11 @@ mono_print_unhandled_exception (MonoObject *exc)
                        free_message = TRUE;
                } else {
                        MonoObject *other_exc = NULL;
-                       str = mono_object_to_string (exc, &other_exc);
+                       str = mono_object_try_to_string (exc, &other_exc, &error);
+                       if (other_exc == NULL && !is_ok (&error))
+                               other_exc = (MonoObject*)mono_error_convert_to_exception (&error);
+                       else
+                               mono_error_cleanup (&error);
                        if (other_exc) {
                                char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc);
                                char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other_exc);
@@ -6389,22 +7765,25 @@ mono_print_unhandled_exception (MonoObject *exc)
 }
 
 /**
- * mono_delegate_ctor:
+ * mono_delegate_ctor_with_method:
  * @this: pointer to an uninitialized delegate object
  * @target: target object
  * @addr: pointer to native code
  * @method: method
+ * @error: set on error.
  *
  * Initialize a delegate and sets a specific method, not the one
  * associated with addr.  This is useful when sharing generic code.
  * In that case addr will most probably not be associated with the
  * correct instantiation of the method.
+ * On failure returns FALSE and sets @error.
  */
-void
-mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoMethod *method)
+gboolean
+mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoMethod *method, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
        MonoDelegate *delegate = (MonoDelegate *)this_obj;
 
        g_assert (this_obj);
@@ -6421,7 +7800,8 @@ mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpoint
        if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
                g_assert (method);
                method = mono_marshal_get_remoting_invoke (method);
-               delegate->method_ptr = mono_compile_method (method);
+               delegate->method_ptr = mono_compile_method_checked (method, error);
+               return_val_if_nok (error, FALSE);
                MONO_OBJECT_SETREF (delegate, target, target);
        } else
 #endif
@@ -6431,6 +7811,9 @@ mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpoint
        }
 
        delegate->invoke_impl = arch_create_delegate_trampoline (delegate->object.vtable->domain, delegate->object.vtable->klass);
+       if (callbacks.init_delegate)
+               callbacks.init_delegate (delegate);
+       return TRUE;
 }
 
 /**
@@ -6438,14 +7821,17 @@ mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpoint
  * @this: pointer to an uninitialized delegate object
  * @target: target object
  * @addr: pointer to native code
+ * @error: set on error.
  *
  * This is used to initialize a delegate.
+ * On failure returns FALSE and sets @error.
  */
-void
-mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr)
+gboolean
+mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
        MonoDomain *domain = mono_domain_get ();
        MonoJitInfo *ji;
        MonoMethod *method = NULL;
@@ -6458,10 +7844,10 @@ mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr)
                ji = mono_jit_info_table_find (mono_get_root_domain (), (char *)mono_get_addr_from_ftnptr (addr));
        if (ji) {
                method = mono_jit_info_get_method (ji);
-               g_assert (!method->klass->generic_container);
+               g_assert (!mono_class_is_gtd (method->klass));
        }
 
-       mono_delegate_ctor_with_method (this_obj, target, addr, method);
+       return mono_delegate_ctor_with_method (this_obj, target, addr, method, error);
 }
 
 /**
@@ -6471,27 +7857,38 @@ mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr)
  * @invoke: optional, delegate invoke.
  * @cb: async callback delegate.
  * @state: state passed to the async callback.
+ * @error: set on error.
  *
  * Translates arguments pointers into a MonoMethodMessage.
+ * On failure returns NULL and sets @error.
  */
 MonoMethodMessage *
 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke, 
-                             MonoDelegate **cb, MonoObject **state)
+                             MonoDelegate **cb, MonoObject **state, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
+
        MonoDomain *domain = mono_domain_get ();
        MonoMethodSignature *sig = mono_method_signature (method);
        MonoMethodMessage *msg;
        int i, count;
 
-       msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class); 
-       
+       msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error); 
+       return_val_if_nok  (error, NULL);
+
        if (invoke) {
-               mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
+               MonoReflectionMethod *rm = mono_method_get_object_checked (domain, invoke, NULL, error);
+               return_val_if_nok (error, NULL);
+               mono_message_init (domain, msg, rm, NULL, error);
+               return_val_if_nok (error, NULL);
                count =  sig->param_count - 2;
        } else {
-               mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
+               MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, NULL, error);
+               return_val_if_nok (error, NULL);
+               mono_message_init (domain, msg, rm, NULL, error);
+               return_val_if_nok (error, NULL);
                count =  sig->param_count;
        }
 
@@ -6507,9 +7904,10 @@ mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *
 
                klass = mono_class_from_mono_type (sig->params [i]);
 
-               if (klass->valuetype)
-                       arg = mono_value_box (domain, klass, vpos);
-               else 
+               if (klass->valuetype) {
+                       arg = mono_value_box_checked (domain, klass, vpos, error);
+                       return_val_if_nok (error, NULL);
+               } else 
                        arg = *((MonoObject **)vpos);
                      
                mono_array_setref (msg->args, i, arg);
@@ -6530,10 +7928,12 @@ mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *
  * Restore results from message based processing back to arguments pointers
  */
 void
-mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
+mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       mono_error_init (error);
+
        MonoMethodSignature *sig = mono_method_signature (method);
        int i, j, type, size, out_len;
        
@@ -6548,8 +7948,10 @@ mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoAr
 
                if (pt->byref) {
                        char *arg;
-                       if (j >= out_len)
-                               mono_raise_exception (mono_get_exception_execution_engine ("The proxy call returned an incorrect number of output arguments"));
+                       if (j >= out_len) {
+                               mono_error_set_execution_engine (error, "The proxy call returned an incorrect number of output arguments");
+                               return;
+                       }
 
                        arg = (char *)mono_array_get (out_args, gpointer, j);
                        type = pt->type;
@@ -6595,10 +7997,37 @@ mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoAr
  */
 gpointer
 mono_load_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, gpointer *res)
+{
+       MonoError error;
+       gpointer result = mono_load_remote_field_checked (this_obj, klass, field, res, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+
+/**
+ * mono_load_remote_field_checked:
+ * @this: pointer to an object
+ * @klass: klass of the object containing @field
+ * @field: the field to load
+ * @res: a storage to store the result
+ * @error: set on error
+ *
+ * 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. @res is a storage location which can be
+ * used to store the result.
+ *
+ * Returns: an address pointing to the value of field.  On failure returns NULL and sets @error.
+ */
+gpointer
+mono_load_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, gpointer *res, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        static MonoMethod *getter = NULL;
+
+       mono_error_init (error);
+
        MonoDomain *domain = mono_domain_get ();
        MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
        MonoClass *field_class;
@@ -6617,29 +8046,40 @@ mono_load_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField *
        
        if (!getter) {
                getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
-               if (!getter)
-                       mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
+               if (!getter) {
+                       mono_error_set_not_supported (error, "Linked away.");
+                       return NULL;
+               }
        }
        
        field_class = mono_class_from_mono_type (field->type);
 
-       msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
-       out_args = mono_array_new (domain, mono_defaults.object_class, 1);
-       mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
+       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);
 
-       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
+       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
+       return_val_if_nok (error, NULL);
 
-       if (exc) mono_raise_exception ((MonoException *)exc);
+       if (exc) {
+               mono_error_set_exception_instance (error, (MonoException *)exc);
+               return NULL;
+       }
 
        if (mono_array_length (out_args) == 0)
                return NULL;
 
-       *res = mono_array_get (out_args, MonoObject *, 0); /* FIXME: GC write abrrier for res */
+       mono_gc_wbarrier_generic_store (res, mono_array_get (out_args, MonoObject *, 0));
 
        if (field_class->valuetype) {
                return ((char *)*res) + sizeof (MonoObject);
@@ -6657,60 +8097,53 @@ mono_load_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField *
  */
 MonoObject *
 mono_load_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassField *field)
+{
+       MonoError error;
+
+       MonoObject *result = mono_load_remote_field_new_checked (this_obj, klass, field, &error);
+       mono_error_cleanup (&error);
+       return result;
+}
+
+/**
+ * mono_load_remote_field_new_checked:
+ * @this: pointer to an object
+ * @klass: klass of the object containing @field
+ * @field: the field to load
+ * @error: set on error.
+ *
+ * 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 sets @error.
+ */
+MonoObject *
+mono_load_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       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;
+       mono_error_init (error);
 
-       g_assert (mono_object_is_transparent_proxy (this_obj));
+       static MonoMethod *tp_load = NULL;
 
-       field_class = mono_class_from_mono_type (field->type);
+       g_assert (mono_object_is_transparent_proxy (this_obj));
 
-       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 (domain, field_class);
-                       val = ((gchar *) res) + sizeof (MonoObject);
-               } else {
-                       val = &res;
+       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;
                }
-               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)
-                       mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
        }
        
-       msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
-       out_args = mono_array_new (domain, mono_defaults.object_class, 1);
-
-       mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
-
-       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);
+       gpointer args[2];
+       args [0] = &klass;
+       args [1] = &field;
 
-       if (exc) mono_raise_exception ((MonoException *)exc);
-
-       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);
 }
 
 /**
@@ -6727,52 +8160,49 @@ mono_load_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFie
 void
 mono_store_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, gpointer val)
 {
+       MonoError error;
+       (void) mono_store_remote_field_checked (this_obj, klass, field, val, &error);
+       mono_error_cleanup (&error);
+}
+
+/**
+ * mono_store_remote_field_checked:
+ * @this_obj: pointer to an object
+ * @klass: klass of the object containing @field
+ * @field: the field to load
+ * @val: the value/object to store
+ * @error: set on error
+ *
+ * This method is called by the runtime on attempts to store fields 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.
+ *
+ * Returns: on success returns TRUE, on failure returns FALSE and sets @error.
+ */
+gboolean
+mono_store_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, gpointer val, MonoError *error)
+{
+       
        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;
 
        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;
-       }
-
-       if (!setter) {
-               setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
-               if (!setter)
-                       mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
+       if (field_class->valuetype) {
+               arg = mono_value_box_checked (domain, field_class, val, error);
+               return_val_if_nok (error, FALSE);
+       } else {
+               arg = *((MonoObject**)val);
        }
 
-       if (field_class->valuetype)
-               arg = mono_value_box (domain, field_class, val);
-       else 
-               arg = *((MonoObject **)val);
-               
-
-       msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
-       mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), 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)));
-       mono_array_setref (msg->args, 2, arg);
-       g_free (full_name);
-
-       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
-
-       if (exc) mono_raise_exception ((MonoException *)exc);
+       return mono_store_remote_field_new_checked (this_obj, klass, field, arg, error);
 }
 
 /**
@@ -6787,45 +8217,47 @@ mono_store_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField
 void
 mono_store_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg)
 {
-       MONO_REQ_GC_UNSAFE_MODE;
+       MonoError error;
+       (void) mono_store_remote_field_new_checked (this_obj, klass, field, arg, &error);
+       mono_error_cleanup (&error);
+}
 
-       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;
+/**
+ * mono_store_remote_field_new_checked:
+ * @this_obj:
+ * @klass:
+ * @field:
+ * @arg:
+ * @error:
+ *
+ * Missing documentation
+ */
+gboolean
+mono_store_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoObject *arg, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
 
-       g_assert (mono_object_is_transparent_proxy (this_obj));
+       static MonoMethod *tp_store = NULL;
 
-       field_class = mono_class_from_mono_type (field->type);
+       mono_error_init (error);
 
-       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;
-       }
+       g_assert (mono_object_is_transparent_proxy (this_obj));
 
-       if (!setter) {
-               setter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldSetter", -1);
-               if (!setter)
-                       mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
+       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 (domain, mono_defaults.mono_method_message_class);
-       mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), 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)));
-       mono_array_setref (msg->args, 2, arg);
-       g_free (full_name);
-
-       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
+       gpointer args[3];
+       args [0] = &klass;
+       args [1] = &field;
+       args [2] = arg;
 
-       if (exc) mono_raise_exception ((MonoException *)exc);
+       mono_runtime_invoke_checked (tp_store, this_obj, args, error);
+       return is_ok (error);
 }
 #endif
 
@@ -6902,6 +8334,11 @@ mono_array_length (MonoArray *array)
  * @size: size of the array elements
  * @idx: index into the array
  *
+ * Use this function to obtain the address for the @idx item on the
+ * @array containing elements of size @size.
+ *
+ * This method performs no bounds checking or type checking.
+ *
  * Returns the address of the @idx element in the array.
  */
 char*
@@ -6914,17 +8351,19 @@ mono_array_addr_with_size (MonoArray *array, int size, uintptr_t idx)
 
 
 MonoArray *
-mono_glist_to_array (GList *list, MonoClass *eclass) 
+mono_glist_to_array (GList *list, MonoClass *eclass, MonoError *error
 {
        MonoDomain *domain = mono_domain_get ();
        MonoArray *res;
        int len, i;
 
+       mono_error_init (error);
        if (!list)
                return NULL;
 
        len = g_list_length (list);
-       res = mono_array_new (domain, eclass, len);
+       res = mono_array_new_checked (domain, eclass, len, error);
+       return_val_if_nok (error, NULL);
 
        for (i = 0; list; list = list->next, i++)
                mono_array_set (res, gpointer, i, list->data);
@@ -6932,3 +8371,68 @@ mono_glist_to_array (GList *list, MonoClass *eclass)
        return res;
 }
 
+#if NEVER_DEFINED
+/*
+ * The following section is purely to declare prototypes and
+ * document the API, as these C files are processed by our
+ * tool
+ */
+
+/**
+ * mono_array_set:
+ * @array: array to alter
+ * @element_type: A C type name, this macro will use the sizeof(type) to determine the element size
+ * @index: index into the array
+ * @value: value to set
+ *
+ * Value Type version: This sets the @index's element of the @array
+ * with elements of size sizeof(type) to the provided @value.
+ *
+ * This macro does not attempt to perform type checking or bounds checking.
+ *
+ * Use this to set value types in a `MonoArray`.
+ */
+void mono_array_set(MonoArray *array, Type element_type, uintptr_t index, Value value)
+{
+}
+
+/**
+ * mono_array_setref:
+ * @array: array to alter
+ * @index: index into the array
+ * @value: value to set
+ *
+ * Reference Type version: This sets the @index's element of the
+ * @array with elements of size sizeof(type) to the provided @value.
+ *
+ * This macro does not attempt to perform type checking or bounds checking.
+ *
+ * Use this to reference types in a `MonoArray`.
+ */
+void mono_array_setref(MonoArray *array, uintptr_t index, MonoObject *object)
+{
+}
+
+/**
+ * mono_array_get:
+ * @array: array on which to operate on
+ * @element_type: C element type (example: MonoString *, int, MonoObject *)
+ * @index: index into the array
+ *
+ * Use this macro to retrieve the @index element of an @array and
+ * extract the value assuming that the elements of the array match
+ * the provided type value.
+ *
+ * This method can be used with both arrays holding value types and
+ * reference types.   For reference types, the @type parameter should
+ * be a `MonoObject*` or any subclass of it, like `MonoString*`.
+ *
+ * This macro does not attempt to perform type checking or bounds checking.
+ *
+ * Returns: The element at the @index position in the @array.
+ */
+Type mono_array_get (MonoArray *array, Type element_type, uintptr_t index)
+{
+}
+#endif