Merge pull request #2670 from lambdageek/dev/monoerror-mono_runtime_object_init
[mono.git] / mono / metadata / object.c
index 8d0abf7f987dad246d19ebc24eca0641fc40d4d4..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"
@@ -71,15 +72,39 @@ static GENERATE_GET_CLASS_WITH_CACHE (activation_services, System.Runtime.Remoti
 #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;
 
-       MonoError error;
        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));
@@ -87,8 +112,8 @@ mono_runtime_object_init (MonoObject *this_obj)
        if (method->klass->valuetype)
                this_obj = (MonoObject *)mono_object_unbox (this_obj);
 
-       mono_runtime_invoke_checked (method, this_obj, NULL, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_runtime_invoke_checked (method, this_obj, NULL, error);
+       return is_ok (error);
 }
 
 /* The pseudo algorithm for type initialization from the spec
@@ -233,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;
@@ -256,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
@@ -272,24 +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;
 
-       MonoError error;
-       MonoException *exc;
-       MonoException *exc_to_throw;
        MonoMethod *method = NULL;
        MonoClass *klass;
        gchar *full_name;
@@ -299,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 ();
@@ -340,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) {
@@ -359,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));
@@ -380,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));
@@ -388,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
@@ -405,15 +428,15 @@ mono_runtime_class_init_full (MonoVTable *vtable, gboolean raise_exception)
        mono_type_initialization_unlock ();
 
        if (do_initialization) {
-               mono_runtime_try_invoke (method, NULL, NULL, (MonoObject**) &exc, &error);
-               if (exc == NULL && !mono_error_ok (&error))
-                       exc = mono_error_convert_to_exception (&error);
-               else
-                       mono_error_cleanup (&error);
+               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")))) {
@@ -423,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.
@@ -433,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);
                }
 
@@ -463,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
@@ -540,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;
@@ -562,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) 
@@ -627,9 +643,15 @@ mono_compile_method (MonoMethod *method)
 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
@@ -1054,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) {
@@ -1837,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:
@@ -1851,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;
        }
 
@@ -1882,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);
 }
 
 /**
@@ -1932,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;
@@ -1948,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;
@@ -1956,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;
                }
        }
@@ -1973,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;
                }
        }
@@ -2001,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;
        }
 
@@ -2165,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;
+                               }
+                       }
                }
        }
 
@@ -2182,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
@@ -2238,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
@@ -2255,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;
 }
@@ -3354,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:
@@ -3400,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);
@@ -3730,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;
@@ -3751,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;
@@ -3772,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;
@@ -4387,7 +4430,8 @@ 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) {
                has_stathread_attribute = mono_custom_attrs_has_attr (cinfo, mono_class_get_sta_thread_attribute_class ());
                if (!cinfo->cached)
@@ -4780,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;
 }
@@ -4910,7 +4954,7 @@ 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;
 }
@@ -4998,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;
 }
@@ -5113,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;
 }
 
@@ -5354,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
@@ -5400,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;
@@ -5782,8 +5831,10 @@ 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;
 }
 
@@ -6051,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 ();
@@ -6071,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);
@@ -6114,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;
 }
 
 /**
@@ -6128,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);
 }
 
 /**
@@ -6816,22 +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;
 
-       MonoError error;
        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;
        }
 
@@ -6840,12 +6917,8 @@ mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
        pa [2] = exc;
        pa [3] = out_args;
 
-       if (exc) {
-               o = mono_runtime_try_invoke (im, NULL, pa, exc, &error);
-       } else {
-               o = mono_runtime_invoke_checked (im, NULL, pa, &error);
-       }
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       o = mono_runtime_try_invoke (im, NULL, pa, exc, error);
+       return_val_if_nok (error, NULL);
 
        return o;
 }
@@ -6872,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
@@ -7280,7 +7356,8 @@ mono_load_remote_field (MonoObject *this_obj, MonoClass *klass, MonoClassField *
        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);
 
@@ -7355,7 +7432,8 @@ mono_load_remote_field_new (MonoObject *this_obj, MonoClass *klass, MonoClassFie
        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);
 
@@ -7429,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);
 }
@@ -7487,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);
 }