2010-05-29 Robert Jordan <robertj@gmx.net>
[mono.git] / mono / metadata / object.c
index c2ecefae260fde3e23ff4b997bd341d379650ad1..11043d598276bfce9d4ae0587376a3276f4de7fa 100644 (file)
@@ -38,6 +38,7 @@
 #include "mono/metadata/security-manager.h"
 #include "mono/metadata/mono-debug-debugger.h"
 #include <mono/metadata/gc-internal.h>
+#include <mono/metadata/verify-internals.h>
 #include <mono/utils/strenc.h>
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-error-internals.h>
@@ -632,6 +633,15 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                size = max_size;
        }
 
+#ifdef HAVE_SGEN_GC
+       /*An Ephemeron cannot be marked by sgen*/
+       if (!static_fields && class->image == mono_defaults.corlib && !strcmp ("Ephemeron", class->name)) {
+               *max_set = 0;
+               memset (bitmap, 0, size / 8);
+               return bitmap;
+       }
+#endif
+
        for (p = class; p != NULL; p = p->parent) {
                gpointer iter = NULL;
                while ((field = mono_class_get_fields (p, &iter))) {
@@ -714,7 +724,7 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                        case MONO_TYPE_CHAR:
                                break;
                        default:
-                               g_assert_not_reached ();
+                               g_error ("compute_class_bitmap: Invalid type %x for field %s:%s\n", type->type, mono_type_get_full_name (field->parent), field->name);
                                break;
                        }
                }
@@ -992,14 +1002,6 @@ mono_install_imt_trampoline (gpointer tramp_code)
        imt_trampoline = tramp_code;
 }
 
-static gpointer vtable_trampoline = NULL;
-
-void
-mono_install_vtable_trampoline (gpointer tramp_code)
-{
-       vtable_trampoline = tramp_code;
-}
-
 #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
 #define mix(a,b,c) { \
        a -= c;  a ^= rot(c, 4);  c += b; \
@@ -1019,6 +1021,14 @@ mono_install_vtable_trampoline (gpointer tramp_code)
        c ^= b; c -= rot(b,24); \
 }
 
+/*
+ * mono_method_get_imt_slot:
+ *
+ *   The IMT slot is embedded into AOTed code, so this must return the same value
+ * for the same method across all executions. This means:
+ * - pointers shouldn't be used as hash values.
+ * - mono_metadata_str_hash () should be used for hashing strings.
+ */
 guint32
 mono_method_get_imt_slot (MonoMethod *method)
 {
@@ -1052,14 +1062,14 @@ mono_method_get_imt_slot (MonoMethod *method)
        }
        
        /* Initialize hashes */
-       hashes [0] = g_str_hash (method->klass->name);
-       hashes [1] = g_str_hash (method->klass->name_space);
-       hashes [2] = g_str_hash (method->name);
+       hashes [0] = mono_metadata_str_hash (method->klass->name);
+       hashes [1] = mono_metadata_str_hash (method->klass->name_space);
+       hashes [2] = mono_metadata_str_hash (method->name);
        hashes [3] = mono_metadata_type_hash (sig->ret);
        for (i = 0; i < sig->param_count; i++) {
                hashes [4 + i] = mono_metadata_type_hash (sig->params [i]);
        }
-       
+
        /* Setup internal state */
        a = b = c = 0xdeadbeef + (((guint32)hashes_count)<<2);
 
@@ -1119,9 +1129,12 @@ add_imt_builder_entry (MonoImtBuilderEntry **imt_builder, MonoMethod *method, gu
        }
        imt_builder [imt_slot] = entry;
 #if DEBUG_IMT
-       printf ("Added IMT slot for method (%p) %s.%s.%s: imt_slot = %d, vtable_slot = %d, colliding with other %d entries\n",
-                       method, method->klass->name_space, method->klass->name,
-                       method->name, imt_slot, vtable_slot, entry->children);
+       {
+       char *method_name = mono_method_full_name (method, TRUE);
+       printf ("Added IMT slot for method (%p) %s: imt_slot = %d, vtable_slot = %d, colliding with other %d entries\n",
+                       method, method_name, imt_slot, vtable_slot, entry->children);
+       g_free (method_name);
+       }
 #endif
 }
 
@@ -1129,13 +1142,14 @@ add_imt_builder_entry (MonoImtBuilderEntry **imt_builder, MonoMethod *method, gu
 static void
 print_imt_entry (const char* message, MonoImtBuilderEntry *e, int num) {
        if (e != NULL) {
+               MonoMethod *method = e->key;
                printf ("  * %s [%d]: (%p) '%s.%s.%s'\n",
                                message,
                                num,
-                               e->method,
-                               e->method->klass->name_space,
-                               e->method->klass->name,
-                               e->method->name);
+                               method,
+                               method->klass->name_space,
+                               method->klass->name,
+                               method->name);
        } else {
                printf ("  * %s: NULL\n", message);
        }
@@ -1249,15 +1263,20 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
        MonoImtBuilderEntry **imt_builder = calloc (MONO_IMT_SIZE, sizeof (MonoImtBuilderEntry*));
        int method_count = 0;
        gboolean record_method_count_for_max_collisions = FALSE;
-       gboolean has_generic_virtual = FALSE;
+       gboolean has_generic_virtual = FALSE, has_variant_iface = FALSE;
 
 #if DEBUG_IMT
-       printf ("Building IMT for class %s.%s\n", klass->name_space, klass->name);
+       printf ("Building IMT for class %s.%s slot %d\n", klass->name_space, klass->name, slot_num);
 #endif
        for (i = 0; i < klass->interface_offsets_count; ++i) {
                MonoClass *iface = klass->interfaces_packed [i];
                int interface_offset = klass->interface_offsets_packed [i];
-               int method_slot_in_interface;
+               int method_slot_in_interface, vt_slot;
+
+               if (mono_class_has_variant_generic_params (iface))
+                       has_variant_iface = TRUE;
+
+               vt_slot = interface_offset;
                for (method_slot_in_interface = 0; method_slot_in_interface < iface->method.count; method_slot_in_interface++) {
                        MonoMethod *method;
 
@@ -1269,15 +1288,22 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
                                 * add_imt_builder_entry anyway.
                                 */
                                method = mono_class_get_method_by_index (iface->generic_class->container_class, method_slot_in_interface);
-                               if (mono_method_get_imt_slot (method) != slot_num)
+                               if (mono_method_get_imt_slot (method) != slot_num) {
+                                       vt_slot ++;
                                        continue;
+                               }
                        }
                        method = mono_class_get_method_by_index (iface, method_slot_in_interface);
                        if (method->is_generic) {
                                has_generic_virtual = TRUE;
+                               vt_slot ++;
                                continue;
                        }
-                       add_imt_builder_entry (imt_builder, method, &imt_collisions_bitmap, interface_offset + method_slot_in_interface, slot_num);
+
+                       if (!(method->flags & METHOD_ATTRIBUTE_STATIC)) {
+                               add_imt_builder_entry (imt_builder, method, &imt_collisions_bitmap, vt_slot, slot_num);
+                               vt_slot ++;
+                       }
                }
        }
        if (extra_interfaces) {
@@ -1305,15 +1331,21 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
                                        MonoImtBuilderEntry *entry;
 
                                        /* Link entries with imt_builder [i] */
-                                       for (entry = entries; entry->next; entry = entry->next)
-                                               ;                                               
+                                       for (entry = entries; entry->next; entry = entry->next) {
+#if DEBUG_IMT
+                                               MonoMethod *method = (MonoMethod*)entry->key;
+                                               char *method_name = mono_method_full_name (method, TRUE);
+                                               printf ("Added extra entry for method (%p) %s: imt_slot = %d\n", method, method_name, i);
+                                               g_free (method_name);
+#endif
+                                       }
                                        entry->next = imt_builder [i];
                                        entries->children += imt_builder [i]->children + 1;
                                }
                                imt_builder [i] = entries;
                        }
 
-                       if (has_generic_virtual) {
+                       if (has_generic_virtual || has_variant_iface) {
                                /*
                                 * There might be collisions later when the the thunk is expanded.
                                 */
@@ -1327,10 +1359,11 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
                        } else {
                                imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], NULL);
                        }
-               }
 #if DEBUG_IMT
-               printf ("initialize_imt_slot[%d]: %p\n", i, imt [i]);
+                       printf ("initialize_imt_slot[%d]: %p methods %d\n", i, imt [i], imt_builder [i]->children + 1);
 #endif
+               }
+
                if (imt_builder [i] != NULL) {
                        int methods_in_slot = imt_builder [i]->children + 1;
                        if (methods_in_slot > mono_stats.imt_max_collisions_in_slot) {
@@ -1403,7 +1436,11 @@ mono_vtable_build_imt_slot (MonoVTable* vtable, int imt_slot)
  * entry points to the last element.  That way appending and removing
  * the first element are both O(1) operations.
  */
+#ifdef MONO_SMALL_CONFIG
+#define NUM_FREE_LISTS         6
+#else
 #define NUM_FREE_LISTS         12
+#endif
 #define FIRST_FREE_LIST_SIZE   64
 #define MAX_WAIT_LENGTH        50
 #define THUNK_THRESHOLD                10
@@ -1542,7 +1579,8 @@ typedef struct _GenericVirtualCase {
 /*
  * get_generic_virtual_entries:
  *
- *   Return IMT entries for the generic virtual method instances for vtable slot
+ *   Return IMT entries for the generic virtual method instances and
+ *   variant interface methods for vtable slot
  * VTABLE_SLOT.
  */ 
 static MonoImtBuilderEntry*
@@ -1588,7 +1626,7 @@ get_generic_virtual_entries (MonoDomain *domain, gpointer *vtable_slot)
  * @code: the method's code
  *
  * Registers a call via unmanaged code to a generic virtual method
- * instantiation.  If the number of calls reaches a threshold
+ * instantiation or variant interface method.  If the number of calls reaches a threshold
  * (THUNK_THRESHOLD), the method is added to the vtable slot's generic
  * virtual method thunk.
  */
@@ -1637,6 +1675,7 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
 
        if (++gvc->count == THUNK_THRESHOLD) {
                gpointer *old_thunk = *vtable_slot;
+               gpointer vtable_trampoline = callbacks.get_vtable_trampoline ? callbacks.get_vtable_trampoline ((gpointer*)vtable_slot - (gpointer*)vtable) : NULL;
 
                if ((gpointer)vtable_slot < (gpointer)vtable)
                        /* Force the rebuild of the thunk at the next call */
@@ -1880,11 +1919,29 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                        if (special_static != SPECIAL_STATIC_NONE) {
                                guint32 size, offset;
                                gint32 align;
+                               gsize default_bitmap [4] = {0};
+                               gsize *bitmap;
+                               int max_set = 0;
+                               MonoClass *fclass;
+                               if (mono_type_is_reference (field->type)) {
+                                       default_bitmap [0] = 1;
+                                       max_set = 1;
+                                       bitmap = default_bitmap;
+                               } else if (mono_type_is_struct (field->type)) {
+                                       fclass = mono_class_from_mono_type (field->type);
+                                       bitmap = compute_class_bitmap (fclass, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, FALSE);
+                               } else {
+                                       default_bitmap [0] = 0;
+                                       max_set = 0;
+                                       bitmap = default_bitmap;
+                               }
                                size = mono_type_size (field->type, &align);
-                               offset = mono_alloc_special_static_data (special_static, size, align);
+                               offset = mono_alloc_special_static_data (special_static, size, align, bitmap, max_set);
                                if (!domain->special_static_fields)
                                        domain->special_static_fields = g_hash_table_new (NULL, NULL);
                                g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
+                               if (bitmap != default_bitmap)
+                                       g_free (bitmap);
                                /* 
                                 * This marks the field as special static to speed up the
                                 * checks in mono_field_static_get/set_value ().
@@ -1928,11 +1985,9 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                }
        }
 
-       /* FIXME: class_vtable_hash is basically obsolete now: remove as soon
-        * as we change the code in appdomain.c to invalidate vtables by
-        * looking at the possible MonoClasses created for the domain.
+       /*  class_vtable_array keeps an array of created vtables
         */
-       g_hash_table_insert (domain->class_vtable_hash, class, vt);
+       g_ptr_array_add (domain->class_vtable_array, vt);
        /* class->runtime_info is protected by the loader lock, both when
         * it it enlarged and when it is stored info.
         */
@@ -1968,10 +2023,10 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
        }
 
        /* Initialize vtable */
-       if (vtable_trampoline) {
+       if (callbacks.get_vtable_trampoline) {
                // This also covers the AOT case
                for (i = 0; i < class->vtable_size; ++i) {
-                       vt->vtable [i] = vtable_trampoline;
+                       vt->vtable [i] = callbacks.get_vtable_trampoline (i);
                }
        } else {
                mono_class_setup_vtable (class);
@@ -1980,7 +2035,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
                        MonoMethod *cm;
 
                        if ((cm = class->vtable [i]))
-                               vt->vtable [i] = vtable_trampoline? vtable_trampoline: arch_create_jit_trampoline (cm);
+                               vt->vtable [i] = arch_create_jit_trampoline (cm);
                }
        }
 
@@ -2009,6 +2064,21 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
 
        /*FIXME check for OOM*/
        vt->type = mono_type_get_object (domain, &class->byval_arg);
+#if HAVE_SGEN_GC
+       if (mono_object_get_class (vt->type) != mono_defaults.monotype_class) {
+               static void *type_desc = NULL;
+
+               if (!type_desc) {
+                       gsize bmap = 1;
+                       type_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);
+               }
+
+               /* This is unregistered in
+                  unregister_vtable_reflection_type() in
+                  domain.c. */
+               mono_gc_register_root ((char*)&vt->type, sizeof (gpointer), type_desc);
+       }
+#endif
        if (class->contextbound)
                vt->remote = 1;
        else
@@ -2030,12 +2100,19 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean
 static MonoVTable *
 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRemotingTarget target_type)
 {
+       MonoError error;
        MonoVTable *vt, *pvt;
        int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
        MonoClass *k;
        GSList *extra_interfaces = NULL;
        MonoClass *class = remote_class->proxy_class;
        gpointer *interface_offsets;
+       uint8_t *bitmap;
+       int bsize;
+       
+#ifdef COMPRESSED_INTERFACE_BITMAP
+       int bcsize;
+#endif
 
        vt = mono_class_vtable (domain, class);
        g_assert (vt); /*FIXME property handle failure*/
@@ -2047,6 +2124,7 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
                GPtrArray *ifaces;
                int method_count;
 
+               /*FIXME test for interfaces with variant generic arguments*/
                if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
                        continue;       /* interface implemented by the class */
                if (g_slist_find (extra_interfaces, iclass))
@@ -2056,10 +2134,12 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
                
                method_count = mono_class_num_methods (iclass);
        
-               ifaces = mono_class_get_implemented_interfaces (iclass);
+               ifaces = mono_class_get_implemented_interfaces (iclass, &error);
+               g_assert (mono_error_ok (&error)); /*FIXME do proper error handling*/
                if (ifaces) {
                        for (i = 0; i < ifaces->len; ++i) {
                                MonoClass *ic = g_ptr_array_index (ifaces, i);
+                               /*FIXME test for interfaces with variant generic arguments*/
                                if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, ic->interface_id))
                                        continue;       /* interface implemented by the class */
                                if (g_slist_find (extra_interfaces, ic))
@@ -2120,7 +2200,12 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        }
 
        pvt->max_interface_id = max_interface_id;
-       pvt->interface_bitmap = mono_domain_alloc0 (domain, sizeof (guint8) * (max_interface_id/8 + 1 ));
+       bsize = sizeof (guint8) * (max_interface_id/8 + 1 );
+#ifdef COMPRESSED_INTERFACE_BITMAP
+       bitmap = g_malloc0 (bsize);
+#else
+       bitmap = mono_domain_alloc0 (domain, bsize);
+#endif
 
        if (! ARCH_USE_IMT) {
                /* initialize interface offsets */
@@ -2132,7 +2217,7 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
        }
        for (i = 0; i < class->interface_offsets_count; ++i) {
                int interface_id = class->interfaces_packed [i]->interface_id;
-               pvt->interface_bitmap [interface_id >> 3] |= (1 << (interface_id & 7));
+               bitmap [interface_id >> 3] |= (1 << (interface_id & 7));
        }
 
        if (extra_interfaces) {
@@ -2149,7 +2234,7 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
                        if (! ARCH_USE_IMT) {
                                interface_offsets [max_interface_id - interf->interface_id] = &pvt->vtable [slot];
                        }
-                       pvt->interface_bitmap [interf->interface_id >> 3] |= (1 << (interf->interface_id & 7));
+                       bitmap [interf->interface_id >> 3] |= (1 << (interf->interface_id & 7));
 
                        iter = NULL;
                        j = 0;
@@ -2171,6 +2256,14 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mono
                }
        }
 
+#ifdef COMPRESSED_INTERFACE_BITMAP
+       bcsize = mono_compress_bitmap (NULL, bitmap, bsize);
+       pvt->interface_bitmap = mono_domain_alloc0 (domain, bcsize);
+       mono_compress_bitmap (pvt->interface_bitmap, bitmap, bsize);
+       g_free (bitmap);
+#else
+       pvt->interface_bitmap = bitmap;
+#endif
        return pvt;
 }
 
@@ -2512,8 +2605,12 @@ mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method)
        /* check method->slot is a valid index: perform isinstance? */
        if (method->slot != -1) {
                if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
-                       if (!is_proxy)
-                               res = vtable [mono_class_interface_offset (klass, method->klass) + method->slot];
+                       if (!is_proxy) {
+                               gboolean variance_used = FALSE;
+                               int iface_offset = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
+                               g_assert (iface_offset > 0);
+                               res = vtable [iface_offset + method->slot];
+                       }
                } else {
                        res = vtable [method->slot];
                }
@@ -2819,6 +2916,26 @@ mono_vtable_get_static_field_data (MonoVTable *vt)
        return vt->data;
 }
 
+static guint8*
+mono_field_get_addr (MonoObject *obj, MonoVTable *vt, MonoClassField *field)
+{
+       guint8 *src;
+
+       if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
+               if (field->offset == -1) {
+                       /* Special static */
+                       gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+                       src = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
+               } else {
+                       src = (guint8*)vt->data + field->offset;
+               }
+       } else {
+               src = (guint8*)obj + field->offset;
+       }
+
+       return src;
+}
+
 /**
  * mono_field_get_value:
  * @obj: Object instance
@@ -2841,6 +2958,8 @@ mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
 {
        void *src;
 
+       g_assert (obj);
+
        g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
 
        src = (char*)obj + field->offset;
@@ -2866,6 +2985,7 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
        gchar *v;
        gboolean is_static = FALSE;
        gboolean is_ref = FALSE;
+       gboolean is_literal = FALSE;
 
        switch (field->type->type) {
        case MONO_TYPE_STRING:
@@ -2893,7 +3013,7 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
                is_ref = field->type->byref;
                break;
        case MONO_TYPE_GENERICINST:
-               is_ref = !field->type->data.generic_class->container_class->valuetype;
+               is_ref = !mono_type_generic_inst_is_valuetype (field->type);
                break;
        default:
                g_error ("type 0x%x not handled in "
@@ -2901,21 +3021,32 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
                return NULL;
        }
 
+       if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
+               is_literal = TRUE;
+
        if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
                is_static = TRUE;
-               vtable = mono_class_vtable (domain, field->parent);
-               if (!vtable) {
-                       char *name = mono_type_get_full_name (field->parent);
-                       g_warning ("Could not retrieve the vtable for type %s in mono_field_get_value_object", name);
-                       g_free (name);
-                       return NULL;
+
+               if (!is_literal) {
+                       vtable = mono_class_vtable (domain, field->parent);
+                       if (!vtable) {
+                               char *name = mono_type_get_full_name (field->parent);
+                               /*FIXME extend this to use the MonoError api*/
+                               g_warning ("Could not retrieve the vtable for type %s in mono_field_get_value_object", name);
+                               g_free (name);
+                               return NULL;
+                       }
+                       if (!vtable->initialized)
+                               mono_runtime_class_init (vtable);
                }
-               if (!vtable->initialized)
-                       mono_runtime_class_init (vtable);
+       } else {
+               g_assert (obj);
        }
        
        if (is_ref) {
-               if (is_static) {
+               if (is_literal) {
+                       get_default_field_value (domain, field, &o);
+               } else if (is_static) {
                        mono_field_static_get_value (vtable, field, &o);
                } else {
                        mono_field_get_value (obj, field, &o);
@@ -2925,9 +3056,16 @@ mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObje
 
        /* boxed value type */
        klass = mono_class_from_mono_type (field->type);
+
+       if (mono_class_is_nullable (klass))
+               return mono_nullable_box (mono_field_get_addr (obj, vtable, field), klass);
+
        o = mono_object_new (domain, klass);
        v = ((gchar *) o) + sizeof (MonoObject);
-       if (is_static) {
+
+       if (is_literal) {
+               get_default_field_value (domain, field, v);
+       } else if (is_static) {
                mono_field_static_get_value (vtable, field, v);
        } else {
                mono_field_get_value (obj, field, v);
@@ -3147,7 +3285,8 @@ mono_get_delegate_invoke (MonoClass *klass)
 
        /* This is called at runtime, so avoid the slower search in metadata */
        mono_class_setup_methods (klass);
-
+       if (klass->exception_type)
+               return NULL;
        im = mono_class_get_method_from_name (klass, "Invoke", -1);
        g_assert (im);
 
@@ -3584,7 +3723,7 @@ mono_unhandled_exception (MonoObject *exc)
                gboolean abort_process = (main_thread && (mono_thread_internal_current () == main_thread->internal_thread)) ||
                                (mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_CURRENT);
                root_appdomain_delegate = *(MonoObject **)(((char *)root_domain->domain) + field->offset);
-               if (current_domain != root_domain && (mono_framework_version () >= 2)) {
+               if (current_domain != root_domain) {
                        current_appdomain_delegate = *(MonoObject **)(((char *)current_domain->domain) + field->offset);
                } else {
                        current_appdomain_delegate = NULL;
@@ -3606,7 +3745,12 @@ mono_unhandled_exception (MonoObject *exc)
        }
 }
 
-/*
+/**
+ * mono_runtime_exec_managed_code:
+ * @domain: Application domain
+ * @main_func: function to invoke from the execution thread
+ * @main_args: parameter to the main_func
+ *
  * Launch a new thread to execute a function
  *
  * main_func is called back from the thread with main_args as the
@@ -3678,8 +3822,6 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
        }
        if (has_stathread_attribute) {
                thread->apartment_state = ThreadApartmentState_STA;
-       } else if (mono_framework_version () == 1) {
-               thread->apartment_state = ThreadApartmentState_Unknown;
        } else {
                thread->apartment_state = ThreadApartmentState_MTA;
        }
@@ -3876,6 +4018,7 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
 
                if (!obj) {
                        obj = mono_object_new (mono_domain_get (), method->klass);
+                       g_assert (obj); /*maybe we should raise a TLE instead?*/
                        if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
                                method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
                        }
@@ -4224,7 +4367,7 @@ mono_object_clone (MonoObject *obj)
 void
 mono_array_full_copy (MonoArray *src, MonoArray *dest)
 {
-       mono_array_size_t size;
+       uintptr_t size;
        MonoClass *klass = src->obj.vtable->klass;
 
        MONO_ARCH_SAVE_REGS;
@@ -4260,8 +4403,8 @@ MonoArray*
 mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
 {
        MonoArray *o;
-       mono_array_size_t size, i;
-       mono_array_size_t *sizes;
+       uintptr_t size, i;
+       uintptr_t *sizes;
        MonoClass *klass = array->obj.vtable->klass;
 
        MONO_ARCH_SAVE_REGS;
@@ -4286,14 +4429,14 @@ mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
                return o;
        }
        
-       sizes = alloca (klass->rank * sizeof(mono_array_size_t) * 2);
+       sizes = alloca (klass->rank * sizeof(intptr_t) * 2);
        size = mono_array_element_size (klass);
        for (i = 0; i < klass->rank; ++i) {
                sizes [i] = array->bounds [i].length;
                size *= array->bounds [i].length;
                sizes [i + klass->rank] = array->bounds [i].lower_bound;
        }
-       o = mono_array_new_full (domain, klass, sizes, sizes + klass->rank);
+       o = mono_array_new_full (domain, klass, sizes, (intptr_t*)sizes + klass->rank);
 #ifdef HAVE_SGEN_GC
        if (klass->element_class->valuetype) {
                if (klass->element_class->has_references)
@@ -4342,9 +4485,9 @@ mono_array_clone (MonoArray *array)
 #endif
 
 gboolean
-mono_array_calc_byte_len (MonoClass *class, mono_array_size_t len, mono_array_size_t *res)
+mono_array_calc_byte_len (MonoClass *class, uintptr_t len, uintptr_t *res)
 {
-       mono_array_size_t byte_len;
+       uintptr_t byte_len;
 
        byte_len = mono_array_element_size (class);
        if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
@@ -4370,9 +4513,9 @@ mono_array_calc_byte_len (MonoClass *class, mono_array_size_t len, mono_array_si
  * lower bounds and type.
  */
 MonoArray*
-mono_array_new_full (MonoDomain *domain, MonoClass *array_class, mono_array_size_t *lengths, mono_array_size_t *lower_bounds)
+mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *lengths, intptr_t *lower_bounds)
 {
-       mono_array_size_t byte_len, len, bounds_size;
+       uintptr_t byte_len, len, bounds_size;
        MonoObject *o;
        MonoArray *array;
        MonoArrayBounds *bounds;
@@ -4472,7 +4615,7 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, mono_array_size
  * This routine creates a new szarray with @n elements of type @eclass.
  */
 MonoArray *
-mono_array_new (MonoDomain *domain, MonoClass *eclass, mono_array_size_t n)
+mono_array_new (MonoDomain *domain, MonoClass *eclass, uintptr_t n)
 {
        MonoClass *ac;
 
@@ -4493,11 +4636,11 @@ mono_array_new (MonoDomain *domain, MonoClass *eclass, mono_array_size_t n)
  * can be sure about the domain it operates in.
  */
 MonoArray *
-mono_array_new_specific (MonoVTable *vtable, mono_array_size_t n)
+mono_array_new_specific (MonoVTable *vtable, uintptr_t n)
 {
        MonoObject *o;
        MonoArray *ao;
-       guint32 byte_len;
+       uintptr_t byte_len;
 
        MONO_ARCH_SAVE_REGS;
 
@@ -4579,9 +4722,13 @@ mono_string_new_size (MonoDomain *domain, gint32 len)
        vtable = mono_class_vtable (domain, mono_defaults.string_class);
        g_assert (vtable);
 
+#ifndef HAVE_SGEN_GC
        s = mono_object_allocate_ptrfree (size, vtable);
 
        s->length = len;
+#else
+       s = mono_gc_alloc_string (vtable, size, len);
+#endif
 #if NEED_TO_ZERO_PTRFREE
        s->chars [len] = 0;
 #endif
@@ -4856,7 +5003,7 @@ mono_object_isinst (MonoObject *obj, MonoClass *klass)
        if (!klass->inited)
                mono_class_init (klass);
 
-       if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE) 
+       if (klass->marshalbyref || (klass->flags & TYPE_ATTRIBUTE_INTERFACE))
                return mono_object_isinst_mbyref (obj, klass);
 
        if (!obj)
@@ -4879,6 +5026,10 @@ mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
                if (MONO_VTABLE_IMPLEMENTS_INTERFACE (vt, klass->interface_id)) {
                        return obj;
                }
+
+               /*If the above check fails we are in the slow path of possibly raising an exception. So it's ok to it this way.*/
+               if (mono_class_has_variant_generic_params (klass) && mono_class_is_assignable_from (klass, obj->vtable->klass))
+                       return obj;
        } else {
                MonoClass *oklass = vt->klass;
                if ((oklass == mono_defaults.transparent_proxy_class))
@@ -5047,10 +5198,14 @@ mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
 {
        MONO_ARCH_SAVE_REGS;
 
-       if (image->dynamic)
-               return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL);
-       else
+       if (image->dynamic) {
+               MonoString *str = mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL);
+               return str;
+       } else {
+               if (!mono_verifier_verify_string_signature (image, idx, NULL))
+                       return NULL; /*FIXME we should probably be raising an exception here*/
                return mono_ldstr_metadata_sig (domain, mono_metadata_user_string (image, idx));
+       }
 }
 
 /**
@@ -5066,7 +5221,7 @@ mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig)
        const char *str = sig;
        MonoString *o, *interned;
        size_t len2;
-       
+
        len2 = mono_metadata_decode_blob_size (str, &str);
        len2 >>= 1;
 
@@ -5157,7 +5312,7 @@ mono_string_to_utf8_checked (MonoString *s, MonoError *error)
  * This is a temporary helper until our string implementation
  * is reworked to always include the null terminating char.
  */
-gunichar2 *
+mono_unichar2*
 mono_string_to_utf16 (MonoString *s)
 {
        char *as;
@@ -6058,7 +6213,6 @@ mono_get_addr_from_ftnptr (gpointer descr)
        return callbacks.get_addr_from_ftnptr (descr);
 }      
 
-#if 0
 /**
  * mono_string_chars:
  * @s: a MonoString
@@ -6066,9 +6220,9 @@ mono_get_addr_from_ftnptr (gpointer descr)
  * Returns a pointer to the UCS16 characters stored in the MonoString
  */
 gunichar2 *
-mono_string_chars(MonoString *s)
+mono_string_chars (MonoString *s)
 {
-       /* This method is here only for documentation extraction, this is a macro */
+       return s->chars;
 }
 
 /**
@@ -6080,7 +6234,33 @@ mono_string_chars(MonoString *s)
 int
 mono_string_length (MonoString *s)
 {
-       /* This method is here only for documentation extraction, this is a macro */
+       return s->length;
+}
+
+/**
+ * mono_array_length:
+ * @array: a MonoArray*
+ *
+ * Returns the total number of elements in the array. This works for
+ * both vectors and multidimensional arrays.
+ */
+uintptr_t
+mono_array_length (MonoArray *array)
+{
+       return array->max_length;
+}
+
+/**
+ * mono_array_addr_with_size:
+ * @array: a MonoArray*
+ * @size: size of the array elements
+ * @idx: index into the array
+ *
+ * Returns the address of the @idx element in the array.
+ */
+char*
+mono_array_addr_with_size (MonoArray *array, int size, uintptr_t idx)
+{
+       return ((char*)(array)->vector) + size * idx;
 }
 
-#endif