2008-02-28 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / class.c
index c0fa757581261fc744e68618abf08999e9a253eb..610542424dd4de15256c21099970f34b6caf502e 100644 (file)
@@ -33,7 +33,7 @@
 #include <mono/metadata/security-manager.h>
 #include <mono/metadata/security-core-clr.h>
 #include <mono/metadata/attrdefs.h>
-#include <mono/os/gc_wrapper.h>
+#include <mono/metadata/gc-internal.h>
 #include <mono/utils/mono-counters.h>
 
 MonoStats mono_stats;
@@ -181,11 +181,12 @@ _mono_type_get_assembly_name (MonoClass *klass, GString *str)
        MonoAssembly *ta = klass->image->assembly;
 
        g_string_append_printf (
-               str, ", %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
+               str, ", %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
                ta->aname.name,
                ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
                ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
-               ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
+               ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null",
+               (ta->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
 }
 
 static inline void
@@ -632,6 +633,7 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin
        MonoMethodInflated *iresult, *cached;
        MonoMethodSignature *sig;
        MonoGenericContext tmp_context;
+       gboolean is_mb_open = FALSE;
 
        /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
        while (method->is_inflated) {
@@ -650,10 +652,25 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin
        if (!method->generic_container && !method->klass->generic_container)
                return method;
 
+       /*
+        * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
+        * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
+        * This is opposite to the way non-SRE MethodInfos behave.
+        *
+        * FIXME: express this better, somehow!
+        */
+       is_mb_open = method->generic_container &&
+               method->klass->image->dynamic && !method->klass->wastypebuilder &&
+               context->method_inst == method->generic_container->context.method_inst;
+
        mono_stats.inflated_method_count++;
        iresult = g_new0 (MonoMethodInflated, 1);
        iresult->context = *context;
        iresult->declaring = method;
+       iresult->is_mb_open = is_mb_open;
+
+       if (!context->method_inst && method->generic_container)
+               iresult->context.method_inst = method->generic_container->context.method_inst;
 
        mono_loader_lock ();
        cached = mono_method_inflated_lookup (iresult, FALSE);
@@ -665,17 +682,21 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin
 
        sig = mono_method_signature (method);
        if (sig->pinvoke) {
-               iresult->method.pinvoke = *(MonoMethodPInvoke*)method;
+               memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
        } else {
-               iresult->method.normal = *(MonoMethodNormal*)method;
+               memcpy (&iresult->method.normal, method, sizeof (MonoMethodNormal));
                iresult->method.normal.header = NULL;
        }
 
        result = (MonoMethod *) iresult;
        result->is_inflated = 1;
-       /* result->generic_container = NULL; */
        result->signature = NULL;
 
+       if (context->method_inst)
+               result->generic_container = NULL;
+
+       /* Due to the memcpy above, !context->method_inst => result->generic_container == method->generic_container */
+
        if (!klass_hint || !klass_hint->generic_class ||
            klass_hint->generic_class->container_class != method->klass ||
            klass_hint->generic_class->context.class_inst != context->class_inst)
@@ -691,11 +712,6 @@ mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hin
                        mono_metadata_free_type (inflated);
        }
 
-       if (context->method_inst)
-               result->generic_container = NULL;
-       else if (method->generic_container)
-               iresult->context.method_inst = method->generic_container->context.method_inst;
-
        mono_method_inflated_lookup (iresult, TRUE);
        mono_loader_unlock ();
        return result;
@@ -805,6 +821,7 @@ mono_class_setup_fields (MonoClass *class)
                MonoClass *gklass = class->generic_class->container_class;
                mono_class_setup_fields (gklass);
                top = gklass->field.count;
+               class->field.count = gklass->field.count;
        }
 
        class->instance_size = 0;
@@ -1209,7 +1226,8 @@ mono_class_layout_fields (MonoClass *class)
                                continue;
 
                        size = mono_type_size (field->type, &align);
-                       
+                       class->min_align = MAX (align, class->min_align);
+
                        /*
                         * When we get here, field->offset is already set by the
                         * loader (for either runtime fields or fields loaded from metadata).
@@ -1316,8 +1334,6 @@ mono_class_setup_methods (MonoClass *class)
                for (i = 0; i < class->method.count; ++i) {
                        int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
                        methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
-                       if (class->valuetype && methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED && !(methods [i]->flags & MONO_METHOD_ATTR_STATIC))
-                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
                }
        }
 
@@ -1757,9 +1773,11 @@ print_implemented_interfaces (MonoClass *klass) {
        
        printf ("Packed interface table for class %s has size %d\n", klass->name, klass->interface_offsets_count);
        for (i = 0; i < klass->interface_offsets_count; i++)
-               printf ("  [%d][UUID %d][SLOT %d] interface %s\n", i,
+               printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s.%s\n", i,
                                klass->interfaces_packed [i]->interface_id,
                                klass->interface_offsets_packed [i],
+                               klass->interfaces_packed [i]->method.count,
+                               klass->interfaces_packed [i]->name_space,
                                klass->interfaces_packed [i]->name );
        printf ("Interface flags: ");
        for (i = 0; i <= klass->max_interface_id; i++)
@@ -1779,6 +1797,12 @@ print_implemented_interfaces (MonoClass *klass) {
                        for (i = 0; i < ifaces->len; i++) {
                                MonoClass *ic = g_ptr_array_index (ifaces, i);
                                printf ("  [UIID %d] interface %s\n", ic->interface_id, ic->name);
+                               printf ("  [%03d][UUID %03d][SLOT %03d][SIZE  %03d] interface %s.%s\n", i,
+                                               ic->interface_id,
+                                               mono_class_interface_offset (klass, ic),
+                                               ic->method.count,
+                                               ic->name_space,
+                                               ic->name );
                        }
                        g_ptr_array_free (ifaces, TRUE);
                }
@@ -2244,6 +2268,267 @@ check_core_clr_override_method (MonoClass *class, MonoMethod *override, MonoMeth
        }
 }
 
+
+static int __use_new_interface_vtable_code = -1;
+static gboolean
+use_new_interface_vtable_code (void) {
+       if (__use_new_interface_vtable_code == -1) {
+               char *env_var = getenv ("MONO_USE_NEW_INTERFACE_VTABLE_CODE");
+               if (env_var == NULL) {
+                       __use_new_interface_vtable_code = TRUE;
+               } else {
+                       if ((strcmp (env_var, "0") == 0) || (strcmp (env_var, "false") == 0) || (strcmp (env_var, "FALSE") == 0)) {
+                               __use_new_interface_vtable_code = FALSE;
+                       } else {
+                               __use_new_interface_vtable_code = TRUE;
+                       }
+               }
+       }
+       return __use_new_interface_vtable_code;
+}
+
+
+#define DEBUG_INTERFACE_VTABLE_CODE 0
+#define TRACE_INTERFACE_VTABLE_CODE 0
+
+#if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
+#define DEBUG_INTERFACE_VTABLE(stmt) do {\
+       stmt;\
+} while (0)
+#else
+#define DEBUG_INTERFACE_VTABLE(stmt)
+#endif
+
+#if TRACE_INTERFACE_VTABLE_CODE
+#define TRACE_INTERFACE_VTABLE(stmt) do {\
+       stmt;\
+} while (0)
+#else
+#define TRACE_INTERFACE_VTABLE(stmt)
+#endif
+
+
+#if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
+static char*
+mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
+{
+       int i;
+       char *result;
+       GString *res = g_string_new ("");
+       
+       g_string_append_c (res, '(');
+       for (i = 0; i < sig->param_count; ++i) {
+               if (i > 0)
+                       g_string_append_c (res, ',');
+               mono_type_get_desc (res, sig->params [i], include_namespace);
+       }
+       g_string_append (res, ")=>");
+       if (sig->ret != NULL) {
+               mono_type_get_desc (res, sig->ret, include_namespace);
+       } else {
+               g_string_append (res, "NULL");
+       }
+       result = res->str;
+       g_string_free (res, FALSE);
+       return result;
+}
+static void
+print_method_signatures (MonoMethod *im, MonoMethod *cm) {
+       char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
+       char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
+       printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
+       g_free (im_sig);
+       g_free (cm_sig);
+       
+}
+
+#endif
+static gboolean
+check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty, gboolean security_enabled) {
+       if (strcmp (im->name, cm->name) == 0) {
+               if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
+                       TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
+                       return FALSE;
+               }
+               if (! slot_is_empty) {
+                       if (require_newslot) {
+                               if (! interface_is_explicitly_implemented_by_class) {
+                                       TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
+                                       return FALSE;
+                               }
+                               if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
+                                       TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
+                                       return FALSE;
+                               }
+                       } else {
+                               TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
+                       }
+               }
+               if (! mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
+                       TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED  "));
+                       TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
+                       TRACE_INTERFACE_VTABLE (printf ("]"));
+                       return FALSE;
+               }
+               TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
+               /* CAS - SecurityAction.InheritanceDemand on interface */
+               if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
+                       mono_secman_inheritancedemand_method (cm, im);
+               }
+
+               if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                       check_core_clr_override_method (class, cm, im);
+               TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
+               return TRUE;
+       } else {
+               MonoClass *ic = im->klass;
+               const char *ic_name_space = ic->name_space;
+               const char *ic_name = ic->name;
+               char *subname;
+               
+               if (! require_newslot) {
+                       TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
+                       return FALSE;
+               }
+               if (cm->klass->rank == 0) {
+                       TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
+                       return FALSE;
+               }
+               if (! mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
+                       TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED  "));
+                       TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
+                       TRACE_INTERFACE_VTABLE (printf ("]"));
+                       return FALSE;
+               }
+               if (mono_class_get_image (ic) != mono_defaults.corlib) {
+                       TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
+                       return FALSE;
+               }
+               if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
+                       TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
+                       return FALSE;
+               }
+               if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0))) {
+                       TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
+                       return FALSE;
+               }
+               
+               subname = strstr (cm->name, ic_name_space);
+               if (subname != cm->name) {
+                       TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
+                       return FALSE;
+               }
+               subname += strlen (ic_name_space);
+               if (subname [0] != '.') {
+                       TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
+                       return FALSE;
+               }
+               subname ++;
+               if (strstr (subname, ic_name) != subname) {
+                       TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
+                       return FALSE;
+               }
+               subname += strlen (ic_name);
+               if (subname [0] != '.') {
+                       TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
+                       return FALSE;
+               }
+               subname ++;
+               if (strcmp (subname, im->name) != 0) {
+                       TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
+                       return FALSE;
+               }
+               
+               TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
+               /* CAS - SecurityAction.InheritanceDemand on interface */
+               if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
+                       mono_secman_inheritancedemand_method (cm, im);
+               }
+
+               if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                       check_core_clr_override_method (class, cm, im);
+               
+               TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
+               return TRUE;
+       }
+}
+
+#if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
+static void
+foreach_override (gpointer key, gpointer value, gpointer user_data) {
+       MonoMethod *method = key;
+       MonoMethod *override = value;
+       MonoClass *method_class = mono_method_get_class (method);
+       MonoClass *override_class = mono_method_get_class (override);
+       
+       printf ("  Method '%s.%s:%s' has override '%s.%s:%s'\n",
+                       mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
+                       mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
+}
+static void
+print_overrides (GHashTable *override_map, const char *message) {
+       if (override_map) {
+               printf ("Override map \"%s\" START:\n", message);
+               g_hash_table_foreach (override_map, foreach_override, NULL);
+               printf ("Override map \"%s\" END.\n", message);
+       } else {
+               printf ("Override map \"%s\" EMPTY.\n", message);
+       }
+}
+static void
+print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
+       char *full_name = mono_type_full_name (&class->byval_arg);
+       int i;
+       int parent_size;
+       
+       printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
+       
+       if (print_interfaces) {
+               print_implemented_interfaces (class);
+               printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
+       }
+       
+       if (class->parent) {
+               parent_size = class->parent->vtable_size;
+       } else {
+               parent_size = 0;
+       }
+       for (i = 0; i < size; ++i) {
+               MonoMethod *cm = vtable [i];
+               if (cm) {
+                       char *cm_name = mono_method_full_name (cm, TRUE);
+                       char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
+                       printf ("  [%c][%03d][INDEX %03d] %s\n", newness, i, cm->slot, cm_name);
+                       g_free (cm_name);
+               }
+       }
+
+       g_free (full_name);
+}
+#endif
+
+static void
+print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
+       int index;
+       char *method_signature;
+       
+       for (index = 0; index < onum; ++index) {
+               g_print (" at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name, 
+                        overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
+       }
+       method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
+       printf ("no implementation for interface method %s::%s(%s) in class %s.%s\n",
+               mono_type_get_name (&ic->byval_arg), im->name, method_signature, class->name_space, class->name);
+       g_free (method_signature);
+       for (index = 0; index < class->method.count; ++index) {
+               MonoMethod *cm = class->methods [index];
+               method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
+
+               printf ("METHOD %s(%s)\n", cm->name, method_signature);
+               g_free (method_signature);
+       }
+}
+
 /*
  * LOCKING: this is supposed to be called with the loader lock held.
  */
@@ -2256,6 +2541,9 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
        GPtrArray *ifaces, *pifaces = NULL;
        GHashTable *override_map = NULL;
        gboolean security_enabled = mono_is_security_manager_active ();
+#if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
+       int first_non_interface_slot;
+#endif
 
        if (class->vtable)
                return;
@@ -2267,6 +2555,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                        max_vtsize += ic->method.count;
                }
                g_ptr_array_free (ifaces, TRUE);
+               ifaces = NULL;
        }
        
        if (class->parent) {
@@ -2285,10 +2574,45 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
 
        cur_slot = setup_interface_offsets (class, cur_slot);
        max_iid = class->max_interface_id;
+       DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
 
-       if (class->parent && class->parent->vtable_size)
-               memcpy (vtable, class->parent->vtable,  sizeof (gpointer) * class->parent->vtable_size);
+       if (use_new_interface_vtable_code ()) {
+               if (class->parent && class->parent->vtable_size) {
+                       MonoClass *parent = class->parent;
+                       int i;
+                       
+                       memcpy (vtable, parent->vtable,  sizeof (gpointer) * parent->vtable_size);
+                       
+                       // Also inherit parent interface vtables, just as a starting point.
+                       // This is needed otherwise bug-77127.exe fails when the property methods
+                       // have different names in the iterface and the class, because for child
+                       // classes the ".override" information is not used anymore.
+                       for (i = 0; i < parent->interface_offsets_count; i++) {
+                               MonoClass *parent_interface = parent->interfaces_packed [i];
+                               int interface_offset = mono_class_interface_offset (class, parent_interface);
+                               
+                               if (interface_offset >= parent->vtable_size) {
+                                       int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
+                                       int j;
+                                       
+                                       mono_class_setup_methods (parent_interface);
+                                       TRACE_INTERFACE_VTABLE (printf ("    +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
+                                       for (j = 0; j < parent_interface->method.count; 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,
+                                                               interface_offset + j, interface_offset, j));
+                                       }
+                               }
+                               
+                       }
+               }
+       } else {
+               if (class->parent && class->parent->vtable_size)
+                       memcpy (vtable, class->parent->vtable,  sizeof (gpointer) * class->parent->vtable_size);
+       }
 
+       TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
        /* override interface methods */
        for (i = 0; i < onum; i++) {
                MonoMethod *decl = overrides [i*2];
@@ -2308,231 +2632,361 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                                check_core_clr_override_method (class, vtable [dslot], decl);
                }
        }
+       TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
+       TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
 
-       for (k = class; k ; k = k->parent) {
-               int nifaces = 0;
-
-               ifaces = mono_class_get_implemented_interfaces (k);
-               if (ifaces) {
-                       nifaces = ifaces->len;
-                       if (k->generic_class) {
-                               pifaces = mono_class_get_implemented_interfaces (
-                                       k->generic_class->container_class);
-                               g_assert (pifaces && (pifaces->len == nifaces));
-                       }
-               }
-               for (i = 0; i < nifaces; i++) {
-                       MonoClass *pic = NULL;
-                       int j, l, io;
-
-                       ic = g_ptr_array_index (ifaces, i);
-                       if (pifaces)
-                               pic = g_ptr_array_index (pifaces, i);
-                       g_assert (ic->interface_id <= k->max_interface_id);
-                       io = mono_class_interface_offset (k, ic);
-
-                       g_assert (io >= 0);
-                       g_assert (io <= max_vtsize);
-
-                       if (k == class) {
-                               mono_class_setup_methods (ic);
-                               for (l = 0; l < ic->method.count; l++) {
-                                       MonoMethod *im = ic->methods [l];                                               
-
-                                       if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
-                                               continue;
-
-                                       for (j = 0; j < class->method.count; ++j) {
-                                               MonoMethod *cm = class->methods [j];
-                                               if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
-                                                   !((cm->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) ||
-                                                   !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
-                                                       continue;
-                                               if (!strcmp(cm->name, im->name) && 
-                                                   mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
-
-                                                       /* CAS - SecurityAction.InheritanceDemand on interface */
-                                                       if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
-                                                               mono_secman_inheritancedemand_method (cm, im);
-                                                       }
-
-                                                       if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
-                                                               check_core_clr_override_method (class, cm, im);
+       if (use_new_interface_vtable_code ()) {
+               // Loop on all implemented interfaces...
+               for (i = 0; i < class->interface_offsets_count; i++) {
+                       MonoClass *parent = class->parent;
+                       int ic_offset;
+                       gboolean interface_is_explicitly_implemented_by_class;
+                       int im_index;
+                       
+                       ic = class->interfaces_packed [i];
+                       ic_offset = mono_class_interface_offset (class, ic);
 
-                                                       g_assert (io + l <= max_vtsize);
-                                                       vtable [io + l] = cm;
-                                               }
+                       mono_class_setup_methods (ic);
+                       
+                       // Check if this interface is explicitly implemented (instead of just inherited)
+                       if (parent != NULL) {
+                               int implemented_interfaces_index;
+                               interface_is_explicitly_implemented_by_class = FALSE;
+                               for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
+                                       if (ic == class->interfaces [implemented_interfaces_index]) {
+                                               interface_is_explicitly_implemented_by_class = TRUE;
+                                               break;
                                        }
                                }
                        } else {
-                               /* already implemented */
-                               if (io >= k->vtable_size)
-                                       continue;
+                               interface_is_explicitly_implemented_by_class = TRUE;
                        }
-
-                       // Override methods with the same fully qualified name
-                       for (l = 0; l < ic->method.count; l++) {
-                               MonoMethod *im = ic->methods [l];                                               
-                               char *qname, *fqname, *cname, *the_cname;
-                               MonoClass *k1;
+                       
+                       // Loop on all interface methods...
+                       for (im_index = 0; im_index < ic->method.count; im_index++) {
+                               MonoMethod *im = ic->methods [im_index];
+                               int im_slot = ic_offset + im->slot;
+                               MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
                                
-                               if (vtable [io + l])
+                               if (im->flags & METHOD_ATTRIBUTE_STATIC)
                                        continue;
 
-                               if (pic) {
-                                       the_cname = mono_type_get_name_full (&pic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
-                                       cname = the_cname;
+                               // If there is an explicit implementation, just use it right away,
+                               // otherwise look for a matching method
+                               if (override_im == NULL) {
+                                       int cm_index;
+                                       
+                                       // First look for a suitable method among the class methods
+                                       for (cm_index = 0; cm_index < class->method.count; cm_index++) {
+                                               MonoMethod *cm = class->methods [cm_index];
+                                               
+                                               TRACE_INTERFACE_VTABLE (printf ("    For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL)));
+                                               if ((cm->flags & METHOD_ATTRIBUTE_VIRTUAL) && check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
+                                                       TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
+                                                       vtable [im_slot] = cm;
+                                                       /* Why do we need this? */
+                                                       if (cm->slot < 0) {
+                                                               cm->slot = im_slot;
+                                                       }
+                                               }
+                                               TRACE_INTERFACE_VTABLE (printf ("\n"));
+                                       }
+                                       
+                                       // If the slot is still empty, look in all the inherited virtual methods...
+                                       if ((vtable [im_slot] == NULL) && class->parent != NULL) {
+                                               MonoClass *parent = class->parent;
+                                               // Reverse order, so that last added methods are preferred
+                                               for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
+                                                       MonoMethod *cm = parent->vtable [cm_index];
+                                                       
+                                                       TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("    For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name));
+                                                       if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
+                                                               TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
+                                                               vtable [im_slot] = cm;
+                                                               /* Why do we need this? */
+                                                               if (cm->slot < 0) {
+                                                                       cm->slot = im_slot;
+                                                               }
+                                                               break;
+                                                       }
+                                                       TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
+                                               }
+                                       }
                                } else {
-                                       the_cname = NULL;
-                                       cname = (char*)ic->name;
+                                       g_assert (vtable [im_slot] == override_im);
                                }
+                       }
+               }
+               
+               // If the class is not abstract, check that all its interface slots are full.
+               // The check is done here and not directly at the end of the loop above because
+               // it can happen (for injected generic array interfaces) that the same slot is
+               // processed multiple times (those interfaces have overlapping slots), and it
+               // will not always be the first pass the one that fills the slot.
+               if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+                       for (i = 0; i < class->interface_offsets_count; i++) {
+                               int ic_offset;
+                               int im_index;
+                               
+                               ic = class->interfaces_packed [i];
+                               ic_offset = mono_class_interface_offset (class, ic);
+                               
+                               for (im_index = 0; im_index < ic->method.count; im_index++) {
+                                       MonoMethod *im = ic->methods [im_index];
+                                       int im_slot = ic_offset + im->slot;
                                        
-                               qname = g_strconcat (cname, ".", im->name, NULL);
-                               if (ic->name_space && ic->name_space [0])
-                                       fqname = g_strconcat (ic->name_space, ".", cname, ".", im->name, NULL);
-                               else
-                                       fqname = NULL;
+                                       if (im->flags & METHOD_ATTRIBUTE_STATIC)
+                                               continue;
 
-                               for (k1 = class; k1; k1 = k1->parent) {
-                                       for (j = 0; j < k1->method.count; ++j) {
-                                               MonoMethod *cm = k1->methods [j];
+                                       TRACE_INTERFACE_VTABLE (printf ("      [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
+                                                       im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
+                                       if (vtable [im_slot] == NULL) {
+                                               print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
+                                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                                               if (override_map)
+                                                       g_hash_table_destroy (override_map);
+                                               return;
+                                       }
+                               }
+                       }
+               }
+       } else {
+               for (k = class; k ; k = k->parent) {
+                       int nifaces = 0;
+
+                       ifaces = mono_class_get_implemented_interfaces (k);
+                       if (ifaces) {
+                               nifaces = ifaces->len;
+                               if (k->generic_class) {
+                                       pifaces = mono_class_get_implemented_interfaces (
+                                               k->generic_class->container_class);
+                                       g_assert (pifaces && (pifaces->len == nifaces));
+                               }
+                       }
+                       for (i = 0; i < nifaces; i++) {
+                               MonoClass *pic = NULL;
+                               int j, l, io;
 
-                                               if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
-                                                       continue;
+                               ic = g_ptr_array_index (ifaces, i);
+                               if (pifaces)
+                                       pic = g_ptr_array_index (pifaces, i);
+                               g_assert (ic->interface_id <= k->max_interface_id);
+                               io = mono_class_interface_offset (k, ic);
 
-                                               if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
-                                                               mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im)) &&
-                                                               ((vtable [io + l] == NULL) || mono_class_is_subclass_of (cm->klass, vtable [io + l]->klass, FALSE))) {
+                               g_assert (io >= 0);
+                               g_assert (io <= max_vtsize);
 
-                                                       /* CAS - SecurityAction.InheritanceDemand on interface */
-                                                       if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
-                                                               mono_secman_inheritancedemand_method (cm, im);
-                                                       }
+                               if (k == class) {
+                                       mono_class_setup_methods (ic);
+                                       for (l = 0; l < ic->method.count; l++) {
+                                               MonoMethod *im = ic->methods [l];                                               
 
-                                                       if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
-                                                               check_core_clr_override_method (class, cm, im);
+                                               if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
+                                                       continue;
 
-                                                       g_assert (io + l <= max_vtsize);
-                                                       vtable [io + l] = cm;
-                                                       break;
+                                               for (j = 0; j < class->method.count; ++j) {
+                                                       MonoMethod *cm = class->methods [j];
+                                                       if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
+                                                           !((cm->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) ||
+                                                           !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
+                                                               continue;
+                                                       if (!strcmp(cm->name, im->name) && 
+                                                           mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
+
+                                                               /* CAS - SecurityAction.InheritanceDemand on interface */
+                                                               if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
+                                                                       mono_secman_inheritancedemand_method (cm, im);
+                                                               }
+
+                                                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                                                                       check_core_clr_override_method (class, cm, im);
+
+                                                               g_assert (io + l <= max_vtsize);
+                                                               vtable [io + l] = cm;
+                                                               TRACE_INTERFACE_VTABLE (printf ("    [NOA] Filling slot %d (%d+%d) with method '%s'.'%s':'%s' ", io + l, io, l, cm->klass->name_space, cm->klass->name, cm->name));
+                                                               TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
+                                                               TRACE_INTERFACE_VTABLE (printf ("\n"));
+                                                       }
                                                }
                                        }
+                               } else {
+                                       /* already implemented */
+                                       if (io >= k->vtable_size)
+                                               continue;
                                }
-                               g_free (the_cname);
-                               g_free (qname);
-                               g_free (fqname);
-                       }
 
-                       // Override methods with the same name
-                       for (l = 0; l < ic->method.count; l++) {
-                               MonoMethod *im = ic->methods [l];                                               
-                               MonoClass *k1;
-
-                               g_assert (io + l <= max_vtsize);
-
-                               if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
-                                       continue;
+                               // Override methods with the same fully qualified name
+                               for (l = 0; l < ic->method.count; l++) {
+                                       MonoMethod *im = ic->methods [l];                                               
+                                       char *qname, *fqname, *cname, *the_cname;
+                                       MonoClass *k1;
                                        
-                               for (k1 = class; k1; k1 = k1->parent) {
-                                       for (j = 0; j < k1->method.count; ++j) {
-                                               MonoMethod *cm = k1->methods [j];
+                                       if (vtable [io + l])
+                                               continue;
 
-                                               if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
-                                                   !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
-                                                       continue;
+                                       if (pic) {
+                                               the_cname = mono_type_get_name_full (&pic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
+                                               cname = the_cname;
+                                       } else {
+                                               the_cname = NULL;
+                                               cname = (char*)ic->name;
+                                       }
                                                
-                                               if (!strcmp(cm->name, im->name) && 
-                                                   mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
-
-                                                       /* CAS - SecurityAction.InheritanceDemand on interface */
-                                                       if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
-                                                               mono_secman_inheritancedemand_method (cm, im);
+                                       qname = g_strconcat (cname, ".", im->name, NULL);
+                                       if (ic->name_space && ic->name_space [0])
+                                               fqname = g_strconcat (ic->name_space, ".", cname, ".", im->name, NULL);
+                                       else
+                                               fqname = NULL;
+
+                                       for (k1 = class; k1; k1 = k1->parent) {
+                                               for (j = 0; j < k1->method.count; ++j) {
+                                                       MonoMethod *cm = k1->methods [j];
+
+                                                       if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
+                                                               continue;
+
+                                                       if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
+                                                                       mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im)) &&
+                                                                       ((vtable [io + l] == NULL) || mono_class_is_subclass_of (cm->klass, vtable [io + l]->klass, FALSE))) {
+
+                                                               /* CAS - SecurityAction.InheritanceDemand on interface */
+                                                               if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
+                                                                       mono_secman_inheritancedemand_method (cm, im);
+                                                               }
+
+                                                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                                                                       check_core_clr_override_method (class, cm, im);
+
+                                                               g_assert (io + l <= max_vtsize);
+                                                               vtable [io + l] = cm;
+                                                               TRACE_INTERFACE_VTABLE (printf ("    [FQN] Filling slot %d (%d+%d) with method '%s'.'%s':'%s' ", io + l, io, l, cm->klass->name_space, cm->klass->name, cm->name));
+                                                               TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
+                                                               TRACE_INTERFACE_VTABLE (printf ("\n"));
+                                                               break;
                                                        }
-
-                                                       if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
-                                                               check_core_clr_override_method (class, cm, im);
-
-                                                       g_assert (io + l <= max_vtsize);
-                                                       vtable [io + l] = cm;
-                                                       break;
                                                }
-                                               
                                        }
-                                       g_assert (io + l <= max_vtsize);
-                                       if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
-                                               break;
+                                       g_free (the_cname);
+                                       g_free (qname);
+                                       g_free (fqname);
                                }
-                       }
 
-                       if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+                               // Override methods with the same name
                                for (l = 0; l < ic->method.count; l++) {
-                                       char *msig;
-                                       MonoMethod *im = ic->methods [l];
-                                       if (im->flags & METHOD_ATTRIBUTE_STATIC)
-                                                       continue;
+                                       MonoMethod *im = ic->methods [l];                                               
+                                       MonoClass *k1;
+
                                        g_assert (io + l <= max_vtsize);
 
-                                       /* 
-                                        * If one of our parents already implements this interface
-                                        * we can inherit the implementation.
-                                        */
-                                       if (!(vtable [io + l])) {
-                                               MonoClass *parent = class->parent;
+                                       if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
+                                               continue;
                                                
-                                               for (; parent; parent = parent->parent) {
-                                                       if (MONO_CLASS_IMPLEMENTS_INTERFACE (parent, ic->interface_id) &&
-                                                                       parent->vtable) {
-                                                               vtable [io + l] = parent->vtable [mono_class_interface_offset (parent, ic) + l];
+                                       for (k1 = class; k1; k1 = k1->parent) {
+                                               for (j = 0; j < k1->method.count; ++j) {
+                                                       MonoMethod *cm = k1->methods [j];
+
+                                                       if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
+                                                           !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
+                                                               continue;
+                                                       
+                                                       if (!strcmp(cm->name, im->name) && 
+                                                           mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
+
+                                                               /* CAS - SecurityAction.InheritanceDemand on interface */
+                                                               if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
+                                                                       mono_secman_inheritancedemand_method (cm, im);
+                                                               }
+
+                                                               if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+                                                                       check_core_clr_override_method (class, cm, im);
+
+                                                               g_assert (io + l <= max_vtsize);
+                                                               vtable [io + l] = cm;
+                                                               TRACE_INTERFACE_VTABLE (printf ("    [SQN] Filling slot %d (%d+%d) with method '%s'.'%s':'%s' ", io + l, io, l, cm->klass->name_space, cm->klass->name, cm->name));
+                                                               TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
+                                                               TRACE_INTERFACE_VTABLE (printf ("\n"));
+                                                               break;
                                                        }
+                                                       
                                                }
+                                               g_assert (io + l <= max_vtsize);
+                                               if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
+                                                       break;
                                        }
+                               }
 
-                                       if (!(vtable [io + l])) {
-                                               for (j = 0; j < onum; ++j) {
-                                                       g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name, 
-                                                                overrides [j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
-                                               }
-                                               msig = mono_signature_get_desc (mono_method_signature (im), FALSE);
-                                               printf ("no implementation for interface method %s::%s(%s) in class %s.%s\n",
-                                                       mono_type_get_name (&ic->byval_arg), im->name, msig, class->name_space, class->name);
-                                               g_free (msig);
-                                               for (j = 0; j < class->method.count; ++j) {
-                                                       MonoMethod *cm = class->methods [j];
-                                                       msig = mono_signature_get_desc (mono_method_signature (cm), TRUE);
+                               if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
+                                       for (l = 0; l < ic->method.count; l++) {
+                                               char *msig;
+                                               MonoMethod *im = ic->methods [l];
+                                               if (im->flags & METHOD_ATTRIBUTE_STATIC)
+                                                               continue;
+                                               g_assert (io + l <= max_vtsize);
+
+                                               /* 
+                                                * If one of our parents already implements this interface
+                                                * we can inherit the implementation.
+                                                */
+                                               if (!(vtable [io + l])) {
+                                                       MonoClass *parent = class->parent;
                                                        
-                                                       printf ("METHOD %s(%s)\n", cm->name, msig);
-                                                       g_free (msig);
+                                                       for (; parent; parent = parent->parent) {
+                                                               if (MONO_CLASS_IMPLEMENTS_INTERFACE (parent, ic->interface_id) &&
+                                                                               parent->vtable) {
+                                                                       vtable [io + l] = parent->vtable [mono_class_interface_offset (parent, ic) + l];
+                                                                       TRACE_INTERFACE_VTABLE (printf ("    [INH] Filling slot %d (%d+%d) with method '%s'.'%s':'%s'\n", io + l, io, l, vtable [io + l]->klass->name_space, vtable [io + l]->klass->name, vtable [io + l]->name));
+                                                               }
+                                                       }
                                                }
 
-                                               mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+                                               if (!(vtable [io + l])) {
+                                                       for (j = 0; j < onum; ++j) {
+                                                               g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name, 
+                                                                        overrides [j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
+                                                       }
+                                                       msig = mono_signature_get_desc (mono_method_signature (im), FALSE);
+                                                       printf ("no implementation for interface method %s::%s(%s) in class %s.%s\n",
+                                                               mono_type_get_name (&ic->byval_arg), im->name, msig, class->name_space, class->name);
+                                                       g_free (msig);
+                                                       for (j = 0; j < class->method.count; ++j) {
+                                                               MonoMethod *cm = class->methods [j];
+                                                               msig = mono_signature_get_desc (mono_method_signature (cm), TRUE);
+                                                               
+                                                               printf ("METHOD %s(%s)\n", cm->name, msig);
+                                                               g_free (msig);
+                                                       }
 
-                                               if (ifaces)
-                                                       g_ptr_array_free (ifaces, TRUE);
-                                               if (override_map)
-                                                       g_hash_table_destroy (override_map);
+                                                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
 
-                                               return;
+                                                       if (ifaces)
+                                                               g_ptr_array_free (ifaces, TRUE);
+                                                       if (override_map)
+                                                               g_hash_table_destroy (override_map);
+
+                                                       return;
+                                               }
                                        }
                                }
-                       }
-               
-                       for (l = 0; l < ic->method.count; l++) {
-                               MonoMethod *im = vtable [io + l];
-
-                               if (im) {
-                                       g_assert (io + l <= max_vtsize);
-                                       if (im->slot < 0) {
-                                               /* FIXME: why do we need this ? */
-                                               im->slot = io + l;
-                                               /* g_assert_not_reached (); */
+                       
+                               for (l = 0; l < ic->method.count; l++) {
+                                       MonoMethod *im = vtable [io + l];
+
+                                       if (im) {
+                                               g_assert (io + l <= max_vtsize);
+                                               if (im->slot < 0) {
+                                                       /* FIXME: why do we need this ? */
+                                                       im->slot = io + l;
+                                                       /* g_assert_not_reached (); */
+                                               }
                                        }
                                }
                        }
-               }
-               if (ifaces)
-                       g_ptr_array_free (ifaces, TRUE);
-       } 
+                       if (ifaces)
+                               g_ptr_array_free (ifaces, TRUE);
+               } 
+       }
 
+       TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
        for (i = 0; i < class->method.count; ++i) {
                MonoMethod *cm;
               
@@ -2649,6 +3103,7 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o
                memcpy (class->vtable, vtable,  sizeof (gpointer) * class->vtable_size);
        }
 
+       DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
        if (mono_print_vtable) {
                int icount = 0;
 
@@ -2886,6 +3341,10 @@ set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
                break;
        }
 
+       case MONO_EXCEPTION_BAD_IMAGE:
+               class->exception_data = error->msg;
+               break;
+
        default :
                g_assert_not_reached ();
        }
@@ -3636,6 +4095,9 @@ mono_generic_class_get_class (MonoGenericClass *gclass)
 
        klass->name = gklass->name;
        klass->name_space = gklass->name_space;
+       
+       mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
+       
        klass->image = gklass->image;
        klass->flags = gklass->flags;
        klass->type_token = gklass->type_token;
@@ -3706,6 +4168,8 @@ mono_generic_class_get_class (MonoGenericClass *gclass)
        if (MONO_CLASS_IS_INTERFACE (klass))
                setup_interface_offsets (klass, 0);
 
+       mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
+       
        mono_loader_unlock ();
 
        return klass;
@@ -4725,7 +5189,7 @@ find_nocase (gpointer key, gpointer value, gpointer user_data)
 
 /**
  * mono_class_from_name_case:
- * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
+ * @image: The MonoImage where the type is looked up in
  * @name_space: the type namespace
  * @name: the type short name.
  *
@@ -4818,7 +5282,7 @@ return_nested_in (MonoClass *class, char *nested) {
 
 /**
  * mono_class_from_name:
- * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
+ * @image: The MonoImage where the type is looked up in
  * @name_space: the type namespace
  * @name: the type short name.
  *
@@ -4974,6 +5438,14 @@ mono_class_has_variant_generic_params (MonoClass *klass)
        return FALSE;
 }
 
+/**
+ * mono_class_is_assignable_from:
+ * @klass: the class to be assigned to
+ * @oklass: the source class
+ *
+ * Return: true if an instance of object oklass can be assigned to an
+ * instance of object @klass
+ */
 gboolean
 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
 {
@@ -5080,10 +5552,11 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
        return mono_class_has_parent (oklass, klass);
 }      
 
-/*
+/**
  * mono_class_get_cctor:
+ * @klass: A MonoClass pointer
  *
- *   Returns the static constructor of @klass if it exists, NULL otherwise.
+ * Returns: the static constructor of @klass if it exists, NULL otherwise.
  */
 MonoMethod*
 mono_class_get_cctor (MonoClass *klass)
@@ -5099,10 +5572,11 @@ mono_class_get_cctor (MonoClass *klass)
        return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
 }
 
-/*
+/**
  * mono_class_get_finalizer:
+ * @klass: The MonoClass pointer
  *
- *   Returns the finalizer method of @klass if it exists, NULL otherwise.
+ * Returns: the finalizer method of @klass if it exists, NULL otherwise.
  */
 MonoMethod*
 mono_class_get_finalizer (MonoClass *klass)
@@ -5122,10 +5596,12 @@ mono_class_get_finalizer (MonoClass *klass)
        }
 }
 
-/*
+/**
  * mono_class_needs_cctor_run:
+ * @klass: the MonoClass pointer
+ * @caller: a MonoMethod describing the caller
  *
- *  Determines whenever the class has a static constructor and whenever it
+ * Determines whenever the class has a static constructor and whenever it
  * needs to be called when executing CALLER.
  */
 gboolean
@@ -5842,6 +6318,18 @@ mono_field_get_flags (MonoClassField *field)
        return field->type->attrs;
 }
 
+/**
+ * mono_field_get_offset;
+ * @field: the MonoClassField to act on
+ *
+ * Returns: the field offset.
+ */
+guint32
+mono_field_get_offset (MonoClassField *field)
+{
+       return field->offset;
+}
+
 /**
  * mono_field_get_data;
  * @field: the MonoClassField to act on
@@ -6175,6 +6663,9 @@ mono_class_get_exception_for_failure (MonoClass *klass)
 
                return ex;
        }
+       case MONO_EXCEPTION_BAD_IMAGE: {
+               return mono_get_exception_bad_image_format (klass->exception_data);
+       }
        default: {
                MonoLoaderError *error;
                MonoException *ex;