Merge pull request #2670 from lambdageek/dev/monoerror-mono_runtime_object_init
[mono.git] / mono / metadata / object.c
index 4c69c85ee982cd5d99cb83badfe30f77392eae7b..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"
@@ -257,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;
@@ -280,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
@@ -296,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;
@@ -323,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 ();
@@ -364,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) {
@@ -383,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));
@@ -404,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));
@@ -412,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
@@ -429,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")))) {
@@ -447,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.
@@ -457,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);
                }
 
@@ -487,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
@@ -564,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;
@@ -586,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) 
@@ -651,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;
 
-       return arch_create_jump_trampoline (domain, method, add_sync_wrapper);
+       MONO_REQ_GC_NEUTRAL_MODE;
+
+       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
@@ -1078,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) {
@@ -1861,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:
@@ -1875,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 (mono_class_has_failure (klass)) {
-               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;
        }
 
@@ -1906,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);
 }
 
 /**
@@ -1956,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;
@@ -1972,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;
@@ -1984,8 +1989,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
                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;
                }
        }
@@ -2006,8 +2010,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
                                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;
                }
        }
@@ -2028,8 +2031,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, gboolean
        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;
        }
 
@@ -2189,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;
+                               }
+                       }
                }
        }
 
@@ -2206,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
@@ -2262,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
@@ -2279,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;
 }
@@ -3378,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:
@@ -3424,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);
@@ -4411,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)
@@ -4804,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;
 }
@@ -4934,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;
 }
@@ -5022,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;
 }
@@ -5137,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;
 }
 
@@ -5378,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
@@ -5424,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;
@@ -5806,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;
 }
 
@@ -6075,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 ();
@@ -6095,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);
@@ -6138,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;
 }
 
 /**
@@ -6152,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);
 }
 
 /**
@@ -6840,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;
        }
 
@@ -6864,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;
 }
@@ -6896,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
@@ -7304,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);
 
@@ -7379,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);
 
@@ -7453,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);
 }
@@ -7511,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);
 }