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
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) {
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 */
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;
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) {
#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));
}
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;
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:
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;
}
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)
{
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);*/
/*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) {
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;
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);
#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;
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)
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
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);
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;
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);
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);
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));
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;
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 {
* @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.
*/
gchar *utf8_fullpath;
int result;
+ g_assert (method != NULL);
+
mono_thread_set_main (mono_thread_current ());
main_args = g_new0 (char*, argc);
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;
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;
}
* 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;
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_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);
}
{
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);
}
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);
+ }
}
/**
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)
{
return res;
}
if (insert) {
+ str = mono_string_get_pinned (str);
mono_g_hash_table_insert (ldstr_table, str, str);
ldstr_unlock ();
return str;
}
/**
- * mono_string_interne:
+ * mono_string_intern:
* @o: String to intern
*
* Interns the string passed.
return interned;
}
+ o = mono_string_get_pinned (o);
mono_g_hash_table_insert (domain->ldstr_table, o, o);
ldstr_unlock ();
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)
{
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.
*
*/
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 ();
}
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));
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:
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);
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);
MonoMethodMessage *msg;
MonoArray *out_args;
MonoObject *exc, *res;
+ char* full_name;
g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
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);
MonoArray *out_args;
MonoObject *exc;
MonoObject *arg;
+ char* full_name;
g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
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);
MonoMethodMessage *msg;
MonoArray *out_args;
MonoObject *exc;
+ char* full_name;
g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
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);
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