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) {
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));
}
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:
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)
{
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)
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);
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 {
* @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.
*/
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)
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
}
/**
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;
}
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;
}
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
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.