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/domain-internals.h>
23 #include "mono/metadata/metadata-internals.h"
24 #include <mono/metadata/assembly.h>
25 #include <mono/metadata/threadpool.h>
26 #include <mono/metadata/marshal.h>
27 #include "mono/metadata/debug-helpers.h"
28 #include "mono/metadata/marshal.h"
29 #include <mono/metadata/threads.h>
30 #include <mono/metadata/threads-types.h>
31 #include <mono/metadata/environment.h>
32 #include "mono/metadata/profiler-private.h"
33 #include <mono/os/gc_wrapper.h>
34 #include <mono/utils/strenc.h>
37 * Enable experimental typed allocation using the GC_gcj_malloc function.
39 #ifdef HAVE_GC_GCJ_MALLOC
40 #define CREATION_SPEEDUP 1
44 mono_runtime_object_init (MonoObject *this)
47 MonoMethod *method = NULL;
48 MonoClass *klass = this->vtable->klass;
50 for (i = 0; i < klass->method.count; ++i) {
51 if (!strcmp (".ctor", klass->methods [i]->name) &&
52 klass->methods [i]->signature->param_count == 0) {
53 method = klass->methods [i];
60 mono_runtime_invoke (method, this, NULL, NULL);
63 /* The pseudo algorithm for type initialization from the spec
64 Note it doesn't say anything about domains - only threads.
66 2. If the type is initialized you are done.
67 2.1. If the type is not yet initialized, try to take an
69 2.2. If successful, record this thread as responsible for
70 initializing the type and proceed to step 2.3.
71 2.2.1. If not, see whether this thread or any thread
72 waiting for this thread to complete already holds the lock.
73 2.2.2. If so, return since blocking would create a deadlock. This thread
74 will now see an incompletely initialized state for the type,
75 but no deadlock will arise.
76 2.2.3 If not, block until the type is initialized then return.
77 2.3 Initialize the parent type and then all interfaces implemented
79 2.4 Execute the type initialization code for this type.
80 2.5 Mark the type as initialized, release the initialization lock,
81 awaken any threads waiting for this type to be initialized,
88 guint32 initializing_tid;
89 guint32 waiting_count;
90 CRITICAL_SECTION initialization_section;
91 } TypeInitializationLock;
93 /* for locking access to type_initialization_hash and blocked_thread_hash */
94 static CRITICAL_SECTION type_initialization_section;
96 /* from vtable to lock */
97 static GHashTable *type_initialization_hash;
99 /* from thread id to thread id being waited on */
100 static GHashTable *blocked_thread_hash;
103 static MonoThread *main_thread;
106 mono_type_initialization_init (void)
108 InitializeCriticalSection (&type_initialization_section);
109 type_initialization_hash = g_hash_table_new (NULL, NULL);
110 blocked_thread_hash = g_hash_table_new (NULL, NULL);
114 * mono_runtime_class_init:
115 * @vtable: vtable that needs to be initialized
117 * This routine calls the class constructor for @vtable.
120 mono_runtime_class_init (MonoVTable *vtable)
124 MonoException *exc_to_throw;
125 MonoMethod *method = NULL;
132 if (vtable->initialized)
137 klass = vtable->klass;
139 for (i = 0; i < klass->method.count; ++i) {
140 method = klass->methods [i];
141 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
142 (strcmp (".cctor", method->name) == 0)) {
149 MonoDomain *domain = vtable->domain;
150 TypeInitializationLock *lock;
151 guint32 tid = GetCurrentThreadId();
152 int do_initialization = 0;
153 MonoDomain *last_domain = NULL;
155 EnterCriticalSection (&type_initialization_section);
156 /* double check... */
157 if (vtable->initialized) {
158 LeaveCriticalSection (&type_initialization_section);
161 lock = g_hash_table_lookup (type_initialization_hash, vtable);
163 /* This thread will get to do the initialization */
164 if (mono_domain_get () != domain) {
165 /* Transfer into the target domain */
166 last_domain = mono_domain_get ();
167 if (!mono_domain_set (domain, FALSE)) {
168 vtable->initialized = 1;
169 LeaveCriticalSection (&type_initialization_section);
170 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
173 lock = g_malloc (sizeof(TypeInitializationLock));
174 InitializeCriticalSection (&lock->initialization_section);
175 lock->initializing_tid = tid;
176 lock->waiting_count = 1;
177 /* grab the vtable lock while this thread still owns type_initialization_section */
178 EnterCriticalSection (&lock->initialization_section);
179 g_hash_table_insert (type_initialization_hash, vtable, lock);
180 do_initialization = 1;
184 if (lock->initializing_tid == tid) {
185 LeaveCriticalSection (&type_initialization_section);
188 /* see if the thread doing the initialization is already blocked on this thread */
189 blocked = GUINT_TO_POINTER (lock->initializing_tid);
190 while ((blocked = g_hash_table_lookup (blocked_thread_hash, blocked))) {
191 if (blocked == GUINT_TO_POINTER (tid)) {
192 LeaveCriticalSection (&type_initialization_section);
196 ++lock->waiting_count;
197 /* record the fact that we are waiting on the initializing thread */
198 g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), GUINT_TO_POINTER (lock->initializing_tid));
200 LeaveCriticalSection (&type_initialization_section);
202 if (do_initialization) {
203 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
205 mono_domain_set (last_domain, TRUE);
206 LeaveCriticalSection (&lock->initialization_section);
208 /* this just blocks until the initializing thread is done */
209 EnterCriticalSection (&lock->initialization_section);
210 LeaveCriticalSection (&lock->initialization_section);
213 EnterCriticalSection (&type_initialization_section);
214 if (lock->initializing_tid != tid)
215 g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
216 --lock->waiting_count;
217 if (lock->waiting_count == 0) {
218 DeleteCriticalSection (&lock->initialization_section);
219 g_hash_table_remove (type_initialization_hash, vtable);
222 vtable->initialized = 1;
223 /* FIXME: if the cctor fails, the type must be marked as unusable */
224 LeaveCriticalSection (&type_initialization_section);
226 vtable->initialized = 1;
231 (klass->image == mono_defaults.corlib &&
232 !strcmp (klass->name_space, "System") &&
233 !strcmp (klass->name, "TypeInitializationException")))
234 return; /* No static constructor found or avoid infinite loop */
236 if (klass->name_space && *klass->name_space)
237 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
239 full_name = g_strdup (klass->name);
241 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
244 mono_raise_exception (exc_to_throw);
248 default_trampoline (MonoMethod *method)
254 default_remoting_trampoline (MonoMethod *method)
256 g_error ("remoting not installed");
260 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
261 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
264 mono_install_trampoline (MonoTrampoline func)
266 arch_create_jit_trampoline = func? func: default_trampoline;
270 mono_install_remoting_trampoline (MonoTrampoline func)
272 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
275 static MonoCompileFunc default_mono_compile_method = NULL;
278 mono_install_compile_method (MonoCompileFunc func)
280 default_mono_compile_method = func;
284 mono_compile_method (MonoMethod *method)
286 if (!default_mono_compile_method) {
287 g_error ("compile method called on uninitialized runtime");
290 return default_mono_compile_method (method);
294 #if 0 && HAVE_BOEHM_GC
296 vtable_finalizer (void *obj, void *data) {
297 g_print ("%s finalized (%p)\n", (char*)data, obj);
303 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
306 * The vtables in the root appdomain are assumed to be reachable by other
307 * roots, and we don't use typed allocation in the other domains.
310 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
313 mono_class_compute_gc_descriptor (MonoClass *class)
315 MonoClassField *field;
319 static gboolean gcj_inited = FALSE;
324 GC_init_gcj_malloc (5, NULL);
328 mono_class_init (class);
330 if (class->gc_descr_inited)
333 class->gc_descr_inited = TRUE;
334 class->gc_descr = GC_NO_DESCRIPTOR;
336 if (class == mono_defaults.string_class) {
337 bitmap = GC_HEADER_BITMAP;
338 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
340 else if (class->rank) {
341 mono_class_compute_gc_descriptor (class->element_class);
343 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
344 bitmap = GC_HEADER_BITMAP;
346 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
347 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
351 static int count = 0;
355 /* GC 6.1 has trouble handling 64 bit descriptors... */
356 if ((class->instance_size / sizeof (gpointer)) > 30) {
357 // printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer));
361 bitmap = GC_HEADER_BITMAP;
368 // printf("KLASS: %s.\n", class->name);
370 for (p = class; p != NULL; p = p->parent) {
371 for (i = 0; i < p->field.count; ++i) {
372 field = &p->fields [i];
373 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
375 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
378 pos = field->offset / sizeof (gpointer);
380 if (field->type->byref)
383 switch (field->type->type) {
384 case MONO_TYPE_BOOLEAN:
396 // printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap);
399 case MONO_TYPE_STRING:
400 case MONO_TYPE_SZARRAY:
401 case MONO_TYPE_CLASS:
402 case MONO_TYPE_OBJECT:
403 case MONO_TYPE_ARRAY:
405 g_assert ((field->offset % sizeof(gpointer)) == 0);
407 bitmap |= ((guint64)1) << pos;
408 // printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap);
410 case MONO_TYPE_VALUETYPE: {
411 MonoClass *fclass = field->type->data.klass;
412 if (!fclass->enumtype) {
413 mono_class_compute_gc_descriptor (fclass);
414 bitmap |= (fclass->gc_bitmap >> (sizeof (MonoObject) / sizeof (gpointer))) << pos;
424 // printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap);
425 class->gc_bitmap = bitmap;
426 /* Convert to the format expected by GC_make_descriptor */
427 bm [0] = (guint32)bitmap;
428 bm [1] = (guint32)(bitmap >> 32);
429 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bm, class->instance_size / sizeof (gpointer));
432 #endif /* CREATION_SPEEDUP */
435 * field_is_special_static:
437 * Returns SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
438 * SPECIAL_STATIC_NONE otherwise.
441 field_is_special_static (MonoClass *fklass, MonoClassField *field)
443 MonoCustomAttrInfo *ainfo;
445 ainfo = mono_custom_attrs_from_field (fklass, field);
448 for (i = 0; i < ainfo->num_attrs; ++i) {
449 MonoClass *klass = ainfo->attrs [i].ctor->klass;
450 if (klass->image == mono_defaults.corlib) {
451 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
452 mono_custom_attrs_free (ainfo);
453 return SPECIAL_STATIC_THREAD;
455 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
456 mono_custom_attrs_free (ainfo);
457 return SPECIAL_STATIC_CONTEXT;
461 mono_custom_attrs_free (ainfo);
462 return SPECIAL_STATIC_NONE;
467 * @domain: the application domain
468 * @class: the class to initialize
470 * VTables are domain specific because we create domain specific code, and
471 * they contain the domain specific static class data.
474 mono_class_vtable (MonoDomain *domain, MonoClass *class)
476 MonoVTable *vt = NULL;
477 MonoClassField *field;
483 guint32 constant_cols [MONO_CONSTANT_SIZE];
487 vt = class->cached_vtable;
488 if (vt && vt->domain == domain)
491 mono_domain_lock (domain);
492 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
493 mono_domain_unlock (domain);
498 mono_class_init (class);
500 mono_stats.used_class_count++;
501 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
503 vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
505 vt = mono_mempool_alloc0 (domain->mp, vtable_size);
511 mono_class_compute_gc_descriptor (class);
512 if (domain != mono_get_root_domain ())
514 * We can't use typed allocation in the non-root domains, since the
515 * collector needs the GC descriptor stored in the vtable even after
516 * the mempool containing the vtable is destroyed when the domain is
517 * unloaded. An alternative might be to allocate vtables in the GC
518 * heap, but this does not seem to work (it leads to crashes inside
519 * libgc). If that approach is tried, two gc descriptors need to be
520 * allocated for each class: one for the root domain, and one for all
521 * other domains. The second descriptor should contain a bit for the
522 * vtable field in MonoObject, since we can no longer assume the
523 * vtable is reachable by other roots after the appdomain is unloaded.
525 vt->gc_descr = GC_NO_DESCRIPTOR;
527 vt->gc_descr = class->gc_descr;
530 if (class->class_size) {
532 vt->data = GC_MALLOC (class->class_size + 8);
533 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
534 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
535 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
537 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
540 mono_stats.class_static_data_size += class->class_size + 8;
544 for (i = class->field.first; i < class->field.last; ++i) {
545 field = &class->fields [i - class->field.first];
546 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
548 if (mono_field_is_deleted (field))
550 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
551 gint32 special_static = field_is_special_static (class, field);
552 if (special_static != SPECIAL_STATIC_NONE) {
553 guint32 size, align, offset;
554 size = mono_type_size (field->type, &align);
555 offset = mono_alloc_special_static_data (special_static, size, align);
556 if (!domain->special_static_fields)
557 domain->special_static_fields = g_hash_table_new (NULL, NULL);
558 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
562 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
563 MonoClass *fklass = mono_class_from_mono_type (field->type);
564 t = (char*)vt->data + field->offset;
565 if (fklass->valuetype) {
566 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
568 /* it's a pointer type: add check */
569 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
570 *t = *(char *)field->data;
574 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
577 if (!field->def_value) {
578 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1), cindex + 1);
581 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
582 field->def_value = g_new0 (MonoConstant, 1);
583 field->def_value->type = constant_cols [MONO_CONSTANT_TYPE];
584 field->def_value->value = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
587 p = field->def_value->value;
588 len = mono_metadata_decode_blob_size (p, &p);
589 t = (char*)vt->data + field->offset;
590 /* should we check that the type matches? */
591 switch (field->def_value->type) {
592 case MONO_TYPE_BOOLEAN:
600 guint16 *val = (guint16*)t;
606 guint32 *val = (guint32*)t;
612 guint64 *val = (guint64*)t;
617 float *val = (float*)t;
622 double *val = (double*)t;
626 case MONO_TYPE_STRING: {
627 gpointer *val = (gpointer*)t;
628 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
629 gunichar2 *copy = g_malloc (len);
631 for (j = 0; j < len/2; j++) {
632 copy [j] = read16 (p);
635 *val = mono_string_new_utf16 (domain, copy, len/2);
638 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
642 case MONO_TYPE_CLASS:
643 /* nothing to do, we malloc0 the data and the value can be 0 only */
646 g_warning ("type 0x%02x should not be in constant table", field->def_value->type);
650 vt->max_interface_id = class->max_interface_id;
652 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
653 sizeof (gpointer) * (class->max_interface_id + 1));
655 /* initialize interface offsets */
656 for (i = 0; i <= class->max_interface_id; ++i) {
657 int slot = class->interface_offsets [i];
659 vt->interface_offsets [i] = &(vt->vtable [slot]);
663 * arch_create_jit_trampoline () can recursively call this function again
664 * because it compiles icall methods right away.
666 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
667 if (!class->cached_vtable)
668 class->cached_vtable = vt;
670 /* initialize vtable */
671 for (i = 0; i < class->vtable_size; ++i) {
674 if ((cm = class->vtable [i]))
675 vt->vtable [i] = arch_create_jit_trampoline (cm);
678 mono_domain_unlock (domain);
680 /* make sure the the parent is initialized */
682 mono_class_vtable (domain, class->parent);
684 vt->type = mono_type_get_object (domain, &class->byval_arg);
685 if (class->contextbound)
694 * mono_class_proxy_vtable:
695 * @domain: the application domain
696 * @remove_class: the remote class
698 * Creates a vtable for transparent proxies. It is basically
699 * a copy of the real vtable of the class wrapped in @remote_class,
700 * but all function pointers invoke the remoting functions, and
701 * vtable->klass points to the transparent proxy class, and not to @class.
704 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class)
706 MonoVTable *vt, *pvt;
707 int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
709 MonoClass *class = remote_class->proxy_class;
711 vt = mono_class_vtable (domain, class);
712 max_interface_id = vt->max_interface_id;
714 /* Calculate vtable space for extra interfaces */
715 for (j = 0; j < remote_class->interface_count; j++) {
716 MonoClass* iclass = remote_class->interfaces[j];
717 int method_count = iclass->method.count;
719 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
720 continue; /* interface implemented by the class */
722 for (i = 0; i < iclass->interface_count; i++)
723 method_count += iclass->interfaces[i]->method.count;
725 extra_interface_vtsize += method_count * sizeof (gpointer);
726 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
729 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
731 mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
733 pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
734 memcpy (pvt, vt, vtsize);
736 pvt->klass = mono_defaults.transparent_proxy_class;
738 /* initialize vtable */
739 for (i = 0; i < class->vtable_size; ++i) {
742 if ((cm = class->vtable [i]))
743 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
746 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
748 /* create trampolines for abstract methods */
749 for (k = class; k; k = k->parent) {
750 for (i = 0; i < k->method.count; i++) {
751 int slot = k->methods [i]->slot;
752 if (!pvt->vtable [slot])
753 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
758 pvt->max_interface_id = max_interface_id;
759 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
760 sizeof (gpointer) * (max_interface_id + 1));
762 /* initialize interface offsets */
763 for (i = 0; i <= class->max_interface_id; ++i) {
764 int slot = class->interface_offsets [i];
766 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
769 if (remote_class->interface_count > 0)
771 int slot = class->vtable_size;
776 /* Create trampolines for the methods of the interfaces */
777 for (n = 0; n < remote_class->interface_count; n++)
779 iclass = remote_class->interfaces[n];
780 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
781 continue; /* interface implemented by the class */
786 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
788 for (j = 0; j < interf->method.count; ++j) {
789 MonoMethod *cm = interf->methods [j];
790 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
792 slot += interf->method.count;
793 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
805 * @domain: the application domain
806 * @class_name: name of the remote class
808 * Creates and initializes a MonoRemoteClass object for a remote type.
812 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
816 mono_domain_lock (domain);
817 rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class_name);
820 mono_domain_unlock (domain);
824 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
826 rc->interface_count = 0;
827 rc->interfaces = NULL;
828 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
829 rc->proxy_class_name = mono_string_to_utf8 (class_name);
831 mono_g_hash_table_insert (domain->proxy_vtable_hash, class_name, rc);
832 mono_upgrade_remote_class (domain, rc, proxy_class);
834 if (rc->vtable == NULL)
835 rc->vtable = mono_class_proxy_vtable (domain, rc);
837 mono_domain_unlock (domain);
843 extend_interface_array (MonoDomain *domain, MonoRemoteClass *remote_class, int amount)
845 /* Extends the array of interfaces. Memory is extended using blocks of 5 pointers */
847 int current_size = ((remote_class->interface_count / 5) + 1) * 5;
848 remote_class->interface_count += amount;
850 if (remote_class->interface_count > current_size || remote_class->interfaces == NULL)
852 int new_size = ((remote_class->interface_count / 5) + 1) * 5;
853 MonoClass **new_array = mono_mempool_alloc (domain->mp, new_size * sizeof (MonoClass*));
855 if (remote_class->interfaces != NULL)
856 memcpy (new_array, remote_class->interfaces, current_size * sizeof (MonoClass*));
858 remote_class->interfaces = new_array;
864 * mono_upgrade_remote_class:
865 * @domain: the application domain
866 * @remote_class: the remote class
867 * @klass: class to which the remote class can be casted.
869 * Updates the vtable of the remote class by adding the necessary method slots
870 * and interface offsets so it can be safely casted to klass. klass can be a
871 * class or an interface.
873 void mono_upgrade_remote_class (MonoDomain *domain, MonoRemoteClass *remote_class, MonoClass *klass)
875 gboolean redo_vtable;
877 mono_domain_lock (domain);
879 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
882 for (i = 0; i < remote_class->interface_count; i++)
883 if (remote_class->interfaces[i] == klass) redo_vtable = FALSE;
886 extend_interface_array (domain, remote_class, 1);
887 remote_class->interfaces [remote_class->interface_count-1] = klass;
891 redo_vtable = (remote_class->proxy_class != klass);
892 remote_class->proxy_class = klass;
896 remote_class->vtable = mono_class_proxy_vtable (domain, remote_class);
899 printf ("remote class upgrade - class:%s num-interfaces:%d\n", remote_class->proxy_class_name, remote_class->interface_count);
901 for (n=0; n<remote_class->interface_count; n++)
902 printf (" I:%s\n", remote_class->interfaces[n]->name);
905 mono_domain_unlock (domain);
909 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
910 * the instance of a callvirt of method.
913 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
917 MonoMethod *res = NULL;
919 klass = mono_object_class (obj);
920 if (klass == mono_defaults.transparent_proxy_class) {
921 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
927 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
930 vtable = klass->vtable;
932 /* check method->slot is a valid index: perform isinstance? */
933 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
935 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
937 if (method->slot != -1)
938 res = vtable [method->slot];
942 if (!res) res = method; /* It may be an interface or abstract class method */
943 res = mono_marshal_get_remoting_invoke (res);
952 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
954 g_error ("runtime invoke called on uninitialized runtime");
958 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
961 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
963 return default_mono_runtime_invoke (method, obj, params, exc);
967 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
970 gpointer *p = (gpointer*)dest;
977 case MONO_TYPE_BOOLEAN:
980 guint8 *p = (guint8*)dest;
981 *p = *(guint8*)value;
986 case MONO_TYPE_CHAR: {
987 guint16 *p = (guint16*)dest;
988 *p = *(guint16*)value;
991 #if SIZEOF_VOID_P == 4
997 gint32 *p = (gint32*)dest;
998 *p = *(gint32*)value;
1001 #if SIZEOF_VOID_P == 8
1006 case MONO_TYPE_U8: {
1007 gint64 *p = (gint64*)dest;
1008 *p = *(gint64*)value;
1011 case MONO_TYPE_R4: {
1012 float *p = (float*)dest;
1013 *p = *(float*)value;
1016 case MONO_TYPE_R8: {
1017 double *p = (double*)dest;
1018 *p = *(double*)value;
1021 case MONO_TYPE_STRING:
1022 case MONO_TYPE_SZARRAY:
1023 case MONO_TYPE_CLASS:
1024 case MONO_TYPE_OBJECT:
1025 case MONO_TYPE_ARRAY:
1026 case MONO_TYPE_PTR: {
1027 gpointer *p = (gpointer*)dest;
1028 *p = deref_pointer? *(gpointer*)value: value;
1031 case MONO_TYPE_VALUETYPE:
1032 if (type->data.klass->enumtype) {
1033 t = type->data.klass->enum_basetype->type;
1037 size = mono_class_value_size (type->data.klass, NULL);
1038 memcpy (dest, value, size);
1042 g_warning ("got type %x", type->type);
1043 g_assert_not_reached ();
1048 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
1052 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1054 dest = (char*)obj + field->offset;
1055 set_value (field->type, dest, value, FALSE);
1059 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
1063 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1065 dest = (char*)vt->data + field->offset;
1066 set_value (field->type, dest, value, FALSE);
1070 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
1074 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1076 src = (char*)obj + field->offset;
1077 set_value (field->type, value, src, TRUE);
1081 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
1085 MonoVTable *vtable = NULL;
1087 gboolean is_static = FALSE;
1088 gboolean is_ref = FALSE;
1090 switch (field->type->type) {
1091 case MONO_TYPE_STRING:
1092 case MONO_TYPE_OBJECT:
1093 case MONO_TYPE_CLASS:
1094 case MONO_TYPE_ARRAY:
1095 case MONO_TYPE_SZARRAY:
1100 case MONO_TYPE_BOOLEAN:
1103 case MONO_TYPE_CHAR:
1112 case MONO_TYPE_VALUETYPE:
1113 is_ref = field->type->byref;
1116 g_error ("type 0x%x not handled in "
1117 "mono_field_get_value_object", field->type->type);
1121 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1123 vtable = mono_class_vtable (domain, field->parent);
1124 if (!vtable->initialized)
1125 mono_runtime_class_init (vtable);
1130 mono_field_static_get_value (vtable, field, &o);
1132 mono_field_get_value (obj, field, &o);
1137 /* boxed value type */
1138 klass = mono_class_from_mono_type (field->type);
1139 o = mono_object_new (domain, klass);
1140 v = ((gchar *) o) + sizeof (MonoObject);
1142 mono_field_static_get_value (vtable, field, v);
1144 mono_field_get_value (obj, field, v);
1152 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1156 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1158 src = (char*)vt->data + field->offset;
1159 set_value (field->type, value, src, TRUE);
1163 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1165 default_mono_runtime_invoke (prop->set, obj, params, exc);
1169 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1171 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1176 mono_get_delegate_invoke (MonoClass *klass)
1183 for (i = 0; i < klass->method.count; ++i) {
1184 if (klass->methods [i]->name[0] == 'I' &&
1185 !strcmp ("Invoke", klass->methods [i]->name)) {
1186 im = klass->methods [i];
1196 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1200 im = mono_get_delegate_invoke (delegate->vtable->klass);
1203 return mono_runtime_invoke (im, delegate, params, exc);
1206 static MonoArray* main_args;
1209 mono_runtime_get_main_args (void)
1215 fire_process_exit_event (void)
1217 MonoClassField *field;
1218 MonoDomain *domain = mono_domain_get ();
1220 MonoObject *delegate, *exc;
1222 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1225 if (domain != mono_get_root_domain ())
1228 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1229 if (delegate == NULL)
1234 mono_runtime_delegate_invoke (delegate, pa, &exc);
1238 * Execute a standard Main() method (argc/argv contains the
1239 * executable name). This method also sets the command line argument value
1240 * needed by System.Environment.
1243 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1247 MonoArray *args = NULL;
1248 MonoDomain *domain = mono_domain_get ();
1249 gchar *utf8_fullpath;
1252 main_thread = mono_thread_current ();
1254 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1256 if (!g_path_is_absolute (argv [0])) {
1257 gchar *basename = g_path_get_basename (argv [0]);
1258 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1262 utf8_fullpath = mono_utf8_from_external (fullpath);
1263 if(utf8_fullpath == NULL) {
1264 /* Printing the arg text will cause glib to
1265 * whinge about "Invalid UTF-8", but at least
1266 * its relevant, and shows the problem text
1269 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1270 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1277 utf8_fullpath = mono_utf8_from_external (argv[0]);
1278 if(utf8_fullpath == NULL) {
1279 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1280 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1285 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1286 g_free (utf8_fullpath);
1288 for (i = 1; i < argc; ++i) {
1292 utf8_arg=mono_utf8_from_external (argv[i]);
1293 if(utf8_arg==NULL) {
1294 /* Ditto the comment about Invalid UTF-8 here */
1295 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1296 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1300 arg = mono_string_new (domain, utf8_arg);
1301 mono_array_set (main_args, gpointer, i, arg);
1305 if (method->signature->param_count) {
1306 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1307 for (i = 0; i < argc; ++i) {
1308 /* The encodings should all work, given that
1309 * we've checked all these args for the
1312 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1313 mono_array_set (args, gpointer, i, arg);
1316 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1319 mono_assembly_set_main (method->klass->image->assembly);
1321 result = mono_runtime_exec_main (method, args, exc);
1322 fire_process_exit_event ();
1326 /* Used in mono_unhandled_exception */
1328 create_unhandled_exception_eventargs (MonoObject *exc)
1332 MonoMethod *method = NULL;
1333 MonoBoolean is_terminating = TRUE;
1337 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1340 mono_class_init (klass);
1342 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1343 for (i = 0; i < klass->method.count; ++i) {
1344 method = klass->methods [i];
1345 if (!strcmp (".ctor", method->name) &&
1346 method->signature->param_count == 2 &&
1347 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1355 args [1] = &is_terminating;
1357 obj = mono_object_new (mono_domain_get (), klass);
1358 mono_runtime_invoke (method, obj, args, NULL);
1364 * We call this function when we detect an unhandled exception
1365 * in the default domain.
1366 * It invokes the * UnhandledException event in AppDomain or prints
1367 * a warning to the console
1370 mono_unhandled_exception (MonoObject *exc)
1372 MonoDomain *domain = mono_domain_get ();
1373 MonoClassField *field;
1374 MonoObject *delegate;
1376 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1377 "UnhandledException");
1380 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1381 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1383 /* set exitcode only in the main thread */
1384 if (mono_thread_current () == main_thread)
1385 mono_environment_exitcode_set (1);
1386 if (domain != mono_get_root_domain () || !delegate) {
1387 mono_print_unhandled_exception (exc);
1389 MonoObject *e = NULL;
1392 pa [0] = domain->domain;
1393 pa [1] = create_unhandled_exception_eventargs (exc);
1394 mono_runtime_delegate_invoke (delegate, pa, &e);
1397 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1398 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1406 * Launch a new thread to start all setup that requires managed code
1409 * main_func is called back from the thread with main_args as the
1410 * parameter. The callback function is expected to start Main()
1411 * eventually. This function then waits for all managed threads to
1415 mono_runtime_exec_managed_code (MonoDomain *domain,
1416 MonoMainThreadFunc main_func,
1419 mono_thread_create (domain, main_func, main_args);
1421 mono_thread_manage ();
1425 * Execute a standard Main() method (args doesn't contain the
1429 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1439 domain = mono_object_domain (args);
1440 if (!domain->entry_assembly) {
1442 gchar *config_suffix;
1443 MonoAssembly *assembly;
1445 assembly = method->klass->image->assembly;
1446 domain->entry_assembly = assembly;
1447 domain->setup->application_base = mono_string_new (domain, assembly->basedir);
1449 config_suffix = g_strconcat (assembly->aname.name, ".exe.config", NULL);
1450 str = g_build_filename (assembly->basedir, config_suffix, NULL);
1451 g_free (config_suffix);
1452 domain->setup->configuration_file = mono_string_new (domain, str);
1456 /* FIXME: check signature of method */
1457 if (method->signature->ret->type == MONO_TYPE_I4) {
1459 res = mono_runtime_invoke (method, NULL, pa, exc);
1461 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1465 mono_environment_exitcode_set (rval);
1467 mono_runtime_invoke (method, NULL, pa, exc);
1471 /* If the return type of Main is void, only
1472 * set the exitcode if an exception was thrown
1473 * (we don't want to blow away an
1474 * explicitly-set exit code)
1477 mono_environment_exitcode_set (rval);
1485 mono_install_runtime_invoke (MonoInvokeFunc func)
1487 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1491 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1494 MonoMethodSignature *sig = method->signature;
1495 gpointer *pa = NULL;
1498 if (NULL != params) {
1499 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1500 for (i = 0; i < mono_array_length (params); i++) {
1501 if (sig->params [i]->byref) {
1505 switch (sig->params [i]->type) {
1508 case MONO_TYPE_BOOLEAN:
1511 case MONO_TYPE_CHAR:
1520 case MONO_TYPE_VALUETYPE:
1521 if (sig->params [i]->byref) {
1522 /* MS seems to create the objects if a null is passed in */
1523 if (! ((gpointer *)params->vector)[i])
1524 ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
1527 g_assert (((gpointer*)params->vector) [i]);
1528 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1530 case MONO_TYPE_STRING:
1531 case MONO_TYPE_OBJECT:
1532 case MONO_TYPE_CLASS:
1533 case MONO_TYPE_ARRAY:
1534 case MONO_TYPE_SZARRAY:
1535 if (sig->params [i]->byref)
1536 pa [i] = &(((gpointer *)params->vector)[i]);
1538 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1541 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1546 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1548 obj = mono_object_new (mono_domain_get (), method->klass);
1549 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1550 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
1553 mono_runtime_invoke (method, obj, pa, exc);
1556 return mono_runtime_invoke (method, obj, pa, exc);
1560 out_of_memory (size_t size)
1563 * we could allocate at program startup some memory that we could release
1564 * back to the system at this point if we're really low on memory (ie, size is
1565 * lower than the memory we set apart)
1567 mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
1571 * mono_object_allocate:
1572 * @size: number of bytes to allocate
1574 * This is a very simplistic routine until we have our GC-aware
1577 * Returns: an allocated object of size @size, or NULL on failure.
1579 static inline void *
1580 mono_object_allocate (size_t size)
1583 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1584 void *o = GC_MALLOC (size);
1586 void *o = calloc (1, size);
1588 mono_stats.new_object_count++;
1591 out_of_memory (size);
1595 #if CREATION_SPEEDUP
1596 static inline void *
1597 mono_object_allocate_spec (size_t size, void *gcdescr)
1599 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1600 void *o = GC_GCJ_MALLOC (size, gcdescr);
1601 mono_stats.new_object_count++;
1604 out_of_memory (size);
1612 * Frees the memory used by the object. Debugging purposes
1613 * only, as we will have our GC system.
1616 mono_object_free (MonoObject *o)
1619 g_error ("mono_object_free called with boehm gc.");
1621 MonoClass *c = o->vtable->klass;
1623 memset (o, 0, c->instance_size);
1630 * @klass: the class of the object that we want to create
1632 * Returns: A newly created object whose definition is
1633 * looked up using @klass
1636 mono_object_new (MonoDomain *domain, MonoClass *klass)
1638 MONO_ARCH_SAVE_REGS;
1639 return mono_object_new_specific (mono_class_vtable (domain, klass));
1643 * mono_object_new_specific:
1644 * @vtable: the vtable of the object that we want to create
1646 * Returns: A newly created object with class and domain specified
1650 mono_object_new_specific (MonoVTable *vtable)
1654 MONO_ARCH_SAVE_REGS;
1659 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1662 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1666 mono_class_init (klass);
1668 for (i = 0; i < klass->method.count; ++i) {
1669 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1670 klass->methods [i]->signature->param_count == 1) {
1671 im = klass->methods [i];
1676 vtable->domain->create_proxy_for_type_method = im;
1679 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1681 o = mono_runtime_invoke (im, NULL, pa, NULL);
1682 if (o != NULL) return o;
1685 return mono_object_new_alloc_specific (vtable);
1689 mono_object_new_fast (MonoVTable *vtable)
1692 MONO_ARCH_SAVE_REGS;
1694 #if CREATION_SPEEDUP
1695 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1696 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1698 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1699 o = mono_object_allocate (vtable->klass->instance_size);
1703 o = mono_object_allocate (vtable->klass->instance_size);
1710 mono_object_new_alloc_specific (MonoVTable *vtable)
1714 #if CREATION_SPEEDUP
1715 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1716 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1718 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1719 o = mono_object_allocate (vtable->klass->instance_size);
1723 o = mono_object_allocate (vtable->klass->instance_size);
1726 if (vtable->klass->has_finalize)
1727 mono_object_register_finalizer (o);
1729 mono_profiler_allocation (o, vtable->klass);
1734 * mono_object_new_from_token:
1735 * @image: Context where the type_token is hosted
1736 * @token: a token of the type that we want to create
1738 * Returns: A newly created object whose definition is
1739 * looked up using @token in the @image image
1742 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1746 class = mono_class_get (image, token);
1748 return mono_object_new (domain, class);
1753 * mono_object_clone:
1754 * @obj: the object to clone
1756 * Returns: A newly created object who is a shallow copy of @obj
1759 mono_object_clone (MonoObject *obj)
1764 size = obj->vtable->klass->instance_size;
1765 o = mono_object_allocate (size);
1766 mono_profiler_allocation (o, obj->vtable->klass);
1768 memcpy (o, obj, size);
1770 if (obj->vtable->klass->has_finalize)
1771 mono_object_register_finalizer (o);
1777 * @array: the array to clone
1779 * Returns: A newly created array who is a shallow copy of @array
1782 mono_array_clone (MonoArray *array)
1787 MonoClass *klass = array->obj.vtable->klass;
1789 MONO_ARCH_SAVE_REGS;
1791 if (array->bounds == NULL) {
1792 size = mono_array_length (array);
1793 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1794 klass, &size, NULL);
1796 size *= mono_array_element_size (klass);
1797 memcpy (o, array, sizeof (MonoArray) + size);
1802 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1803 size = mono_array_element_size (klass);
1804 for (i = 0; i < klass->rank; ++i) {
1805 sizes [i] = array->bounds [i].length;
1806 size *= array->bounds [i].length;
1807 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1809 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1810 klass, sizes, sizes + klass->rank);
1811 memcpy (o, array, sizeof(MonoArray) + size);
1816 /* helper macros to check for overflow when calculating the size of arrays */
1817 #define MYGUINT32_MAX 4294967295U
1818 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1819 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1820 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1821 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1822 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1825 * mono_array_new_full:
1826 * @domain: domain where the object is created
1827 * @array_class: array class
1828 * @lengths: lengths for each dimension in the array
1829 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1831 * This routine creates a new array objects with the given dimensions,
1832 * lower bounds and type.
1835 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1836 guint32 *lengths, guint32 *lower_bounds)
1838 guint32 byte_len, len;
1841 MonoArrayBounds *bounds;
1845 if (!array_class->inited)
1846 mono_class_init (array_class);
1848 byte_len = mono_array_element_size (array_class);
1851 if (array_class->rank == 1 &&
1852 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1857 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1859 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1861 for (i = 0; i < array_class->rank; ++i) {
1862 bounds [i].length = lengths [i];
1863 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1864 out_of_memory (MYGUINT32_MAX);
1869 for (i = 0; i < array_class->rank; ++i)
1870 bounds [i].lower_bound = lower_bounds [i];
1873 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1874 out_of_memory (MYGUINT32_MAX);
1876 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1877 out_of_memory (MYGUINT32_MAX);
1878 byte_len += sizeof (MonoArray);
1880 * Following three lines almost taken from mono_object_new ():
1881 * they need to be kept in sync.
1883 vtable = mono_class_vtable (domain, array_class);
1884 #if CREATION_SPEEDUP
1885 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1886 o = mono_object_allocate_spec (byte_len, vtable);
1888 o = mono_object_allocate (byte_len);
1892 o = mono_object_allocate (byte_len);
1896 array = (MonoArray*)o;
1898 array->bounds = bounds;
1899 array->max_length = len;
1901 mono_profiler_allocation (o, array_class);
1908 * @domain: domain where the object is created
1909 * @eclass: element class
1910 * @n: number of array elements
1912 * This routine creates a new szarray with @n elements of type @eclass.
1915 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1919 MONO_ARCH_SAVE_REGS;
1921 ac = mono_array_class_get (eclass, 1);
1922 g_assert (ac != NULL);
1924 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1928 * mono_array_new_specific:
1929 * @vtable: a vtable in the appropriate domain for an initialized class
1930 * @n: number of array elements
1932 * This routine is a fast alternative to mono_array_new() for code which
1933 * can be sure about the domain it operates in.
1936 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1940 guint32 byte_len, elem_size;
1942 MONO_ARCH_SAVE_REGS;
1944 elem_size = mono_array_element_size (vtable->klass);
1945 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1946 out_of_memory (MYGUINT32_MAX);
1947 byte_len = n * elem_size;
1948 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1949 out_of_memory (MYGUINT32_MAX);
1950 byte_len += sizeof (MonoArray);
1951 #if CREATION_SPEEDUP
1952 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1953 o = mono_object_allocate_spec (byte_len, vtable);
1955 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1956 o = mono_object_allocate (byte_len);
1960 o = mono_object_allocate (byte_len);
1964 ao = (MonoArray *)o;
1967 mono_profiler_allocation (o, vtable->klass);
1973 * mono_string_new_utf16:
1974 * @text: a pointer to an utf16 string
1975 * @len: the length of the string
1977 * Returns: A newly created string object which contains @text.
1980 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1984 s = mono_string_new_size (domain, len);
1985 g_assert (s != NULL);
1987 memcpy (mono_string_chars (s), text, len * 2);
1993 * mono_string_new_size:
1994 * @text: a pointer to an utf16 string
1995 * @len: the length of the string
1997 * Returns: A newly created string object of @len
2000 mono_string_new_size (MonoDomain *domain, gint32 len)
2004 size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2006 /* overflow ? can't fit it, can't allocate it! */
2010 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2012 #if CREATION_SPEEDUP
2013 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2014 s = mono_object_allocate_spec (size, vtable);
2016 s = (MonoString*)mono_object_allocate (size);
2017 s->object.vtable = vtable;
2020 s = (MonoString*)mono_object_allocate (size);
2021 s->object.vtable = vtable;
2025 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2031 * mono_string_new_len:
2032 * @text: a pointer to an utf8 string
2033 * @length: number of bytes in @text to consider
2035 * Returns: A newly created string object which contains @text.
2038 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2040 GError *error = NULL;
2041 MonoString *o = NULL;
2043 glong items_written;
2045 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2048 o = mono_string_new_utf16 (domain, ut, items_written);
2050 g_error_free (error);
2059 * @text: a pointer to an utf8 string
2061 * Returns: A newly created string object which contains @text.
2064 mono_string_new (MonoDomain *domain, const char *text)
2066 GError *error = NULL;
2067 MonoString *o = NULL;
2069 glong items_written;
2074 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2077 o = mono_string_new_utf16 (domain, ut, items_written);
2079 g_error_free (error);
2087 * mono_string_new_wrapper:
2088 * @text: pointer to utf8 characters.
2090 * Helper function to create a string object from @text in the current domain.
2093 mono_string_new_wrapper (const char *text)
2095 MonoDomain *domain = mono_domain_get ();
2097 MONO_ARCH_SAVE_REGS;
2100 return mono_string_new (domain, text);
2107 * @class: the class of the value
2108 * @value: a pointer to the unboxed data
2110 * Returns: A newly created object which contains @value.
2113 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2119 g_assert (class->valuetype);
2121 vtable = mono_class_vtable (domain, class);
2122 size = mono_class_instance_size (class);
2123 res = mono_object_allocate (size);
2124 res->vtable = vtable;
2125 mono_profiler_allocation (res, class);
2127 size = size - sizeof (MonoObject);
2129 #if NO_UNALIGNED_ACCESS
2130 memcpy ((char *)res + sizeof (MonoObject), value, size);
2134 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2137 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2140 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2143 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2146 memcpy ((char *)res + sizeof (MonoObject), value, size);
2149 if (class->has_finalize)
2150 mono_object_register_finalizer (res);
2155 mono_object_unbox (MonoObject *obj)
2157 /* add assert for valuetypes? */
2158 return ((char*)obj) + sizeof (MonoObject);
2162 * mono_object_isinst:
2164 * @klass: a pointer to a class
2166 * Returns: @obj if @obj is derived from @klass
2169 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2172 mono_class_init (klass);
2174 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2175 return mono_object_isinst_mbyref (obj, klass);
2180 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2184 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2193 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2194 if ((klass->interface_id <= vt->max_interface_id) &&
2195 (vt->interface_offsets [klass->interface_id] != 0))
2199 MonoClass *oklass = vt->klass;
2200 if ((oklass == mono_defaults.transparent_proxy_class))
2201 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2203 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2207 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2209 MonoDomain *domain = mono_domain_get ();
2211 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2212 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2213 MonoMethod *im = NULL;
2217 for (i = 0; i < rpklass->method.count; ++i) {
2218 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2219 im = rpklass->methods [i];
2224 im = mono_object_get_virtual_method (rp, im);
2227 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2230 res = mono_runtime_invoke (im, rp, pa, NULL);
2232 if (*(MonoBoolean *) mono_object_unbox(res)) {
2233 /* Update the vtable of the remote type, so it can safely cast to this new type */
2234 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2235 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2244 * mono_object_castclass_mbyref:
2246 * @klass: a pointer to a class
2248 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2251 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2253 if (!obj) return NULL;
2254 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2256 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2258 "InvalidCastException"));
2263 MonoDomain *orig_domain;
2269 str_lookup (MonoDomain *domain, gpointer user_data)
2271 LDStrInfo *info = user_data;
2272 if (info->res || domain == info->orig_domain)
2274 mono_domain_lock (domain);
2275 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2276 mono_domain_unlock (domain);
2280 mono_string_is_interned_lookup (MonoString *str, int insert)
2282 MonoGHashTable *ldstr_table;
2285 char *ins = g_malloc (4 + str->length * 2);
2288 /* Encode the length */
2289 /* Same code as in mono_image_insert_string () */
2291 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2294 * ins is stored in the hash table as a key and needs to have the same
2295 * representation as in the metadata: we swap the character bytes on big
2298 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2301 char *p2 = (char *)mono_string_chars (str);
2302 for (i = 0; i < str->length; ++i) {
2309 memcpy (p, mono_string_chars (str), str->length * 2);
2311 domain = ((MonoObject *)str)->vtable->domain;
2312 ldstr_table = domain->ldstr_table;
2313 mono_domain_lock (domain);
2314 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2315 mono_domain_unlock (domain);
2320 mono_g_hash_table_insert (ldstr_table, ins, str);
2321 mono_domain_unlock (domain);
2324 LDStrInfo ldstr_info;
2325 ldstr_info.orig_domain = domain;
2326 ldstr_info.ins = ins;
2327 ldstr_info.res = NULL;
2329 mono_domain_foreach (str_lookup, &ldstr_info);
2330 if (ldstr_info.res) {
2332 * the string was already interned in some other domain:
2333 * intern it in the current one as well.
2335 mono_g_hash_table_insert (ldstr_table, ins, str);
2336 mono_domain_unlock (domain);
2340 mono_domain_unlock (domain);
2346 mono_string_is_interned (MonoString *o)
2348 return mono_string_is_interned_lookup (o, FALSE);
2352 mono_string_intern (MonoString *str)
2354 return mono_string_is_interned_lookup (str, TRUE);
2359 * @domain: the domain where the string will be used.
2360 * @image: a metadata context
2361 * @idx: index into the user string table.
2363 * Implementation for the ldstr opcode.
2366 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2368 const char *str, *sig;
2372 MONO_ARCH_SAVE_REGS;
2375 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2377 sig = str = mono_metadata_user_string (image, idx);
2379 mono_domain_lock (domain);
2380 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2381 mono_domain_unlock (domain);
2385 len2 = mono_metadata_decode_blob_size (str, &str);
2388 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2389 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2392 guint16 *p2 = (guint16*)mono_string_chars (o);
2393 for (i = 0; i < len2; ++i) {
2394 *p2 = GUINT16_FROM_LE (*p2);
2399 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2400 mono_domain_unlock (domain);
2406 * mono_string_to_utf8:
2407 * @s: a System.String
2409 * Return the UTF8 representation for @s.
2410 * the resulting buffer nedds to be freed with g_free().
2413 mono_string_to_utf8 (MonoString *s)
2416 GError *error = NULL;
2422 return g_strdup ("");
2424 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2426 g_warning (error->message);
2427 g_error_free (error);
2434 * mono_string_to_utf16:
2437 * Return an null-terminated array of the utf-16 chars
2438 * contained in @s. The result must be freed with g_free().
2439 * This is a temporary helper until our string implementation
2440 * is reworked to always include the null terminating char.
2443 mono_string_to_utf16 (MonoString *s)
2450 as = g_malloc ((s->length * 2) + 2);
2451 as [(s->length * 2)] = '\0';
2452 as [(s->length * 2) + 1] = '\0';
2455 return (gunichar2 *)(as);
2458 memcpy (as, mono_string_chars(s), s->length * 2);
2459 return (gunichar2 *)(as);
2463 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2466 mono_string_from_utf16 (gunichar2 *data)
2468 MonoDomain *domain = mono_domain_get ();
2474 while (data [len]) len++;
2476 return mono_string_new_utf16 (domain, data, len);
2480 default_ex_handler (MonoException *ex)
2482 MonoObject *o = (MonoObject*)ex;
2483 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2487 static MonoExceptionFunc ex_handler = default_ex_handler;
2490 mono_install_handler (MonoExceptionFunc func)
2492 ex_handler = func? func: default_ex_handler;
2496 * mono_raise_exception:
2497 * @ex: exception object
2499 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2502 mono_raise_exception (MonoException *ex)
2505 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2506 * that will cause gcc to omit the function epilog, causing problems when
2507 * the JIT tries to walk the stack, since the return address on the stack
2508 * will point into the next function in the executable, not this one.
2515 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2517 MonoWaitHandle *res;
2519 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2521 res->handle = handle;
2527 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2529 MonoAsyncResult *res;
2531 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2534 res->async_state = state;
2536 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2538 res->sync_completed = FALSE;
2539 res->completed = FALSE;
2545 mono_message_init (MonoDomain *domain,
2546 MonoMethodMessage *this,
2547 MonoReflectionMethod *method,
2548 MonoArray *out_args)
2550 MonoMethodSignature *sig = method->method->signature;
2556 this->method = method;
2558 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2559 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2560 this->async_result = NULL;
2561 this->call_type = CallType_Sync;
2563 names = g_new (char *, sig->param_count);
2564 mono_method_get_param_names (method->method, (const char **) names);
2565 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2567 for (i = 0; i < sig->param_count; i++) {
2568 name = mono_string_new (domain, names [i]);
2569 mono_array_set (this->names, gpointer, i, name);
2573 for (i = 0, j = 0; i < sig->param_count; i++) {
2575 if (sig->params [i]->byref) {
2577 gpointer arg = mono_array_get (out_args, gpointer, j);
2578 mono_array_set (this->args, gpointer, i, arg);
2582 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2587 mono_array_set (this->arg_types, guint8, i, arg_type);
2592 * mono_remoting_invoke:
2593 * @real_proxy: pointer to a RealProxy object
2594 * @msg: The MonoMethodMessage to execute
2595 * @exc: used to store exceptions
2596 * @out_args: used to store output arguments
2598 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2599 * IMessage interface and it is not trivial to extract results from there. So
2600 * we call an helper method PrivateInvoke instead of calling
2601 * RealProxy::Invoke() directly.
2603 * Returns: the result object.
2606 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2607 MonoObject **exc, MonoArray **out_args)
2609 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2612 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2618 klass = mono_defaults.real_proxy_class;
2620 for (i = 0; i < klass->method.count; ++i) {
2621 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2622 klass->methods [i]->signature->param_count == 4) {
2623 im = klass->methods [i];
2629 real_proxy->vtable->domain->private_invoke_method = im;
2632 pa [0] = real_proxy;
2637 return mono_runtime_invoke (im, NULL, pa, exc);
2641 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2642 MonoObject **exc, MonoArray **out_args)
2646 MonoMethodSignature *sig;
2647 int i, j, outarg_count = 0;
2649 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2651 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2652 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2653 target = tp->rp->unwrapped_server;
2655 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2659 domain = mono_domain_get ();
2660 method = msg->method->method;
2661 sig = method->signature;
2663 for (i = 0; i < sig->param_count; i++) {
2664 if (sig->params [i]->byref)
2668 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2671 for (i = 0, j = 0; i < sig->param_count; i++) {
2672 if (sig->params [i]->byref) {
2674 arg = mono_array_get (msg->args, gpointer, i);
2675 mono_array_set (*out_args, gpointer, j, arg);
2680 return mono_runtime_invoke_array (method, target, msg->args, exc);
2684 mono_print_unhandled_exception (MonoObject *exc)
2686 char *message = (char *) "";
2690 gboolean free_message = FALSE;
2693 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2694 klass = exc->vtable->klass;
2696 while (klass && method == NULL) {
2697 for (i = 0; i < klass->method.count; ++i) {
2698 method = klass->methods [i];
2699 if (!strcmp ("ToString", method->name) &&
2700 method->signature->param_count == 0 &&
2701 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2702 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2709 klass = klass->parent;
2714 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2716 message = mono_string_to_utf8 (str);
2717 free_message = TRUE;
2722 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2723 * exc->vtable->klass->name, message);
2725 g_printerr ("\nUnhandled Exception: %s\n", message);
2732 * mono_delegate_ctor:
2733 * @this: pointer to an uninitialized delegate object
2734 * @target: target object
2735 * @addr: pointer to native code
2737 * This is used to initialize a delegate. We also insert the method_info if
2738 * we find the info with mono_jit_info_table_find().
2741 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2743 MonoDomain *domain = mono_domain_get ();
2744 MonoDelegate *delegate = (MonoDelegate *)this;
2745 MonoMethod *method = NULL;
2752 class = this->vtable->klass;
2754 if ((ji = mono_jit_info_table_find (domain, addr))) {
2755 method = ji->method;
2756 delegate->method_info = mono_method_get_object (domain, method, NULL);
2759 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2761 method = mono_marshal_get_remoting_invoke (method);
2762 delegate->method_ptr = mono_compile_method (method);
2763 delegate->target = target;
2765 delegate->method_ptr = addr;
2766 delegate->target = target;
2771 * mono_method_call_message_new:
2773 * Translates arguments pointers into a Message.
2776 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2777 MonoDelegate **cb, MonoObject **state)
2779 MonoDomain *domain = mono_domain_get ();
2780 MonoMethodSignature *sig = method->signature;
2781 MonoMethodMessage *msg;
2784 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2787 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2788 count = sig->param_count - 2;
2790 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2791 count = sig->param_count;
2794 for (i = 0; i < count; i++) {
2799 if (sig->params [i]->byref)
2800 vpos = *((gpointer *)params [i]);
2804 type = sig->params [i]->type;
2805 class = mono_class_from_mono_type (sig->params [i]);
2807 if (class->valuetype)
2808 arg = mono_value_box (domain, class, vpos);
2810 arg = *((MonoObject **)vpos);
2812 mono_array_set (msg->args, gpointer, i, arg);
2815 if (cb != NULL && state != NULL) {
2816 *cb = *((MonoDelegate **)params [i]);
2818 *state = *((MonoObject **)params [i]);
2825 * mono_method_return_message_restore:
2827 * Restore results from message based processing back to arguments pointers
2830 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2832 MonoMethodSignature *sig = method->signature;
2833 int i, j, type, size;
2834 for (i = 0, j = 0; i < sig->param_count; i++) {
2835 MonoType *pt = sig->params [i];
2838 char *arg = mono_array_get (out_args, gpointer, j);
2842 case MONO_TYPE_VOID:
2843 g_assert_not_reached ();
2847 case MONO_TYPE_BOOLEAN:
2850 case MONO_TYPE_CHAR:
2857 case MONO_TYPE_VALUETYPE: {
2858 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2859 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2862 case MONO_TYPE_STRING:
2863 case MONO_TYPE_CLASS:
2864 case MONO_TYPE_ARRAY:
2865 case MONO_TYPE_SZARRAY:
2866 case MONO_TYPE_OBJECT:
2867 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2870 g_assert_not_reached ();
2879 * mono_load_remote_field:
2880 * @this: pointer to an object
2881 * @klass: klass of the object containing @field
2882 * @field: the field to load
2883 * @res: a storage to store the result
2885 * This method is called by the runtime on attempts to load fields of
2886 * transparent proxy objects. @this points to such TP, @klass is the class of
2887 * the object containing @field. @res is a storage location which can be
2888 * used to store the result.
2890 * Returns: an address pointing to the value of field.
2893 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2895 static MonoMethod *getter = NULL;
2896 MonoDomain *domain = mono_domain_get ();
2897 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2898 MonoClass *field_class;
2899 MonoMethodMessage *msg;
2900 MonoArray *out_args;
2904 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2909 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2910 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2917 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2918 MonoMethod *cm = mono_defaults.object_class->methods [i];
2920 if (!strcmp (cm->name, "FieldGetter")) {
2928 field_class = mono_class_from_mono_type (field->type);
2930 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2931 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2932 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2934 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2935 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2937 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2939 if (exc) mono_raise_exception ((MonoException *)exc);
2941 *res = mono_array_get (out_args, MonoObject *, 0);
2943 if (field_class->valuetype) {
2944 return ((char *)*res) + sizeof (MonoObject);
2950 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2952 static MonoMethod *getter = NULL;
2953 MonoDomain *domain = mono_domain_get ();
2954 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2955 MonoClass *field_class;
2956 MonoMethodMessage *msg;
2957 MonoArray *out_args;
2958 MonoObject *exc, *res;
2960 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2962 field_class = mono_class_from_mono_type (field->type);
2964 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2966 if (field_class->valuetype) {
2967 res = mono_object_new (domain, field_class);
2968 val = ((gchar *) res) + sizeof (MonoObject);
2972 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2979 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2980 MonoMethod *cm = mono_defaults.object_class->methods [i];
2982 if (!strcmp (cm->name, "FieldGetter")) {
2990 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2991 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2992 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2994 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2995 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2997 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2999 if (exc) mono_raise_exception ((MonoException *)exc);
3001 res = mono_array_get (out_args, MonoObject *, 0);
3007 * mono_store_remote_field:
3008 * @this: pointer to an object
3009 * @klass: klass of the object containing @field
3010 * @field: the field to load
3011 * @val: the value/object to store
3013 * This method is called by the runtime on attempts to store fields of
3014 * transparent proxy objects. @this points to such TP, @klass is the class of
3015 * the object containing @field. @val is the new value to store in @field.
3018 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3020 static MonoMethod *setter = NULL;
3021 MonoDomain *domain = mono_domain_get ();
3022 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3023 MonoClass *field_class;
3024 MonoMethodMessage *msg;
3025 MonoArray *out_args;
3029 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3031 field_class = mono_class_from_mono_type (field->type);
3033 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3034 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3035 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3042 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3043 MonoMethod *cm = mono_defaults.object_class->methods [i];
3045 if (!strcmp (cm->name, "FieldSetter")) {
3053 if (field_class->valuetype)
3054 arg = mono_value_box (domain, field_class, val);
3056 arg = *((MonoObject **)val);
3059 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3060 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3062 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3063 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3064 mono_array_set (msg->args, gpointer, 2, arg);
3066 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3068 if (exc) mono_raise_exception ((MonoException *)exc);
3072 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3074 static MonoMethod *setter = NULL;
3075 MonoDomain *domain = mono_domain_get ();
3076 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3077 MonoClass *field_class;
3078 MonoMethodMessage *msg;
3079 MonoArray *out_args;
3082 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3084 field_class = mono_class_from_mono_type (field->type);
3086 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3087 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3088 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3095 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3096 MonoMethod *cm = mono_defaults.object_class->methods [i];
3098 if (!strcmp (cm->name, "FieldSetter")) {
3106 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3107 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3109 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3110 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3111 mono_array_set (msg->args, gpointer, 2, arg);
3113 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3115 if (exc) mono_raise_exception ((MonoException *)exc);