merge 99244:99306
[mono.git] / mono / metadata / class.c
index 406c79cd2746d2fdc6ab0f70aa2a484285ecdb28..2cd4c838425e982bd4a098fd86a529d80ae03536 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;
@@ -121,7 +121,7 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token)
                                i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
                        }
                }
-               g_warning ("TypeRef ResolutionScope not yet handled (%d)", idx);
+               g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
                return NULL;
        }
        case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
@@ -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;
@@ -801,10 +817,21 @@ mono_class_setup_fields (MonoClass *class)
        if (class->size_inited)
                return;
 
+       if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
+               /*
+                * This happens when a generic instance of an unfinished generic typebuilder
+                * is used as an element type for creating an array type. We can't initialize
+                * the fields of this class using the fields of gklass, since gklass is not
+                * finished yet, fields could be added to it later.
+                */
+               return;
+       }
+
        if (class->generic_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 +1236,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).
@@ -1234,18 +1262,15 @@ mono_class_layout_fields (MonoClass *class)
                break;
        }
 
-#if NO_UNALIGNED_ACCESS
        if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
                /*
-                * For small structs, set min_align to at least the struct size, since the
-                * JIT memset/memcpy code assumes this and generates unaligned accesses
-                * otherwise. See #78990 for a testcase.
-                * FIXME: Fix the memset/memcpy code instead.
+                * For small structs, set min_align to at least the struct size to improve
+                * performance, and since the JIT memset/memcpy code assumes this and generates 
+                * unaligned accesses otherwise. See #78990 for a testcase.
                 */
                if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
                        class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
        }
-#endif
 
        class->size_inited = 1;
 
@@ -1316,8 +1341,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);
                }
        }
 
@@ -1659,73 +1682,6 @@ mono_class_get_implemented_interfaces (MonoClass *klass)
        return res;
 }
 
-typedef struct _IOffsetInfo IOffsetInfo;
-struct _IOffsetInfo {
-       IOffsetInfo *next;
-       int size;
-       int next_free;
-       int data [MONO_ZERO_LEN_ARRAY];
-};
-
-static IOffsetInfo *cached_offset_info = NULL;
-static int next_offset_info_size = 128;
-
-static int*
-cache_interface_offsets (int max_iid, int *data)
-{
-       IOffsetInfo *cached_info;
-       int *cached;
-       int new_size;
-       for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
-               cached = cached_info->data;
-               while (cached < cached_info->data + cached_info->size && *cached) {
-                       if (*cached == max_iid) {
-                               int i, matched = TRUE;
-                               cached++;
-                               for (i = 0; i < max_iid; ++i) {
-                                       if (cached [i] != data [i]) {
-                                               matched = FALSE;
-                                               break;
-                                       }
-                               }
-                               if (matched)
-                                       return cached;
-                               cached += max_iid;
-                       } else {
-                               cached += *cached + 1;
-                       }
-               }
-       }
-       /* find a free slot */
-       for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
-               if (cached_info->size - cached_info->next_free >= max_iid + 1) {
-                       cached = &cached_info->data [cached_info->next_free];
-                       *cached++ = max_iid;
-                       memcpy (cached, data, max_iid * sizeof (int));
-                       cached_info->next_free += max_iid + 1;
-                       return cached;
-               }
-       }
-       /* allocate a new chunk */
-       if (max_iid + 1 < next_offset_info_size) {
-               new_size = next_offset_info_size;
-               if (next_offset_info_size < 4096)
-                       next_offset_info_size += next_offset_info_size >> 2;
-       } else {
-               new_size = max_iid + 1;
-       }
-       cached_info = g_malloc0 (sizeof (IOffsetInfo) + sizeof (int) * new_size);
-       cached_info->size = new_size;
-       /*g_print ("allocated %d offset entries at %p (total: %d)\n", new_size, cached_info->data, offset_info_total_size);*/
-       cached = &cached_info->data [0];
-       *cached++ = max_iid;
-       memcpy (cached, data, max_iid * sizeof (int));
-       cached_info->next_free += max_iid + 1;
-       cached_info->next = cached_offset_info;
-       cached_offset_info = cached_info;
-       return cached;
-}
-
 static int
 compare_interface_ids (const void *p_key, const void *p_element) {
        const MonoClass *key = p_key;
@@ -1757,9 +1713,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 +1737,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 +2208,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 +2481,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 +2495,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 +2514,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 +2572,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 +3043,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 +3281,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 ();
        }
@@ -3181,6 +3580,16 @@ mono_class_init (MonoClass *class)
        return class_init_ok;
 }
 
+static gboolean
+is_corlib_image (MonoImage *image)
+{
+       /* FIXME: allow the dynamic case for our compilers and with full trust */
+       if (image->dynamic)
+               return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
+       else
+               return image == mono_defaults.corlib;
+}
+
 /*
  * LOCKING: this assumes the loader lock is held
  */
@@ -3189,6 +3598,7 @@ mono_class_setup_mono_type (MonoClass *class)
 {
        const char *name = class->name;
        const char *nspace = class->name_space;
+       gboolean is_corlib = is_corlib_image (class->image);
 
        class->this_arg.byref = 1;
        class->this_arg.data.klass = class;
@@ -3196,7 +3606,7 @@ mono_class_setup_mono_type (MonoClass *class)
        class->byval_arg.data.klass = class;
        class->byval_arg.type = MONO_TYPE_CLASS;
 
-       if (!strcmp (nspace, "System")) {
+       if (is_corlib && !strcmp (nspace, "System")) {
                if (!strcmp (name, "ValueType")) {
                        /*
                         * do not set the valuetype bit for System.ValueType.
@@ -3218,10 +3628,11 @@ mono_class_setup_mono_type (MonoClass *class)
                        class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
                }
        }
-       
+
        if (class->valuetype) {
                int t = MONO_TYPE_VALUETYPE;
-               if (!strcmp (nspace, "System")) {
+
+               if (is_corlib && !strcmp (nspace, "System")) {
                        switch (*name) {
                        case 'B':
                                if (!strcmp (name, "Boolean")) {
@@ -3311,8 +3722,9 @@ void
 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
 {
        gboolean system_namespace;
+       gboolean is_corlib = is_corlib_image (class->image);
 
-       system_namespace = !strcmp (class->name_space, "System");
+       system_namespace = !strcmp (class->name_space, "System") && is_corlib;
 
        /* if root of the hierarchy */
        if (system_namespace && !strcmp (class->name, "Object")) {
@@ -3333,11 +3745,13 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
                        if (parent == mono_defaults.object_class)
                                parent = mono_defaults.com_object_class;
                }
-               class->parent = parent;
-
+               if (!parent) {
+                       /* set the parent to something useful and safe, but mark the type as broken */
+                       parent = mono_defaults.object_class;
+                       mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+               }
 
-               if (!parent)
-                       g_assert_not_reached (); /* FIXME */
+               class->parent = parent;
 
                if (parent->generic_class && !parent->name) {
                        /*
@@ -3367,10 +3781,10 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent)
                                class->delegate  = 1;
                }
 
-               if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) && 
+               if (class->parent->enumtype || (is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) && 
                                                (strcmp (class->parent->name_space, "System") == 0)))
                        class->valuetype = 1;
-               if (((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
+               if (is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
                        class->valuetype = class->enumtype = 1;
                }
                /*class->enumtype = class->parent->enumtype; */
@@ -3636,6 +4050,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 +4123,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;
@@ -4529,8 +4948,15 @@ mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *c
 {
        MonoClass *class = NULL;
 
-       if (image->dynamic)
+       if (image->dynamic) {
+               int table = mono_metadata_token_table (type_token);
+
+               if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
+                       mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
+                       return NULL;
+               }
                return mono_lookup_dynamic_token (image, type_token, context);
+       }
 
        switch (type_token & 0xff000000){
        case MONO_TOKEN_TYPE_DEF:
@@ -4718,7 +5144,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.
  *
@@ -4811,7 +5237,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.
  *
@@ -4967,6 +5393,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)
 {
@@ -5073,10 +5507,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)
@@ -5092,10 +5527,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)
@@ -5115,10 +5551,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
@@ -5209,7 +5647,7 @@ mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
 {
        if (image->dynamic) {
                MonoClass *tmp_handle_class;
-               gpointer obj = mono_lookup_dynamic_token_class (image, token, &tmp_handle_class, context);
+               gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
 
                g_assert (tmp_handle_class);
                if (handle_class)
@@ -5299,13 +5737,13 @@ mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *
 {
        MonoClass *handle_class;
 
-       return lookup_dynamic (image, token, &handle_class, context);
+       return lookup_dynamic (image, token, TRUE, &handle_class, context);
 }
 
 gpointer
-mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, MonoClass **handle_class, MonoGenericContext *context)
+mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
 {
-       return lookup_dynamic (image, token, handle_class, context);
+       return lookup_dynamic (image, token, valid_token, handle_class, context);
 }
 
 static MonoGetCachedClassInfo get_cached_class_info = NULL;
@@ -5835,6 +6273,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
@@ -6092,17 +6542,8 @@ mono_classes_init (void)
 void
 mono_classes_cleanup (void)
 {
-       IOffsetInfo *cached_info, *next;
-
        if (global_interface_bitset)
                mono_bitset_free (global_interface_bitset);
-
-       for (cached_info = cached_offset_info; cached_info;) {
-               next = cached_info->next;
-
-               g_free (cached_info);
-               cached_info = next;
-       }
 }
 
 /**
@@ -6168,6 +6609,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;
@@ -6184,6 +6628,46 @@ mono_class_get_exception_for_failure (MonoClass *klass)
        }
 }
 
+static gboolean
+is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
+ {
+       do {
+               if (outer_klass == inner_klass)
+                       return TRUE;
+               inner_klass = inner_klass->nested_in;
+       } while (inner_klass);
+       return FALSE;
+}
+
+/*
+ * Subtype can only access parent members with family protection if the site object
+ * is subclass of Subtype. For example:
+ * class A { protected int x; }
+ * class B : A {
+ *     void valid_access () {
+ *             B b;
+ *             b.x = 0;
+ *  }
+ *  void invalid_access () {
+ *             A a;
+ *             a.x = 0;
+ *  }
+ * }
+ * */
+static gboolean
+is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
+{
+       if (!mono_class_has_parent (access_klass, member_klass))
+               return FALSE;
+
+       if (context_klass == NULL)
+               return TRUE;
+       /*if access_klass is not member_klass context_klass must be type compat*/
+       if (access_klass != member_klass && !mono_class_has_parent (context_klass, access_klass))
+               return FALSE;
+       return TRUE;
+}
+
 static gboolean
 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
 {
@@ -6202,7 +6686,7 @@ can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
                if (friend->public_key_token [0]) {
                        if (!accessing->aname.public_key_token [0])
                                continue;
-                       if (strcmp ((char*)friend->public_key_token, (char*)accessing->aname.public_key_token))
+                       if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
                                continue;
                }
                return TRUE;
@@ -6226,9 +6710,50 @@ get_generic_definition_class (MonoClass *klass)
        return NULL;
 }
 
+static gboolean
+can_access_type (MonoClass *access_klass, MonoClass *member_klass)
+{
+       int access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+
+       if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
+               return TRUE;
+
+       if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
+               return FALSE;
+
+       switch (access_level) {
+       case TYPE_ATTRIBUTE_NOT_PUBLIC:
+               return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
+
+       case TYPE_ATTRIBUTE_PUBLIC:
+               return TRUE;
+
+       case TYPE_ATTRIBUTE_NESTED_PUBLIC:
+               return TRUE;
+
+       case TYPE_ATTRIBUTE_NESTED_PRIVATE:
+               return is_nesting_type (member_klass, access_klass);
+
+       case TYPE_ATTRIBUTE_NESTED_FAMILY:
+               return mono_class_has_parent (access_klass, member_klass->nested_in); 
+
+       case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
+               return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
+
+       case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
+               return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
+                       mono_class_has_parent (access_klass, member_klass->nested_in);
+
+       case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
+               return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
+                       mono_class_has_parent (access_klass, member_klass->nested_in);
+       }
+       return FALSE;
+}
+
 /* FIXME: check visibility of type, too */
 static gboolean
-can_access_member (MonoClass *access_klass, MonoClass *member_klass, int access_level)
+can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
 {
        MonoClass *member_generic_def;
        if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
@@ -6241,7 +6766,7 @@ can_access_member (MonoClass *access_klass, MonoClass *member_klass, int access_
                else
                        access_container = access_klass->generic_class->container_class;
 
-               if (can_access_member (access_container, member_generic_def, access_level))
+               if (can_access_member (access_container, member_generic_def, context_klass, access_level))
                        return TRUE;
        }
 
@@ -6254,18 +6779,18 @@ can_access_member (MonoClass *access_klass, MonoClass *member_klass, int access_
        case FIELD_ATTRIBUTE_PRIVATE:
                return access_klass == member_klass;
        case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
-               if (mono_class_has_parent (access_klass, member_klass) &&
+               if (is_valid_family_access (access_klass, member_klass, context_klass) &&
                    can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
                        return TRUE;
                return FALSE;
        case FIELD_ATTRIBUTE_ASSEMBLY:
                return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
        case FIELD_ATTRIBUTE_FAMILY:
-               if (mono_class_has_parent (access_klass, member_klass))
+               if (is_valid_family_access (access_klass, member_klass, context_klass))
                        return TRUE;
                return FALSE;
        case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
-               if (mono_class_has_parent (access_klass, member_klass))
+               if (is_valid_family_access (access_klass, member_klass, context_klass))
                        return TRUE;
                return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
        case FIELD_ATTRIBUTE_PUBLIC:
@@ -6278,11 +6803,11 @@ gboolean
 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
 {
        /* FIXME: check all overlapping fields */
-       int can = can_access_member (method->klass, field->parent, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
+       int can = can_access_member (method->klass, field->parent, NULL, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
        if (!can) {
                MonoClass *nested = method->klass->nested_in;
                while (nested) {
-                       can = can_access_member (nested, field->parent, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
+                       can = can_access_member (nested, field->parent, NULL, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
                        if (can)
                                return TRUE;
                        nested = nested->nested_in;
@@ -6294,11 +6819,11 @@ mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
 gboolean
 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
 {
-       int can = can_access_member (method->klass, called->klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
+       int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
        if (!can) {
                MonoClass *nested = method->klass->nested_in;
                while (nested) {
-                       can = can_access_member (nested, called->klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
+                       can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
                        if (can)
                                return TRUE;
                        nested = nested->nested_in;
@@ -6316,6 +6841,78 @@ mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
        return can;
 }
 
+/*
+ * mono_method_can_access_method_with_context:
+ * @method: The caller method 
+ * @called: The called method 
+ * @context_klass:TThe static type on stack of the owner @called object used
+ * 
+ * This function must be used with instance calls, as they have more strict family accessibility.
+ * It can be used with static mehthod, but context_klass should be NULL.
+ * 
+ * Returns: TRUE if caller have proper visibility and acessibility to @called
+ */
+gboolean
+mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
+{
+       MonoClass *access_class = method->klass;
+       MonoClass *member_class = called->klass;
+       int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
+       if (!can) {
+               MonoClass *nested = access_class->nested_in;
+               while (nested) {
+                       can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
+                       if (can)
+                               return TRUE;
+                       nested = nested->nested_in;
+               }
+       }
+
+       if (!can)
+               return FALSE;
+
+       if (!can_access_type (access_class, member_class) && (!access_class->nested_in || !can_access_type (access_class->nested_in, member_class)))
+               return FALSE;
+       return TRUE;
+}
+
+
+/*
+ * mono_method_can_access_method_with_context:
+ * @method: The caller method 
+ * @field: The accessed field
+ * @context_klass: The static type on stack of the owner @field object used
+ * 
+ * This function must be used with instance fields, as they have more strict family accessibility.
+ * It can be used with static fields, but context_klass should be NULL.
+ * 
+ * Returns: TRUE if caller have proper visibility and acessibility to @field
+ */
+gboolean
+mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
+{
+       MonoClass *access_class = method->klass;
+       MonoClass *member_class = field->parent;
+       /* FIXME: check all overlapping fields */
+       int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
+       if (!can) {
+               MonoClass *nested = access_class->nested_in;
+               while (nested) {
+                       can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
+                       if (can)
+                               return TRUE;
+                       nested = nested->nested_in;
+               }
+       }
+
+       if (!can)
+               return FALSE;
+
+       if (!can_access_type (access_class, member_class) && (!access_class->nested_in || !can_access_type (access_class->nested_in, member_class)))
+               return FALSE;
+       return TRUE;
+}
+
 /**
  * mono_type_is_valid_enum_basetype:
  * @type: The MonoType to check
@@ -6405,7 +7002,11 @@ mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
 gboolean
 mono_class_generic_sharing_enabled (MonoClass *class)
 {
+#if defined(__i386__) || defined(__x86_64__)
        static int generic_sharing = MONO_GENERIC_SHARING_CORLIB;
+#else
+       static int generic_sharing = MONO_GENERIC_SHARING_NONE;
+#endif
        static gboolean inited = FALSE;
 
        if (!inited) {