2 * object.c: Object creation for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2001-2004 Ximian, Inc.
15 #include <mono/metadata/mono-endian.h>
16 #include <mono/metadata/tabledefs.h>
17 #include <mono/metadata/tokentype.h>
18 #include <mono/metadata/loader.h>
19 #include <mono/metadata/object.h>
20 #include <mono/metadata/gc-internal.h>
21 #include <mono/metadata/exception.h>
22 #include <mono/metadata/appdomain.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/threadpool.h>
25 #include <mono/metadata/marshal.h>
26 #include "mono/metadata/debug-helpers.h"
27 #include "mono/metadata/marshal.h"
28 #include <mono/metadata/threads.h>
29 #include <mono/metadata/environment.h>
30 #include "mono/metadata/profiler-private.h"
31 #include <mono/os/gc_wrapper.h>
32 #include <mono/utils/strenc.h>
35 * Enable experimental typed allocation using the GC_gcj_malloc function.
37 #ifdef HAVE_GC_GCJ_MALLOC
38 #define CREATION_SPEEDUP 1
42 mono_runtime_object_init (MonoObject *this)
45 MonoMethod *method = NULL;
46 MonoClass *klass = this->vtable->klass;
48 for (i = 0; i < klass->method.count; ++i) {
49 if (!strcmp (".ctor", klass->methods [i]->name) &&
50 klass->methods [i]->signature->param_count == 0) {
51 method = klass->methods [i];
58 mono_runtime_invoke (method, this, NULL, NULL);
62 * mono_runtime_class_init:
63 * @vtable: vtable that needs to be initialized
65 * This routine calls the class constructor for @vtable.
68 mono_runtime_class_init (MonoVTable *vtable)
72 MonoException *exc_to_throw;
73 MonoMethod *method = NULL;
77 MonoDomain *last_domain = NULL;
81 if (vtable->initialized || vtable->initializing)
86 klass = vtable->klass;
88 for (i = 0; i < klass->method.count; ++i) {
89 method = klass->methods [i];
90 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
91 (strcmp (".cctor", method->name) == 0)) {
98 mono_domain_lock (vtable->domain);
100 if (vtable->initialized || vtable->initializing) {
101 mono_domain_unlock (vtable->domain);
104 vtable->initializing = 1;
105 if (mono_domain_get () != vtable->domain) {
106 /* Transfer into the target domain */
107 last_domain = mono_domain_get ();
108 if (!mono_domain_set (vtable->domain, FALSE)) {
109 vtable->initialized = 1;
110 vtable->initializing = 0;
111 mono_domain_unlock (vtable->domain);
112 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
115 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
117 mono_domain_set (last_domain, TRUE);
118 vtable->initialized = 1;
119 vtable->initializing = 0;
120 /* FIXME: if the cctor fails, the type must be marked as unusable */
121 mono_domain_unlock (vtable->domain);
123 vtable->initialized = 1;
128 (klass->image == mono_defaults.corlib &&
129 !strcmp (klass->name_space, "System") &&
130 !strcmp (klass->name, "TypeInitializationException")))
131 return; /* No static constructor found or avoid infinite loop */
133 if (klass->name_space && *klass->name_space)
134 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
136 full_name = g_strdup (klass->name);
138 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
141 mono_raise_exception (exc_to_throw);
145 default_trampoline (MonoMethod *method)
151 default_remoting_trampoline (MonoMethod *method)
153 g_error ("remoting not installed");
157 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
158 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
161 mono_install_trampoline (MonoTrampoline func)
163 arch_create_jit_trampoline = func? func: default_trampoline;
167 mono_install_remoting_trampoline (MonoTrampoline func)
169 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
172 static MonoCompileFunc default_mono_compile_method = NULL;
175 mono_install_compile_method (MonoCompileFunc func)
177 default_mono_compile_method = func;
181 mono_compile_method (MonoMethod *method)
183 if (!default_mono_compile_method) {
184 g_error ("compile method called on uninitialized runtime");
187 return default_mono_compile_method (method);
191 #if 0 && HAVE_BOEHM_GC
193 vtable_finalizer (void *obj, void *data) {
194 g_print ("%s finalized (%p)\n", (char*)data, obj);
200 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
203 * The vtables in the root appdomain are assumed to be reachable by other
204 * roots, and we don't use typed allocation in the other domains.
207 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
210 mono_class_compute_gc_descriptor (MonoClass *class)
212 MonoClassField *field;
216 static gboolean gcj_inited = FALSE;
221 GC_init_gcj_malloc (5, NULL);
225 mono_class_init (class);
227 if (class->gc_descr_inited)
230 class->gc_descr_inited = TRUE;
231 class->gc_descr = GC_NO_DESCRIPTOR;
233 if (class == mono_defaults.string_class) {
234 bitmap = GC_HEADER_BITMAP;
235 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
237 else if (class->rank) {
238 mono_class_compute_gc_descriptor (class->element_class);
240 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
241 bitmap = GC_HEADER_BITMAP;
243 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
244 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
248 static int count = 0;
252 /* GC 6.1 has trouble handling 64 bit descriptors... */
253 if ((class->instance_size / sizeof (gpointer)) > 30) {
254 // printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer));
258 bitmap = GC_HEADER_BITMAP;
265 // printf("KLASS: %s.\n", class->name);
267 for (p = class; p != NULL; p = p->parent) {
268 for (i = 0; i < p->field.count; ++i) {
269 field = &p->fields [i];
270 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
272 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
275 pos = field->offset / sizeof (gpointer);
277 if (field->type->byref)
280 switch (field->type->type) {
281 case MONO_TYPE_BOOLEAN:
293 // printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap);
296 case MONO_TYPE_STRING:
297 case MONO_TYPE_SZARRAY:
298 case MONO_TYPE_CLASS:
299 case MONO_TYPE_OBJECT:
300 case MONO_TYPE_ARRAY:
302 g_assert ((field->offset % sizeof(gpointer)) == 0);
304 bitmap |= ((guint64)1) << pos;
305 // printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap);
307 case MONO_TYPE_VALUETYPE: {
308 MonoClass *fclass = field->type->data.klass;
309 if (!fclass->enumtype) {
310 mono_class_compute_gc_descriptor (fclass);
311 bitmap |= (fclass->gc_bitmap >> (sizeof (MonoObject) / sizeof (gpointer))) << pos;
321 // printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap);
322 class->gc_bitmap = bitmap;
323 /* Convert to the format expected by GC_make_descriptor */
324 bm [0] = (guint32)bitmap;
325 bm [1] = (guint32)(bitmap >> 32);
326 class->gc_descr = (gpointer)GC_make_descriptor (&bm, class->instance_size / sizeof (gpointer));
329 #endif /* CREATION_SPEEDUP */
332 * field_is_special_static:
334 * Returns SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
335 * SPECIAL_STATIC_NONE otherwise.
338 field_is_special_static (MonoClass *fklass, MonoClassField *field)
340 MonoCustomAttrInfo *ainfo;
342 ainfo = mono_custom_attrs_from_field (fklass, field);
345 for (i = 0; i < ainfo->num_attrs; ++i) {
346 MonoClass *klass = ainfo->attrs [i].ctor->klass;
347 if (klass->image == mono_defaults.corlib) {
348 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
349 mono_custom_attrs_free (ainfo);
350 return SPECIAL_STATIC_THREAD;
352 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
353 mono_custom_attrs_free (ainfo);
354 return SPECIAL_STATIC_CONTEXT;
358 mono_custom_attrs_free (ainfo);
359 return SPECIAL_STATIC_NONE;
364 * @domain: the application domain
365 * @class: the class to initialize
367 * VTables are domain specific because we create domain specific code, and
368 * they contain the domain specific static class data.
371 mono_class_vtable (MonoDomain *domain, MonoClass *class)
373 MonoVTable *vt = NULL;
374 MonoClassField *field;
380 guint32 constant_cols [MONO_CONSTANT_SIZE];
384 vt = class->cached_vtable;
385 if (vt && vt->domain == domain)
388 mono_domain_lock (domain);
389 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
390 mono_domain_unlock (domain);
395 mono_class_init (class);
397 mono_stats.used_class_count++;
398 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
400 vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
402 vt = mono_mempool_alloc0 (domain->mp, vtable_size);
408 mono_class_compute_gc_descriptor (class);
409 if (domain != mono_root_domain)
411 * We can't use typed allocation in the non-root domains, since the
412 * collector needs the GC descriptor stored in the vtable even after
413 * the mempool containing the vtable is destroyed when the domain is
414 * unloaded. An alternative might be to allocate vtables in the GC
415 * heap, but this does not seem to work (it leads to crashes inside
416 * libgc). If that approach is tried, two gc descriptors need to be
417 * allocated for each class: one for the root domain, and one for all
418 * other domains. The second descriptor should contain a bit for the
419 * vtable field in MonoObject, since we can no longer assume the
420 * vtable is reachable by other roots after the appdomain is unloaded.
422 vt->gc_descr = GC_NO_DESCRIPTOR;
424 vt->gc_descr = class->gc_descr;
427 if (class->class_size) {
429 vt->data = GC_MALLOC (class->class_size + 8);
430 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
431 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
432 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
434 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
437 mono_stats.class_static_data_size += class->class_size + 8;
441 for (i = class->field.first; i < class->field.last; ++i) {
442 field = &class->fields [i - class->field.first];
443 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
445 if (mono_field_is_deleted (field))
447 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
448 gint32 special_static = field_is_special_static (class, field);
449 if (special_static != SPECIAL_STATIC_NONE) {
450 guint32 size, align, offset;
451 size = mono_type_size (field->type, &align);
452 offset = mono_alloc_special_static_data (special_static, size, align);
453 if (!domain->special_static_fields)
454 domain->special_static_fields = g_hash_table_new (NULL, NULL);
455 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
459 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
460 MonoClass *fklass = mono_class_from_mono_type (field->type);
461 t = (char*)vt->data + field->offset;
462 if (fklass->valuetype) {
463 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
465 /* it's a pointer type: add check */
466 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
467 *t = *(char *)field->data;
471 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
474 if (!field->def_value) {
475 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1), cindex + 1);
478 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
479 field->def_value = g_new0 (MonoConstant, 1);
480 field->def_value->type = constant_cols [MONO_CONSTANT_TYPE];
481 field->def_value->value = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
484 p = field->def_value->value;
485 len = mono_metadata_decode_blob_size (p, &p);
486 t = (char*)vt->data + field->offset;
487 /* should we check that the type matches? */
488 switch (field->def_value->type) {
489 case MONO_TYPE_BOOLEAN:
497 guint16 *val = (guint16*)t;
503 guint32 *val = (guint32*)t;
509 guint64 *val = (guint64*)t;
514 float *val = (float*)t;
519 double *val = (double*)t;
523 case MONO_TYPE_STRING: {
524 gpointer *val = (gpointer*)t;
525 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
526 gunichar2 *copy = g_malloc (len);
528 for (j = 0; j < len/2; j++) {
529 copy [j] = read16 (p);
532 *val = mono_string_new_utf16 (domain, copy, len/2);
535 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
539 case MONO_TYPE_CLASS:
540 /* nothing to do, we malloc0 the data and the value can be 0 only */
543 g_warning ("type 0x%02x should not be in constant table", field->def_value->type);
547 vt->max_interface_id = class->max_interface_id;
549 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
550 sizeof (gpointer) * (class->max_interface_id + 1));
552 /* initialize interface offsets */
553 for (i = 0; i <= class->max_interface_id; ++i) {
554 int slot = class->interface_offsets [i];
556 vt->interface_offsets [i] = &(vt->vtable [slot]);
560 * arch_create_jit_trampoline () can recursively call this function again
561 * because it compiles icall methods right away.
563 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
564 if (!class->cached_vtable)
565 class->cached_vtable = vt;
567 /* initialize vtable */
568 for (i = 0; i < class->vtable_size; ++i) {
571 if ((cm = class->vtable [i]))
572 vt->vtable [i] = arch_create_jit_trampoline (cm);
575 mono_domain_unlock (domain);
577 /* make sure the the parent is initialized */
579 mono_class_vtable (domain, class->parent);
581 vt->type = mono_type_get_object (domain, &class->byval_arg);
582 if (class->contextbound)
591 * mono_class_proxy_vtable:
592 * @domain: the application domain
593 * @remove_class: the remote class
595 * Creates a vtable for transparent proxies. It is basically
596 * a copy of the real vtable of the class wrapped in @remote_class,
597 * but all function pointers invoke the remoting functions, and
598 * vtable->klass points to the transparent proxy class, and not to @class.
601 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class)
603 MonoVTable *vt, *pvt;
604 int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
606 MonoClass *class = remote_class->proxy_class;
608 vt = mono_class_vtable (domain, class);
609 max_interface_id = vt->max_interface_id;
611 /* Calculate vtable space for extra interfaces */
612 for (j = 0; j < remote_class->interface_count; j++) {
613 MonoClass* iclass = remote_class->interfaces[j];
614 int method_count = iclass->method.count;
616 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
617 continue; /* interface implemented by the class */
619 for (i = 0; i < iclass->interface_count; i++)
620 method_count += iclass->interfaces[i]->method.count;
622 extra_interface_vtsize += method_count * sizeof (gpointer);
623 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
626 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
628 mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
630 pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
631 memcpy (pvt, vt, vtsize);
633 pvt->klass = mono_defaults.transparent_proxy_class;
635 /* initialize vtable */
636 for (i = 0; i < class->vtable_size; ++i) {
639 if ((cm = class->vtable [i]))
640 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
643 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
645 /* create trampolines for abstract methods */
646 for (k = class; k; k = k->parent) {
647 for (i = 0; i < k->method.count; i++) {
648 int slot = k->methods [i]->slot;
649 if (!pvt->vtable [slot])
650 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
655 pvt->max_interface_id = max_interface_id;
656 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
657 sizeof (gpointer) * (max_interface_id + 1));
659 /* initialize interface offsets */
660 for (i = 0; i <= class->max_interface_id; ++i) {
661 int slot = class->interface_offsets [i];
663 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
666 if (remote_class->interface_count > 0)
668 int slot = class->vtable_size;
673 /* Create trampolines for the methods of the interfaces */
674 for (n = 0; n < remote_class->interface_count; n++)
676 iclass = remote_class->interfaces[n];
677 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
678 continue; /* interface implemented by the class */
683 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
685 for (j = 0; j < interf->method.count; ++j) {
686 MonoMethod *cm = interf->methods [j];
687 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
689 slot += interf->method.count;
690 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
702 * @domain: the application domain
703 * @class_name: name of the remote class
705 * Creates and initializes a MonoRemoteClass object for a remote type.
709 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
713 mono_domain_lock (domain);
714 rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class_name);
717 mono_domain_unlock (domain);
721 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
723 rc->interface_count = 0;
724 rc->interfaces = NULL;
725 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
726 rc->proxy_class_name = mono_string_to_utf8 (class_name);
728 mono_g_hash_table_insert (domain->proxy_vtable_hash, class_name, rc);
729 mono_upgrade_remote_class (domain, rc, proxy_class);
731 if (rc->vtable == NULL)
732 rc->vtable = mono_class_proxy_vtable (domain, rc);
734 mono_domain_unlock (domain);
740 extend_interface_array (MonoDomain *domain, MonoRemoteClass *remote_class, int amount)
742 /* Extends the array of interfaces. Memory is extended using blocks of 5 pointers */
744 int current_size = ((remote_class->interface_count / 5) + 1) * 5;
745 remote_class->interface_count += amount;
747 if (remote_class->interface_count > current_size || remote_class->interfaces == NULL)
749 int new_size = ((remote_class->interface_count / 5) + 1) * 5;
750 MonoClass **new_array = mono_mempool_alloc (domain->mp, new_size * sizeof (MonoClass*));
752 if (remote_class->interfaces != NULL)
753 memcpy (new_array, remote_class->interfaces, current_size * sizeof (MonoClass*));
755 remote_class->interfaces = new_array;
761 * mono_upgrade_remote_class:
762 * @domain: the application domain
763 * @remote_class: the remote class
764 * @klass: class to which the remote class can be casted.
766 * Updates the vtable of the remote class by adding the necessary method slots
767 * and interface offsets so it can be safely casted to klass. klass can be a
768 * class or an interface.
770 void mono_upgrade_remote_class (MonoDomain *domain, MonoRemoteClass *remote_class, MonoClass *klass)
772 gboolean redo_vtable;
774 mono_domain_lock (domain);
776 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
779 for (i = 0; i < remote_class->interface_count; i++)
780 if (remote_class->interfaces[i] == klass) redo_vtable = FALSE;
783 extend_interface_array (domain, remote_class, 1);
784 remote_class->interfaces [remote_class->interface_count-1] = klass;
788 redo_vtable = (remote_class->proxy_class != klass);
789 remote_class->proxy_class = klass;
793 remote_class->vtable = mono_class_proxy_vtable (domain, remote_class);
796 printf ("remote class upgrade - class:%s num-interfaces:%d\n", remote_class->proxy_class_name, remote_class->interface_count);
798 for (n=0; n<remote_class->interface_count; n++)
799 printf (" I:%s\n", remote_class->interfaces[n]->name);
802 mono_domain_unlock (domain);
806 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
807 * the instance of a callvirt of method.
810 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
814 MonoMethod *res = NULL;
816 klass = mono_object_class (obj);
817 if (klass == mono_defaults.transparent_proxy_class) {
818 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
824 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
827 vtable = klass->vtable;
829 /* check method->slot is a valid index: perform isinstance? */
830 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
832 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
834 res = vtable [method->slot];
838 if (!res) res = method; /* It may be an interface or abstract class method */
839 res = mono_marshal_get_remoting_invoke (res);
848 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
850 g_error ("runtime invoke called on uninitialized runtime");
854 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
857 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
859 return default_mono_runtime_invoke (method, obj, params, exc);
863 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
866 gpointer *p = (gpointer*)dest;
873 case MONO_TYPE_BOOLEAN:
876 guint8 *p = (guint8*)dest;
877 *p = *(guint8*)value;
882 case MONO_TYPE_CHAR: {
883 guint16 *p = (guint16*)dest;
884 *p = *(guint16*)value;
887 #if SIZEOF_VOID_P == 4
893 gint32 *p = (gint32*)dest;
894 *p = *(gint32*)value;
897 #if SIZEOF_VOID_P == 8
903 gint64 *p = (gint64*)dest;
904 *p = *(gint64*)value;
908 float *p = (float*)dest;
913 double *p = (double*)dest;
914 *p = *(double*)value;
917 case MONO_TYPE_STRING:
918 case MONO_TYPE_SZARRAY:
919 case MONO_TYPE_CLASS:
920 case MONO_TYPE_OBJECT:
921 case MONO_TYPE_ARRAY:
922 case MONO_TYPE_PTR: {
923 gpointer *p = (gpointer*)dest;
924 *p = deref_pointer? *(gpointer*)value: value;
927 case MONO_TYPE_VALUETYPE:
928 if (type->data.klass->enumtype) {
929 t = type->data.klass->enum_basetype->type;
933 size = mono_class_value_size (type->data.klass, NULL);
934 memcpy (dest, value, size);
938 g_warning ("got type %x", type->type);
939 g_assert_not_reached ();
944 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
948 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
950 dest = (char*)obj + field->offset;
951 set_value (field->type, dest, value, FALSE);
955 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
959 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
961 dest = (char*)vt->data + field->offset;
962 set_value (field->type, dest, value, FALSE);
966 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
970 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
972 src = (char*)obj + field->offset;
973 set_value (field->type, value, src, TRUE);
977 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
981 MonoVTable *vtable = NULL;
983 gboolean is_static = FALSE;
984 gboolean is_ref = FALSE;
986 switch (field->type->type) {
987 case MONO_TYPE_STRING:
988 case MONO_TYPE_OBJECT:
989 case MONO_TYPE_CLASS:
990 case MONO_TYPE_ARRAY:
991 case MONO_TYPE_SZARRAY:
996 case MONO_TYPE_BOOLEAN:
1008 case MONO_TYPE_VALUETYPE:
1009 is_ref = field->type->byref;
1012 g_error ("type 0x%x not handled in "
1013 "mono_field_get_value_object", field->type->type);
1017 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1019 vtable = mono_class_vtable (domain, field->parent);
1020 if (!vtable->initialized)
1021 mono_runtime_class_init (vtable);
1026 mono_field_static_get_value (vtable, field, &o);
1028 mono_field_get_value (obj, field, &o);
1033 /* boxed value type */
1034 klass = mono_class_from_mono_type (field->type);
1035 o = mono_object_new (domain, klass);
1036 v = ((gchar *) o) + sizeof (MonoObject);
1038 mono_field_static_get_value (vtable, field, v);
1040 mono_field_get_value (obj, field, v);
1048 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1052 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1054 src = (char*)vt->data + field->offset;
1055 set_value (field->type, value, src, TRUE);
1059 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1061 default_mono_runtime_invoke (prop->set, obj, params, exc);
1065 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1067 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1072 mono_get_delegate_invoke (MonoClass *klass)
1079 for (i = 0; i < klass->method.count; ++i) {
1080 if (klass->methods [i]->name[0] == 'I' &&
1081 !strcmp ("Invoke", klass->methods [i]->name)) {
1082 im = klass->methods [i];
1092 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1096 im = mono_get_delegate_invoke (delegate->vtable->klass);
1099 return mono_runtime_invoke (im, delegate, params, exc);
1102 static MonoArray* main_args;
1105 mono_runtime_get_main_args (void)
1111 fire_process_exit_event (void)
1113 MonoClassField *field;
1114 MonoDomain *domain = mono_domain_get ();
1116 MonoObject *delegate, *exc;
1118 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1121 if (domain != mono_root_domain)
1124 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1125 if (delegate == NULL)
1130 mono_runtime_delegate_invoke (delegate, pa, &exc);
1134 * Execute a standard Main() method (argc/argv contains the
1135 * executable name). This method also sets the command line argument value
1136 * needed by System.Environment.
1139 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1143 MonoArray *args = NULL;
1144 MonoDomain *domain = mono_domain_get ();
1145 gchar *utf8_fullpath;
1148 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1150 if (!g_path_is_absolute (argv [0])) {
1151 gchar *basename = g_path_get_basename (argv [0]);
1152 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1156 utf8_fullpath = mono_utf8_from_external (fullpath);
1157 if(utf8_fullpath == NULL) {
1158 /* Printing the arg text will cause glib to
1159 * whinge about "Invalid UTF-8", but at least
1160 * its relevant, and shows the problem text
1163 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1164 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1171 utf8_fullpath = mono_utf8_from_external (argv[0]);
1172 if(utf8_fullpath == NULL) {
1173 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1174 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1179 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1180 g_free (utf8_fullpath);
1182 for (i = 1; i < argc; ++i) {
1186 utf8_arg=mono_utf8_from_external (argv[i]);
1187 if(utf8_arg==NULL) {
1188 /* Ditto the comment about Invalid UTF-8 here */
1189 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1190 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1194 arg = mono_string_new (domain, utf8_arg);
1195 mono_array_set (main_args, gpointer, i, arg);
1199 if (method->signature->param_count) {
1200 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1201 for (i = 0; i < argc; ++i) {
1202 /* The encodings should all work, given that
1203 * we've checked all these args for the
1206 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1207 mono_array_set (args, gpointer, i, arg);
1210 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1213 mono_assembly_set_main (method->klass->image->assembly);
1215 result = mono_runtime_exec_main (method, args, exc);
1216 fire_process_exit_event ();
1220 /* Used in mono_unhandled_exception */
1222 create_unhandled_exception_eventargs (MonoObject *exc)
1226 MonoMethod *method = NULL;
1227 MonoBoolean is_terminating = TRUE;
1231 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1234 mono_class_init (klass);
1236 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1237 for (i = 0; i < klass->method.count; ++i) {
1238 method = klass->methods [i];
1239 if (!strcmp (".ctor", method->name) &&
1240 method->signature->param_count == 2 &&
1241 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1249 args [1] = &is_terminating;
1251 obj = mono_object_new (mono_domain_get (), klass);
1252 mono_runtime_invoke (method, obj, args, NULL);
1258 * We call this function when we detect an unhandled exception
1259 * in the default domain.
1260 * It invokes the * UnhandledException event in AppDomain or prints
1261 * a warning to the console
1264 mono_unhandled_exception (MonoObject *exc)
1266 MonoDomain *domain = mono_domain_get ();
1267 MonoClassField *field;
1268 MonoObject *delegate;
1270 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1271 "UnhandledException");
1274 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1275 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1277 /* set exitcode only in the main thread? */
1278 mono_environment_exitcode_set (1);
1279 if (domain != mono_root_domain || !delegate) {
1280 mono_print_unhandled_exception (exc);
1282 MonoObject *e = NULL;
1285 pa [0] = domain->domain;
1286 pa [1] = create_unhandled_exception_eventargs (exc);
1287 mono_runtime_delegate_invoke (delegate, pa, &e);
1290 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1291 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1299 * Launch a new thread to start all setup that requires managed code
1302 * main_func is called back from the thread with main_args as the
1303 * parameter. The callback function is expected to start Main()
1304 * eventually. This function then waits for all managed threads to
1308 mono_runtime_exec_managed_code (MonoDomain *domain,
1309 MonoMainThreadFunc main_func,
1312 mono_thread_create (domain, main_func, main_args);
1314 mono_thread_manage ();
1318 * Execute a standard Main() method (args doesn't contain the
1322 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1332 domain = mono_object_domain (args);
1333 if (!domain->entry_assembly) {
1334 domain->entry_assembly = method->klass->image->assembly;
1335 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
1338 /* FIXME: check signature of method */
1339 if (method->signature->ret->type == MONO_TYPE_I4) {
1341 res = mono_runtime_invoke (method, NULL, pa, exc);
1343 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1347 mono_environment_exitcode_set (rval);
1349 mono_runtime_invoke (method, NULL, pa, exc);
1353 /* If the return type of Main is void, only
1354 * set the exitcode if an exception was thrown
1355 * (we don't want to blow away an
1356 * explicitly-set exit code)
1359 mono_environment_exitcode_set (rval);
1367 mono_install_runtime_invoke (MonoInvokeFunc func)
1369 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1373 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1376 MonoMethodSignature *sig = method->signature;
1377 gpointer *pa = NULL;
1380 if (NULL != params) {
1381 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1382 for (i = 0; i < mono_array_length (params); i++) {
1383 if (sig->params [i]->byref) {
1387 switch (sig->params [i]->type) {
1390 case MONO_TYPE_BOOLEAN:
1393 case MONO_TYPE_CHAR:
1402 case MONO_TYPE_VALUETYPE:
1403 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1405 case MONO_TYPE_STRING:
1406 case MONO_TYPE_OBJECT:
1407 case MONO_TYPE_CLASS:
1408 case MONO_TYPE_ARRAY:
1409 case MONO_TYPE_SZARRAY:
1410 if (sig->params [i]->byref)
1411 pa [i] = &(((gpointer *)params->vector)[i]);
1413 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1416 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1421 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1423 obj = mono_object_new (mono_domain_get (), method->klass);
1424 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1425 method = mono_marshal_get_remoting_invoke (method->klass->vtable [method->slot]);
1428 mono_runtime_invoke (method, obj, pa, exc);
1431 return mono_runtime_invoke (method, obj, pa, exc);
1435 out_of_memory (size_t size)
1438 * we could allocate at program startup some memory that we could release
1439 * back to the system at this point if we're really low on memory (ie, size is
1440 * lower than the memory we set apart)
1442 mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
1446 * mono_object_allocate:
1447 * @size: number of bytes to allocate
1449 * This is a very simplistic routine until we have our GC-aware
1452 * Returns: an allocated object of size @size, or NULL on failure.
1454 static inline void *
1455 mono_object_allocate (size_t size)
1458 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1459 void *o = GC_MALLOC (size);
1461 void *o = calloc (1, size);
1463 mono_stats.new_object_count++;
1466 out_of_memory (size);
1470 #if CREATION_SPEEDUP
1471 static inline void *
1472 mono_object_allocate_spec (size_t size, void *gcdescr)
1474 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1475 void *o = GC_GCJ_MALLOC (size, gcdescr);
1476 mono_stats.new_object_count++;
1479 out_of_memory (size);
1487 * Frees the memory used by the object. Debugging purposes
1488 * only, as we will have our GC system.
1491 mono_object_free (MonoObject *o)
1494 g_error ("mono_object_free called with boehm gc.");
1496 MonoClass *c = o->vtable->klass;
1498 memset (o, 0, c->instance_size);
1505 * @klass: the class of the object that we want to create
1507 * Returns: A newly created object whose definition is
1508 * looked up using @klass
1511 mono_object_new (MonoDomain *domain, MonoClass *klass)
1513 MONO_ARCH_SAVE_REGS;
1514 return mono_object_new_specific (mono_class_vtable (domain, klass));
1518 * mono_object_new_specific:
1519 * @vtable: the vtable of the object that we want to create
1521 * Returns: A newly created object with class and domain specified
1525 mono_object_new_specific (MonoVTable *vtable)
1529 MONO_ARCH_SAVE_REGS;
1534 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1537 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1541 mono_class_init (klass);
1543 for (i = 0; i < klass->method.count; ++i) {
1544 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1545 klass->methods [i]->signature->param_count == 1) {
1546 im = klass->methods [i];
1551 vtable->domain->create_proxy_for_type_method = im;
1554 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1556 o = mono_runtime_invoke (im, NULL, pa, NULL);
1557 if (o != NULL) return o;
1560 return mono_object_new_alloc_specific (vtable);
1564 mono_object_new_fast (MonoVTable *vtable)
1567 MONO_ARCH_SAVE_REGS;
1569 #if CREATION_SPEEDUP
1570 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1571 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1573 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1574 o = mono_object_allocate (vtable->klass->instance_size);
1578 o = mono_object_allocate (vtable->klass->instance_size);
1585 mono_object_new_alloc_specific (MonoVTable *vtable)
1589 #if CREATION_SPEEDUP
1590 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1591 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1593 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1594 o = mono_object_allocate (vtable->klass->instance_size);
1598 o = mono_object_allocate (vtable->klass->instance_size);
1601 if (vtable->klass->has_finalize)
1602 mono_object_register_finalizer (o);
1604 mono_profiler_allocation (o, vtable->klass);
1609 * mono_object_new_from_token:
1610 * @image: Context where the type_token is hosted
1611 * @token: a token of the type that we want to create
1613 * Returns: A newly created object whose definition is
1614 * looked up using @token in the @image image
1617 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1621 class = mono_class_get (image, token);
1623 return mono_object_new (domain, class);
1628 * mono_object_clone:
1629 * @obj: the object to clone
1631 * Returns: A newly created object who is a shallow copy of @obj
1634 mono_object_clone (MonoObject *obj)
1639 size = obj->vtable->klass->instance_size;
1640 o = mono_object_allocate (size);
1641 mono_profiler_allocation (o, obj->vtable->klass);
1643 memcpy (o, obj, size);
1645 if (obj->vtable->klass->has_finalize)
1646 mono_object_register_finalizer (o);
1652 * @array: the array to clone
1654 * Returns: A newly created array who is a shallow copy of @array
1657 mono_array_clone (MonoArray *array)
1662 MonoClass *klass = array->obj.vtable->klass;
1664 MONO_ARCH_SAVE_REGS;
1666 if (array->bounds == NULL) {
1667 size = mono_array_length (array);
1668 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1669 klass, &size, NULL);
1671 size *= mono_array_element_size (klass);
1672 memcpy (o, array, sizeof (MonoArray) + size);
1677 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1678 size = mono_array_element_size (klass);
1679 for (i = 0; i < klass->rank; ++i) {
1680 sizes [i] = array->bounds [i].length;
1681 size *= array->bounds [i].length;
1682 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1684 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1685 klass, sizes, sizes + klass->rank);
1686 memcpy (o, array, sizeof(MonoArray) + size);
1691 /* helper macros to check for overflow when calculating the size of arrays */
1692 #define MYGUINT32_MAX 4294967295U
1693 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1694 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1695 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1696 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1697 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1700 * mono_array_new_full:
1701 * @domain: domain where the object is created
1702 * @array_class: array class
1703 * @lengths: lengths for each dimension in the array
1704 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1706 * This routine creates a new array objects with the given dimensions,
1707 * lower bounds and type.
1710 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1711 guint32 *lengths, guint32 *lower_bounds)
1713 guint32 byte_len, len;
1716 MonoArrayBounds *bounds;
1720 if (!array_class->inited)
1721 mono_class_init (array_class);
1723 byte_len = mono_array_element_size (array_class);
1726 if (array_class->rank == 1 &&
1727 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1732 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1734 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1736 for (i = 0; i < array_class->rank; ++i) {
1737 bounds [i].length = lengths [i];
1738 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1739 out_of_memory (MYGUINT32_MAX);
1744 for (i = 0; i < array_class->rank; ++i)
1745 bounds [i].lower_bound = lower_bounds [i];
1748 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1749 out_of_memory (MYGUINT32_MAX);
1751 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1752 out_of_memory (MYGUINT32_MAX);
1753 byte_len += sizeof (MonoArray);
1755 * Following three lines almost taken from mono_object_new ():
1756 * they need to be kept in sync.
1758 vtable = mono_class_vtable (domain, array_class);
1759 #if CREATION_SPEEDUP
1760 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1761 o = mono_object_allocate_spec (byte_len, vtable);
1763 o = mono_object_allocate (byte_len);
1767 o = mono_object_allocate (byte_len);
1771 array = (MonoArray*)o;
1773 array->bounds = bounds;
1774 array->max_length = len;
1776 mono_profiler_allocation (o, array_class);
1783 * @domain: domain where the object is created
1784 * @eclass: element class
1785 * @n: number of array elements
1787 * This routine creates a new szarray with @n elements of type @eclass.
1790 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1794 MONO_ARCH_SAVE_REGS;
1796 ac = mono_array_class_get (eclass, 1);
1797 g_assert (ac != NULL);
1799 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1803 * mono_array_new_specific:
1804 * @vtable: a vtable in the appropriate domain for an initialized class
1805 * @n: number of array elements
1807 * This routine is a fast alternative to mono_array_new() for code which
1808 * can be sure about the domain it operates in.
1811 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1815 guint32 byte_len, elem_size;
1817 MONO_ARCH_SAVE_REGS;
1819 elem_size = mono_array_element_size (vtable->klass);
1820 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1821 out_of_memory (MYGUINT32_MAX);
1822 byte_len = n * elem_size;
1823 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1824 out_of_memory (MYGUINT32_MAX);
1825 byte_len += sizeof (MonoArray);
1826 #if CREATION_SPEEDUP
1827 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1828 o = mono_object_allocate_spec (byte_len, vtable);
1830 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1831 o = mono_object_allocate (byte_len);
1835 o = mono_object_allocate (byte_len);
1839 ao = (MonoArray *)o;
1842 mono_profiler_allocation (o, vtable->klass);
1848 * mono_string_new_utf16:
1849 * @text: a pointer to an utf16 string
1850 * @len: the length of the string
1852 * Returns: A newly created string object which contains @text.
1855 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1859 s = mono_string_new_size (domain, len);
1860 g_assert (s != NULL);
1862 memcpy (mono_string_chars (s), text, len * 2);
1868 * mono_string_new_size:
1869 * @text: a pointer to an utf16 string
1870 * @len: the length of the string
1872 * Returns: A newly created string object of @len
1875 mono_string_new_size (MonoDomain *domain, gint32 len)
1880 vtable = mono_class_vtable (domain, mono_defaults.string_class);
1882 #if CREATION_SPEEDUP
1883 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1884 s = mono_object_allocate_spec (sizeof (MonoString) + ((len + 1) * 2), vtable);
1886 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1887 s->object.vtable = vtable;
1890 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1891 s->object.vtable = vtable;
1895 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
1901 * mono_string_new_len:
1902 * @text: a pointer to an utf8 string
1903 * @length: number of bytes in @text to consider
1905 * Returns: A newly created string object which contains @text.
1908 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1910 GError *error = NULL;
1911 MonoString *o = NULL;
1913 glong items_written;
1915 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1918 o = mono_string_new_utf16 (domain, ut, items_written);
1920 g_error_free (error);
1929 * @text: a pointer to an utf8 string
1931 * Returns: A newly created string object which contains @text.
1934 mono_string_new (MonoDomain *domain, const char *text)
1936 GError *error = NULL;
1937 MonoString *o = NULL;
1939 glong items_written;
1944 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1947 o = mono_string_new_utf16 (domain, ut, items_written);
1949 g_error_free (error);
1957 * mono_string_new_wrapper:
1958 * @text: pointer to utf8 characters.
1960 * Helper function to create a string object from @text in the current domain.
1963 mono_string_new_wrapper (const char *text)
1965 MonoDomain *domain = mono_domain_get ();
1967 MONO_ARCH_SAVE_REGS;
1970 return mono_string_new (domain, text);
1977 * @class: the class of the value
1978 * @value: a pointer to the unboxed data
1980 * Returns: A newly created object which contains @value.
1983 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1989 g_assert (class->valuetype);
1991 vtable = mono_class_vtable (domain, class);
1992 size = mono_class_instance_size (class);
1993 res = mono_object_allocate (size);
1994 res->vtable = vtable;
1995 mono_profiler_allocation (res, class);
1997 size = size - sizeof (MonoObject);
1999 #if NO_UNALIGNED_ACCESS
2000 memcpy ((char *)res + sizeof (MonoObject), value, size);
2004 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2007 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2010 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2013 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2016 memcpy ((char *)res + sizeof (MonoObject), value, size);
2019 if (class->has_finalize)
2020 mono_object_register_finalizer (res);
2025 mono_object_unbox (MonoObject *obj)
2027 /* add assert for valuetypes? */
2028 return ((char*)obj) + sizeof (MonoObject);
2032 * mono_object_isinst:
2034 * @klass: a pointer to a class
2036 * Returns: @obj if @obj is derived from @klass
2039 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2042 mono_class_init (klass);
2044 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2045 return mono_object_isinst_mbyref (obj, klass);
2050 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2054 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2063 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2064 if ((klass->interface_id <= vt->max_interface_id) &&
2065 (vt->interface_offsets [klass->interface_id] != 0))
2069 MonoClass *oklass = vt->klass;
2070 if ((oklass == mono_defaults.transparent_proxy_class))
2071 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2073 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2077 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2079 MonoDomain *domain = mono_domain_get ();
2081 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2082 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2083 MonoMethod *im = NULL;
2087 for (i = 0; i < rpklass->method.count; ++i) {
2088 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2089 im = rpklass->methods [i];
2094 im = mono_object_get_virtual_method (rp, im);
2097 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2100 res = mono_runtime_invoke (im, rp, pa, NULL);
2102 if (*(MonoBoolean *) mono_object_unbox(res)) {
2103 /* Update the vtable of the remote type, so it can safely cast to this new type */
2104 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2105 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2114 * mono_object_castclass_mbyref:
2116 * @klass: a pointer to a class
2118 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2121 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2123 if (!obj) return NULL;
2124 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2126 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2128 "InvalidCastException"));
2133 MonoDomain *orig_domain;
2139 str_lookup (MonoDomain *domain, gpointer user_data)
2141 LDStrInfo *info = user_data;
2142 if (info->res || domain == info->orig_domain)
2144 mono_domain_lock (domain);
2145 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2146 mono_domain_unlock (domain);
2150 mono_string_is_interned_lookup (MonoString *str, int insert)
2152 MonoGHashTable *ldstr_table;
2155 char *ins = g_malloc (4 + str->length * 2);
2158 /* Encode the length */
2159 /* Same code as in mono_image_insert_string () */
2161 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2164 * ins is stored in the hash table as a key and needs to have the same
2165 * representation as in the metadata: we swap the character bytes on big
2168 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2171 char *p2 = (char *)mono_string_chars (str);
2172 for (i = 0; i < str->length; ++i) {
2179 memcpy (p, mono_string_chars (str), str->length * 2);
2181 domain = ((MonoObject *)str)->vtable->domain;
2182 ldstr_table = domain->ldstr_table;
2183 mono_domain_lock (domain);
2184 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2185 mono_domain_unlock (domain);
2190 mono_g_hash_table_insert (ldstr_table, ins, str);
2191 mono_domain_unlock (domain);
2194 LDStrInfo ldstr_info;
2195 ldstr_info.orig_domain = domain;
2196 ldstr_info.ins = ins;
2197 ldstr_info.res = NULL;
2199 mono_domain_foreach (str_lookup, &ldstr_info);
2200 if (ldstr_info.res) {
2202 * the string was already interned in some other domain:
2203 * intern it in the current one as well.
2205 mono_g_hash_table_insert (ldstr_table, ins, str);
2206 mono_domain_unlock (domain);
2210 mono_domain_unlock (domain);
2216 mono_string_is_interned (MonoString *o)
2218 return mono_string_is_interned_lookup (o, FALSE);
2222 mono_string_intern (MonoString *str)
2224 return mono_string_is_interned_lookup (str, TRUE);
2229 * @domain: the domain where the string will be used.
2230 * @image: a metadata context
2231 * @idx: index into the user string table.
2233 * Implementation for the ldstr opcode.
2236 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2238 const char *str, *sig;
2242 MONO_ARCH_SAVE_REGS;
2245 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2247 sig = str = mono_metadata_user_string (image, idx);
2249 mono_domain_lock (domain);
2250 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2251 mono_domain_unlock (domain);
2255 len2 = mono_metadata_decode_blob_size (str, &str);
2258 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2259 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2262 guint16 *p2 = (guint16*)mono_string_chars (o);
2263 for (i = 0; i < len2; ++i) {
2264 *p2 = GUINT16_FROM_LE (*p2);
2269 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2270 mono_domain_unlock (domain);
2276 * mono_string_to_utf8:
2277 * @s: a System.String
2279 * Return the UTF8 representation for @s.
2280 * the resulting buffer nedds to be freed with g_free().
2283 mono_string_to_utf8 (MonoString *s)
2286 GError *error = NULL;
2292 return g_strdup ("");
2294 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2296 g_warning (error->message);
2297 g_error_free (error);
2304 * mono_string_to_utf16:
2307 * Return an null-terminated array of the utf-16 chars
2308 * contained in @s. The result must be freed with g_free().
2309 * This is a temporary helper until our string implementation
2310 * is reworked to always include the null terminating char.
2313 mono_string_to_utf16 (MonoString *s)
2320 as = g_malloc ((s->length * 2) + 2);
2321 as [(s->length * 2)] = '\0';
2322 as [(s->length * 2) + 1] = '\0';
2325 return (gunichar2 *)(as);
2328 memcpy (as, mono_string_chars(s), s->length * 2);
2329 return (gunichar2 *)(as);
2333 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2336 mono_string_from_utf16 (gunichar2 *data)
2338 MonoDomain *domain = mono_domain_get ();
2344 while (data [len]) len++;
2346 return mono_string_new_utf16 (domain, data, len);
2350 default_ex_handler (MonoException *ex)
2352 MonoObject *o = (MonoObject*)ex;
2353 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2357 static MonoExceptionFunc ex_handler = default_ex_handler;
2360 mono_install_handler (MonoExceptionFunc func)
2362 ex_handler = func? func: default_ex_handler;
2366 * mono_raise_exception:
2367 * @ex: exception object
2369 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2372 mono_raise_exception (MonoException *ex)
2375 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2376 * that will cause gcc to omit the function epilog, causing problems when
2377 * the JIT tries to walk the stack, since the return address on the stack
2378 * will point into the next function in the executable, not this one.
2385 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2387 MonoWaitHandle *res;
2389 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2391 res->handle = handle;
2397 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2399 MonoAsyncResult *res;
2401 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2404 res->async_state = state;
2406 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2408 res->sync_completed = FALSE;
2409 res->completed = FALSE;
2415 mono_message_init (MonoDomain *domain,
2416 MonoMethodMessage *this,
2417 MonoReflectionMethod *method,
2418 MonoArray *out_args)
2420 MonoMethodSignature *sig = method->method->signature;
2426 this->method = method;
2428 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2429 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2430 this->async_result = NULL;
2431 this->call_type = CallType_Sync;
2433 names = g_new (char *, sig->param_count);
2434 mono_method_get_param_names (method->method, (const char **) names);
2435 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2437 for (i = 0; i < sig->param_count; i++) {
2438 name = mono_string_new (domain, names [i]);
2439 mono_array_set (this->names, gpointer, i, name);
2443 for (i = 0, j = 0; i < sig->param_count; i++) {
2445 if (sig->params [i]->byref) {
2447 gpointer arg = mono_array_get (out_args, gpointer, j);
2448 mono_array_set (this->args, gpointer, i, arg);
2452 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2457 mono_array_set (this->arg_types, guint8, i, arg_type);
2462 * mono_remoting_invoke:
2463 * @real_proxy: pointer to a RealProxy object
2464 * @msg: The MonoMethodMessage to execute
2465 * @exc: used to store exceptions
2466 * @out_args: used to store output arguments
2468 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2469 * IMessage interface and it is not trivial to extract results from there. So
2470 * we call an helper method PrivateInvoke instead of calling
2471 * RealProxy::Invoke() directly.
2473 * Returns: the result object.
2476 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2477 MonoObject **exc, MonoArray **out_args)
2479 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2482 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2488 klass = mono_defaults.real_proxy_class;
2490 for (i = 0; i < klass->method.count; ++i) {
2491 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2492 klass->methods [i]->signature->param_count == 4) {
2493 im = klass->methods [i];
2499 real_proxy->vtable->domain->private_invoke_method = im;
2502 pa [0] = real_proxy;
2507 return mono_runtime_invoke (im, NULL, pa, exc);
2511 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2512 MonoObject **exc, MonoArray **out_args)
2516 MonoMethodSignature *sig;
2517 int i, j, outarg_count = 0;
2519 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2521 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2522 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2523 target = tp->rp->unwrapped_server;
2525 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2529 domain = mono_domain_get ();
2530 method = msg->method->method;
2531 sig = method->signature;
2533 for (i = 0; i < sig->param_count; i++) {
2534 if (sig->params [i]->byref)
2538 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2541 for (i = 0, j = 0; i < sig->param_count; i++) {
2542 if (sig->params [i]->byref) {
2544 arg = mono_array_get (msg->args, gpointer, i);
2545 mono_array_set (*out_args, gpointer, j, arg);
2550 return mono_runtime_invoke_array (method, target, msg->args, exc);
2554 mono_print_unhandled_exception (MonoObject *exc)
2556 char *message = (char *) "";
2560 gboolean free_message = FALSE;
2563 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2564 klass = exc->vtable->klass;
2566 while (klass && method == NULL) {
2567 for (i = 0; i < klass->method.count; ++i) {
2568 method = klass->methods [i];
2569 if (!strcmp ("ToString", method->name) &&
2570 method->signature->param_count == 0 &&
2571 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2572 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2579 klass = klass->parent;
2584 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2586 message = mono_string_to_utf8 (str);
2587 free_message = TRUE;
2592 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2593 * exc->vtable->klass->name, message);
2595 g_printerr ("\nUnhandled Exception: %s\n", message);
2602 * mono_delegate_ctor:
2603 * @this: pointer to an uninitialized delegate object
2604 * @target: target object
2605 * @addr: pointer to native code
2607 * This is used to initialize a delegate. We also insert the method_info if
2608 * we find the info with mono_jit_info_table_find().
2611 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2613 MonoDomain *domain = mono_domain_get ();
2614 MonoDelegate *delegate = (MonoDelegate *)this;
2615 MonoMethod *method = NULL;
2622 class = this->vtable->klass;
2624 if ((ji = mono_jit_info_table_find (domain, addr))) {
2625 method = ji->method;
2626 delegate->method_info = mono_method_get_object (domain, method, NULL);
2629 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2631 method = mono_marshal_get_remoting_invoke (method);
2632 delegate->method_ptr = mono_compile_method (method);
2633 delegate->target = target;
2635 delegate->method_ptr = addr;
2636 delegate->target = target;
2641 * mono_method_call_message_new:
2643 * Translates arguments pointers into a Message.
2646 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2647 MonoDelegate **cb, MonoObject **state)
2649 MonoDomain *domain = mono_domain_get ();
2650 MonoMethodSignature *sig = method->signature;
2651 MonoMethodMessage *msg;
2654 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2657 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2658 count = sig->param_count - 2;
2660 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2661 count = sig->param_count;
2664 for (i = 0; i < count; i++) {
2669 if (sig->params [i]->byref)
2670 vpos = *((gpointer *)params [i]);
2674 type = sig->params [i]->type;
2675 class = mono_class_from_mono_type (sig->params [i]);
2677 if (class->valuetype)
2678 arg = mono_value_box (domain, class, vpos);
2680 arg = *((MonoObject **)vpos);
2682 mono_array_set (msg->args, gpointer, i, arg);
2685 if (cb != NULL && state != NULL) {
2686 *cb = *((MonoDelegate **)params [i]);
2688 *state = *((MonoObject **)params [i]);
2695 * mono_method_return_message_restore:
2697 * Restore results from message based processing back to arguments pointers
2700 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2702 MonoMethodSignature *sig = method->signature;
2703 int i, j, type, size;
2704 for (i = 0, j = 0; i < sig->param_count; i++) {
2705 MonoType *pt = sig->params [i];
2708 char *arg = mono_array_get (out_args, gpointer, j);
2712 case MONO_TYPE_VOID:
2713 g_assert_not_reached ();
2717 case MONO_TYPE_BOOLEAN:
2720 case MONO_TYPE_CHAR:
2727 case MONO_TYPE_VALUETYPE: {
2728 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2729 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2732 case MONO_TYPE_STRING:
2733 case MONO_TYPE_CLASS:
2734 case MONO_TYPE_ARRAY:
2735 case MONO_TYPE_SZARRAY:
2736 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2739 g_assert_not_reached ();
2748 * mono_load_remote_field:
2749 * @this: pointer to an object
2750 * @klass: klass of the object containing @field
2751 * @field: the field to load
2752 * @res: a storage to store the result
2754 * This method is called by the runtime on attempts to load fields of
2755 * transparent proxy objects. @this points to such TP, @klass is the class of
2756 * the object containing @field. @res is a storage location which can be
2757 * used to store the result.
2759 * Returns: an address pointing to the value of field.
2762 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2764 static MonoMethod *getter = NULL;
2765 MonoDomain *domain = mono_domain_get ();
2766 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2767 MonoClass *field_class;
2768 MonoMethodMessage *msg;
2769 MonoArray *out_args;
2773 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2778 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2779 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2786 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2787 MonoMethod *cm = mono_defaults.object_class->methods [i];
2789 if (!strcmp (cm->name, "FieldGetter")) {
2797 field_class = mono_class_from_mono_type (field->type);
2799 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2800 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2801 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2803 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2804 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2806 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2808 if (exc) mono_raise_exception ((MonoException *)exc);
2810 *res = mono_array_get (out_args, MonoObject *, 0);
2812 if (field_class->valuetype) {
2813 return ((char *)*res) + sizeof (MonoObject);
2819 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2821 static MonoMethod *getter = NULL;
2822 MonoDomain *domain = mono_domain_get ();
2823 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2824 MonoClass *field_class;
2825 MonoMethodMessage *msg;
2826 MonoArray *out_args;
2827 MonoObject *exc, *res;
2829 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2831 field_class = mono_class_from_mono_type (field->type);
2833 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2835 if (field_class->valuetype) {
2836 res = mono_object_new (domain, field_class);
2837 val = ((gchar *) res) + sizeof (MonoObject);
2841 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2848 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2849 MonoMethod *cm = mono_defaults.object_class->methods [i];
2851 if (!strcmp (cm->name, "FieldGetter")) {
2859 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2860 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2861 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2863 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2864 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2866 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2868 if (exc) mono_raise_exception ((MonoException *)exc);
2870 res = mono_array_get (out_args, MonoObject *, 0);
2876 * mono_store_remote_field:
2877 * @this: pointer to an object
2878 * @klass: klass of the object containing @field
2879 * @field: the field to load
2880 * @val: the value/object to store
2882 * This method is called by the runtime on attempts to store fields of
2883 * transparent proxy objects. @this points to such TP, @klass is the class of
2884 * the object containing @field. @val is the new value to store in @field.
2887 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
2889 static MonoMethod *setter = NULL;
2890 MonoDomain *domain = mono_domain_get ();
2891 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2892 MonoClass *field_class;
2893 MonoMethodMessage *msg;
2894 MonoArray *out_args;
2898 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2900 field_class = mono_class_from_mono_type (field->type);
2902 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2903 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
2904 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
2911 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2912 MonoMethod *cm = mono_defaults.object_class->methods [i];
2914 if (!strcmp (cm->name, "FieldSetter")) {
2922 if (field_class->valuetype)
2923 arg = mono_value_box (domain, field_class, val);
2925 arg = *((MonoObject **)val);
2928 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2929 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2931 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2932 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2933 mono_array_set (msg->args, gpointer, 2, arg);
2935 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2937 if (exc) mono_raise_exception ((MonoException *)exc);
2941 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
2943 static MonoMethod *setter = NULL;
2944 MonoDomain *domain = mono_domain_get ();
2945 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2946 MonoClass *field_class;
2947 MonoMethodMessage *msg;
2948 MonoArray *out_args;
2951 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2953 field_class = mono_class_from_mono_type (field->type);
2955 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2956 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
2957 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
2964 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2965 MonoMethod *cm = mono_defaults.object_class->methods [i];
2967 if (!strcmp (cm->name, "FieldSetter")) {
2975 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2976 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2978 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2979 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2980 mono_array_set (msg->args, gpointer, 2, arg);
2982 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2984 if (exc) mono_raise_exception ((MonoException *)exc);