Mark tests as not working under TARGET_JVM
[mono.git] / mono / metadata / object.c
index 0ab4716b85346471281203b3aa26171d858d3e2a..30d3059882003d455a157ec6adde2b4de045d58d 100644 (file)
@@ -173,6 +173,55 @@ mono_type_initialization_init (void)
        InitializeCriticalSection (&ldstr_section);
 }
 
+void
+mono_type_initialization_cleanup (void)
+{
+#if 0
+       /* This is causing race conditions with
+        * mono_release_type_locks
+        */
+       DeleteCriticalSection (&type_initialization_section);
+#endif
+       DeleteCriticalSection (&ldstr_section);
+}
+
+/**
+ * get_type_init_exception_for_vtable:
+ *
+ *   Return the stored type initialization exception for VTABLE.
+ */
+static MonoException*
+get_type_init_exception_for_vtable (MonoVTable *vtable)
+{
+       MonoDomain *domain = vtable->domain;
+       MonoClass *klass = vtable->klass;
+       MonoException *ex;
+       gchar *full_name;
+
+       g_assert (vtable->init_failed);
+
+       /* 
+        * If the initializing thread was rudely aborted, the exception is not stored
+        * in the hash.
+        */
+       ex = NULL;
+       mono_domain_lock (domain);
+       if (domain->type_init_exception_hash)
+               ex = mono_g_hash_table_lookup (domain->type_init_exception_hash, klass);
+       mono_domain_unlock (domain);
+
+       if (!ex) {
+               if (klass->name_space && *klass->name_space)
+                       full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
+               else
+                       full_name = g_strdup (klass->name);
+               ex = mono_get_exception_type_initialization (full_name, NULL);
+               g_free (full_name);
+       }
+
+       return ex;
+}
+
 /*
  * mono_runtime_class_init:
  * @vtable: vtable that needs to be initialized
@@ -196,6 +245,13 @@ mono_runtime_class_init (MonoVTable *vtable)
        exc = NULL;
        klass = vtable->klass;
 
+       if (!klass->image->checked_module_cctor) {
+               mono_image_check_for_module_cctor (klass->image);
+               if (klass->image->has_module_cctor) {
+                       MonoClass *module_klass = mono_class_get (klass->image, MONO_TOKEN_TYPE_DEF | 1);
+                       mono_runtime_class_init (mono_class_vtable (vtable->domain, module_klass));
+               }
+       }
        method = mono_class_get_cctor (klass);
 
        if (method) {
@@ -211,6 +267,13 @@ mono_runtime_class_init (MonoVTable *vtable)
                        mono_type_initialization_unlock ();
                        return;
                }
+               if (vtable->init_failed) {
+                       mono_type_initialization_unlock ();
+
+                       /* The type initialization already failed once, rethrow the same exception */
+                       mono_raise_exception (get_type_init_exception_for_vtable (vtable));
+                       return;
+               }                       
                lock = g_hash_table_lookup (type_initialization_hash, vtable);
                if (lock == NULL) {
                        /* This thread will get to do the initialization */
@@ -264,6 +327,33 @@ mono_runtime_class_init (MonoVTable *vtable)
 
                if (do_initialization) {
                        mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
+
+                       /* If the initialization failed, mark the class as unusable. */
+                       /* Avoid infinite loops */
+                       if (!(exc == NULL ||
+                                 (klass->image == mono_defaults.corlib &&              
+                                  !strcmp (klass->name_space, "System") &&
+                                  !strcmp (klass->name, "TypeInitializationException")))) {
+                               vtable->init_failed = 1;
+
+                               if (klass->name_space && *klass->name_space)
+                                       full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
+                               else
+                                       full_name = g_strdup (klass->name);
+                               exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
+                               g_free (full_name);
+
+                               /* 
+                                * Store the exception object so it could be thrown on subsequent 
+                                * accesses.
+                                */
+                               mono_domain_lock (domain);
+                               if (!domain->type_init_exception_hash)
+                                       domain->type_init_exception_hash = mono_g_hash_table_new_type (mono_aligned_addr_hash, NULL, MONO_HASH_VALUE_GC);
+                               mono_g_hash_table_insert (domain->type_init_exception_hash, klass, exc_to_throw);
+                               mono_domain_unlock (domain);
+                       }
+
                        if (last_domain)
                                mono_domain_set (last_domain, TRUE);
                        lock->done = TRUE;
@@ -283,37 +373,34 @@ mono_runtime_class_init (MonoVTable *vtable)
                        g_hash_table_remove (type_initialization_hash, vtable);
                        g_free (lock);
                }
-               vtable->initialized = 1;
-               /* FIXME: if the cctor fails, the type must be marked as unusable */
+               if (!vtable->init_failed)
+                       vtable->initialized = 1;
                mono_type_initialization_unlock ();
+
+               if (vtable->init_failed) {
+                       /* Either we were the initializing thread or we waited for the initialization */
+                       mono_raise_exception (get_type_init_exception_for_vtable (vtable));
+               }
        } else {
                vtable->initialized = 1;
                return;
        }
-
-       if (exc == NULL ||
-           (klass->image == mono_defaults.corlib &&            
-            !strcmp (klass->name_space, "System") &&
-            !strcmp (klass->name, "TypeInitializationException")))
-               return; /* No static constructor found or avoid infinite loop */
-
-       if (klass->name_space && *klass->name_space)
-               full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
-       else
-               full_name = g_strdup (klass->name);
-
-       exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
-       g_free (full_name);
-
-       mono_raise_exception (exc_to_throw);
 }
 
 static
 gboolean release_type_locks (gpointer key, gpointer value, gpointer user)
 {
+       MonoVTable *vtable = (MonoVTable*)key;
+
        TypeInitializationLock *lock = (TypeInitializationLock*) value;
        if (lock->initializing_tid == GPOINTER_TO_UINT (user) && !lock->done) {
                lock->done = TRUE;
+               /* 
+                * Have to set this since it cannot be set by the normal code in 
+                * mono_runtime_class_init (). In this case, the exception object is not stored,
+                * and get_type_init_exception_for_class () needs to be aware of this.
+                */
+               vtable->init_failed = 1;
                LeaveCriticalSection (&lock->initialization_section);
                --lock->waiting_count;
                if (lock->waiting_count == 0) {
@@ -470,13 +557,18 @@ mono_install_init_vtable (MonoInitVTableFunc func)
 #define BITMAP_EL_SIZE (sizeof (gsize) * 8)
 
 static gsize*
-compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int *max_set)
+compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int *max_set, gboolean static_fields)
 {
        MonoClassField *field;
        MonoClass *p;
        guint32 pos;
-       int max_size = class->instance_size / sizeof (gpointer);
-       if (max_size > size) {
+       int max_size;
+
+       if (static_fields)
+               max_size = mono_class_data_size (class) / sizeof (gpointer);
+       else
+               max_size = class->instance_size / sizeof (gpointer);
+       if (max_size >= size) {
                bitmap = g_malloc0 (sizeof (gsize) * ((max_size) + 1));
        }
 
@@ -485,8 +577,13 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                while ((field = mono_class_get_fields (p, &iter))) {
                        MonoType *type;
 
-                       if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA))
-                               continue;
+                       if (static_fields) {
+                               if (!(field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA)))
+                                       continue;
+                       } else {
+                               if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA))
+                                       continue;
+                       }
                        /* FIXME: should not happen, flag as type load error */
                        if (field->type->byref)
                                break;
@@ -496,11 +593,18 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
 
                        type = mono_type_get_underlying_type (field->type);
                        switch (type->type) {
-                       /* FIXME: _I and _U and _PTR should be removed eventually */
                        case MONO_TYPE_I:
-                       case MONO_TYPE_U:
                        case MONO_TYPE_PTR:
                        case MONO_TYPE_FNPTR:
+                               break;
+                       /* only UIntPtr is allowed to be GC-tracked and only in mscorlib */
+                       case MONO_TYPE_U:
+#ifdef HAVE_SGEN_GC
+                               break;
+#else
+                               if (class->image != mono_defaults.corlib)
+                                       break;
+#endif
                        case MONO_TYPE_STRING:
                        case MONO_TYPE_SZARRAY:
                        case MONO_TYPE_CLASS:
@@ -525,7 +629,7 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                                MonoClass *fclass = mono_class_from_mono_type (field->type);
                                if (fclass->has_references) {
                                        /* remove the object header */
-                                       compute_class_bitmap (fclass, bitmap, size, pos - (sizeof (MonoObject) / sizeof (gpointer)), max_set);
+                                       compute_class_bitmap (fclass, bitmap, size, pos - (sizeof (MonoObject) / sizeof (gpointer)), max_set, FALSE);
                                }
                                break;
                        }
@@ -547,10 +651,154 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                                break;
                        }
                }
+               if (static_fields)
+                       break;
+       }
+       return bitmap;
+}
+
+#if 0
+/* 
+ * similar to the above, but sets the bits in the bitmap for any non-ref field
+ * and ignores static fields
+ */
+static gsize*
+compute_class_non_ref_bitmap (MonoClass *class, gsize *bitmap, int size, int offset)
+{
+       MonoClassField *field;
+       MonoClass *p;
+       guint32 pos, pos2;
+       int max_size;
+
+       max_size = class->instance_size / sizeof (gpointer);
+       if (max_size >= size) {
+               bitmap = g_malloc0 (sizeof (gsize) * ((max_size) + 1));
+       }
+
+       for (p = class; p != NULL; p = p->parent) {
+               gpointer iter = NULL;
+               while ((field = mono_class_get_fields (p, &iter))) {
+                       MonoType *type;
+
+                       if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA))
+                               continue;
+                       /* FIXME: should not happen, flag as type load error */
+                       if (field->type->byref)
+                               break;
+
+                       pos = field->offset / sizeof (gpointer);
+                       pos += offset;
+
+                       type = mono_type_get_underlying_type (field->type);
+                       switch (type->type) {
+#if SIZEOF_VOID_P == 8
+                       case MONO_TYPE_I:
+                       case MONO_TYPE_U:
+                       case MONO_TYPE_PTR:
+                       case MONO_TYPE_FNPTR:
+#endif
+                       case MONO_TYPE_I8:
+                       case MONO_TYPE_U8:
+                       case MONO_TYPE_R8:
+                               if ((((field->offset + 7) / sizeof (gpointer)) + offset) != pos) {
+                                       pos2 = ((field->offset + 7) / sizeof (gpointer)) + offset;
+                                       bitmap [pos2 / BITMAP_EL_SIZE] |= ((gsize)1) << (pos2 % BITMAP_EL_SIZE);
+                               }
+                               /* fall through */
+#if SIZEOF_VOID_P == 4
+                       case MONO_TYPE_I:
+                       case MONO_TYPE_U:
+                       case MONO_TYPE_PTR:
+                       case MONO_TYPE_FNPTR:
+#endif
+                       case MONO_TYPE_I4:
+                       case MONO_TYPE_U4:
+                       case MONO_TYPE_R4:
+                               if ((((field->offset + 3) / sizeof (gpointer)) + offset) != pos) {
+                                       pos2 = ((field->offset + 3) / sizeof (gpointer)) + offset;
+                                       bitmap [pos2 / BITMAP_EL_SIZE] |= ((gsize)1) << (pos2 % BITMAP_EL_SIZE);
+                               }
+                               /* fall through */
+                       case MONO_TYPE_CHAR:
+                       case MONO_TYPE_I2:
+                       case MONO_TYPE_U2:
+                               if ((((field->offset + 1) / sizeof (gpointer)) + offset) != pos) {
+                                       pos2 = ((field->offset + 1) / sizeof (gpointer)) + offset;
+                                       bitmap [pos2 / BITMAP_EL_SIZE] |= ((gsize)1) << (pos2 % BITMAP_EL_SIZE);
+                               }
+                               /* fall through */
+                       case MONO_TYPE_BOOLEAN:
+                       case MONO_TYPE_I1:
+                       case MONO_TYPE_U1:
+                               bitmap [pos / BITMAP_EL_SIZE] |= ((gsize)1) << (pos % BITMAP_EL_SIZE);
+                               break;
+                       case MONO_TYPE_STRING:
+                       case MONO_TYPE_SZARRAY:
+                       case MONO_TYPE_CLASS:
+                       case MONO_TYPE_OBJECT:
+                       case MONO_TYPE_ARRAY:
+                               break;
+                       case MONO_TYPE_GENERICINST:
+                               if (!mono_type_generic_inst_is_valuetype (type)) {
+                                       break;
+                               } else {
+                                       /* fall through */
+                               }
+                       case MONO_TYPE_VALUETYPE: {
+                               MonoClass *fclass = mono_class_from_mono_type (field->type);
+                               /* remove the object header */
+                               compute_class_non_ref_bitmap (fclass, bitmap, size, pos - (sizeof (MonoObject) / sizeof (gpointer)));
+                               break;
+                       }
+                       default:
+                               g_assert_not_reached ();
+                               break;
+                       }
+               }
        }
        return bitmap;
 }
 
+/**
+ * mono_class_insecure_overlapping:
+ * check if a class with explicit layout has references and non-references
+ * fields overlapping.
+ *
+ * Returns: TRUE if it is insecure to load the type.
+ */
+gboolean
+mono_class_insecure_overlapping (MonoClass *klass)
+{
+       int max_set = 0;
+       gsize *bitmap;
+       gsize default_bitmap [4] = {0};
+       gsize *nrbitmap;
+       gsize default_nrbitmap [4] = {0};
+       int i, insecure = FALSE;
+               return FALSE;
+
+       bitmap = compute_class_bitmap (klass, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, FALSE);
+       nrbitmap = compute_class_non_ref_bitmap (klass, default_nrbitmap, sizeof (default_nrbitmap) * 8, 0);
+
+       for (i = 0; i <= max_set; i += sizeof (bitmap [0]) * 8) {
+               int idx = i % (sizeof (bitmap [0]) * 8);
+               if (bitmap [idx] & nrbitmap [idx]) {
+                       insecure = TRUE;
+                       break;
+               }
+       }
+       if (bitmap != default_bitmap)
+               g_free (bitmap);
+       if (nrbitmap != default_nrbitmap)
+               g_free (nrbitmap);
+       if (insecure) {
+               g_print ("class %s.%s in assembly %s has overlapping references\n", klass->name_space, klass->name, klass->image->name);
+               return FALSE;
+       }
+       return insecure;
+}
+#endif
+
 static void
 mono_class_compute_gc_descriptor (MonoClass *class)
 {
@@ -604,7 +852,7 @@ mono_class_compute_gc_descriptor (MonoClass *class)
                                class->name_space, class->name);*/
                } else {
                        /* remove the object header */
-                       bitmap = compute_class_bitmap (class->element_class, default_bitmap, sizeof (default_bitmap) * 8, - (sizeof (MonoObject) / sizeof (gpointer)), &max_set);
+                       bitmap = compute_class_bitmap (class->element_class, default_bitmap, sizeof (default_bitmap) * 8, - (sizeof (MonoObject) / sizeof (gpointer)), &max_set, FALSE);
                        class->gc_descr = mono_gc_make_descr_for_array (TRUE, bitmap, mono_array_element_size (class) / sizeof (gpointer), mono_array_element_size (class));
                        /*printf ("new vt array descriptor: 0x%x for %s.%s\n", class->gc_descr,
                                class->name_space, class->name);*/
@@ -616,7 +864,7 @@ mono_class_compute_gc_descriptor (MonoClass *class)
                /*static int count = 0;
                if (count++ > 58)
                        return;*/
-               bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set);
+               bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, FALSE);
 #ifdef HAVE_BOEHM_GC
                /* It seems there are issues when the bitmap doesn't fit: play it safe */
                if (max_set >= 30) {
@@ -699,7 +947,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
        char *t;
        int i;
        gboolean inited = FALSE;
-       guint32 vtable_size;
+       guint32 vtable_size, class_size;
        guint32 cindex;
        guint32 constant_cols [MONO_CONSTANT_SIZE];
        gpointer iter;
@@ -711,11 +959,21 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
                mono_domain_unlock (domain);
                return runtime_info->domain_vtables [domain->domain_id];
        }
-       if (!class->inited)
-               mono_class_init (class);
+       if (!class->inited || class->exception_type) {
+               if (!mono_class_init (class) || class->exception_type){
+                       MonoException *exc;
+                       mono_domain_unlock (domain);
+                       exc = mono_class_get_exception_for_failure (class);
+                       g_assert (exc);
+                       mono_raise_exception (exc);
+               }
+       }
 
-       mono_class_setup_vtable (class);
+       mono_class_init (class);
 
+       /* FIXME: This should be done by mono_class_init () for dynamic classes as well */
+       if (class->image->dynamic)
+               mono_class_setup_vtable (class);
 
        vtable_size = sizeof (gpointer) * (class->max_interface_id + 1) +
                sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
@@ -749,14 +1007,24 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
 #endif
                vt->gc_descr = class->gc_descr;
 
-       if (class->class_size) {
+       if ((class_size = mono_class_data_size (class))) {
                if (class->has_static_refs) {
-                       vt->data = mono_gc_alloc_fixed (class->class_size, NULL);
+                       gpointer statics_gc_descr;
+                       int max_set = 0;
+                       gsize default_bitmap [4] = {0};
+                       gsize *bitmap;
+
+                       bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, TRUE);
+                       /*g_print ("bitmap 0x%x for %s.%s (size: %d)\n", bitmap [0], class->name_space, class->name, class_size);*/
+                       statics_gc_descr = mono_gc_make_descr_from_bitmap (bitmap, max_set? max_set + 1: 0);
+                       vt->data = mono_gc_alloc_fixed (class_size, statics_gc_descr);
                        mono_domain_add_class_static_data (domain, class, vt->data, NULL);
+                       if (bitmap != default_bitmap)
+                               g_free (bitmap);
                } else {
-                       vt->data = mono_mempool_alloc0 (domain->mp, class->class_size);
+                       vt->data = mono_mempool_alloc0 (domain->mp, class_size);
                }
-               mono_stats.class_static_data_size += class->class_size;
+               mono_stats.class_static_data_size += class_size;
        }
 
        cindex = -1;
@@ -770,7 +1038,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
                        gint32 special_static = class->no_special_static_fields ? SPECIAL_STATIC_NONE : field_is_special_static (class, field);
                        if (special_static != SPECIAL_STATIC_NONE) {
                                guint32 size, offset;
-                               int align;
+                               gint32 align;
                                size = mono_type_size (field->type, &align);
                                offset = mono_alloc_special_static_data (special_static, size, align);
                                if (!domain->special_static_fields)
@@ -1100,6 +1368,22 @@ create_remote_class_key (MonoRemoteClass *remote_class, MonoClass *extra_class)
        return key;
 }
 
+/**
+ * copy_remote_class_key:
+ *
+ *   Make a copy of KEY in the mempool MP and return the copy.
+ */
+static gpointer*
+copy_remote_class_key (MonoMemPool *mp, gpointer *key)
+{
+       int key_size = (GPOINTER_TO_UINT (key [0]) + 1) * sizeof (gpointer);
+       gpointer *mp_key = mono_mempool_alloc (mp, key_size);
+
+       memcpy (mp_key, key, key_size);
+
+       return mp_key;
+}
+
 /**
  * mono_remote_class:
  * @domain: the application domain
@@ -1112,7 +1396,7 @@ MonoRemoteClass*
 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
 {
        MonoRemoteClass *rc;
-       gpointer* key;
+       gpointer* key, *mp_key;
        
        key = create_remote_class_key (NULL, proxy_class);
        
@@ -1125,6 +1409,10 @@ mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_
                return rc;
        }
 
+       mp_key = copy_remote_class_key (domain->mp, key);
+       g_free (key);
+       key = mp_key;
+
        if (proxy_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
                rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*));
                rc->interface_count = 1;
@@ -1138,7 +1426,7 @@ mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_
        
        rc->default_vtable = NULL;
        rc->xdomain_vtable = NULL;
-       rc->proxy_class_name = mono_string_to_utf8 (class_name);
+       rc->proxy_class_name = mono_string_to_utf8_mp (domain->mp, class_name);
 
        g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
 
@@ -1154,7 +1442,7 @@ static MonoRemoteClass*
 clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass *extra_class)
 {
        MonoRemoteClass *rc;
-       gpointer* key;
+       gpointer* key, *mp_key;
        
        key = create_remote_class_key (remote_class, extra_class);
        rc = g_hash_table_lookup (domain->proxy_vtable_hash, key);
@@ -1163,6 +1451,10 @@ clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass
                return rc;
        }
 
+       mp_key = copy_remote_class_key (domain->mp, key);
+       g_free (key);
+       key = mp_key;
+
        if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
                int i,j;
                rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*) * (remote_class->interface_count + 1));
@@ -1206,8 +1498,16 @@ mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mon
                mono_domain_unlock (domain);
                return remote_class->xdomain_vtable;
        }
-       if (remote_class->default_vtable == NULL)
-               remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN);
+       if (remote_class->default_vtable == NULL) {
+               MonoType *type;
+               MonoClass *klass;
+               type = ((MonoReflectionType *)rp->class_to_proxy)->type;
+               klass = mono_class_from_mono_type (type);
+               if ((klass->is_com_object || (mono_defaults.com_object_class && klass == mono_defaults.com_object_class)) && !mono_class_vtable (mono_domain_get (), klass)->remote)
+                       remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_COMINTEROP);
+               else
+                       remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN);
+       }
        
        mono_domain_unlock (domain);
        return remote_class->default_vtable;
@@ -1414,13 +1714,17 @@ handle_enum:
        case MONO_TYPE_CLASS:
        case MONO_TYPE_OBJECT:
        case MONO_TYPE_ARRAY:
+               mono_gc_wbarrier_generic_store (dest, deref_pointer? *(gpointer*)value: value);
+               return;
+       case MONO_TYPE_FNPTR:
        case MONO_TYPE_PTR: {
                gpointer *p = (gpointer*)dest;
                *p = deref_pointer? *(gpointer*)value: value;
                return;
        }
        case MONO_TYPE_VALUETYPE:
-               if (type->data.klass->enumtype) {
+               /* note that 't' and 'type->type' can be different */
+               if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
                        t = type->data.klass->enum_basetype->type;
                        goto handle_enum;
                } else {
@@ -1448,7 +1752,8 @@ handle_enum:
  * @value: The value to be set
  *
  * Sets the value of the field described by @field in the object instance @obj
- * to the value passed in @value.
+ * to the value passed in @value.   This method should only be used for instance
+ * fields.   For static fields, use mono_field_static_set_value.
  *
  * The value must be on the native format of the field type. 
  */
@@ -1899,6 +2204,8 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
        gchar *utf8_fullpath;
        int result;
 
+       g_assert (method != NULL);
+       
        mono_thread_set_main (mono_thread_current ());
 
        main_args = g_new0 (char*, argc);
@@ -2367,7 +2674,8 @@ mono_object_new_specific (MonoVTable *vtable)
 
        MONO_ARCH_SAVE_REGS;
        
-       if (vtable->remote)
+       /* check for is_com_object for COM Interop */
+       if (vtable->remote || vtable->klass->is_com_object)
        {
                gpointer pa [1];
                MonoMethod *im = vtable->domain->create_proxy_for_type_method;
@@ -2533,7 +2841,11 @@ mono_object_clone (MonoObject *obj)
        o = mono_object_allocate (size, obj->vtable);
        /* do not copy the sync state */
        memcpy ((char*)o + sizeof (MonoObject), (char*)obj + sizeof (MonoObject), size - sizeof (MonoObject));
-       
+
+#ifdef HAVE_SGEN_GC
+       if (obj->vtable->klass->has_references)
+               mono_gc_wbarrier_object (o);
+#endif
        mono_profiler_allocation (o, obj->vtable->klass);
 
        if (obj->vtable->klass->has_finalize)
@@ -2561,7 +2873,18 @@ mono_array_full_copy (MonoArray *src, MonoArray *dest)
        size = mono_array_length (src);
        g_assert (size == mono_array_length (dest));
        size *= mono_array_element_size (klass);
+#ifdef HAVE_SGEN_GC
+       if (klass->valuetype) {
+               if (klass->has_references)
+                       mono_value_copy_array (dest, 0, src, mono_array_length (src));
+               else
+                       memcpy (&dest->vector, &src->vector, size);
+       } else {
+               mono_array_memcpy_refs (dest, 0, src, 0, mono_array_length (src));
+       }
+#else
        memcpy (&dest->vector, &src->vector, size);
+#endif
 }
 
 /**
@@ -2587,7 +2910,18 @@ mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
                o = mono_array_new_full (domain, klass, &size, NULL);
 
                size *= mono_array_element_size (klass);
+#ifdef HAVE_SGEN_GC
+               if (klass->valuetype) {
+                       if (klass->has_references)
+                               mono_value_copy_array (o, 0, array, mono_array_length (array));
+                       else
+                               memcpy (&o->vector, &array->vector, size);
+               } else {
+                       mono_array_memcpy_refs (o, 0, array, 0, mono_array_length (array));
+               }
+#else
                memcpy (&o->vector, &array->vector, size);
+#endif
                return o;
        }
        
@@ -2599,7 +2933,18 @@ mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
                sizes [i + klass->rank] = array->bounds [i].lower_bound;
        }
        o = mono_array_new_full (domain, klass, sizes, sizes + klass->rank);
+#ifdef HAVE_SGEN_GC
+       if (klass->valuetype) {
+               if (klass->has_references)
+                       mono_value_copy_array (o, 0, array, mono_array_length (array));
+               else
+                       memcpy (&o->vector, &array->vector, size);
+       } else {
+               mono_array_memcpy_refs (o, 0, array, 0, mono_array_length (array));
+       }
+#else
        memcpy (&o->vector, &array->vector, size);
+#endif
 
        return o;
 }
@@ -2635,8 +2980,7 @@ mono_array_clone (MonoArray *array)
  * lower bounds and type.
  */
 MonoArray*
-mono_array_new_full (MonoDomain *domain, MonoClass *array_class, 
-                    guint32 *lengths, guint32 *lower_bounds)
+mono_array_new_full (MonoDomain *domain, MonoClass *array_class, guint32 *lengths, guint32 *lower_bounds)
 {
        guint32 byte_len, len, bounds_size;
        MonoObject *o;
@@ -2934,6 +3278,10 @@ mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
 
        size = size - sizeof (MonoObject);
 
+#ifdef HAVE_SGEN_GC
+       mono_gc_wbarrier_value_copy ((char *)res + sizeof (MonoObject), value, 1, class);
+#endif
+
 #if NO_UNALIGNED_ACCESS
        memcpy ((char *)res + sizeof (MonoObject), value, size);
 #else
@@ -2972,6 +3320,7 @@ void
 mono_value_copy (gpointer dest, gpointer src, MonoClass *klass)
 {
        int size = mono_class_value_size (klass, NULL);
+       mono_gc_wbarrier_value_copy (dest, src, 1, klass);
        memcpy (dest, src, size);
 }
 
@@ -2991,6 +3340,7 @@ mono_value_copy_array (MonoArray *dest, int dest_idx, gpointer src, int count)
 {
        int size = mono_array_element_size (dest->obj.vtable->klass);
        char *d = mono_array_addr_with_size (dest, size, dest_idx);
+       mono_gc_wbarrier_value_copy (d, src, count, mono_object_class (dest)->element_class);
        memmove (d, src, size * count);
 }
 
@@ -3027,13 +3377,20 @@ guint
 mono_object_get_size (MonoObject* o)
 {
        MonoClass* klass = mono_object_class (o);
-       
-       if (klass == mono_defaults.string_class)
+       if (klass == mono_defaults.string_class) {
                return sizeof (MonoString) + 2 * mono_string_length ((MonoString*) o) + 2;
-       else if (klass->parent == mono_defaults.array_class)
-               return sizeof (MonoArray) + mono_array_element_size (klass) * mono_array_length ((MonoArray*) o);
-       else
+       } else if (o->vtable->rank) {
+               MonoArray *array = (MonoArray*)o;
+               size_t size = sizeof (MonoArray) + mono_array_element_size (klass) * mono_array_length (array);
+               if (array->bounds) {
+                       size += 3;
+                       size &= ~3;
+                       size += sizeof (MonoArrayBounds) * o->vtable->rank;
+               }
+               return size;
+       } else {
                return mono_class_instance_size (klass);
+       }
 }
 
 /**
@@ -3163,6 +3520,24 @@ str_lookup (MonoDomain *domain, gpointer user_data)
        info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
 }
 
+#ifdef HAVE_SGEN_GC
+
+static MonoString*
+mono_string_get_pinned (MonoString *str)
+{
+       int size;
+       MonoString *news;
+       size = sizeof (MonoString) + 2 * (mono_string_length (str) + 1);
+       news = mono_gc_alloc_pinned_obj (((MonoObject*)str)->vtable, size);
+       memcpy (mono_string_chars (news), mono_string_chars (str), mono_string_length (str) * 2);
+       news->length = mono_string_length (str);
+       return news;
+}
+
+#else
+#define mono_string_get_pinned(str) (str)
+#endif
+
 static MonoString*
 mono_string_is_interned_lookup (MonoString *str, int insert)
 {
@@ -3178,6 +3553,7 @@ mono_string_is_interned_lookup (MonoString *str, int insert)
                return res;
        }
        if (insert) {
+               str = mono_string_get_pinned (str);
                mono_g_hash_table_insert (ldstr_table, str, str);
                ldstr_unlock ();
                return str;
@@ -3215,7 +3591,7 @@ mono_string_is_interned (MonoString *o)
 }
 
 /**
- * mono_string_interne:
+ * mono_string_intern:
  * @o: String to intern
  *
  * Interns the string passed.  
@@ -3282,6 +3658,7 @@ mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig)
                return interned;
        }
 
+       o = mono_string_get_pinned (o);
        mono_g_hash_table_insert (domain->ldstr_table, o, o);
        ldstr_unlock ();
 
@@ -3368,6 +3745,31 @@ mono_string_from_utf16 (gunichar2 *data)
        return mono_string_new_utf16 (domain, data, len);
 }
 
+/**
+ * mono_string_to_utf8_mp:
+ * @s: a System.String
+ *
+ * Same as mono_string_to_utf8, but allocate the string from a mempool.
+ */
+char *
+mono_string_to_utf8_mp (MonoMemPool *mp, MonoString *s)
+{
+       char *r = mono_string_to_utf8 (s);
+       char *mp_s;
+       int len;
+
+       if (!r)
+               return NULL;
+
+       len = strlen (r) + 1;
+       mp_s = mono_mempool_alloc (mp, len);
+       memcpy (mp_s, r, len);
+
+       g_free (r);
+
+       return mp_s;
+}
+
 static void
 default_ex_handler (MonoException *ex)
 {
@@ -3424,14 +3826,43 @@ MonoWaitHandle *
 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
 {
        MonoWaitHandle *res;
+       gpointer params [1];
+       static MonoMethod *handle_set;
 
        res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
 
-       res->handle = handle;
+       /* Even though this method is virtual, it's safe to invoke directly, since the object type matches.  */
+       if (!handle_set)
+               handle_set = mono_class_get_property_from_name (mono_defaults.waithandle_class, "Handle")->set;
+
+       params [0] = &handle;
+       mono_runtime_invoke (handle_set, res, params, NULL);
 
        return res;
 }
 
+HANDLE
+mono_wait_handle_get_handle (MonoWaitHandle *handle)
+{
+       static MonoClassField *f_os_handle;
+       static MonoClassField *f_safe_handle;
+
+       if (!f_os_handle && !f_safe_handle) {
+               f_os_handle = mono_class_get_field_from_name (mono_defaults.waithandle_class, "os_handle");
+               f_safe_handle = mono_class_get_field_from_name (mono_defaults.waithandle_class, "safe_wait_handle");
+       }
+
+       if (f_os_handle) {
+               HANDLE retval;
+               mono_field_get_value ((MonoObject*)handle, f_os_handle, &retval);
+               return retval;
+       } else {
+               MonoSafeHandle *sh;
+               mono_field_get_value ((MonoObject*)handle, f_safe_handle, &sh);
+               return sh->handle;
+       }
+}
+
 /**
  * mono_async_result_new:
  * @domain:domain where the object will be created.
@@ -3444,7 +3875,7 @@ mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
  *
  */
 MonoAsyncResult *
-mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
+mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data, MonoObject *object_data)
 {
        MonoAsyncResult *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
        MonoMethod *method = mono_get_context_capture_method ();
@@ -3456,6 +3887,7 @@ mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpo
        }
 
        res->data = data;
+       MONO_OBJECT_SETREF (res, object_data, object_data);
        MONO_OBJECT_SETREF (res, async_state, state);
        if (handle != NULL)
                MONO_OBJECT_SETREF (res, handle, (MonoObject *) mono_wait_handle_new (domain, handle));
@@ -3797,8 +4229,14 @@ mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoAr
                        case MONO_TYPE_R4:
                        case MONO_TYPE_R8:
                        case MONO_TYPE_VALUETYPE: {
-                               size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
-                               memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size); 
+                               if (arg) {
+                                       size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
+                                       memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size); 
+                               }
+                               else {
+                                       size = mono_class_value_size (mono_class_from_mono_type (pt), NULL);
+                                       memset (*((gpointer *)params [i]), 0, size);
+                               }
                                break;
                        }
                        case MONO_TYPE_STRING:
@@ -3841,12 +4279,10 @@ mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fiel
        MonoMethodMessage *msg;
        MonoArray *out_args;
        MonoObject *exc;
-       gpointer tmp;
+       char* full_name;
 
        g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
-
-       if (!res)
-               res = &tmp;
+       g_assert (res != NULL);
 
        if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
                mono_field_get_value (tp->rp->unwrapped_server, field, res);
@@ -3864,8 +4300,10 @@ mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fiel
        out_args = mono_array_new (domain, mono_defaults.object_class, 1);
        mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
 
-       mono_array_setref (msg->args, 0, mono_string_new (domain, klass->name));
+       full_name = mono_type_get_full_name (klass);
+       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
        mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
+       g_free (full_name);
 
        mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
 
@@ -3900,6 +4338,7 @@ mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *
        MonoMethodMessage *msg;
        MonoArray *out_args;
        MonoObject *exc, *res;
+       char* full_name;
 
        g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
 
@@ -3927,8 +4366,10 @@ mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *
 
        mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
 
-       mono_array_setref (msg->args, 0, mono_string_new (domain, klass->name));
+       full_name = mono_type_get_full_name (klass);
+       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
        mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
+       g_free (full_name);
 
        mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
 
@@ -3964,6 +4405,7 @@ mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fie
        MonoArray *out_args;
        MonoObject *exc;
        MonoObject *arg;
+       char* full_name;
 
        g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
 
@@ -3989,9 +4431,11 @@ mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *fie
        msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
        mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
 
-       mono_array_setref (msg->args, 0, mono_string_new (domain, klass->name));
+       full_name = mono_type_get_full_name (klass);
+       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
        mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
        mono_array_setref (msg->args, 2, arg);
+       g_free (full_name);
 
        mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
 
@@ -4017,6 +4461,7 @@ mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField
        MonoMethodMessage *msg;
        MonoArray *out_args;
        MonoObject *exc;
+       char* full_name;
 
        g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
 
@@ -4036,9 +4481,11 @@ mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField
        msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
        mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
 
-       mono_array_setref (msg->args, 0, mono_string_new (domain, klass->name));
+       full_name = mono_type_get_full_name (klass);
+       mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
        mono_array_setref (msg->args, 1, mono_string_new (domain, field->name));
        mono_array_setref (msg->args, 2, arg);
+       g_free (full_name);
 
        mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
 
@@ -4060,3 +4507,30 @@ mono_get_addr_from_ftnptr (gpointer descr)
        return descr;
 #endif
 }      
+
+#if 0
+/**
+ * mono_string_chars:
+ * @s: a MonoString
+ *
+ * Returns a pointer to the UCS16 characters stored in the MonoString
+ */
+gunichar2 *
+mono_string_chars(MonoString *s)
+{
+       /* This method is here only for documentation extraction, this is a macro */
+}
+
+/**
+ * mono_string_length:
+ * @s: MonoString
+ *
+ * Returns the lenght in characters of the string
+ */
+int
+mono_string_length (MonoString *s)
+{
+       /* This method is here only for documentation extraction, this is a macro */
+}
+
+#endif