mono_runtime_invoke (method, this, NULL, NULL);
}
+/* The pseudo algorithm for type initialization from the spec
+Note it doesn't say anything about domains - only threads.
+
+2. If the type is initialized you are done.
+2.1. If the type is not yet initialized, try to take an
+ initialization lock.
+2.2. If successful, record this thread as responsible for
+ initializing the type and proceed to step 2.3.
+2.2.1. If not, see whether this thread or any thread
+ waiting for this thread to complete already holds the lock.
+2.2.2. If so, return since blocking would create a deadlock. This thread
+ will now see an incompletely initialized state for the type,
+ but no deadlock will arise.
+2.2.3 If not, block until the type is initialized then return.
+2.3 Initialize the parent type and then all interfaces implemented
+ by this type.
+2.4 Execute the type initialization code for this type.
+2.5 Mark the type as initialized, release the initialization lock,
+ awaken any threads waiting for this type to be initialized,
+ and return.
+
+*/
+
+typedef struct
+{
+ guint32 initializing_tid;
+ guint32 waiting_count;
+ CRITICAL_SECTION initialization_section;
+} TypeInitializationLock;
+
+/* for locking access to type_initialization_hash and blocked_thread_hash */
+static CRITICAL_SECTION type_initialization_section;
+
+/* from vtable to lock */
+static GHashTable *type_initialization_hash;
+
+/* from thread id to thread id being waited on */
+static GHashTable *blocked_thread_hash;
+
+/* Main thread */
+static MonoThread *main_thread;
+
+void
+mono_type_initialization_init (void)
+{
+ InitializeCriticalSection (&type_initialization_section);
+ type_initialization_hash = g_hash_table_new (NULL, NULL);
+ blocked_thread_hash = g_hash_table_new (NULL, NULL);
+}
+
/*
* mono_runtime_class_init:
* @vtable: vtable that needs to be initialized
MonoClass *klass;
gchar *full_name;
gboolean found;
- MonoDomain *last_domain = NULL;
MONO_ARCH_SAVE_REGS;
- if (vtable->initialized || vtable->initializing)
+ if (vtable->initialized)
return;
exc = NULL;
}
if (found) {
- mono_domain_lock (vtable->domain);
+ MonoDomain *domain = vtable->domain;
+ TypeInitializationLock *lock;
+ guint32 tid = GetCurrentThreadId();
+ int do_initialization = 0;
+ MonoDomain *last_domain = NULL;
+
+ EnterCriticalSection (&type_initialization_section);
/* double check... */
- if (vtable->initialized || vtable->initializing) {
- mono_domain_unlock (vtable->domain);
+ if (vtable->initialized) {
+ LeaveCriticalSection (&type_initialization_section);
return;
}
- vtable->initializing = 1;
- if (mono_domain_get () != vtable->domain) {
- /* Transfer into the target domain */
- last_domain = mono_domain_get ();
- if (!mono_domain_set (vtable->domain, FALSE)) {
- vtable->initialized = 1;
- vtable->initializing = 0;
- mono_domain_unlock (vtable->domain);
- mono_raise_exception (mono_get_exception_appdomain_unloaded ());
+ lock = g_hash_table_lookup (type_initialization_hash, vtable);
+ if (lock == NULL) {
+ /* This thread will get to do the initialization */
+ if (mono_domain_get () != domain) {
+ /* Transfer into the target domain */
+ last_domain = mono_domain_get ();
+ if (!mono_domain_set (domain, FALSE)) {
+ vtable->initialized = 1;
+ LeaveCriticalSection (&type_initialization_section);
+ mono_raise_exception (mono_get_exception_appdomain_unloaded ());
+ }
+ }
+ lock = g_malloc (sizeof(TypeInitializationLock));
+ InitializeCriticalSection (&lock->initialization_section);
+ lock->initializing_tid = tid;
+ lock->waiting_count = 1;
+ /* grab the vtable lock while this thread still owns type_initialization_section */
+ EnterCriticalSection (&lock->initialization_section);
+ g_hash_table_insert (type_initialization_hash, vtable, lock);
+ do_initialization = 1;
+ } else {
+ gpointer blocked;
+
+ if (lock->initializing_tid == tid) {
+ LeaveCriticalSection (&type_initialization_section);
+ return;
}
+ /* see if the thread doing the initialization is already blocked on this thread */
+ blocked = GUINT_TO_POINTER (lock->initializing_tid);
+ while ((blocked = g_hash_table_lookup (blocked_thread_hash, blocked))) {
+ if (blocked == GUINT_TO_POINTER (tid)) {
+ LeaveCriticalSection (&type_initialization_section);
+ return;
+ }
+ }
+ ++lock->waiting_count;
+ /* record the fact that we are waiting on the initializing thread */
+ g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), GUINT_TO_POINTER (lock->initializing_tid));
+ }
+ LeaveCriticalSection (&type_initialization_section);
+
+ if (do_initialization) {
+ mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
+ if (last_domain)
+ mono_domain_set (last_domain, TRUE);
+ LeaveCriticalSection (&lock->initialization_section);
+ } else {
+ /* this just blocks until the initializing thread is done */
+ EnterCriticalSection (&lock->initialization_section);
+ LeaveCriticalSection (&lock->initialization_section);
+ }
+
+ EnterCriticalSection (&type_initialization_section);
+ if (lock->initializing_tid != tid)
+ g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
+ --lock->waiting_count;
+ if (lock->waiting_count == 0) {
+ DeleteCriticalSection (&lock->initialization_section);
+ g_hash_table_remove (type_initialization_hash, vtable);
+ g_free (lock);
}
- mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
- if (last_domain)
- mono_domain_set (last_domain, TRUE);
vtable->initialized = 1;
- vtable->initializing = 0;
/* FIXME: if the cctor fails, the type must be marked as unusable */
- mono_domain_unlock (vtable->domain);
+ LeaveCriticalSection (&type_initialization_section);
} else {
vtable->initialized = 1;
return;
{
MonoClassField *field;
guint64 bitmap;
+ guint32 bm [2];
int i;
static gboolean gcj_inited = FALSE;
// printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap);
class->gc_bitmap = bitmap;
- class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, class->instance_size / sizeof (gpointer));
+ /* Convert to the format expected by GC_make_descriptor */
+ bm [0] = (guint32)bitmap;
+ bm [1] = (guint32)(bitmap >> 32);
+ class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bm, class->instance_size / sizeof (gpointer));
}
}
#endif /* CREATION_SPEEDUP */
/**
* mono_class_proxy_vtable:
* @domain: the application domain
- * @class: the class to proxy
+ * @remove_class: the remote class
*
* Creates a vtable for transparent proxies. It is basically
- * a copy of the real vtable of @class, but all function pointers invoke
- * the remoting functions, and vtable->klass points to the
- * transparent proxy class, and not to @class.
+ * a copy of the real vtable of the class wrapped in @remote_class,
+ * but all function pointers invoke the remoting functions, and
+ * vtable->klass points to the transparent proxy class, and not to @class.
*/
-MonoVTable *
-mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
+static MonoVTable *
+mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class)
{
MonoVTable *vt, *pvt;
- int i, j, vtsize, interface_vtsize = 0;
- MonoClass* iclass = NULL;
- MonoClass* k;
-
- mono_domain_lock (domain);
- pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class);
+ int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
+ MonoClass *k;
+ MonoClass *class = remote_class->proxy_class;
- if (pvt) {
- mono_domain_unlock (domain);
- return pvt;
- }
+ vt = mono_class_vtable (domain, class);
+ max_interface_id = vt->max_interface_id;
- if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
- int method_count;
- iclass = class;
- class = mono_defaults.marshalbyrefobject_class;
+ /* Calculate vtable space for extra interfaces */
+ for (j = 0; j < remote_class->interface_count; j++) {
+ MonoClass* iclass = remote_class->interfaces[j];
+ int method_count = iclass->method.count;
+
+ if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
+ continue; /* interface implemented by the class */
- method_count = iclass->method.count;
for (i = 0; i < iclass->interface_count; i++)
method_count += iclass->interfaces[i]->method.count;
- interface_vtsize = method_count * sizeof (gpointer);
+ extra_interface_vtsize += method_count * sizeof (gpointer);
+ if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
}
- vt = mono_class_vtable (domain, class);
vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
- mono_stats.class_vtable_size += vtsize + interface_vtsize;
+ mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
- pvt = mono_mempool_alloc (domain->mp, vtsize + interface_vtsize);
+ pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
memcpy (pvt, vt, vtsize);
pvt->klass = mono_defaults.transparent_proxy_class;
}
}
- if (iclass)
+ 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]);
+ }
+
+ if (remote_class->interface_count > 0)
{
- int slot;
+ int slot = class->vtable_size;
MonoClass* interf;
+ MonoClass* iclass;
+ int n;
- pvt->max_interface_id = iclass->max_interface_id;
+ /* 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 */
- pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
- sizeof (gpointer) * (pvt->max_interface_id + 1));
+ i = -1;
+ interf = iclass;
+ do {
+ pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
+
+ for (j = 0; j < interf->method.count; ++j) {
+ MonoMethod *cm = interf->methods [j];
+ pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
+ }
+ slot += interf->method.count;
+ if (++i < iclass->interface_count) interf = iclass->interfaces[i];
+ else interf = NULL;
+
+ } while (interf);
+ }
+ }
- /* Create trampolines for the methods of the interfaces */
- slot = class->vtable_size;
- interf = iclass;
- i = -1;
- do {
- pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
-
- for (j = 0; j < interf->method.count; ++j) {
- MonoMethod *cm = interf->methods [j];
- pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
- }
- slot += interf->method.count;
- if (++i < iclass->interface_count) interf = iclass->interfaces[i];
- else interf = NULL;
-
- } while (interf);
+ return pvt;
+}
+
+/**
+ * mono_remote_class:
+ * @domain: the application domain
+ * @class_name: name of the remote class
+ *
+ * Creates and initializes a MonoRemoteClass object for a remote type.
+ *
+ */
+MonoRemoteClass*
+mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
+{
+ MonoRemoteClass *rc;
- class = iclass;
+ mono_domain_lock (domain);
+ rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class_name);
+
+ if (rc) {
+ mono_domain_unlock (domain);
+ return rc;
}
- else
+
+ rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
+ rc->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);
+
+ mono_g_hash_table_insert (domain->proxy_vtable_hash, class_name, rc);
+ mono_upgrade_remote_class (domain, rc, proxy_class);
+
+ if (rc->vtable == NULL)
+ rc->vtable = mono_class_proxy_vtable (domain, rc);
+
+ mono_domain_unlock (domain);
+
+ return rc;
+}
+
+static void
+extend_interface_array (MonoDomain *domain, MonoRemoteClass *remote_class, int amount)
+{
+ /* Extends the array of interfaces. Memory is extended using blocks of 5 pointers */
+
+ int current_size = ((remote_class->interface_count / 5) + 1) * 5;
+ remote_class->interface_count += amount;
+
+ if (remote_class->interface_count > current_size || remote_class->interfaces == NULL)
{
- pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
- sizeof (gpointer) * (pvt->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]);
+ 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*));
+
+ remote_class->interfaces = new_array;
+ }
+}
+
+
+/**
+ * mono_upgrade_remote_class:
+ * @domain: the application domain
+ * @remote_class: the remote class
+ * @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)
+{
+ gboolean redo_vtable;
+
+ mono_domain_lock (domain);
+
+ 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;
}
}
+ else {
+ redo_vtable = (remote_class->proxy_class != klass);
+ remote_class->proxy_class = klass;
+ }
- mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
+ if (redo_vtable)
+ remote_class->vtable = mono_class_proxy_vtable (domain, remote_class);
+/*
+ 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);
-
- return pvt;
}
/*
klass = mono_object_class (obj);
if (klass == mono_defaults.transparent_proxy_class) {
- klass = ((MonoTransparentProxy *)obj)->klass;
+ klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
is_proxy = TRUE;
} else {
is_proxy = FALSE;
if (!is_proxy)
res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
} else {
- res = vtable [method->slot];
+ if (method->slot != -1)
+ res = vtable [method->slot];
}
if (is_proxy) {
MonoDomain *domain = mono_domain_get ();
gchar *utf8_fullpath;
int result;
-
+
+ main_thread = mono_thread_current ();
+
main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
if (!g_path_is_absolute (argv [0])) {
if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
- /* set exitcode only in the main thread? */
- mono_environment_exitcode_set (1);
+ /* set exitcode only in the main thread */
+ if (mono_thread_current () == main_thread)
+ mono_environment_exitcode_set (1);
if (domain != mono_root_domain || !delegate) {
mono_print_unhandled_exception (exc);
} else {
case MONO_TYPE_R4:
case MONO_TYPE_R8:
case MONO_TYPE_VALUETYPE:
+ g_assert (((gpointer*)params->vector) [i]);
pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
break;
case MONO_TYPE_STRING:
if (!obj) {
obj = mono_object_new (mono_domain_get (), method->klass);
if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
- method = mono_marshal_get_remoting_invoke (method->klass->vtable [method->slot]);
+ method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
}
}
mono_runtime_invoke (method, obj, pa, exc);
MonoObject *
mono_object_isinst (MonoObject *obj, MonoClass *klass)
{
- MonoVTable *vt;
- MonoClass *oklass;
+ if (!klass->inited)
+ mono_class_init (klass);
- if (klass->marshalbyref)
+ if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
return mono_object_isinst_mbyref (obj, klass);
if (!obj)
return NULL;
- vt = obj->vtable;
- oklass = vt->klass;
-
- if (!klass->inited)
- mono_class_init (klass);
-
- if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
- if ((klass->interface_id <= vt->max_interface_id) &&
- (vt->interface_offsets [klass->interface_id] != 0))
- return obj;
- else
- return NULL;
- }
-
- return mono_class_is_assignable_from (klass, oklass) ? obj : NULL;
+ return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
}
MonoObject *
mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
{
MonoVTable *vt;
- MonoClass *oklass;
if (!obj)
return NULL;
vt = obj->vtable;
- oklass = vt->klass;
-
- if (oklass != klass && oklass == mono_defaults.transparent_proxy_class) {
- oklass = ((MonoTransparentProxy *)obj)->klass;
+
+ if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if ((klass->interface_id <= vt->max_interface_id) &&
+ (vt->interface_offsets [klass->interface_id] != 0))
+ return obj;
+ }
+ else {
+ MonoClass *oklass = vt->klass;
+ if ((oklass == mono_defaults.transparent_proxy_class))
+ oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
+
if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
return obj;
+ }
- /* Check for IRemotingTypeInfo */
- if (((MonoTransparentProxy *)obj)->custom_type_info) {
-
- MonoObject *res;
- MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
- MonoClass *rpklass = rp->vtable->klass;
- MonoMethod *im = NULL;
- gpointer pa [2];
- int i;
-
- for (i = 0; i < rpklass->method.count; ++i) {
- if (!strcmp ("CanCastTo", rpklass->methods [i]->name) &&
- rpklass->methods [i]->signature->param_count == 2) {
- im = rpklass->methods [i];
- break;
- }
+ if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
+ {
+ MonoDomain *domain = mono_domain_get ();
+ MonoObject *res;
+ MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
+ MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
+ MonoMethod *im = NULL;
+ gpointer pa [2];
+ int i;
+
+ for (i = 0; i < rpklass->method.count; ++i) {
+ if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
+ im = rpklass->methods [i];
+ break;
}
-
- g_assert (im);
-
- pa [0] = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
- pa [1] = obj;
-
- res = mono_runtime_invoke (im, rp, pa, NULL);
- if (*(MonoBoolean *) mono_object_unbox(res))
- return obj;
}
+
+ im = mono_object_get_virtual_method (rp, im);
+ g_assert (im);
+
+ pa [0] = mono_type_get_object (domain, &klass->byval_arg);
+ pa [1] = obj;
- return NULL;
+ res = mono_runtime_invoke (im, rp, pa, NULL);
+
+ 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 = ((MonoTransparentProxy *)obj)->remote_class->vtable;
+ return obj;
+ }
}
- if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
- return obj;
- else
- return NULL;
+ return NULL;
}
/**
if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
- if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
+ if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
target = tp->rp->unwrapped_server;
} else {
return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
if (!res)
res = &tmp;
- if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
+ if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
mono_field_get_value (tp->rp->unwrapped_server, field, res);
return res;
}
field_class = mono_class_from_mono_type (field->type);
- if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
+ if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
gpointer val;
if (field_class->valuetype) {
res = mono_object_new (domain, field_class);
field_class = mono_class_from_mono_type (field->type);
- if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
- if (field_class->valuetype)
- mono_field_set_value (tp->rp->unwrapped_server, field, val);
- else
- mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
+ if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
+ if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
+ else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
return;
}
field_class = mono_class_from_mono_type (field->type);
- if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
- if (field_class->valuetype)
- mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
- else
- mono_field_set_value (tp->rp->unwrapped_server, field, arg);
+ if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
+ if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
+ else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
return;
}