#include <mono/metadata/environment.h>
#include "mono/metadata/profiler-private.h"
#include "mono/metadata/security-manager.h"
+#include "mono/metadata/mono-debug-debugger.h"
#include <mono/os/gc_wrapper.h>
#include <mono/utils/strenc.h>
static MonoString*
mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig);
+#define ldstr_lock() EnterCriticalSection (&ldstr_section)
+#define ldstr_unlock() LeaveCriticalSection (&ldstr_section)
+static CRITICAL_SECTION ldstr_section;
+
void
mono_runtime_object_init (MonoObject *this)
{
} TypeInitializationLock;
/* for locking access to type_initialization_hash and blocked_thread_hash */
+#define mono_type_initialization_lock() EnterCriticalSection (&type_initialization_section)
+#define mono_type_initialization_unlock() LeaveCriticalSection (&type_initialization_section)
static CRITICAL_SECTION type_initialization_section;
/* from vtable to lock */
InitializeCriticalSection (&type_initialization_section);
type_initialization_hash = g_hash_table_new (NULL, NULL);
blocked_thread_hash = g_hash_table_new (NULL, NULL);
+ 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);
}
/*
int do_initialization = 0;
MonoDomain *last_domain = NULL;
- EnterCriticalSection (&type_initialization_section);
+ mono_type_initialization_lock ();
/* double check... */
if (vtable->initialized) {
- LeaveCriticalSection (&type_initialization_section);
+ mono_type_initialization_unlock ();
return;
}
lock = g_hash_table_lookup (type_initialization_hash, vtable);
last_domain = mono_domain_get ();
if (!mono_domain_set (domain, FALSE)) {
vtable->initialized = 1;
- LeaveCriticalSection (&type_initialization_section);
+ mono_type_initialization_unlock ();
mono_raise_exception (mono_get_exception_appdomain_unloaded ());
}
}
TypeInitializationLock *pending_lock;
if (lock->initializing_tid == tid || lock->done) {
- LeaveCriticalSection (&type_initialization_section);
+ mono_type_initialization_unlock ();
return;
}
/* see if the thread doing the initialization is already blocked on this thread */
while ((pending_lock = (TypeInitializationLock*) g_hash_table_lookup (blocked_thread_hash, blocked))) {
if (pending_lock->initializing_tid == tid) {
if (!pending_lock->done) {
- LeaveCriticalSection (&type_initialization_section);
+ mono_type_initialization_unlock ();
return;
} else {
/* the thread doing the initialization is blocked on this thread,
/* record the fact that we are waiting on the initializing thread */
g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock);
}
- LeaveCriticalSection (&type_initialization_section);
+ mono_type_initialization_unlock ();
if (do_initialization) {
mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
LeaveCriticalSection (&lock->initialization_section);
}
- EnterCriticalSection (&type_initialization_section);
+ mono_type_initialization_lock ();
if (lock->initializing_tid != tid)
g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
--lock->waiting_count;
}
vtable->initialized = 1;
/* FIXME: if the cctor fails, the type must be marked as unusable */
- LeaveCriticalSection (&type_initialization_section);
+ mono_type_initialization_unlock ();
} else {
vtable->initialized = 1;
return;
void
mono_release_type_locks (MonoThread *thread)
{
- EnterCriticalSection (&type_initialization_section);
- g_hash_table_foreach_remove (type_initialization_hash, release_type_locks, GUINT_TO_POINTER (thread->tid));
- LeaveCriticalSection (&type_initialization_section);
+ mono_type_initialization_lock ();
+ g_hash_table_foreach_remove (type_initialization_hash, release_type_locks, (gpointer)(gsize)(thread->tid));
+ mono_type_initialization_unlock ();
}
static gpointer
return NULL;
}
+static gpointer
+default_delegate_trampoline (MonoMethod *method, gpointer addr)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
static MonoRemotingTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
+static MonoDelegateTrampoline arch_create_delegate_trampoline = default_delegate_trampoline;
void
mono_install_trampoline (MonoTrampoline func)
arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
}
+void
+mono_install_delegate_trampoline (MonoDelegateTrampoline func)
+{
+ arch_create_delegate_trampoline = func? func: default_delegate_trampoline;
+}
+
static MonoCompileFunc default_mono_compile_method = NULL;
/**
#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);
+ 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;
case MONO_TYPE_U:
case MONO_TYPE_PTR:
case MONO_TYPE_FNPTR:
+#ifdef HAVE_SGEN_GC
+ break;
+#endif
case MONO_TYPE_STRING:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_CLASS:
bitmap [pos / BITMAP_EL_SIZE] |= ((gsize)1) << (pos % BITMAP_EL_SIZE);
*max_set = MAX (*max_set, pos);
break;
+ case MONO_TYPE_GENERICINST:
+ if (!mono_type_generic_inst_is_valuetype (type)) {
+ g_assert ((field->offset % sizeof(gpointer)) == 0);
+
+ bitmap [pos / BITMAP_EL_SIZE] |= ((gsize)1) << (pos % BITMAP_EL_SIZE);
+ *max_set = MAX (*max_set, pos);
+ break;
+ } else {
+ /* fall through */
+ }
case MONO_TYPE_VALUETYPE: {
- MonoClass *fclass = field->type->data.klass;
+ 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;
}
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;
+ gpointer *interface_offsets;
mono_domain_lock (domain);
runtime_info = class->runtime_info;
return runtime_info->domain_vtables [domain->domain_id];
}
if (!class->inited)
- mono_class_init (class);
+ if (!mono_class_init (class)){
+ MonoException *exc;
+ mono_domain_unlock (domain);
+ exc = mono_class_get_exception_for_failure (class);
+ g_assert (exc);
+ mono_raise_exception (exc);
+ }
- mono_stats.used_class_count++;
- mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
+ mono_class_init (class);
- vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
+ /* 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);
- vt = mono_mempool_alloc0 (domain->mp, vtable_size);
+ mono_stats.used_class_count++;
+ mono_stats.class_vtable_size += vtable_size;
+ interface_offsets = mono_mempool_alloc0 (domain->mp, vtable_size);
+ vt = (MonoVTable*) (interface_offsets + class->max_interface_id + 1);
vt->klass = class;
vt->rank = class->rank;
vt->domain = domain;
#endif
vt->gc_descr = class->gc_descr;
- if (class->class_size) {
- if (class->has_static_refs)
- vt->data = mono_gc_alloc_fixed (class->class_size, NULL);
- else
- vt->data = mono_mempool_alloc0 (domain->mp, class->class_size);
- mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
- mono_stats.class_static_data_size += class->class_size;
+ if ((class_size = mono_class_data_size (class))) {
+ if (class->has_static_refs) {
+ 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_size);
+ }
+ mono_stats.class_static_data_size += class_size;
}
cindex = -1;
if (mono_field_is_deleted (field))
continue;
if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
- gint32 special_static = field_is_special_static (class, field);
+ 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, align, offset;
+ guint32 size, offset;
+ int align;
size = mono_type_size (field->type, &align);
offset = mono_alloc_special_static_data (special_static, size, align);
if (!domain->special_static_fields)
memcpy (t, field->data, mono_class_value_size (fklass, NULL));
} else {
/* it's a pointer type: add check */
- g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
+ g_assert ((fklass->byval_arg.type == MONO_TYPE_PTR) || (fklass->byval_arg.type == MONO_TYPE_FNPTR));
*t = *(char *)field->data;
}
continue;
vt->max_interface_id = class->max_interface_id;
- vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
- sizeof (gpointer) * (class->max_interface_id + 1));
-
/* initialize interface offsets */
for (i = 0; i <= class->max_interface_id; ++i) {
int slot = class->interface_offsets [i];
if (slot >= 0)
- vt->interface_offsets [i] = &(vt->vtable [slot]);
+ interface_offsets [class->max_interface_id - i] = &(vt->vtable [slot]);
}
/*
/* FIXME: class_vtable_hash is basically obsolete now: remove as soon
* as we change the code in appdomain.c to invalidate vtables by
* looking at the possible MonoClasses created for the domain.
- * Or we can reuse static_data_hash, by using vtable as a key
- * and always inserting into that hash.
*/
g_hash_table_insert (domain->class_vtable_hash, class, vt);
/* class->runtime_info is protected by the loader lock, both when
MonoVTable *vt, *pvt;
int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
MonoClass *k;
+ GSList *extra_interfaces = NULL;
MonoClass *class = remote_class->proxy_class;
+ gpointer *interface_offsets;
vt = mono_class_vtable (domain, class);
max_interface_id = vt->max_interface_id;
-
+
/* Calculate vtable space for extra interfaces */
for (j = 0; j < remote_class->interface_count; j++) {
MonoClass* iclass = remote_class->interfaces[j];
- int method_count = mono_class_num_methods (iclass);
-
- if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
- continue; /* interface implemented by the class */
+ GPtrArray *ifaces;
+ int method_count;
- for (i = 0; i < iclass->interface_count; i++)
- method_count += mono_class_num_methods (iclass->interfaces[i]);
+ if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != -1)
+ continue; /* interface implemented by the class */
+ if (g_slist_find (extra_interfaces, iclass))
+ continue;
+
+ extra_interfaces = g_slist_prepend (extra_interfaces, iclass);
+
+ method_count = mono_class_num_methods (iclass);
+
+ ifaces = mono_class_get_implemented_interfaces (iclass);
+ if (ifaces) {
+ for (i = 0; i < ifaces->len; ++i) {
+ MonoClass *ic = g_ptr_array_index (ifaces, i);
+ if (ic->interface_id <= class->max_interface_id && class->interface_offsets[ic->interface_id] != -1)
+ continue; /* interface implemented by the class */
+ if (g_slist_find (extra_interfaces, ic))
+ continue;
+ extra_interfaces = g_slist_prepend (extra_interfaces, ic);
+ method_count += mono_class_num_methods (ic);
+ }
+ g_ptr_array_free (ifaces, TRUE);
+ }
extra_interface_vtsize += method_count * sizeof (gpointer);
if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
}
- vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
+ vtsize = sizeof (gpointer) * (max_interface_id + 1) +
+ sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
- pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
- memcpy (pvt, vt, vtsize);
+ interface_offsets = mono_mempool_alloc0 (domain->mp, vtsize + extra_interface_vtsize);
+ pvt = (MonoVTable*)(interface_offsets + max_interface_id + 1);
+ memcpy (pvt, vt, sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer));
pvt->klass = mono_defaults.transparent_proxy_class;
/* we need to keep the GC descriptor for a transparent proxy or we confuse the precise GC */
}
pvt->max_interface_id = max_interface_id;
- pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
- sizeof (gpointer) * (max_interface_id + 1));
/* initialize interface offsets */
for (i = 0; i <= class->max_interface_id; ++i) {
int slot = class->interface_offsets [i];
if (slot >= 0)
- pvt->interface_offsets [i] = &(pvt->vtable [slot]);
+ interface_offsets [max_interface_id - i] = &(pvt->vtable [slot]);
}
- if (remote_class->interface_count > 0)
- {
+ if (extra_interfaces) {
int slot = class->vtable_size;
MonoClass* interf;
- MonoClass* iclass;
- int n;
+ gpointer iter;
+ MonoMethod* cm;
+ GSList *list_item;
/* Create trampolines for the methods of the interfaces */
- for (n = 0; n < remote_class->interface_count; n++)
- {
- iclass = remote_class->interfaces[n];
- if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
- continue; /* interface implemented by the class */
-
- i = -1;
- interf = iclass;
- do {
- MonoMethod* cm;
- gpointer iter;
-
- pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
-
- iter = NULL;
- j = 0;
- while ((cm = mono_class_get_methods (interf, &iter)))
- pvt->vtable [slot + j++] = arch_create_remoting_trampoline (cm, target_type);
-
- slot += mono_class_num_methods (interf);
- if (++i < iclass->interface_count) interf = iclass->interfaces[i];
- else interf = NULL;
-
- } while (interf);
+ for (list_item = extra_interfaces; list_item != NULL; list_item=list_item->next) {
+ interf = list_item->data;
+ interface_offsets [max_interface_id - interf->interface_id] = &pvt->vtable [slot];
+
+ iter = NULL;
+ j = 0;
+ while ((cm = mono_class_get_methods (interf, &iter)))
+ pvt->vtable [slot + j++] = arch_create_remoting_trampoline (cm, target_type);
+
+ slot += mono_class_num_methods (interf);
}
+ g_slist_free (extra_interfaces);
}
return pvt;
}
+/**
+ * mono_class_has_special_static_fields:
+ *
+ * Returns whenever @klass has any thread/context static fields.
+ */
+gboolean
+mono_class_has_special_static_fields (MonoClass *klass)
+{
+ MonoClassField *field;
+ gpointer iter;
+
+ iter = NULL;
+ while ((field = mono_class_get_fields (klass, &iter))) {
+ if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
+ continue;
+ if (mono_field_is_deleted (field))
+ continue;
+ if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
+ if (field_is_special_static (klass, field) != SPECIAL_STATIC_NONE)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * create_remote_class_key:
+ * Creates an array of pointers that can be used as a hash key for a remote class.
+ * The first element of the array is the number of pointers.
+ */
+static gpointer*
+create_remote_class_key (MonoRemoteClass *remote_class, MonoClass *extra_class)
+{
+ gpointer *key;
+ int i, j;
+
+ if (remote_class == NULL) {
+ if (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ key = g_malloc (sizeof(gpointer) * 3);
+ key [0] = GINT_TO_POINTER (2);
+ key [1] = mono_defaults.marshalbyrefobject_class;
+ key [2] = extra_class;
+ } else {
+ key = g_malloc (sizeof(gpointer) * 2);
+ key [0] = GINT_TO_POINTER (1);
+ key [1] = extra_class;
+ }
+ } else {
+ if (extra_class != NULL && (extra_class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+ key = g_malloc (sizeof(gpointer) * (remote_class->interface_count + 3));
+ key [0] = GINT_TO_POINTER (remote_class->interface_count + 2);
+ key [1] = remote_class->proxy_class;
+
+ // Keep the list of interfaces sorted
+ for (i = 0, j = 2; i < remote_class->interface_count; i++, j++) {
+ if (extra_class && remote_class->interfaces [i] > extra_class) {
+ key [j++] = extra_class;
+ extra_class = NULL;
+ }
+ key [j] = remote_class->interfaces [i];
+ }
+ if (extra_class)
+ key [j] = extra_class;
+ } else {
+ // Replace the old class. The interface list is the same
+ key = g_malloc (sizeof(gpointer) * (remote_class->interface_count + 2));
+ key [0] = GINT_TO_POINTER (remote_class->interface_count + 1);
+ key [1] = extra_class != NULL ? extra_class : remote_class->proxy_class;
+ for (i = 0; i < remote_class->interface_count; i++)
+ key [2 + i] = remote_class->interfaces [i];
+ }
+ }
+
+ 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, *mp_key;
+
+ key = create_remote_class_key (NULL, proxy_class);
+
mono_domain_lock (domain);
- rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class_name);
+ rc = g_hash_table_lookup (domain->proxy_vtable_hash, key);
if (rc) {
+ g_free (key);
mono_domain_unlock (domain);
return rc;
}
- rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
+ 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->interfaces [0] = proxy_class;
+ rc->proxy_class = mono_defaults.marshalbyrefobject_class;
+ } else {
+ rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
+ rc->interface_count = 0;
+ rc->proxy_class = proxy_class;
+ }
+
rc->default_vtable = NULL;
rc->xdomain_vtable = NULL;
- rc->interface_count = 0;
- rc->interfaces = NULL;
- rc->proxy_class = mono_defaults.marshalbyrefobject_class;
- rc->proxy_class_name = mono_string_to_utf8 (class_name);
+ rc->proxy_class_name = mono_string_to_utf8_mp (domain->mp, class_name);
- mono_g_hash_table_insert (domain->proxy_vtable_hash, class_name, rc);
- mono_upgrade_remote_class (domain, rc, proxy_class);
+ g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
mono_domain_unlock (domain);
-
return rc;
}
-static void
-extend_interface_array (MonoDomain *domain, MonoRemoteClass *remote_class, int amount)
+/**
+ * clone_remote_class:
+ * Creates a copy of the remote_class, adding the provided class or interface
+ */
+static MonoRemoteClass*
+clone_remote_class (MonoDomain *domain, MonoRemoteClass* remote_class, MonoClass *extra_class)
{
- /* Extends the array of interfaces. Memory is extended using blocks of 5 pointers */
+ MonoRemoteClass *rc;
+ gpointer* key, *mp_key;
+
+ key = create_remote_class_key (remote_class, extra_class);
+ rc = g_hash_table_lookup (domain->proxy_vtable_hash, key);
+ if (rc != NULL) {
+ g_free (key);
+ return rc;
+ }
- int current_size = ((remote_class->interface_count / 5) + 1) * 5;
- remote_class->interface_count += amount;
+ mp_key = copy_remote_class_key (domain->mp, key);
+ g_free (key);
+ key = mp_key;
- if (remote_class->interface_count > current_size || remote_class->interfaces == NULL)
- {
- int new_size = ((remote_class->interface_count / 5) + 1) * 5;
- MonoClass **new_array = mono_mempool_alloc (domain->mp, new_size * sizeof (MonoClass*));
-
- if (remote_class->interfaces != NULL)
- memcpy (new_array, remote_class->interfaces, current_size * sizeof (MonoClass*));
+ 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));
+ rc->proxy_class = remote_class->proxy_class;
+ rc->interface_count = remote_class->interface_count + 1;
- remote_class->interfaces = new_array;
+ // Keep the list of interfaces sorted, since the hash key of
+ // the remote class depends on this
+ for (i = 0, j = 0; i < remote_class->interface_count; i++, j++) {
+ if (remote_class->interfaces [i] > extra_class && i == j)
+ rc->interfaces [j++] = extra_class;
+ rc->interfaces [j] = remote_class->interfaces [i];
+ }
+ if (i == j)
+ rc->interfaces [j] = extra_class;
+ } else {
+ // Replace the old class. The interface array is the same
+ rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass) + sizeof(MonoClass*) * remote_class->interface_count);
+ rc->proxy_class = extra_class;
+ rc->interface_count = remote_class->interface_count;
+ if (rc->interface_count > 0)
+ memcpy (rc->interfaces, remote_class->interfaces, rc->interface_count * sizeof (MonoClass*));
}
+
+ rc->default_vtable = NULL;
+ rc->xdomain_vtable = NULL;
+ rc->proxy_class_name = remote_class->proxy_class_name;
+
+ g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
+
+ return rc;
}
gpointer
mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *rp)
{
+ mono_domain_lock (domain);
if (rp->target_domain_id != -1) {
if (remote_class->xdomain_vtable == NULL)
remote_class->xdomain_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_APPDOMAIN);
+ 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 || 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;
}
-
/**
* mono_upgrade_remote_class:
* @domain: the application domain
- * @remote_class: the remote class
+ * @tproxy: the proxy whose remote class has to be upgraded.
* @klass: class to which the remote class can be casted.
*
* Updates the vtable of the remote class by adding the necessary method slots
* and interface offsets so it can be safely casted to klass. klass can be a
* class or an interface.
*/
-void mono_upgrade_remote_class (MonoDomain *domain, MonoRemoteClass *remote_class, MonoClass *klass)
+void
+mono_upgrade_remote_class (MonoDomain *domain, MonoObject *proxy_object, MonoClass *klass)
{
+ MonoTransparentProxy *tproxy;
+ MonoRemoteClass *remote_class;
gboolean redo_vtable;
mono_domain_lock (domain);
+ tproxy = (MonoTransparentProxy*) proxy_object;
+ remote_class = tproxy->remote_class;
+
if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
int i;
redo_vtable = TRUE;
- for (i = 0; i < remote_class->interface_count; i++)
- if (remote_class->interfaces[i] == klass) redo_vtable = FALSE;
-
- if (redo_vtable) {
- extend_interface_array (domain, remote_class, 1);
- remote_class->interfaces [remote_class->interface_count-1] = klass;
- }
+ for (i = 0; i < remote_class->interface_count && redo_vtable; i++)
+ if (remote_class->interfaces [i] == klass)
+ redo_vtable = FALSE;
}
else {
redo_vtable = (remote_class->proxy_class != klass);
- remote_class->proxy_class = klass;
}
if (redo_vtable) {
- remote_class->default_vtable = NULL;
- remote_class->xdomain_vtable = NULL;
+ tproxy->remote_class = clone_remote_class (domain, remote_class, klass);
+ proxy_object->vtable = mono_remote_class_vtable (domain, tproxy->remote_class, tproxy->rp);
}
-/*
- int n;
- printf ("remote class upgrade - class:%s num-interfaces:%d\n", remote_class->proxy_class_name, remote_class->interface_count);
- for (n=0; n<remote_class->interface_count; n++)
- printf (" I:%s\n", remote_class->interfaces[n]->name);
-*/
-
mono_domain_unlock (domain);
}
+
/**
* mono_object_get_virtual_method:
* @obj: object to operate on.
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;
goto handle_enum;
} else {
int size;
- size = mono_class_value_size (type->data.klass, NULL);
+ size = mono_class_value_size (mono_class_from_mono_type (type), NULL);
if (value == NULL)
memset (dest, 0, size);
else
memcpy (dest, value, size);
}
return;
+ case MONO_TYPE_GENERICINST:
+ t = type->data.generic_class->container_class->byval_arg.type;
+ goto handle_enum;
default:
g_warning ("got type %x", type->type);
g_assert_not_reached ();
set_value (field->type, dest, value, FALSE);
}
+/* Used by the debugger */
+void *
+mono_vtable_get_static_field_data (MonoVTable *vt)
+{
+ return vt->data;
+}
+
/**
* mono_field_get_value:
* @obj: Object instance
case MONO_TYPE_VALUETYPE:
is_ref = field->type->byref;
break;
+ case MONO_TYPE_GENERICINST:
+ is_ref = !field->type->data.generic_class->container_class->valuetype;
+ break;
default:
g_error ("type 0x%x not handled in "
"mono_field_get_value_object", field->type->type);
return default_mono_runtime_invoke (prop->get, obj, params, exc);
}
+/*
+ * mono_nullable_init:
+ * @buf: The nullable structure to initialize.
+ * @value: the value to initialize from
+ * @klass: the type for the object
+ *
+ * Initialize the nullable structure pointed to by @buf from @value which
+ * should be a boxed value type. The size of @buf should be able to hold
+ * as much data as the @klass->instance_size (which is the number of bytes
+ * that will be copies).
+ *
+ * Since Nullables have variable structure, we can not define a C
+ * structure for them.
+ */
+void
+mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
+{
+ MonoClass *param_class = klass->cast_class;
+
+ g_assert (mono_class_from_mono_type (klass->fields [0].type) == param_class);
+ g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class);
+
+ *(guint8*)(buf + klass->fields [1].offset - sizeof (MonoObject)) = value ? 1 : 0;
+ if (value)
+ memcpy (buf + klass->fields [0].offset - sizeof (MonoObject), mono_object_unbox (value), mono_class_value_size (param_class, NULL));
+ else
+ memset (buf + klass->fields [0].offset - sizeof (MonoObject), 0, mono_class_value_size (param_class, NULL));
+}
+
+/**
+ * mono_nullable_box:
+ * @buf: The buffer representing the data to be boxed
+ * @klass: the type to box it as.
+ *
+ * Creates a boxed vtype or NULL from the Nullable structure pointed to by
+ * @buf.
+ */
+MonoObject*
+mono_nullable_box (guint8 *buf, MonoClass *klass)
+{
+ MonoClass *param_class = klass->cast_class;
+
+ g_assert (mono_class_from_mono_type (klass->fields [0].type) == param_class);
+ g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class);
+
+ if (*(guint8*)(buf + klass->fields [1].offset - sizeof (MonoObject))) {
+ MonoObject *o = mono_object_new (mono_domain_get (), param_class);
+ memcpy (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), mono_class_value_size (param_class, NULL));
+ return o;
+ }
+ else
+ return NULL;
+}
/**
* mono_get_delegate_invoke:
res = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, num_main_args);
for (i = 0; i < num_main_args; ++i)
- mono_array_set (res, gpointer, i, mono_string_new (domain, main_args [i]));
+ mono_array_setref (res, i, mono_string_new (domain, main_args [i]));
return res;
}
gchar *utf8_fullpath;
int result;
+ g_assert (method != NULL);
+
mono_thread_set_main (mono_thread_current ());
main_args = g_new0 (char*, argc);
*/
gchar *str = mono_utf8_from_external (argv [i]);
MonoString *arg = mono_string_new (domain, str);
- mono_array_set (args, gpointer, i, arg);
+ mono_array_setref (args, i, arg);
g_free (str);
}
} else {
domain = mono_object_domain (args);
if (!domain->entry_assembly) {
gchar *str;
- gchar *config_suffix;
MonoAssembly *assembly;
assembly = method->klass->image->assembly;
domain->entry_assembly = assembly;
- domain->setup->application_base = mono_string_new (domain, assembly->basedir);
+ MONO_OBJECT_SETREF (domain->setup, application_base, mono_string_new (domain, assembly->basedir));
- config_suffix = g_strconcat (assembly->aname.name, ".exe.config", NULL);
- str = g_build_filename (assembly->basedir, config_suffix, NULL);
- g_free (config_suffix);
- domain->setup->configuration_file = mono_string_new (domain, str);
+ str = g_strconcat (assembly->image->name, ".config", NULL);
+ MONO_OBJECT_SETREF (domain->setup, configuration_file, mono_string_new (domain, str));
g_free (str);
}
MonoMethodSignature *sig = mono_method_signature (method);
gpointer *pa = NULL;
int i;
-
+
if (NULL != params) {
pa = alloca (sizeof (gpointer) * mono_array_length (params));
for (i = 0; i < mono_array_length (params); i++) {
- if (sig->params [i]->byref) {
- /* nothing to do */
- }
+ MonoType *t = sig->params [i];
- switch (sig->params [i]->type) {
+ again:
+ switch (t->type) {
case MONO_TYPE_U1:
case MONO_TYPE_I1:
case MONO_TYPE_BOOLEAN:
case MONO_TYPE_R4:
case MONO_TYPE_R8:
case MONO_TYPE_VALUETYPE:
- /* MS seems to create the objects if a null is passed in */
- if (! ((gpointer *)params->vector)[i])
- ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
- pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
+ if (t->type == MONO_TYPE_VALUETYPE && mono_class_is_nullable (mono_class_from_mono_type (sig->params [i]))) {
+ if (t->byref)
+ /* FIXME: */
+ g_assert_not_reached ();
+ /* The runtime invoke wrapper needs the original boxed vtype */
+ pa [i] = (char *)(((gpointer *)params->vector)[i]);
+ } else {
+ /* MS seems to create the objects if a null is passed in */
+ if (!((gpointer *)params->vector)[i])
+ ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
+
+ if (t->byref) {
+ /*
+ * We can't pass the unboxed vtype byref to the callee, since
+ * that would mean the callee would be able to modify boxed
+ * primitive types. So we (and MS) make a copy of the boxed
+ * object, pass that to the callee, and replace the original
+ * boxed object in the arg array with the copy.
+ */
+ MonoObject *orig = mono_array_get (params, MonoObject*, i);
+ MonoObject *copy = mono_value_box (mono_domain_get (), orig->vtable->klass, mono_object_unbox (orig));
+ mono_array_setref (params, i, copy);
+ }
+
+ pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
+ }
break;
case MONO_TYPE_STRING:
case MONO_TYPE_OBJECT:
case MONO_TYPE_CLASS:
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
- if (sig->params [i]->byref)
+ if (t->byref)
pa [i] = &(((gpointer *)params->vector)[i]);
else
pa [i] = (char *)(((gpointer *)params->vector)[i]);
break;
+ case MONO_TYPE_GENERICINST:
+ t = &t->data.generic_class->container_class->byval_arg;
+ goto again;
default:
g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
}
if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
void *o = obj;
+
+ if (mono_class_is_nullable (method->klass)) {
+ /* Need to create a boxed vtype instead */
+ g_assert (!obj);
+
+ if (!params)
+ return NULL;
+ else
+ return mono_value_box (mono_domain_get (), method->klass->cast_class, pa [0]);
+ }
+
if (!obj) {
obj = mono_object_new (mono_domain_get (), method->klass);
if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
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;
mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
{
MonoArray *o;
- int size, i;
+ guint32 size, i;
guint32 *sizes;
MonoClass *klass = array->obj.vtable->klass;
byte_len = mono_array_element_size (array_class);
len = 1;
- if (array_class->rank == 1 &&
- (lower_bounds == NULL || lower_bounds [0] == 0)) {
+ /* A single dimensional array with a 0 lower bound is the same as an szarray */
+ if (array_class->rank == 1 && ((array_class->byval_arg.type == MONO_TYPE_SZARRAY) || (lower_bounds && lower_bounds [0] == 0))) {
len = lengths [0];
if ((int) len < 0)
arith_overflow ();
return res;
}
+/*
+ * mono_value_copy:
+ * @dest: destination pointer
+ * @src: source pointer
+ * @klass: a valuetype class
+ *
+ * Copy a valuetype from @src to @dest. This function must be used
+ * when @klass contains references fields.
+ */
+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);
+}
+
+/*
+ * mono_value_copy_array:
+ * @dest: destination array
+ * @dest_idx: index in the @dest array
+ * @src: source pointer
+ * @count: number of items
+ *
+ * Copy @count valuetype items from @src to @dest. This function must be used
+ * when @klass contains references fields.
+ * Overlap is handled.
+ */
+void
+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);
+}
+
/**
* mono_object_get_domain:
* @obj: object to query
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);
+ }
}
/**
vt = obj->vtable;
if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
- if ((klass->interface_id <= vt->max_interface_id) &&
- (vt->interface_offsets [klass->interface_id] != 0))
- return obj;
- }
- else {
+ if (klass->interface_id <= vt->max_interface_id) {
+ /* the interface_offsets array is stored before the vtable */
+ gpointer *interface_offsets = (gpointer*)vt;
+ if (interface_offsets [- (klass->interface_id + 1)] != NULL)
+ return obj;
+ }
+ } else {
MonoClass *oklass = vt->klass;
if ((oklass == mono_defaults.transparent_proxy_class))
oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
if (*(MonoBoolean *) mono_object_unbox(res)) {
/* Update the vtable of the remote type, so it can safely cast to this new type */
- mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
- obj->vtable = mono_remote_class_vtable (domain, ((MonoTransparentProxy *)obj)->remote_class, (MonoRealProxy *)rp);
+ mono_upgrade_remote_class (domain, obj, klass);
return obj;
}
}
LDStrInfo *info = user_data;
if (info->res || domain == info->orig_domain)
return;
- mono_domain_lock (domain);
info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
- mono_domain_unlock (domain);
}
+#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)
{
domain = ((MonoObject *)str)->vtable->domain;
ldstr_table = domain->ldstr_table;
- mono_domain_lock (domain);
+ ldstr_lock ();
if ((res = mono_g_hash_table_lookup (ldstr_table, str))) {
- mono_domain_unlock (domain);
+ ldstr_unlock ();
return res;
}
if (insert) {
+ str = mono_string_get_pinned (str);
mono_g_hash_table_insert (ldstr_table, str, str);
- mono_domain_unlock (domain);
+ ldstr_unlock ();
return str;
} else {
LDStrInfo ldstr_info;
* intern it in the current one as well.
*/
mono_g_hash_table_insert (ldstr_table, str, str);
- mono_domain_unlock (domain);
+ ldstr_unlock ();
return str;
}
}
- mono_domain_unlock (domain);
+ ldstr_unlock ();
return NULL;
}
}
}
#endif
- mono_domain_lock (domain);
+ ldstr_lock ();
if ((interned = mono_g_hash_table_lookup (domain->ldstr_table, o))) {
- mono_domain_unlock (domain);
+ ldstr_unlock ();
/* o will get garbage collected */
return interned;
}
+ o = mono_string_get_pinned (o);
mono_g_hash_table_insert (domain->ldstr_table, o, o);
- mono_domain_unlock (domain);
+ ldstr_unlock ();
return o;
}
as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
if (error) {
- g_warning (error->message);
+ MonoException *exc = mono_get_exception_argument ("string", error->message);
g_error_free (error);
+ mono_raise_exception(exc);
}
return as;
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)
{
*/
if (((MonoObject*)ex)->vtable->klass == mono_defaults.threadabortexception_class)
- mono_thread_current ()->abort_exc = ex;
+ MONO_OBJECT_SETREF (mono_thread_current (), abort_exc, ex);
ex_handler (ex);
}
*
*/
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 *res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
+ MonoMethod *method = mono_get_context_capture_method ();
- res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
+ /* we must capture the execution context from the original thread */
+ if (method) {
+ MONO_OBJECT_SETREF (res, execution_context, mono_runtime_invoke (method, NULL, NULL, NULL));
+ /* note: result may be null if the flow is suppressed */
+ }
res->data = data;
- res->async_state = state;
+ MONO_OBJECT_SETREF (res, object_data, object_data);
+ MONO_OBJECT_SETREF (res, async_state, state);
if (handle != NULL)
- res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
+ MONO_OBJECT_SETREF (res, handle, (MonoObject *) mono_wait_handle_new (domain, handle));
res->sync_completed = FALSE;
res->completed = FALSE;
char **names;
guint8 arg_type;
- this->method = method;
+ MONO_OBJECT_SETREF (this, method, method);
- this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
- this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
+ MONO_OBJECT_SETREF (this, args, mono_array_new (domain, mono_defaults.object_class, sig->param_count));
+ MONO_OBJECT_SETREF (this, arg_types, mono_array_new (domain, mono_defaults.byte_class, sig->param_count));
this->async_result = NULL;
this->call_type = CallType_Sync;
names = g_new (char *, sig->param_count);
mono_method_get_param_names (method->method, (const char **) names);
- this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
+ MONO_OBJECT_SETREF (this, names, mono_array_new (domain, mono_defaults.string_class, sig->param_count));
for (i = 0; i < sig->param_count; i++) {
name = mono_string_new (domain, names [i]);
- mono_array_set (this->names, gpointer, i, name);
+ mono_array_setref (this->names, i, name);
}
g_free (names);
if (sig->params [i]->byref) {
if (out_args) {
- gpointer arg = mono_array_get (out_args, gpointer, j);
- mono_array_set (this->args, gpointer, i, arg);
+ MonoObject* arg = mono_array_get (out_args, gpointer, j);
+ mono_array_setref (this->args, i, arg);
j++;
}
arg_type = 2;
arg_type |= 1;
} else {
arg_type = 1;
+ if (sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT)
+ arg_type |= 4;
}
mono_array_set (this->arg_types, guint8, i, arg_type);
}
outarg_count++;
}
+ /* FIXME: GC ensure we insert a write barrier for out_args, maybe in the caller? */
*out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
*exc = NULL;
for (i = 0, j = 0; i < sig->param_count; i++) {
if (sig->params [i]->byref) {
- gpointer arg;
+ MonoObject* arg;
arg = mono_array_get (msg->args, gpointer, i);
- mono_array_set (*out_args, gpointer, j, arg);
+ mono_array_setref (*out_args, j, arg);
j++;
}
}
class = this->vtable->klass;
- if ((ji = mono_jit_info_table_find (domain, addr))) {
+ if ((ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (addr)))) {
method = ji->method;
- delegate->method_info = mono_method_get_object (domain, method, NULL);
+ MONO_OBJECT_SETREF (delegate, method_info, mono_method_get_object (domain, method, NULL));
}
if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
g_assert (method);
method = mono_marshal_get_remoting_invoke (method);
delegate->method_ptr = mono_compile_method (method);
- delegate->target = target;
+ MONO_OBJECT_SETREF (delegate, target, target);
} else if (mono_method_signature (method)->hasthis && method->klass->valuetype) {
method = mono_marshal_get_unbox_wrapper (method);
delegate->method_ptr = mono_compile_method (method);
- delegate->target = target;
+ MONO_OBJECT_SETREF (delegate, target, target);
} else {
+ if (method) {
+ /*
+ * Replace the original trampoline with a delegate trampoline
+ * which will patch delegate->method_ptr with the address of the
+ * compiled method.
+ */
+ addr = arch_create_delegate_trampoline (method, addr);
+ }
delegate->method_ptr = addr;
- delegate->target = target;
+ MONO_OBJECT_SETREF (delegate, target, target);
}
}
else
arg = *((MonoObject **)vpos);
- mono_array_set (msg->args, gpointer, i, arg);
+ mono_array_setref (msg->args, i, arg);
}
if (cb != NULL && state != NULL) {
mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
{
MonoMethodSignature *sig = mono_method_signature (method);
- int i, j, type, size;
+ int i, j, type, size, out_len;
+
+ if (out_args == NULL)
+ return;
+ out_len = mono_array_length (out_args);
+ if (out_len == 0)
+ return;
+
for (i = 0, j = 0; i < sig->param_count; i++) {
MonoType *pt = sig->params [i];
if (pt->byref) {
- char *arg = mono_array_get (out_args, gpointer, j);
+ char *arg;
+ if (j >= out_len)
+ mono_raise_exception (mono_get_exception_execution_engine ("The proxy call returned an incorrect number of output arguments"));
+
+ arg = mono_array_get (out_args, gpointer, j);
type = pt->type;
switch (type) {
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_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
- mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->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);
if (mono_array_length (out_args) == 0)
return NULL;
- *res = mono_array_get (out_args, MonoObject *, 0);
+ *res = mono_array_get (out_args, MonoObject *, 0); /* FIXME: GC write abrrier for res */
if (field_class->valuetype) {
return ((char *)*res) + sizeof (MonoObject);
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_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
- mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->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_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
- mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
- mono_array_set (msg->args, gpointer, 2, arg);
+ 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_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
- mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
- mono_array_set (msg->args, gpointer, 2, arg);
+ 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);
if (exc) mono_raise_exception ((MonoException *)exc);
}
+/*
+ * mono_get_addr_from_ftnptr:
+ *
+ * Given a pointer to a function descriptor, return the function address.
+ * This is only needed on IA64.
+ */
+gpointer
+mono_get_addr_from_ftnptr (gpointer descr)
+{
+#ifdef __ia64__
+ return *(gpointer*)descr;
+#else
+ return descr;
+#endif
+}