Mark tests as not working under TARGET_JVM
[mono.git] / mono / metadata / object.c
index c7a2675759ac726eb5d0f1431b08abacc7720aaf..30d3059882003d455a157ec6adde2b4de045d58d 100644 (file)
@@ -245,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) {
@@ -561,7 +568,7 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
                max_size = mono_class_data_size (class) / sizeof (gpointer);
        else
                max_size = class->instance_size / sizeof (gpointer);
-       if (max_size > size) {
+       if (max_size >= size) {
                bitmap = g_malloc0 (sizeof (gsize) * ((max_size) + 1));
        }
 
@@ -586,13 +593,17 @@ 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:
@@ -646,6 +657,148 @@ compute_class_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int
        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)
 {
@@ -884,7 +1037,8 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class)
                if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
                        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, align;
+                               guint32 size, offset;
+                               gint32 align;
                                size = mono_type_size (field->type, &align);
                                offset = mono_alloc_special_static_data (special_static, size, align);
                                if (!domain->special_static_fields)
@@ -1349,7 +1503,7 @@ mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, Mon
                MonoClass *klass;
                type = ((MonoReflectionType *)rp->class_to_proxy)->type;
                klass = mono_class_from_mono_type (type);
-               if ((klass->is_com_object || klass == mono_defaults.com_object_class) && !mono_class_vtable (mono_domain_get (), klass)->remote)
+               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);
@@ -1569,7 +1723,8 @@ handle_enum:
                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 {
@@ -1597,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. 
  */
@@ -2685,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)
@@ -2713,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
 }
 
 /**
@@ -2739,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;
        }
        
@@ -2751,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;
 }
@@ -3085,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
@@ -3629,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.