Merge branch 'master' into msbuilddll2
[mono.git] / mono / metadata / class.c
index 73e0a145e6d204e46b45bdb43921b19e2755aca3..b64c1086e039b0594608e7f2d1c64f9dbd82e47b 100644 (file)
@@ -16,9 +16,6 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#if !HOST_WIN32
-#include <mono/io-layer/atomic.h>
-#endif
 #include <mono/metadata/image.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/metadata.h>
@@ -44,6 +41,9 @@
 #include <mono/utils/mono-error-internals.h>
 #include <mono/utils/mono-logger-internal.h>
 #include <mono/utils/mono-memory-model.h>
+#include <mono/utils/atomic.h>
+#include <mono/utils/bsearch.h>
+
 MonoStats mono_stats;
 
 gboolean mono_print_vtable = FALSE;
@@ -55,7 +55,7 @@ guint32 classes_size, class_ext_size;
 /* Function supplied by the runtime to find classes by name using information from the AOT file */
 static MonoGetClassFromName get_class_from_name = NULL;
 
-static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
+static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
@@ -71,7 +71,6 @@ static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass
 
 
 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
-void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass) = NULL;
 
 
 /*
@@ -219,8 +218,15 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
                                guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
                                const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
 
-                               if (strcmp (nname, name) == 0)
-                                       return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested);
+                               if (strcmp (nname, name) == 0) {
+                                       MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error);
+                                       if (!mono_error_ok (&error)) {
+                                               mono_loader_set_error_from_mono_error (&error);
+                                               mono_error_cleanup (&error); /*FIXME don't swallow error message.*/
+                                               return NULL;
+                                       }
+                                       return res;
+                               }
 
                                i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
                        }
@@ -588,7 +594,7 @@ is_valid_generic_argument (MonoType *type)
 {
        switch (type->type) {
        case MONO_TYPE_VOID:
-       case MONO_TYPE_TYPEDBYREF:
+       //case MONO_TYPE_TYPEDBYREF:
                return FALSE;
        }
        return TRUE;
@@ -1421,6 +1427,52 @@ mono_class_setup_fields (MonoClass *class)
        MonoGenericContainer *container = NULL;
        MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
 
+       /*
+        * FIXME: We have a race condition here.  It's possible that this function returns
+        * to its caller with `instance_size` set to `0` instead of the actual size.  This
+        * is not a problem when the function is called recursively on the same class,
+        * because the size will be initialized by the outer invocation.  What follows is a
+        * description of how it can occur in other cases, too.  There it is a problem,
+        * because it can lead to the GC being asked to allocate an object of size `0`,
+        * which SGen chokes on.  The race condition is triggered infrequently by
+        * `tests/sgen-suspend.cs`.
+        *
+        * This function is called for a class whenever one of its subclasses is inited.
+        * For example, it's called for every subclass of Object.  What it does is this:
+        *
+        *     if (class->setup_fields_called)
+        *         return;
+        *     ...
+        *     class->instance_size = 0;
+        *     ...
+        *     class->setup_fields_called = 1;
+        *     ... critical point
+        *     class->instance_size = actual_instance_size;
+        *
+        * The last two steps are sometimes reversed, but that only changes the way in which
+        * the race condition works.
+        *
+        * Assume thread A goes through this function and makes it to the critical point.
+        * Now thread B runs the function and, since `setup_fields_called` is set, returns
+        * immediately, but `instance_size` is incorrect.
+        *
+        * The other case looks like this:
+        *
+        *     if (class->setup_fields_called)
+        *         return;
+        *     ... critical point X
+        *     class->instance_size = 0;
+        *     ... critical point Y
+        *     class->instance_size = actual_instance_size;
+        *     ...
+        *     class->setup_fields_called = 1;
+        *
+        * Assume thread A goes through the function and makes it to critical point X.  Now
+        * thread B runs through the whole of the function, returning, assuming
+        * `instance_size` is set.  At that point thread A gets to run and makes it to
+        * critical point Y, at which time `instance_size` is `0` again, invalidating thread
+        * B's assumption.
+        */
        if (class->setup_fields_called)
                return;
 
@@ -1498,6 +1550,7 @@ mono_class_setup_fields (MonoClass *class)
                mono_memory_barrier ();
                class->size_inited = 1;
                class->fields_inited = 1;
+               class->setup_fields_called = 1;
                return;
        }
 
@@ -2115,9 +2168,6 @@ mono_class_setup_methods (MonoClass *class)
 
        class->methods = methods;
 
-       if (mono_debugger_class_loaded_methods_func)
-               mono_debugger_class_loaded_methods_func (class);
-
        mono_loader_unlock ();
 }
 
@@ -2640,7 +2690,7 @@ compare_interface_ids (const void *p_key, const void *p_element) {
 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
 int
 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
-       MonoClass **result = bsearch (
+       MonoClass **result = mono_binary_search (
                        itf,
                        klass->interfaces_packed,
                        klass->interface_offsets_count,
@@ -2869,9 +2919,12 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
         * We collect the types needed to build the
         * instantiations in interfaces at intervals of 3/5, because 3/5 are
         * the generic interfaces needed to implement.
+        *
+        * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
+        * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
         */
-       nifaces = generic_ireadonlylist_class ? 5 : 3;
        if (eclass->valuetype) {
+               nifaces = generic_ireadonlylist_class ? 5 : 3;
                fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
 
                /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
@@ -2893,6 +2946,7 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
                int idepth = eclass->idepth;
                if (!internal_enumerator)
                        idepth--;
+               nifaces = generic_ireadonlylist_class ? 2 : 3;
 
                // FIXME: This doesn't seem to work/required for generic params
                if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
@@ -2956,10 +3010,16 @@ get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enume
 
                interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
                interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
-               interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
-               if (generic_ireadonlylist_class) {
-                       interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
-                       interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
+
+               if (eclass->valuetype) {
+                       interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
+                       if (generic_ireadonlylist_class) {
+                               interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
+                               interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
+                       }
+               } else {
+                       if (!generic_ireadonlylist_class)
+                               interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
                }
        }
        if (internal_enumerator) {
@@ -3553,10 +3613,6 @@ mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
        if (class->vtable)
                return;
 
-       if (mono_debug_using_mono_debugger ())
-               /* The debugger currently depends on this */
-               mono_class_setup_methods (class);
-
        if (MONO_CLASS_IS_INTERFACE (class)) {
                /* This sets method->slot for all methods if this is an interface */
                mono_class_setup_methods (class);
@@ -3739,8 +3795,9 @@ check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *c
                        mono_secman_inheritancedemand_method (cm, im);
                }
 
-               if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+               if (mono_security_core_clr_enabled ())
                        mono_security_core_clr_check_override (class, cm, im);
+
                TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
                if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
                        char *body_name = mono_method_full_name (cm, TRUE);
@@ -3824,9 +3881,9 @@ check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *c
                        mono_secman_inheritancedemand_method (cm, im);
                }
 
-               if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+               if (mono_security_core_clr_enabled ())
                        mono_security_core_clr_check_override (class, cm, im);
-               
+
                TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
                if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
                        char *body_name = mono_method_full_name (cm, TRUE);
@@ -4056,7 +4113,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
        int i, max_vtsize = 0, max_iid, cur_slot = 0;
        GPtrArray *ifaces = NULL;
        GHashTable *override_map = NULL;
-       gboolean security_enabled = mono_is_security_manager_active ();
+       gboolean security_enabled = mono_security_enabled ();
        MonoMethod *cm;
        gpointer class_iter;
 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
@@ -4228,7 +4285,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
 
                        g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
 
-                       if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                       if (mono_security_core_clr_enabled ())
                                mono_security_core_clr_check_override (class, vtable [dslot], decl);
                }
        }
@@ -4408,7 +4465,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                                        mono_secman_inheritancedemand_method (cm, m1);
                                                }
 
-                                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                                               if (mono_security_core_clr_enabled ())
                                                        mono_security_core_clr_check_override (class, cm, m1);
 
                                                slot = mono_method_get_vtable_slot (m1);
@@ -4469,7 +4526,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
                        g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
 
-                       if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                       if (mono_security_core_clr_enabled ())
                                mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
                }
        }
@@ -4611,6 +4668,23 @@ mono_method_get_vtable_slot (MonoMethod *method)
                mono_class_setup_vtable (method->klass);
                if (method->klass->exception_type)
                        return -1;
+               if (method->slot == -1) {
+                       MonoClass *gklass;
+                       int i;
+
+                       /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
+                       g_assert (method->klass->generic_class);
+                       gklass = method->klass->generic_class->container_class;
+                       mono_class_setup_methods (method->klass);
+                       g_assert (method->klass->methods);
+                       for (i = 0; i < method->klass->method.count; ++i) {
+                               if (method->klass->methods [i] == method)
+                                       break;
+                       }
+                       g_assert (i < method->klass->method.count);
+                       g_assert (gklass->methods);
+                       method->slot = gklass->methods [i]->slot;
+               }
                g_assert (method->slot != -1);
        }
        return method->slot;
@@ -4879,7 +4953,7 @@ mono_class_init (MonoClass *class)
        }
 
        /* CAS - SecurityAction.InheritanceDemand */
-       if (mono_is_security_manager_active () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
+       if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
                mono_secman_inheritancedemand_class (class, class->parent);
        }
 
@@ -5062,7 +5136,7 @@ mono_class_init (MonoClass *class)
                setup_interface_offsets (class, 0, TRUE);
        }
 
-       if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+       if (mono_security_core_clr_enabled ())
                mono_security_core_clr_check_inheritance (class);
 
        if (mono_loader_get_last_error ()) {
@@ -5288,7 +5362,7 @@ mono_class_setup_mono_type (MonoClass *class)
 
 #ifndef DISABLE_COM
 /*
- * COM initialization (using mono_init_com_types) is delayed until needed. 
+ * COM initialization is delayed until needed.
  * However when a [ComImport] attribute is present on a type it will trigger
  * the initialization. This is not a problem unless the BCL being executed 
  * lacks the types that COM depends on (e.g. Variant on Silverlight).
@@ -5297,7 +5371,7 @@ static void
 init_com_from_comimport (MonoClass *class)
 {
        /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
-       if ((mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)) {
+       if (mono_security_core_clr_enabled ()) {
                /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
                if (!mono_security_core_clr_determine_platform_image (class->image)) {
                        /* but it can not be made available for application (i.e. user code) since all COM calls
@@ -5307,8 +5381,8 @@ init_com_from_comimport (MonoClass *class)
                        return;
                }
        }
+
        /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
-       mono_init_com_types ();
 }
 #endif /*DISABLE_COM*/
 
@@ -5341,7 +5415,7 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
                if (MONO_CLASS_IS_IMPORT (class)) {
                        init_com_from_comimport (class);
                        if (parent == mono_defaults.object_class)
-                               parent = mono_defaults.com_object_class;
+                               parent = mono_class_get_com_object_class ();
                }
 #endif
                if (!parent) {
@@ -5361,21 +5435,24 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
                        return;
                }
 
+#ifndef DISABLE_REMOTING
                class->marshalbyref = parent->marshalbyref;
                class->contextbound  = parent->contextbound;
+#endif
+
                class->delegate  = parent->delegate;
-               if (MONO_CLASS_IS_IMPORT (class))
-                       class->is_com_object = 1;
-               else
-                       class->is_com_object = parent->is_com_object;
+
+               if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
+                       mono_class_set_is_com_object (class);
                
                if (system_namespace) {
+#ifndef DISABLE_REMOTING
                        if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
                                class->marshalbyref = 1;
 
                        if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject")) 
                                class->contextbound  = 1;
-
+#endif
                        if (*class->name == 'D' && !strcmp (class->name, "Delegate")) 
                                class->delegate  = 1;
                }
@@ -5409,7 +5486,7 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
  *  - supertypes: array of classes: each element has a class in the hierarchy
  *    starting from @class up to System.Object
  * 
- * LOCKING: this assumes the loader lock is held
+ * LOCKING: This function is atomic, in case of contention we waste memory.
  */
 void
 mono_class_setup_supertypes (MonoClass *class)
@@ -5417,7 +5494,8 @@ mono_class_setup_supertypes (MonoClass *class)
        int ms;
        MonoClass **supertypes;
 
-       if (class->supertypes)
+       mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
+       if (supertypes)
                return;
 
        if (class->parent && !class->parent->supertypes)
@@ -5455,10 +5533,34 @@ fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
        return TRUE;
 }
 
+static void
+mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
+{
+       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
+       mono_error_set_type_load_class (error, class, msg);
+}
+
+static void
+mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
+{
+       MonoLoaderError *lerror = mono_loader_get_last_error ();
+
+       if (lerror) {
+               set_failure_from_loader_error (class, lerror);
+               mono_error_set_from_loader_error (error);
+               if (msg)
+                       g_free (msg);
+       } else {
+               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
+               mono_error_set_type_load_class (error, class, msg);
+       }
+}
+
 /**
  * mono_class_create_from_typedef:
  * @image: image where the token is valid
  * @type_token:  typedef token
+ * @error:  used to return any error found while creating the type
  *
  * Create the MonoClass* representing the specified type token.
  * @type_token must be a TypeDef token.
@@ -5466,7 +5568,7 @@ fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
  * FIXME: don't return NULL on failure, just the the caller figure it out.
  */
 static MonoClass *
-mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
+mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
 {
        MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
        MonoClass *class, *parent = NULL;
@@ -5480,13 +5582,19 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        guint32 field_last, method_last;
        guint32 nesting_tokeen;
 
-       if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows)
+       mono_error_init (error);
+
+       if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
+               mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
+               g_assert (!mono_loader_get_last_error ());
                return NULL;
+       }
 
        mono_loader_lock ();
 
        if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
                mono_loader_unlock ();
+               g_assert (!mono_loader_get_last_error ());
                return class;
        }
 
@@ -5537,19 +5645,18 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                }
                parent = mono_class_get_full (image, parent_token, context);
 
-               if (parent == NULL){
-                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load parent type"));
-                       mono_loader_clear_error ();
+               if (parent == NULL) {
+                       mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
                        goto parent_failure;
                }
 
                for (tmp = parent; tmp; tmp = tmp->parent) {
                        if (tmp == class) {
-                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cycle found while resolving parent"));
+                               mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
                                goto parent_failure;
                        }
                        if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
-                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Parent extends generic instance of this type"));
+                               mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
                                goto parent_failure;
                        }
                }
@@ -5568,11 +5675,13 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
         * so it has to come after setup_mono_type ().
         */
        if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
-               class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen);
-               if (!class->nested_in) {
-                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load nestedin type"));
+               class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
+               if (!mono_error_ok (error)) {
+                       /*FIXME implement a mono_class_set_failure_from_mono_error */
+                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
                        mono_loader_unlock ();
                        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+                       g_assert (!mono_loader_get_last_error ());
                        return NULL;
                }
        }
@@ -5590,7 +5699,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        if (!class->enumtype) {
                if (!mono_metadata_interfaces_from_typedef_full (
                            image, type_token, &interfaces, &icount, FALSE, context)){
-                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load interfaces"));
+                       mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
                        mono_loader_unlock ();
                        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
                        return NULL;
@@ -5640,9 +5749,10 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
                if (!enum_basetype) {
                        /*set it to a default value as the whole runtime can't handle this to be null*/
                        class->cast_class = class->element_class = mono_defaults.int32_class;
-                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                       mono_class_set_failure_and_error (class, error, "Could not enum basetype");
                        mono_loader_unlock ();
                        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+                       g_assert (!mono_loader_get_last_error ());
                        return NULL;
                }
                class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
@@ -5654,12 +5764,10 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
         * work.
         */
        if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
-               char *class_name = g_strdup_printf("%s.%s", class->name_space, class->name);
-               char *error = concat_two_strings_with_zero (class->image, class_name, class->image->assembly_name);
-               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, error);
-               g_free (class_name);
+               mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
                mono_loader_unlock ();
                mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+               g_assert (!mono_loader_get_last_error ());
                return NULL;
        }
 
@@ -5671,6 +5779,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        mono_loader_unlock ();
 
        mono_profiler_class_loaded (class, MONO_PROFILE_OK);
+       g_assert (!mono_loader_get_last_error ());
 
        return class;
 
@@ -5678,8 +5787,8 @@ parent_failure:
        mono_class_setup_mono_type (class);
        mono_loader_unlock ();
        mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+       g_assert (!mono_loader_get_last_error ());
        return NULL;
-
 }
 
 /** is klass Nullable<T>? */
@@ -6531,6 +6640,9 @@ mono_class_data_size (MonoClass *klass)
 {      
        if (!klass->inited)
                mono_class_init (klass);
+       /* This can happen with dynamically created types */
+       if (!klass->fields_inited)
+               mono_class_setup_fields_locking (klass);
 
        /* in arrays, sizes.class_size is unioned with element_size
         * and arrays have no static fields
@@ -6983,7 +7095,13 @@ mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *c
 
        switch (type_token & 0xff000000){
        case MONO_TOKEN_TYPE_DEF:
-               class = mono_class_create_from_typedef (image, type_token);
+               class = mono_class_create_from_typedef (image, type_token, &error);
+               if (!mono_error_ok (&error)) {
+                       mono_loader_set_error_from_mono_error (&error);
+                       /*FIXME don't swallow the error message*/
+                       mono_error_cleanup (&error);
+                       return NULL;
+               }
                break;          
        case MONO_TOKEN_TYPE_REF:
                class = mono_class_from_typeref (image, type_token);
@@ -7334,7 +7452,11 @@ search_modules (MonoImage *image, const char *name_space, const char *name)
  * @name: the type short name.
  *
  * Obtains a MonoClass with a given namespace and a given name which
- * is located in the given MonoImage.   
+ * is located in the given MonoImage.
+ *
+ * To reference nested classes, use the "/" character as a separator.
+ * For example use "Foo/Bar" to reference the class Bar that is nested
+ * inside Foo, like this: "class Foo { class Bar {} }".
  */
 MonoClass *
 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
@@ -7446,11 +7568,31 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name
        return class;
 }
 
-/*FIXME test for interfaces with variant generic arguments*/
+/**
+ * mono_class_is_subclass_of:
+ * @klass: class to probe if it is a subclass of another one
+ * @klassc: the class we suspect is the base class
+ * @check_interfaces: whether we should perform interface checks
+ *
+ * This method determines whether @klass is a subclass of @klassc.
+ *
+ * If the @check_interfaces flag is set, then if @klassc is an interface
+ * this method return true if the @klass implements the interface or
+ * if @klass is an interface, if one of its base classes is @klass.
+ *
+ * If @check_interfaces is false then, then if @klass is not an interface
+ * then it returns true if the @klass is a subclass of @klassc.
+ *
+ * if @klass is an interface and @klassc is System.Object, then this function
+ * return true.
+ *
+ */
 gboolean
 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
                           gboolean check_interfaces)
 {
+/*FIXME test for interfaces with variant generic arguments*/
+       
        if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
                if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
                        return TRUE;
@@ -8518,7 +8660,7 @@ mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
        MonoMethod** method;
        if (!iter)
                return NULL;
-       if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) {
+       if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
                if (!*iter) {
                        mono_class_setup_methods (klass);
                        /*
@@ -8711,6 +8853,7 @@ mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
 MonoClass*
 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
 {
+       MonoError error;
        GList *item;
        int i;
 
@@ -8726,9 +8869,11 @@ mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
                                MonoClass* nclass;
                                guint32 cols [MONO_NESTED_CLASS_SIZE];
                                mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
-                               nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
-                               if (!nclass) {
-                                       mono_loader_clear_error ();
+                               nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
+                               if (!mono_error_ok (&error)) {
+                                       /*FIXME don't swallow the error message*/
+                                       mono_error_cleanup (&error);
+
                                        i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
                                        continue;
                                }
@@ -8762,6 +8907,32 @@ mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
        return NULL;
 }
 
+
+/**
+ * mono_class_is_delegate
+ * @klass: the MonoClass to act on
+ *
+ * Returns: true if the MonoClass represents a System.Delegate.
+ */
+mono_bool
+mono_class_is_delegate (MonoClass *klass)
+{
+       return klass->delegate;
+}
+
+/**
+ * mono_class_implements_interface
+ * @klass: The MonoClass to act on
+ * @interface: The interface to check if @klass implements.
+ *
+ * Returns: true if @klass implements @interface.
+ */
+mono_bool
+mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
+{
+       return mono_class_is_assignable_from (iface, klass);
+}
+
 /**
  * mono_field_get_name:
  * @field: the MonoClassField to act on
@@ -9224,6 +9395,7 @@ mono_class_get_exception_for_failure (MonoClass *klass)
        gpointer exception_data = mono_class_get_exception_data (klass);
 
        switch (klass->exception_type) {
+#ifndef DISABLE_SECURITY
        case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
                MonoDomain *domain = mono_domain_get ();
                MonoSecurityManager* secman = mono_security_manager_get_methods ();
@@ -9240,6 +9412,7 @@ mono_class_get_exception_for_failure (MonoClass *klass)
                mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
                return (MonoException*) exc;
        }
+#endif
        case MONO_EXCEPTION_TYPE_LOAD: {
                MonoString *name;
                MonoException *ex;
@@ -9374,7 +9547,7 @@ can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
 
        /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
         * anywhere so untrusted friends are not safe to access platform's code internals */
-       if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+       if (mono_security_core_clr_enabled ()) {
                if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
                        return FALSE;
        }
@@ -9699,6 +9872,21 @@ mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, Mo
        return TRUE;
 }
 
+/*
+ * mono_class_can_access_class:
+ * @source_class: The source class 
+ * @target_class: The accessed class
+ * 
+ * This function returns is @target_class is visible to @source_class
+ * 
+ * Returns: TRUE if source have proper visibility and acessibility to target
+ */
+gboolean
+mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
+{
+       return can_access_type (source_class, target_class);
+}
+
 /**
  * mono_type_is_valid_enum_basetype:
  * @type: The MonoType to check
@@ -9921,16 +10109,8 @@ mono_field_resolve_type (MonoClassField *field, MonoError *error)
                /* FIELD signature == 0x06 */
                g_assert (*sig == 0x06);
                field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
-               if (!field->type) {
-                       MonoLoaderError *lerror = mono_loader_get_last_error ();
-
-                       mono_error_set_type_load_class (error, class, "Could not load field %s type", field->name);
-                       if (lerror)
-                               set_failure_from_loader_error (class, lerror);
-                       else
-                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
-                       mono_loader_clear_error ();
-               }
+               if (!field->type)
+                       mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
        }
 }
 
@@ -10010,3 +10190,10 @@ mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
        }
        return NULL;
 }
+
+char*
+mono_class_full_name (MonoClass *klass)
+{
+       return mono_type_full_name (&klass->byval_arg);
+}
+