Merge pull request #2820 from kumpera/license-change-rebased
[mono.git] / mono / metadata / class.c
index 983f1ca4149d90e78ab62646b4c9983b3d2a415d..f7b36279f4af17942f00dd9af24aea8a7ba2e9b3 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #ifdef HAVE_ALLOCA_H
@@ -905,11 +906,7 @@ mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
        MonoError error;
        MonoType *result;
        result = mono_class_inflate_generic_type_checked (type, context, &error);
-
-       if (!mono_error_ok (&error)) {
-               mono_error_cleanup (&error);
-               return NULL;
-       }
+       mono_error_cleanup (&error);
        return result;
 }
 
@@ -955,6 +952,11 @@ mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoG
        return inflated;
 }
 
+/*
+ * mono_class_inflate_generic_class:
+ *
+ *   Inflate the class @gklass with @context. Set @error on failure.
+ */
 MonoClass*
 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
 {
@@ -969,24 +971,6 @@ mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext
 
        return res;
 }
-/*
- * mono_class_inflate_generic_class:
- *
- *   Inflate the class GKLASS with CONTEXT.
- */
-MonoClass*
-mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
-{
-       MonoError error;
-       MonoClass *res;
-
-       res = mono_class_inflate_generic_class_checked (gklass, context, &error);
-       g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
-
-       return res;
-}
-
-
 
 static MonoGenericContext
 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
@@ -1381,11 +1365,11 @@ mono_type_has_exceptions (MonoType *type)
        case MONO_TYPE_CLASS:
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_SZARRAY:
-               return type->data.klass->exception_type;
+               return mono_class_has_failure (type->data.klass);
        case MONO_TYPE_ARRAY:
-               return type->data.array->eklass->exception_type;
+               return mono_class_has_failure (type->data.array->eklass);
        case MONO_TYPE_GENERICINST:
-               return mono_generic_class_get_class (type->data.generic_class)->exception_type;
+               return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
        default:
                return FALSE;
        }
@@ -1497,6 +1481,7 @@ mono_class_setup_fields (MonoClass *klass)
        int i, blittable = TRUE;
        guint32 real_size = 0;
        guint32 packing_size = 0;
+       int instance_size;
        gboolean explicit_size;
        MonoClassField *field;
        MonoGenericContainer *container = NULL;
@@ -1566,13 +1551,13 @@ mono_class_setup_fields (MonoClass *klass)
 
        if (gtd) {
                mono_class_setup_fields (gtd);
-               if (gtd->exception_type) {
+               if (mono_class_has_failure (gtd)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        return;
                }
        }
 
-       klass->instance_size = 0;
+       instance_size = 0;
        if (!klass->rank)
                klass->sizes.class_size = 0;
 
@@ -1581,18 +1566,18 @@ mono_class_setup_fields (MonoClass *klass)
                mono_class_init (klass->parent);
                if (!klass->parent->size_inited) {
                        mono_class_setup_fields (klass->parent);
-                       if (klass->parent->exception_type) {
+                       if (mono_class_has_failure (klass->parent)) {
                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                                return;
                        }
                }
-               klass->instance_size += klass->parent->instance_size;
+               instance_size += klass->parent->instance_size;
                klass->min_align = klass->parent->min_align;
                /* we use |= since it may have been set already */
                klass->has_references |= klass->parent->has_references;
                blittable = klass->parent->blittable;
        } else {
-               klass->instance_size = sizeof (MonoObject);
+               instance_size = sizeof (MonoObject);
                klass->min_align = 1;
        }
 
@@ -1614,14 +1599,16 @@ mono_class_setup_fields (MonoClass *klass)
                        return;
                }
                klass->packing_size = packing_size;
-               real_size += klass->instance_size;
+               real_size += instance_size;
        }
 
        if (!top) {
                if (explicit_size && real_size) {
-                       klass->instance_size = MAX (real_size, klass->instance_size);
+                       instance_size = MAX (real_size, instance_size);
                }
                klass->blittable = blittable;
+               if (!klass->instance_size)
+                       klass->instance_size = instance_size;
                mono_memory_barrier ();
                klass->size_inited = 1;
                klass->fields_inited = 1;
@@ -1697,7 +1684,7 @@ mono_class_setup_fields (MonoClass *klass)
                                MonoClass *field_class = mono_class_from_mono_type (field->type);
                                if (field_class) {
                                        mono_class_setup_fields (field_class);
-                                       if (field_class->exception_type) {
+                                       if (mono_class_has_failure (field_class)) {
                                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                                                break;
                                        }
@@ -1735,12 +1722,12 @@ mono_class_setup_fields (MonoClass *klass)
                return;
        }
        if (explicit_size && real_size) {
-               klass->instance_size = MAX (real_size, klass->instance_size);
+               instance_size = MAX (real_size, instance_size);
        }
 
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return;
-       mono_class_layout_fields (klass);
+       mono_class_layout_fields (klass, instance_size);
 
        /*valuetypes can't be neither bigger than 1Mb or empty. */
        if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
@@ -1821,6 +1808,7 @@ type_has_references (MonoClass *klass, MonoType *ftype)
 /*
  * mono_class_layout_fields:
  * @class: a class
+ * @instance_size: base instance size
  *
  * Compute the placement of fields inside an object or struct, according to
  * the layout rules and set the following fields in @class:
@@ -1833,7 +1821,7 @@ type_has_references (MonoClass *klass, MonoType *ftype)
  * LOCKING: this is supposed to be called with the loader lock held.
  */
 void
-mono_class_layout_fields (MonoClass *klass)
+mono_class_layout_fields (MonoClass *klass, int instance_size)
 {
        int i;
        const int top = klass->field.count;
@@ -1914,7 +1902,6 @@ mono_class_layout_fields (MonoClass *klass)
        /*
         * Compute field layout and total size (not considering static fields)
         */
-
        switch (layout) {
        case TYPE_ATTRIBUTE_AUTO_LAYOUT:
        case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
@@ -1929,7 +1916,7 @@ mono_class_layout_fields (MonoClass *klass)
 
                if (klass->parent) {
                        mono_class_setup_fields (klass->parent);
-                       if (klass->parent->exception_type) {
+                       if (mono_class_has_failure (klass->parent)) {
                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                                return;
                        }
@@ -1990,11 +1977,11 @@ mono_class_layout_fields (MonoClass *klass)
                                real_size = field->offset + size;
                        }
 
-                       klass->instance_size = MAX (real_size, klass->instance_size);
+                       instance_size = MAX (real_size, instance_size);
        
-                       if (klass->instance_size & (klass->min_align - 1)) {
-                               klass->instance_size += klass->min_align - 1;
-                               klass->instance_size &= ~(klass->min_align - 1);
+                       if (instance_size & (klass->min_align - 1)) {
+                               instance_size += klass->min_align - 1;
+                               instance_size &= ~(klass->min_align - 1);
                        }
                }
                break;
@@ -2079,10 +2066,10 @@ mono_class_layout_fields (MonoClass *klass)
                        g_free (ref_bitmap);
                }
 
-               klass->instance_size = MAX (real_size, klass->instance_size);
-               if (klass->instance_size & (klass->min_align - 1)) {
-                       klass->instance_size += klass->min_align - 1;
-                       klass->instance_size &= ~(klass->min_align - 1);
+               instance_size = MAX (real_size, instance_size);
+               if (instance_size & (klass->min_align - 1)) {
+                       instance_size += klass->min_align - 1;
+                       instance_size &= ~(klass->min_align - 1);
                }
                break;
        }
@@ -2098,11 +2085,17 @@ mono_class_layout_fields (MonoClass *klass)
                 * unaligned accesses otherwise. See #78990 for a testcase.
                 */
                if (mono_align_small_structs) {
-                       if (klass->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
-                               klass->min_align = MAX (klass->min_align, klass->instance_size - sizeof (MonoObject));
+                       if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
+                               klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
                }
        }
 
+       if (klass->instance_size && !klass->image->dynamic) {
+               /* Might be already set using cached info */
+               g_assert (klass->instance_size == instance_size);
+       } else {
+               klass->instance_size = instance_size;
+       }
        mono_memory_barrier ();
        klass->size_inited = 1;
 
@@ -2187,9 +2180,9 @@ mono_class_setup_methods (MonoClass *klass)
                MonoClass *gklass = klass->generic_class->container_class;
 
                mono_class_init (gklass);
-               if (!gklass->exception_type)
+               if (!mono_class_has_failure (gklass))
                        mono_class_setup_methods (gklass);
-               if (gklass->exception_type) {
+               if (mono_class_has_failure (gklass)) {
                        /* FIXME make exception_data less opaque so it's possible to dup it here */
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
                        return;
@@ -2370,7 +2363,7 @@ mono_class_get_method_by_index (MonoClass *klass, int index)
                return m;
        } else {
                mono_class_setup_methods (klass);
-               if (klass->exception_type) /*FIXME do proper error handling*/
+               if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
                        return NULL;
                g_assert (index >= 0 && index < klass->method.count);
                return klass->methods [index];
@@ -2392,7 +2385,7 @@ mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
        g_assert (method->klass == gklass);
 
        mono_class_setup_methods (gklass);
-       g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
+       g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
 
        for (i = 0; i < gklass->method.count; ++i) {
                if (gklass->methods [i] == method) {
@@ -2441,7 +2434,7 @@ mono_class_get_vtable_entry (MonoClass *klass, int offset)
                g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
        } else {
                mono_class_setup_vtable (klass);
-               if (klass->exception_type)
+               if (mono_class_has_failure (klass))
                        return NULL;
                m = klass->vtable [offset];
        }
@@ -2487,7 +2480,7 @@ mono_class_setup_properties (MonoClass *klass)
 
                mono_class_init (gklass);
                mono_class_setup_properties (gklass);
-               if (gklass->exception_type) {
+               if (mono_class_has_failure (gklass)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
                        return;
                }
@@ -2519,7 +2512,7 @@ mono_class_setup_properties (MonoClass *klass)
 
                if (count) {
                        mono_class_setup_methods (klass);
-                       if (klass->exception_type)
+                       if (mono_class_has_failure (klass))
                                return;
                }
 
@@ -2620,7 +2613,7 @@ mono_class_setup_events (MonoClass *klass)
                MonoGenericContext *context = NULL;
 
                mono_class_setup_events (gklass);
-               if (gklass->exception_type) {
+               if (mono_class_has_failure (gklass)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
                        return;
                }
@@ -2660,7 +2653,7 @@ mono_class_setup_events (MonoClass *klass)
 
                if (count) {
                        mono_class_setup_methods (klass);
-                       if (klass->exception_type) {
+                       if (mono_class_has_failure (klass)) {
                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
                                return;
                        }
@@ -2859,7 +2852,7 @@ collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError
                        *res = g_ptr_array_new ();
                g_ptr_array_add (*res, ic);
                mono_class_init (ic);
-               if (ic->exception_type) {
+               if (mono_class_has_failure (ic)) {
                        mono_error_set_type_load_class (error, ic, "Error Loading class");
                        return;
                }
@@ -3102,15 +3095,15 @@ get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enume
        all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
 
        if (!generic_icollection_class) {
-               generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
+               generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
                        "System.Collections.Generic", "ICollection`1");
-               generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
+               generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
                        "System.Collections.Generic", "IEnumerable`1");
-               generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
+               generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
                        "System.Collections.Generic", "IEnumerator`1");
-               generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
+               generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
                        "System.Collections.Generic", "IReadOnlyList`1");
-               generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
+               generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
                        "System.Collections.Generic", "IReadOnlyCollection`1");
        }
 
@@ -3294,7 +3287,7 @@ count_virtual_methods (MonoClass *klass)
 
        if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
                mono_class_setup_methods (klass);
-               if (klass->exception_type)
+               if (mono_class_has_failure (klass))
                        return -1;
 
                for (i = 0; i < klass->method.count; ++i) {
@@ -3762,11 +3755,11 @@ mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
        int i;
        if (!klass->generic_class) {
                mono_class_setup_vtable_full (klass, in_setup);
-               return klass->exception_type == 0;
+               return !mono_class_has_failure (klass);
        }
 
        mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
-       if (klass->generic_class->container_class->exception_type) {
+       if (mono_class_has_failure (klass->generic_class->container_class)) {
                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
                return FALSE;
        }
@@ -3809,6 +3802,7 @@ mono_class_setup_vtable (MonoClass *klass)
 static void
 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
 {
+       MonoError error;
        MonoMethod **overrides;
        MonoGenericContext *context;
        guint32 type_token;
@@ -3824,7 +3818,7 @@ mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
                return;
        }
 
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return;
 
        if (g_list_find (in_setup, klass))
@@ -3859,7 +3853,14 @@ mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
                 * This is true since we don't do layout all over again for them, we simply inflate
                 * the layout of the parent.
                 */
-               mono_reflection_get_dynamic_overrides (klass, &overrides, &onum);
+               mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
+               if (!is_ok (&error)) {
+                       mono_loader_unlock ();
+                       g_list_remove (in_setup, klass);
+                       mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf("Could not load list of method overrides due to %s", mono_error_get_message (&error)));
+                       mono_error_cleanup (&error);
+                       return;
+               }
        } else {
                /* The following call fails if there are missing methods in the type */
                /* FIXME it's probably a good idea to avoid this for generic instances. */
@@ -4218,7 +4219,7 @@ print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, Mono
        g_free (method_signature);
        g_free (type_name);
        mono_class_setup_methods (klass);
-       if (klass->exception_type) {
+       if (mono_class_has_failure (klass)) {
                char *name = mono_type_get_full_name (klass);
                mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
                g_free (name);
@@ -4342,7 +4343,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                mono_class_init (klass->parent);
                mono_class_setup_vtable_full (klass->parent, in_setup);
 
-               if (klass->parent->exception_type) {
+               if (mono_class_has_failure (klass->parent)) {
                        char *name = mono_type_get_full_name (klass->parent);
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
                        g_free (name);
@@ -4381,7 +4382,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                MonoMethod **tmp;
 
                mono_class_setup_vtable_full (gklass, in_setup);
-               if (gklass->exception_type != MONO_EXCEPTION_NONE) {
+               if (mono_class_has_failure (gklass)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        return;
                }
@@ -4437,7 +4438,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                                
                                mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
                                TRACE_INTERFACE_VTABLE (printf ("    +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
-                               for (j = 0; j < parent_interface->method.count && !klass->exception_type; j++) {
+                               for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
                                        vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
                                        TRACE_INTERFACE_VTABLE (printf ("    --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
                                                        parent_interface_offset + j, parent_interface_offset, j,
@@ -4499,7 +4500,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
                        virt_methods = g_slist_prepend (virt_methods, cm);
                }
-               if (klass->exception_type)
+               if (mono_class_has_failure (klass))
                        goto fail;
        }
        
@@ -4514,7 +4515,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                ic_offset = mono_class_interface_offset (klass, ic);
 
                mono_class_setup_methods (ic);
-               if (ic->exception_type)
+               if (mono_class_has_failure (ic))
                        goto fail;
                
                // Check if this interface is explicitly implemented (instead of just inherited)
@@ -4561,7 +4562,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                                                }
                                        }
                                        TRACE_INTERFACE_VTABLE (printf ("\n"));
-                                       if (klass->exception_type)  /*Might be set by check_interface_method_override*/
+                                       if (mono_class_has_failure (klass))  /*Might be set by check_interface_method_override*/
                                                goto fail;
                                }
                                
@@ -4582,7 +4583,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                                                        }
                                                        break;
                                                }
-                                               if (klass->exception_type) /*Might be set by check_interface_method_override*/
+                                               if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
                                                        goto fail;
                                                TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
                                        }
@@ -4677,7 +4678,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
                                                break;
                                        }
                                }
-                               if (k->exception_type)
+                               if (mono_class_has_failure (k))
                                        goto fail;
                                
                                if (slot >= 0) 
@@ -4852,7 +4853,7 @@ mono_method_get_vtable_slot (MonoMethod *method)
 {
        if (method->slot == -1) {
                mono_class_setup_vtable (method->klass);
-               if (method->klass->exception_type)
+               if (mono_class_has_failure (method->klass))
                        return -1;
                if (method->slot == -1) {
                        MonoClass *gklass;
@@ -4948,7 +4949,7 @@ generic_array_methods (MonoClass *klass)
        if (generic_array_method_num)
                return generic_array_method_num;
        mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
-       g_assert (!klass->parent->exception_type); /*So hitting this assert is a huge problem*/
+       g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
        for (i = 0; i < klass->parent->method.count; i++) {
                MonoMethod *m = klass->parent->methods [i];
                if (!strncmp (m->name, "InternalArray__", 15)) {
@@ -5108,18 +5109,18 @@ mono_class_init (MonoClass *klass)
        g_assert (klass);
 
        /* Double-checking locking pattern */
-       if (klass->inited || klass->exception_type)
-               return klass->exception_type == MONO_EXCEPTION_NONE;
+       if (klass->inited || mono_class_has_failure (klass))
+               return !mono_class_has_failure (klass);
 
        /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
 
        /* We do everything inside the lock to prevent races */
        mono_loader_lock ();
 
-       if (klass->inited || klass->exception_type) {
+       if (klass->inited || mono_class_has_failure (klass)) {
                mono_loader_unlock ();
                /* Somebody might have gotten in before us */
-               return klass->exception_type == MONO_EXCEPTION_NONE;
+               return !mono_class_has_failure (klass);
        }
 
        if (klass->init_pending) {
@@ -5139,7 +5140,7 @@ mono_class_init (MonoClass *klass)
                MonoClass *element_class = klass->element_class;
                if (!element_class->inited) 
                        mono_class_init (element_class);
-               if (element_class->exception_type != MONO_EXCEPTION_NONE) {
+               if (mono_class_has_failure (element_class)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        goto leave;
                }
@@ -5157,9 +5158,9 @@ mono_class_init (MonoClass *klass)
 
                mono_class_init (gklass);
                // FIXME: Why is this needed ?
-               if (!gklass->exception_type)
+               if (!mono_class_has_failure (gklass))
                        mono_class_setup_methods (gklass);
-               if (gklass->exception_type) {
+               if (mono_class_has_failure (gklass)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
                        goto leave;
                }
@@ -5192,7 +5193,7 @@ mono_class_init (MonoClass *klass)
        else
                if (!klass->size_inited){
                        mono_class_setup_fields (klass);
-                       if (klass->exception_type || mono_loader_get_last_error ())
+                       if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
                                goto leave;
                }
                                
@@ -5246,7 +5247,7 @@ mono_class_init (MonoClass *klass)
                klass->has_cctor = gklass->has_cctor;
 
                mono_class_setup_vtable (gklass);
-               if (gklass->exception_type) {
+               if (mono_class_has_failure (gklass)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        goto leave;
                }
@@ -5278,7 +5279,7 @@ mono_class_init (MonoClass *klass)
                                        klass->has_cctor = 1;
                        } else {
                                mono_class_setup_methods (klass);
-                               if (klass->exception_type)
+                               if (mono_class_has_failure (klass))
                                        goto leave;
 
                                for (i = 0; i < klass->method.count; ++i) {
@@ -5297,7 +5298,7 @@ mono_class_init (MonoClass *klass)
                int first_iface_slot;
                /* This will compute klass->parent->vtable_size for some classes */
                mono_class_init (klass->parent);
-               if (klass->parent->exception_type) {
+               if (mono_class_has_failure (klass->parent)) {
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                        goto leave;
                }
@@ -5306,7 +5307,7 @@ mono_class_init (MonoClass *klass)
                if (!klass->parent->vtable_size) {
                        /* FIXME: Get rid of this somehow */
                        mono_class_setup_vtable (klass->parent);
-                       if (klass->parent->exception_type) {
+                       if (mono_class_has_failure (klass->parent)) {
                                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
                                goto leave;
                        }
@@ -5325,7 +5326,7 @@ mono_class_init (MonoClass *klass)
                mono_security_core_clr_check_inheritance (klass);
 
        if (mono_loader_get_last_error ()) {
-               if (klass->exception_type == MONO_EXCEPTION_NONE) {
+               if (!mono_class_has_failure (klass)) {
                        set_failure_from_loader_error (klass, mono_loader_get_last_error ());
                }
                mono_loader_clear_error ();
@@ -5344,7 +5345,7 @@ mono_class_init (MonoClass *klass)
 
        mono_loader_unlock ();
 
-       return klass->exception_type == MONO_EXCEPTION_NONE;
+       return !mono_class_has_failure (klass);
 }
 
 /*
@@ -5379,7 +5380,7 @@ mono_class_has_finalizer (MonoClass *klass)
                                 * ignores overrides.
                                 */
                                mono_class_setup_vtable (klass);
-                               if (klass->exception_type || mono_loader_get_last_error ())
+                               if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
                                        cmethod = NULL;
                                else
                                        cmethod = klass->vtable [finalize_slot];
@@ -5734,22 +5735,6 @@ mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char
        mono_error_set_type_load_class (error, klass, msg);
 }
 
-static void
-mono_class_set_failure_from_loader_error (MonoClass *klass, MonoError *error, char *msg)
-{
-       MonoLoaderError *lerror = mono_loader_get_last_error ();
-
-       if (lerror) {
-               set_failure_from_loader_error (klass, lerror);
-               mono_error_set_from_loader_error (error);
-               if (msg)
-                       g_free (msg);
-       } else {
-               mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, msg);
-               mono_error_set_type_load_class (error, klass, msg);
-       }
-}
-
 /**
  * mono_class_create_from_typedef:
  * @image: image where the token is valid
@@ -6217,7 +6202,7 @@ make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
                CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
                pos++;
        } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
-               CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_from_name (mono_defaults.corlib, "System", "ValueType") );
+               CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
        } else {
                CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
        }
@@ -6261,7 +6246,7 @@ make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
 
        if (count - pos > 0) {
                mono_class_setup_vtable (klass->parent);
-               if (klass->parent->exception_type)
+               if (mono_class_has_failure (klass->parent))
                        mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
                else
                        setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
@@ -6743,7 +6728,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
 
        /* for the building corlib use System.Array from it */
        if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
-               parent = mono_class_from_name (image, "System", "Array");
+               parent = mono_class_load_from_name (image, "System", "Array");
                corlib_type = TRUE;
        } else {
                parent = mono_defaults.array_class;
@@ -6780,7 +6765,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
 
        if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
                /*Arrays of those two types are invalid.*/
-               mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+               mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
        } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
                if (!eclass->ref_info_handle || eclass->wastypebuilder) {
                        g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
@@ -6797,7 +6782,7 @@ mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
                mono_class_init (eclass);
        if (!eclass->size_inited)
                mono_class_setup_fields (eclass);
-       if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
+       if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
                mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
 
        klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
@@ -6985,7 +6970,7 @@ static MonoClassField *
 mono_class_get_field_idx (MonoClass *klass, int idx)
 {
        mono_class_setup_fields_locking (klass);
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return NULL;
 
        while (klass) {
@@ -7067,7 +7052,7 @@ mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoTyp
        int i;
 
        mono_class_setup_fields_locking (klass);
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return NULL;
 
        while (klass) {
@@ -7473,7 +7458,7 @@ mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
                        mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
                        return NULL;
                }
-               klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
+               klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
                goto done;
        }
 
@@ -7523,8 +7508,11 @@ mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext
        mono_error_init (error);
 
        //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
-       if (image_is_dynamic (image))
-               return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
+       if (image_is_dynamic (image)) {
+               MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
+               return_val_if_nok (error, NULL);
+               return mono_class_get_type (klass);
+       }
 
        if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
                MonoClass *klass = mono_class_get_checked (image, type_token, error);
@@ -7733,7 +7721,8 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char
 {
        MonoError error;
        MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
-       g_assert (!mono_error_ok (&error));
+       mono_error_cleanup (&error);
+
        return res;
 }
 
@@ -7836,13 +7825,15 @@ return_nested_in (MonoClass *klass, char *nested)
 }
 
 static MonoClass*
-search_modules (MonoImage *image, const char *name_space, const char *name)
+search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
 {
        MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
        MonoImage *file_image;
        MonoClass *klass;
        int i;
 
+       mono_error_init (error);
+
        /* 
         * The EXPORTEDTYPES table only contains public types, so have to search the
         * modules as well.
@@ -7857,8 +7848,8 @@ search_modules (MonoImage *image, const char *name_space, const char *name)
 
                file_image = mono_image_load_file_for_image (image, i + 1);
                if (file_image) {
-                       klass = mono_class_from_name (file_image, name_space, name);
-                       if (klass)
+                       klass = mono_class_from_name_checked (file_image, name_space, name, error);
+                       if (klass || !is_ok (error))
                                return klass;
                }
        }
@@ -7867,7 +7858,7 @@ search_modules (MonoImage *image, const char *name_space, const char *name)
 }
 
 static MonoClass *
-mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
+mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
 {
        GHashTable *nspace_table;
        MonoImage *loaded_image;
@@ -7900,8 +7891,11 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
        if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
                gboolean res = get_class_from_name (image, name_space, name, &klass);
                if (res) {
-                       if (!klass)
-                               klass = search_modules (image, name_space, name);
+                       if (!klass) {
+                               klass = search_modules (image, name_space, name, error);
+                               if (!is_ok (error))
+                                       return NULL;
+                       }
                        if (nested)
                                return klass ? return_nested_in (klass, nested) : NULL;
                        else
@@ -7924,15 +7918,15 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
                for (i = 0; i < image->module_count; ++i) {
                        MonoImage *module = image->modules [i];
 
-                       klass = mono_class_from_name (module, name_space, name);
-                       if (klass)
+                       klass = mono_class_from_name_checked (module, name_space, name, error);
+                       if (klass || !is_ok (error))
                                return klass;
                }
        }
 
        if (!token) {
-               klass = search_modules (image, name_space, name);
-               if (klass)
+               klass = search_modules (image, name_space, name, error);
+               if (klass || !is_ok (error))
                        return klass;
        }
 
@@ -7953,7 +7947,7 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
                        loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
                        if (!loaded_image)
                                return NULL;
-                       klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, error, visited_images);
+                       klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
                        if (nested)
                                return klass ? return_nested_in (klass, nested) : NULL;
                        return klass;
@@ -7966,9 +7960,9 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
                        g_assert (image->references [assembly_idx - 1]);
                        if (image->references [assembly_idx - 1] == (gpointer)-1)
                                return NULL;                    
-                       klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, error, visited_images);
+                       klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
                        if (nested)
-                               return return_nested_in (klass, nested);
+                               return klass ? return_nested_in (klass, nested) : NULL;
                        return klass;
                } else {
                        g_assert_not_reached ();
@@ -7983,6 +7977,18 @@ mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, cons
        return klass;
 }
 
+/**
+ * mono_class_from_name_checked:
+ * @image: The MonoImage where the type is looked up in
+ * @name_space: the type namespace
+ * @name: the type short name.
+ *
+ * Obtains a MonoClass with a given namespace and a given name which
+ * is located in the given MonoImage.
+ *
+ * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
+ * set if the class was not found or it will return NULL and set the error if there was a loading error.
+ */
 MonoClass *
 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
 {
@@ -7991,7 +7997,7 @@ mono_class_from_name_checked (MonoImage *image, const char* name_space, const ch
 
        visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
 
-       klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
+       klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
 
        g_hash_table_destroy (visited_images);
 
@@ -8018,13 +8024,61 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
        MonoClass *klass;
 
        klass = mono_class_from_name_checked (image, name_space, name, &error);
-       if (!mono_error_ok (&error)) {
-               mono_loader_set_error_from_mono_error (&error);
-               mono_error_cleanup (&error); /* FIXME Don't swallow the error */
-       }
+       mono_error_cleanup (&error); /* FIXME Don't swallow the error */
+
+       return klass;
+}
+
+/**
+ * mono_class_load_from_name:
+ * @image: The MonoImage where the type is looked up in
+ * @name_space: the type namespace
+ * @name: the type short name.
+ *
+ * This function works exactly like mono_class_from_name but it will abort if the class is not found.
+ * This function should be used by the runtime for critical types to which there's no way to recover but crash
+ * If they are missing. Thing of System.Object or System.String.
+ */
+MonoClass *
+mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
+{
+       MonoError error;
+       MonoClass *klass;
+
+       klass = mono_class_from_name_checked (image, name_space, name, &error);
+       if (!klass)
+               g_error ("Runtime critical type %s.%s not found", name_space, name);
+       if (!mono_error_ok (&error))
+               g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
+       return klass;
+}
+
+/**
+ * mono_class_try_load_from_name:
+ * @image: The MonoImage where the type is looked up in
+ * @name_space: the type namespace
+ * @name: the type short name.
+ *
+ * This function tries to load a type, returning the class was found or NULL otherwise.
+ * This function should be used by the runtime when probing for optional types, those that could have being linked out.
+ *
+ * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
+ * a type that we would otherwise assume to be available but was not due some error.
+ *
+ */
+MonoClass*
+mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
+{
+       MonoError error;
+       MonoClass *klass;
+
+       klass = mono_class_from_name_checked (image, name_space, name, &error);
+       if (!mono_error_ok (&error))
+               g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
        return klass;
 }
 
+
 /**
  * mono_class_is_subclass_of:
  * @klass: class to probe if it is a subclass of another one
@@ -8284,6 +8338,7 @@ mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
 gboolean
 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
 {
+       MonoError error;
        /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
        if (!klass->inited)
                mono_class_init (klass);
@@ -8291,7 +8346,7 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
        if (!oklass->inited)
                mono_class_init (oklass);
 
-       if (klass->exception_type || oklass->exception_type)
+       if (mono_class_has_failure (klass) || mono_class_has_failure  (oklass))
                return FALSE;
 
        if (mono_type_is_generic_argument (&klass->byval_arg)) {
@@ -8317,12 +8372,18 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
                }
 
                /* interface_offsets might not be set for dynamic classes */
-               if (oklass->ref_info_handle && !oklass->interface_bitmap)
+               if (oklass->ref_info_handle && !oklass->interface_bitmap) {
                        /* 
                         * oklass might be a generic type parameter but they have 
                         * interface_offsets set.
                         */
-                       return mono_reflection_call_is_assignable_to (oklass, klass);
+                       gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
+                       if (!is_ok (&error)) {
+                               mono_error_cleanup (&error);
+                               return FALSE;
+                       }
+                       return result;
+               }
                if (!oklass->interface_bitmap)
                        /* Happens with generic instances of not-yet created dynamic types */
                        return FALSE;
@@ -8330,7 +8391,6 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
                        return TRUE;
 
                if (mono_class_has_variant_generic_params (klass)) {
-                       MonoError error;
                        int i;
                        mono_class_setup_interfaces (oklass, &error);
                        if (!mono_error_ok (&error)) {
@@ -8727,8 +8787,9 @@ mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
 
        if (image_is_dynamic (image)) {
                MonoClass *tmp_handle_class;
-               gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
+               gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
 
+               mono_error_assert_ok (error);
                g_assert (tmp_handle_class);
                if (handle_class)
                        *handle_class = tmp_handle_class;
@@ -8808,30 +8869,18 @@ mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
        return NULL;
 }
 
-/**
- * This function might need to call runtime functions so it can't be part
- * of the metadata library.
- */
-static MonoLookupDynamicToken lookup_dynamic = NULL;
-
-void
-mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
-{
-       lookup_dynamic = func;
-}
-
 gpointer
-mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
+mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
 {
        MonoClass *handle_class;
-
-       return lookup_dynamic (image, token, TRUE, &handle_class, context);
+       mono_error_init (error);
+       return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
 }
 
 gpointer
-mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
+mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
 {
-       return lookup_dynamic (image, token, valid_token, handle_class, context);
+       return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
 }
 
 static MonoGetCachedClassInfo get_cached_class_info = NULL;
@@ -9123,7 +9172,7 @@ mono_class_get_fields (MonoClass* klass, gpointer *iter)
                return NULL;
        if (!*iter) {
                mono_class_setup_fields_locking (klass);
-               if (klass->exception_type)
+               if (mono_class_has_failure (klass))
                        return NULL;
                /* start from the first */
                if (klass->field.count) {
@@ -9912,7 +9961,7 @@ mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int p
 gboolean
 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
 {
-       if (klass->exception_type)
+       if (mono_class_has_failure (klass))
                return FALSE;
 
        mono_loader_lock ();
@@ -9986,7 +10035,7 @@ mono_class_get_exception_for_failure (MonoClass *klass)
 {
        gpointer exception_data = mono_class_get_exception_data (klass);
 
-       switch (klass->exception_type) {
+       switch (mono_class_get_failure(klass)) {
        case MONO_EXCEPTION_TYPE_LOAD: {
                MonoString *name;
                MonoException *ex;
@@ -10025,6 +10074,9 @@ mono_class_get_exception_for_failure (MonoClass *klass)
        case MONO_EXCEPTION_BAD_IMAGE: {
                return mono_get_exception_bad_image_format ((const char *)exception_data);
        }
+       case MONO_EXCEPTION_INVALID_PROGRAM: {
+               return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
+       }
        default: {
                MonoLoaderError *error;
                MonoException *ex;
@@ -10813,3 +10865,5 @@ mono_class_full_name (MonoClass *klass)
        return mono_type_full_name (&klass->byval_arg);
 }
 
+/* Declare all shared lazy type lookup functions */
+GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)