Merge pull request #2670 from lambdageek/dev/monoerror-mono_runtime_object_init
[mono.git] / mono / metadata / object.c
index bd31aaa2a8be8a431b5335ba6ebdf626fcfcfadb..00ec533a19490dbee8626d7f070cf7aff8eb832c 100644 (file)
@@ -23,6 +23,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"
@@ -59,26 +60,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
@@ -223,6 +258,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;
@@ -246,12 +282,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
@@ -262,23 +300,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;
@@ -288,39 +328,35 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
        int do_initialization = 0;
        MonoDomain *last_domain = 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 ();
@@ -329,15 +365,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) {
@@ -348,9 +383,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));
@@ -369,7 +403,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));
@@ -377,7 +411,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
@@ -394,11 +428,15 @@ 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_runtime_try_invoke (method, NULL, NULL, (MonoObject**) &exc, error);
+               if (exc != NULL && mono_error_ok (error)) {
+                       mono_error_set_exception_instance (error, exc);
+               }
 
                /* If the initialization failed, mark the class as unusable. */
                /* Avoid infinite loops */
-               if (!(exc == NULL ||
+               if (!(mono_error_ok(error) ||
                          (klass->image == mono_defaults.corlib &&
                           !strcmp (klass->name_space, "System") &&
                           !strcmp (klass->name, "TypeInitializationException")))) {
@@ -408,9 +446,17 @@ 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);
+                       return_val_if_nok (error, FALSE);
 
+                       mono_error_set_exception_instance (error, exc_to_throw);
+
+                       MonoException *exc_to_store = mono_error_convert_to_exception (error);
+                       /* What we really want to do here is clone the error object and store one copy in the
+                        * domain's exception hash and use the other one to error out here. */
+                       mono_error_set_exception_instance (error, exc_to_store);
                        /*
                         * Store the exception object so it could be thrown on subsequent
                         * accesses.
@@ -418,7 +464,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
                        mono_domain_lock (domain);
                        if (!domain->type_init_exception_hash)
                                domain->type_init_exception_hash = mono_g_hash_table_new_type (mono_aligned_addr_hash, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "type initialization exceptions table");
-                       mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_throw);
+                       mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_store);
                        mono_domain_unlock (domain);
                }
 
@@ -448,11 +494,10 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
 
        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
@@ -525,8 +570,6 @@ 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;
@@ -547,18 +590,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) 
@@ -584,20 +615,6 @@ mono_set_always_build_imt_thunks (gboolean value)
        always_build_imt_thunks = value;
 }
 
-static MonoCompileFunc default_mono_compile_method = NULL;
-
-/**
- * mono_install_compile_method:
- * @func: function to install
- *
- * This is a VM internal routine
- */
-void        
-mono_install_compile_method (MonoCompileFunc func)
-{
-       default_mono_compile_method = func;
-}
-
 /**
  * mono_compile_method:
  * @method: The method to compile.
@@ -608,21 +625,33 @@ mono_install_compile_method (MonoCompileFunc func)
 gpointer 
 mono_compile_method (MonoMethod *method)
 {
+       gpointer res;
+       MonoError error;
+
        MONO_REQ_GC_NEUTRAL_MODE
 
-       if (!default_mono_compile_method) {
+       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);
+       if (!mono_error_ok (&error))
+               mono_error_raise_exception (&error);
+       return res;
 }
 
 gpointer
 mono_runtime_create_jump_trampoline (MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper)
 {
-       MONO_REQ_GC_NEUTRAL_MODE
+       MonoError error;
+       gpointer res;
+
+       MONO_REQ_GC_NEUTRAL_MODE;
 
-       return arch_create_jump_trampoline (domain, method, add_sync_wrapper);
+       res = callbacks.create_jump_trampoline (domain, method, add_sync_wrapper, &error);
+       if (!mono_error_ok (&error))
+               mono_error_raise_exception (&error); /* FIXME: Don't raise here */
+       return res;
 }
 
 gpointer
@@ -1047,9 +1076,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) {
@@ -1830,7 +1861,7 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
        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:
@@ -1844,30 +1875,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_exception_instance (error, mono_class_get_exception_for_failure (klass));
                return NULL;
        }
 
@@ -1875,7 +1910,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);
 }
 
 /**
@@ -1925,11 +1960,10 @@ 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;
 
-       MonoError error;
        MonoVTable *vt;
        MonoClassRuntimeInfo *runtime_info, *old_info;
        MonoClassField *field;
@@ -1941,6 +1975,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;
@@ -1949,12 +1985,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_exception_instance (error, mono_class_get_exception_for_failure (klass));
                        return NULL;
                }
        }
@@ -1966,17 +2001,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)
+                       if (!mono_class_has_failure (klass))
                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        mono_domain_unlock (domain);
                        mono_loader_unlock ();
-                       if (raise_on_error)
-                               mono_raise_exception (mono_class_get_exception_for_failure (klass));
+                       mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
                        return NULL;
                }
        }
@@ -1994,11 +2028,10 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
        /* 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_exception_instance (error, mono_class_get_exception_for_failure (klass));
                return NULL;
        }
 
@@ -2158,8 +2191,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;
+                               }
+                       }
                }
        }
 
@@ -2175,9 +2215,12 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
         */
        /* Special case System.MonoType to avoid infinite recursion */
        if (klass != mono_defaults.monotype_class) {
-               /*FIXME check for OOM*/
-               vt->type = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               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.monotype_class)
                        /* This is unregistered in
@@ -2231,9 +2274,12 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
        }
 
        if (klass == mono_defaults.monotype_class) {
-               /*FIXME check for OOM*/
-               vt->type = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               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.monotype_class)
                        /* This is unregistered in
@@ -2248,7 +2294,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;
 }
@@ -2846,13 +2892,33 @@ 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);
+
+       MONO_PREPARE_RESET_BLOCKING;
+
+       result = callbacks.runtime_invoke (method, obj, params, exc, error);
+
+       MONO_FINISH_RESET_BLOCKING;
+
+       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:
@@ -2890,23 +2956,118 @@ static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
  */
 MonoObject*
 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
+{
+       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);
+       }
+       return res;
+}
+
+/**
+ * mono_runtime_try_invoke:
+ * @method: method to invoke
+ * @obJ: object instance
+ * @params: arguments to the method
+ * @exc: exception information.
+ * @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).
+ * 
+ * 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;
 
-       MonoObject *result;
+       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));
 
-       if (mono_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
-               mono_profiler_method_start_invoke (method);
+       return do_runtime_invoke (method, obj, params, exc, error);
+}
 
-       result = default_mono_runtime_invoke (method, obj, params, exc);
+/**
+ * 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_profiler_get_events () & MONO_PROFILE_METHOD_EVENTS)
-               mono_profiler_method_end_invoke (method);
+       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 result;
+       return do_runtime_invoke (method, obj, params, NULL, error);
 }
 
 /**
@@ -3232,7 +3393,7 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
        MonoType *type = mono_field_get_type_checked (field, &error);
 
        if (!mono_error_ok (&error))
-               mono_error_raise_exception (&error);
+               mono_error_raise_exception (&error);  /* FIXME don't raise here */
 
        switch (type->type) {
        case MONO_TYPE_STRING:
@@ -3278,9 +3439,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);
+                       mono_error_raise_exception (&error);  /* FIXME don't raise here */
+
+                       if (!vtable->initialized) {
+                               mono_runtime_class_init_full (vtable, &error);
+                               mono_error_raise_exception (&error);  /* FIXME don't raise here */
+                       }
                }
        } else {
                g_assert (obj);
@@ -3304,7 +3469,7 @@ 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);
                }
@@ -3323,7 +3488,10 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
                args [1] = mono_type_get_object_checked (mono_domain_get (), type, &error);
                mono_error_raise_exception (&error); /* FIXME don't raise here */
 
-               return mono_runtime_invoke (m, NULL, args, NULL);
+               o = mono_runtime_invoke_checked (m, NULL, args, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+               return o;
        }
 
        /* boxed value type */
@@ -3332,7 +3500,8 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
        if (mono_class_is_nullable (klass))
                return mono_nullable_box (mono_field_get_addr (obj, vtable, field), klass);
 
-       o = mono_object_new (domain, klass);
+       o = mono_object_new_checked (domain, klass, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
        v = ((gchar *) o) + sizeof (MonoObject);
 
        if (is_literal) {
@@ -3473,7 +3642,13 @@ 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_raise_exception (&error); /* FIXME don't raise here */
+       }
 }
 
 /**
@@ -3498,7 +3673,15 @@ 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_raise_exception (&error); /* FIXME don't raise here */
+       }
+
+       return val;
 }
 
 /*
@@ -3552,6 +3735,8 @@ mono_nullable_box (guint8 *buf, MonoClass *klass)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+       
        MonoClass *param_class = klass->cast_class;
 
        mono_class_setup_fields_locking (klass);
@@ -3561,7 +3746,8 @@ mono_nullable_box (guint8 *buf, MonoClass *klass)
        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);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
                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
@@ -3587,7 +3773,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;
@@ -3608,7 +3794,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;
@@ -3629,7 +3815,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;
@@ -3653,14 +3839,27 @@ mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError 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);
+               if (*exc == NULL && !mono_error_ok (&error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+               else
+                       mono_error_cleanup (&error);
+       } else {
+               o = mono_runtime_invoke_checked (im, delegate, params, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+       }
+
+       return o;
 }
 
 static char **main_args = NULL;
@@ -3848,11 +4047,12 @@ 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_from_name (mono_defaults.corlib, "System.Runtime.Remoting", "RemotingServices");
+               MonoClass *klass = mono_class_get_remoting_services_class ();
                serialize_method = mono_class_get_method_from_name (klass, "SerializeCallData", -1);
        }
 
@@ -3865,7 +4065,13 @@ serialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 
        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;
 
@@ -3879,11 +4085,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) {
@@ -3893,7 +4100,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;
 
@@ -3919,7 +4132,8 @@ make_transparent_proxy (MonoObject *obj, gboolean *failure, MonoObject **exc)
 
        g_assert (mono_class_is_marshalbyref (obj->vtable->klass));
 
-       real_proxy = (MonoRealProxy*) mono_object_new (domain, mono_defaults.real_proxy_class);
+       real_proxy = (MonoRealProxy*) mono_object_new_checked (domain, mono_defaults.real_proxy_class, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
        reflection_type = mono_type_get_object_checked (domain, &obj->vtable->klass->byval_arg, &error);
        mono_error_raise_exception (&error); /* FIXME don't raise here */
 
@@ -3927,7 +4141,12 @@ make_transparent_proxy (MonoObject *obj, gboolean *failure, MonoObject **exc)
        MONO_OBJECT_SETREF (real_proxy, unwrapped_server, obj);
 
        *exc = NULL;
-       transparent_proxy = (MonoTransparentProxy*) mono_runtime_invoke (get_proxy_method, real_proxy, NULL, exc);
+
+       transparent_proxy = (MonoTransparentProxy*) mono_runtime_try_invoke (get_proxy_method, real_proxy, NULL, exc, &error);
+       if (*exc == NULL && !mono_error_ok (&error))
+               *exc = (MonoObject*) mono_error_convert_to_exception (&error); /* FIXME change make_transparent_proxy outarg to MonoError */
+       else
+               mono_error_cleanup (&error);
        if (*exc)
                *failure = TRUE;
 
@@ -3957,6 +4176,7 @@ mono_object_xdomain_representation (MonoObject *obj, MonoDomain *target_domain,
        MonoObject *deserialized = NULL;
        gboolean failure = FALSE;
 
+       g_assert (exc != NULL);
        *exc = NULL;
 
 #ifndef DISABLE_REMOTING
@@ -3987,15 +4207,14 @@ create_unhandled_exception_eventargs (MonoObject *exc)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError 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 */
@@ -4005,8 +4224,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);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+       mono_runtime_invoke_checked (method, obj, args, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return obj;
 }
@@ -4176,6 +4398,7 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoDomain *domain;
        gpointer pa [1];
        int rval;
@@ -4207,12 +4430,10 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
                }
        }
 
-       cinfo = mono_custom_attrs_from_method (method);
+       cinfo = mono_custom_attrs_from_method_checked (method, &error);
+       mono_error_cleanup (&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 {
@@ -4228,7 +4449,17 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
        /* FIXME: check signature of method */
        if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
                MonoObject *res;
-               res = mono_runtime_invoke (method, NULL, pa, exc);
+               if (exc) {
+                       res = mono_runtime_try_invoke (method, NULL, pa, exc, &error);
+                       if (*exc == NULL && !mono_error_ok (&error))
+                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+                       else
+                               mono_error_cleanup (&error);
+               } else {
+                       res = mono_runtime_invoke_checked (method, NULL, pa, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               }
+
                if (!exc || !*exc)
                        rval = *(guint32 *)((char *)res + sizeof (MonoObject));
                else
@@ -4236,7 +4467,17 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
 
                mono_environment_exitcode_set (rval);
        } else {
-               mono_runtime_invoke (method, NULL, pa, exc);
+               if (exc) {
+                       mono_runtime_try_invoke (method, NULL, pa, exc, &error);
+                       if (*exc == NULL && !mono_error_ok (&error))
+                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+                       else
+                               mono_error_cleanup (&error);
+               } else {
+                       mono_runtime_invoke_checked (method, NULL, pa, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               }
+
                if (!exc || !*exc)
                        rval = 0;
                else {
@@ -4253,19 +4494,6 @@ 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
- */
-void
-mono_install_runtime_invoke (MonoInvokeFunc func)
-{
-       default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
-}
-
-
 /**
  * mono_runtime_invoke_array:
  * @method: method to invoke
@@ -4287,7 +4515,7 @@ mono_install_runtime_invoke (MonoInvokeFunc func)
  * respective reference representation.
  * 
  * From unmanaged code you'll usually use the
- * mono_runtime_invoke() variant.
+ * 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
@@ -4345,8 +4573,11 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                                                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 (sig->params [i]), &error);
+                                               mono_error_raise_exception (&error); /* FIXME don't raise here */
+                                               mono_array_setref (params, i, o); 
+                                       }
 
                                        if (t->byref) {
                                                /*
@@ -4414,8 +4645,8 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                }
 
                if (!obj) {
-                       obj = mono_object_new (mono_domain_get (), method->klass);
-                       g_assert (obj); /*maybe we should raise a TLE instead?*/
+                       obj = mono_object_new_checked (mono_domain_get (), method->klass, &error);
+                       g_assert (obj && mono_error_ok (&error)); /*maybe we should raise a TLE instead?*/ /* FIXME don't swallow error */
 #ifndef DISABLE_REMOTING
                        if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
                                method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
@@ -4429,21 +4660,41 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                        obj = mono_value_box (mono_domain_get (), method->klass, obj);
                }
 
-               mono_runtime_invoke (method, o, pa, exc);
+               if (exc) {
+                       mono_runtime_try_invoke (method, o, pa, exc, &error);
+                       if (*exc == NULL && !mono_error_ok (&error))
+                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+                       else
+                               mono_error_cleanup (&error);
+               } else {
+                       mono_runtime_invoke_checked (method, o, pa, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               }
+
                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);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
                        mono_nullable_init ((guint8 *)mono_object_unbox (nullable), mono_value_box (mono_domain_get (), method->klass->cast_class, obj), 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);
+                       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, pa, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               }
 
                if (sig->ret->type == MONO_TYPE_PTR) {
                        MonoClass *pointer_class;
@@ -4455,7 +4706,7 @@ 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);
 
@@ -4464,8 +4715,9 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
                        box_args [1] = mono_type_get_object_checked (mono_domain_get (), sig->ret, &error);
                        mono_error_raise_exception (&error); /* FIXME don't raise here */
 
-                       res = mono_runtime_invoke (box_method, NULL, box_args, &box_exc);
-                       g_assert (!box_exc);
+                       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) {
@@ -4502,16 +4754,50 @@ mono_object_new (MonoDomain *domain, MonoClass *klass)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoVTable *vtable;
+       MonoError error;
 
-       vtable = mono_class_vtable (domain, klass);
-       if (!vtable)
-               return NULL;
+       MonoObject * result = mono_object_new_checked (domain, klass, &error);
+
+       mono_error_raise_exception (&error);
+       return result;
+}
+
+MonoObject *
+ves_icall_object_new (MonoDomain *domain, MonoClass *klass)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
 
        MonoError error;
-       MonoObject *o = mono_object_new_specific_checked (vtable, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
+       MonoObject * result = mono_object_new_checked (domain, klass, &error);
+
+       mono_error_raise_exception (&error);
+       return result;
+}
+
+/**
+ * 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,
+ * so the consumer of this routine has to invoke any constructors on
+ * its own to initialize the object.
+ *
+ * It returns NULL on failure and sets @error.
+ */
+MonoObject *
+mono_object_new_checked (MonoDomain *domain, MonoClass *klass, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       MonoVTable *vtable;
+
+       vtable = mono_class_vtable (domain, klass);
+       g_assert (vtable); /* FIXME don't swallow the error */
+
+       MonoObject *o = mono_object_new_specific_checked (vtable, error);
        return o;
 }
 
@@ -4538,7 +4824,7 @@ mono_object_new_pinned (MonoDomain *domain, MonoClass *klass, MonoError *error)
        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);
+               mono_object_register_finalizer (o, error);
 
        return o;
 }
@@ -4576,7 +4862,7 @@ mono_object_new_specific_checked (MonoVTable *vtable, MonoError *error)
                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);
@@ -4593,8 +4879,12 @@ mono_object_new_specific_checked (MonoVTable *vtable, MonoError *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_checked (vtable, error);
@@ -4610,6 +4900,20 @@ ves_icall_object_new_specific (MonoVTable *vtable)
        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)
 {
@@ -4620,6 +4924,22 @@ mono_object_new_alloc_specific (MonoVTable *vtable)
        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)
 {
@@ -4634,11 +4954,26 @@ mono_object_new_alloc_specific_checked (MonoVTable *vtable, MonoError *error)
        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);
+               mono_object_register_finalizer (o, error);
 
        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)
 {
@@ -4649,6 +4984,23 @@ mono_object_new_fast (MonoVTable *vtable)
        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)
 {
@@ -4690,7 +5042,7 @@ mono_object_new_mature (MonoVTable *vtable, MonoError *error)
        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);
+               mono_object_register_finalizer (o, error);
 
        return o;
 }
@@ -4749,12 +5101,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 */
+       
+       result = mono_object_new_checked (domain, klass, &error);
 
-       return mono_object_new (domain, klass);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       return result;
+       
 }
 
 
@@ -4800,7 +5157,7 @@ mono_object_clone_checked (MonoObject *obj, MonoError *error)
        mono_gc_wbarrier_object_copy (o, obj);
 
        if (obj->vtable->klass->has_finalize)
-               mono_object_register_finalizer (o);
+               mono_object_register_finalizer (o, error);
        return o;
 }
 
@@ -5041,7 +5398,9 @@ mono_array_new_full_checked (MonoDomain *domain, MonoClass *array_class, uintptr
         * 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
@@ -5087,7 +5446,10 @@ mono_array_new (MonoDomain *domain, MonoClass *eclass, uintptr_t n)
        ac = mono_array_class_get (eclass, 1);
        g_assert (ac);
 
-       arr = mono_array_new_specific_checked (mono_class_vtable_full (domain, ac, TRUE), n, &error);
+       MonoVTable *vtable = mono_class_vtable_full (domain, ac, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+       arr = mono_array_new_specific_checked (vtable, n, &error);
        mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return arr;
@@ -5163,12 +5525,34 @@ 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_raise_exception (&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_checked (domain, len, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
-
-       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;
 }
@@ -5271,20 +5655,24 @@ mono_string_new_len (MonoDomain *domain, const char *text, guint length)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       GError *error = NULL;
+       MonoError error;
+       GError *eg_error = NULL;
        MonoString *o = NULL;
        guint16 *ut;
        glong items_written;
 
-       ut = eg_utf8_to_utf16_with_nuls (text, length, NULL, &items_written, &error);
+       mono_error_init (&error);
 
-       if (!error)
-               o = mono_string_new_utf16 (domain, ut, items_written);
+       ut = eg_utf8_to_utf16_with_nuls (text, length, NULL, &items_written, &eg_error);
+
+       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);
 
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
        return o;
 }
 
@@ -5293,48 +5681,78 @@ 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);
+    mono_error_raise_exception (error);
+    
 /*FIXME g_utf8_get_char, g_utf8_next_char and g_utf8_validate are not part of eglib.*/
 #if 0
-       MonoError error;
        gunichar2 *str;
        const gchar *end;
        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_checked (domain, len, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       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;
 }
@@ -5413,12 +5831,14 @@ mono_value_box (MonoDomain *domain, MonoClass *klass, gpointer value)
        }
 #endif
 #endif
-       if (klass->has_finalize)
-               mono_object_register_finalizer (res);
+       if (klass->has_finalize) {
+               mono_object_register_finalizer (res, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+       }
        return res;
 }
 
-/*
+/**
  * mono_value_copy:
  * @dest: destination pointer
  * @src: source pointer
@@ -5435,7 +5855,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
@@ -5474,8 +5894,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)
@@ -5605,8 +6027,9 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
                mono_error_raise_exception (&error); /* FIXME don't raise here */
                pa [1] = obj;
 
-               res = mono_runtime_invoke (im, rp, pa, NULL);
-       
+               res = mono_runtime_invoke_checked (im, rp, pa, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+
                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);
@@ -5679,15 +6102,16 @@ mono_string_get_pinned (MonoString *str, MonoError *error)
 }
 
 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;
 
-       MonoError error;
        MonoGHashTable *ldstr_table;
        MonoString *s, *res;
        MonoDomain *domain;
        
+       mono_error_init (error);
+
        domain = ((MonoObject *)str)->vtable->domain;
        ldstr_table = domain->ldstr_table;
        ldstr_lock ();
@@ -5699,8 +6123,8 @@ mono_string_is_interned_lookup (MonoString *str, int insert)
        if (insert) {
                /* Allocate outside the lock */
                ldstr_unlock ();
-               s = mono_string_get_pinned (str, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               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);
@@ -5742,9 +6166,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;
 }
 
 /**
@@ -5756,10 +6182,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);
 }
 
 /**
@@ -5806,7 +6251,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);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
        {
                int i;
@@ -6041,6 +6487,8 @@ mono_string_from_utf16 (gunichar2 *data)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+       MonoString *res = NULL;
        MonoDomain *domain = mono_domain_get ();
        int len = 0;
 
@@ -6049,7 +6497,9 @@ mono_string_from_utf16 (gunichar2 *data)
 
        while (data [len]) len++;
 
-       return mono_string_new_utf16 (domain, data, len);
+       res = mono_string_new_utf16_checked (domain, data, len, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       return res;
 }
 
 /**
@@ -6202,18 +6652,22 @@ mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoWaitHandle *res;
        gpointer params [1];
        static MonoMethod *handle_set;
 
-       res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.manualresetevent_class);
+       res = (MonoWaitHandle *)mono_object_new_checked (domain, mono_defaults.manualresetevent_class, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        /* 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);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        return res;
 }
@@ -6223,23 +6677,16 @@ 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;
 }
 
 
@@ -6280,7 +6727,9 @@ mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpo
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
-       MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
+       MonoError error;
+       MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new_checked (domain, mono_defaults.asyncresult_class, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
        MonoObject *context = mono_runtime_capture_context (domain);
        /* we must capture the execution context from the original thread */
        if (context) {
@@ -6305,6 +6754,7 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
        MonoAsyncCall *ac;
        MonoObject *res;
 
@@ -6331,11 +6781,8 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
                        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_runtime_invoke_checked (ac->cb_method, ac->cb_target, (gpointer*) &ares, &error);
+                       mono_error_raise_exception (&error);
                }
        }
 
@@ -6442,20 +6889,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_generic_error (error, "System", "NotSupportedException", "Linked away.");
+                       return NULL;
+               }
                real_proxy->vtable->domain->private_invoke_method = im;
        }
 
@@ -6464,7 +6917,10 @@ 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
 
@@ -6489,7 +6945,10 @@ 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);
+                       ret = mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+                       return ret;
                }
        }
 #endif
@@ -6546,7 +7005,9 @@ mono_object_to_string (MonoObject *obj, MonoObject **exc)
        MONO_REQ_GC_UNSAFE_MODE;
 
        static MonoMethod *to_string = NULL;
+       MonoError error;
        MonoMethod *method;
+       MonoString *s;
        void *target = obj;
 
        g_assert (obj);
@@ -6561,7 +7022,18 @@ mono_object_to_string (MonoObject *obj, MonoObject **exc)
                target = mono_object_unbox (obj);
        }
 
-       return (MonoString *) mono_runtime_invoke (method, target, NULL, exc);
+       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); /* FIXME don't raise here */
+       }
+
+       return s;
 }
 
 /**
@@ -6720,18 +7192,25 @@ mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError 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); 
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
        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);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_message_init (domain, msg, rm, 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);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               mono_message_init (domain, msg, rm, NULL);
                count =  sig->param_count;
        }
 
@@ -6838,6 +7317,8 @@ mono_load_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField *
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+
        static MonoMethod *getter = NULL;
        MonoDomain *domain = mono_domain_get ();
        MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
@@ -6863,16 +7344,20 @@ mono_load_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField *
        
        field_class = mono_class_from_mono_type (field->type);
 
-       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);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
        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);
+       MonoReflectionMethod *rm = mono_method_get_object_checked (domain, getter, NULL, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_message_init (domain, msg, rm, 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);
 
-       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
+       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        if (exc) mono_raise_exception ((MonoException *)exc);
 
@@ -6900,6 +7385,8 @@ mono_load_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFie
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+
        static MonoMethod *getter = NULL;
        MonoDomain *domain = mono_domain_get ();
        MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
@@ -6916,7 +7403,8 @@ mono_load_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFie
        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);
+                       res = mono_object_new_checked (domain, field_class, &error);
+                       mono_error_raise_exception (&error); /* FIXME don't raise here */
                        val = ((gchar *) res) + sizeof (MonoObject);
                } else {
                        val = &res;
@@ -6931,17 +7419,21 @@ mono_load_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFie
                        mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
        }
        
-       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);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
        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);
+       MonoReflectionMethod *rm = mono_method_get_object_checked (domain, getter, NULL, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_message_init (domain, msg, rm, 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);
 
-       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
+       mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        if (exc) mono_raise_exception ((MonoException *)exc);
 
@@ -6969,6 +7461,8 @@ mono_store_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+
        static MonoMethod *setter = NULL;
        MonoDomain *domain = mono_domain_get ();
        MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
@@ -7001,8 +7495,11 @@ mono_store_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField
                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);
+       msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_message_init (domain, msg, rm, NULL);
 
        full_name = mono_type_get_full_name (klass);
        mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
@@ -7010,7 +7507,8 @@ mono_store_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField
        mono_array_setref (msg->args, 2, arg);
        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);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        if (exc) mono_raise_exception ((MonoException *)exc);
 }
@@ -7029,6 +7527,8 @@ mono_store_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFi
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
+       MonoError error;
+
        static MonoMethod *setter = NULL;
        MonoDomain *domain = mono_domain_get ();
        MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
@@ -7054,8 +7554,11 @@ mono_store_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFi
                        mono_raise_exception (mono_get_exception_not_supported ("Linked away."));
        }
 
-       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);
+       msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       MonoReflectionMethod *rm = mono_method_get_object_checked (domain, setter, NULL, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_message_init (domain, msg, rm, NULL);
 
        full_name = mono_type_get_full_name (klass);
        mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
@@ -7063,7 +7566,8 @@ mono_store_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFi
        mono_array_setref (msg->args, 2, arg);
        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);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        if (exc) mono_raise_exception ((MonoException *)exc);
 }
@@ -7142,6 +7646,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*
@@ -7172,3 +7681,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