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);
61 /* The pseudo algorithm for type initialization from the spec
62 Note it doesn't say anything about domains - only threads.
64 2. If the type is initialized you are done.
65 2.1. If the type is not yet initialized, try to take an
67 2.2. If successful, record this thread as responsible for
68 initializing the type and proceed to step 2.3.
69 2.2.1. If not, see whether this thread or any thread
70 waiting for this thread to complete already holds the lock.
71 2.2.2. If so, return since blocking would create a deadlock. This thread
72 will now see an incompletely initialized state for the type,
73 but no deadlock will arise.
74 2.2.3 If not, block until the type is initialized then return.
75 2.3 Initialize the parent type and then all interfaces implemented
77 2.4 Execute the type initialization code for this type.
78 2.5 Mark the type as initialized, release the initialization lock,
79 awaken any threads waiting for this type to be initialized,
86 guint32 initializing_tid;
87 guint32 waiting_count;
88 CRITICAL_SECTION initialization_section;
89 } TypeInitializationLock;
91 /* for locking access to type_initialization_hash and blocked_thread_hash */
92 static CRITICAL_SECTION type_initialization_section;
94 /* from vtable to lock */
95 static GHashTable *type_initialization_hash;
97 /* from thread id to thread id being waited on */
98 static GHashTable *blocked_thread_hash;
101 static MonoThread *main_thread;
104 mono_type_initialization_init (void)
106 InitializeCriticalSection (&type_initialization_section);
107 type_initialization_hash = g_hash_table_new (NULL, NULL);
108 blocked_thread_hash = g_hash_table_new (NULL, NULL);
112 * mono_runtime_class_init:
113 * @vtable: vtable that needs to be initialized
115 * This routine calls the class constructor for @vtable.
118 mono_runtime_class_init (MonoVTable *vtable)
122 MonoException *exc_to_throw;
123 MonoMethod *method = NULL;
130 if (vtable->initialized)
135 klass = vtable->klass;
137 for (i = 0; i < klass->method.count; ++i) {
138 method = klass->methods [i];
139 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
140 (strcmp (".cctor", method->name) == 0)) {
147 MonoDomain *domain = vtable->domain;
148 TypeInitializationLock *lock;
149 guint32 tid = GetCurrentThreadId();
150 int do_initialization = 0;
151 MonoDomain *last_domain = NULL;
153 EnterCriticalSection (&type_initialization_section);
154 /* double check... */
155 if (vtable->initialized) {
156 LeaveCriticalSection (&type_initialization_section);
159 lock = g_hash_table_lookup (type_initialization_hash, vtable);
161 /* This thread will get to do the initialization */
162 if (mono_domain_get () != domain) {
163 /* Transfer into the target domain */
164 last_domain = mono_domain_get ();
165 if (!mono_domain_set (domain, FALSE)) {
166 vtable->initialized = 1;
167 LeaveCriticalSection (&type_initialization_section);
168 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
171 lock = g_malloc (sizeof(TypeInitializationLock));
172 InitializeCriticalSection (&lock->initialization_section);
173 lock->initializing_tid = tid;
174 lock->waiting_count = 1;
175 /* grab the vtable lock while this thread still owns type_initialization_section */
176 EnterCriticalSection (&lock->initialization_section);
177 g_hash_table_insert (type_initialization_hash, vtable, lock);
178 do_initialization = 1;
182 if (lock->initializing_tid == tid) {
183 LeaveCriticalSection (&type_initialization_section);
186 /* see if the thread doing the initialization is already blocked on this thread */
187 blocked = GUINT_TO_POINTER (lock->initializing_tid);
188 while ((blocked = g_hash_table_lookup (blocked_thread_hash, blocked))) {
189 if (blocked == GUINT_TO_POINTER (tid)) {
190 LeaveCriticalSection (&type_initialization_section);
194 ++lock->waiting_count;
195 /* record the fact that we are waiting on the initializing thread */
196 g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), GUINT_TO_POINTER (lock->initializing_tid));
198 LeaveCriticalSection (&type_initialization_section);
200 if (do_initialization) {
201 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
203 mono_domain_set (last_domain, TRUE);
204 LeaveCriticalSection (&lock->initialization_section);
206 /* this just blocks until the initializing thread is done */
207 EnterCriticalSection (&lock->initialization_section);
208 LeaveCriticalSection (&lock->initialization_section);
211 EnterCriticalSection (&type_initialization_section);
212 if (lock->initializing_tid != tid)
213 g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
214 --lock->waiting_count;
215 if (lock->waiting_count == 0) {
216 DeleteCriticalSection (&lock->initialization_section);
217 g_hash_table_remove (type_initialization_hash, vtable);
220 vtable->initialized = 1;
221 /* FIXME: if the cctor fails, the type must be marked as unusable */
222 LeaveCriticalSection (&type_initialization_section);
224 vtable->initialized = 1;
229 (klass->image == mono_defaults.corlib &&
230 !strcmp (klass->name_space, "System") &&
231 !strcmp (klass->name, "TypeInitializationException")))
232 return; /* No static constructor found or avoid infinite loop */
234 if (klass->name_space && *klass->name_space)
235 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
237 full_name = g_strdup (klass->name);
239 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
242 mono_raise_exception (exc_to_throw);
246 default_trampoline (MonoMethod *method)
252 default_remoting_trampoline (MonoMethod *method)
254 g_error ("remoting not installed");
258 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
259 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
262 mono_install_trampoline (MonoTrampoline func)
264 arch_create_jit_trampoline = func? func: default_trampoline;
268 mono_install_remoting_trampoline (MonoTrampoline func)
270 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
273 static MonoCompileFunc default_mono_compile_method = NULL;
276 mono_install_compile_method (MonoCompileFunc func)
278 default_mono_compile_method = func;
282 mono_compile_method (MonoMethod *method)
284 if (!default_mono_compile_method) {
285 g_error ("compile method called on uninitialized runtime");
288 return default_mono_compile_method (method);
292 #if 0 && HAVE_BOEHM_GC
294 vtable_finalizer (void *obj, void *data) {
295 g_print ("%s finalized (%p)\n", (char*)data, obj);
301 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
304 * The vtables in the root appdomain are assumed to be reachable by other
305 * roots, and we don't use typed allocation in the other domains.
308 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
311 mono_class_compute_gc_descriptor (MonoClass *class)
313 MonoClassField *field;
317 static gboolean gcj_inited = FALSE;
322 GC_init_gcj_malloc (5, NULL);
326 mono_class_init (class);
328 if (class->gc_descr_inited)
331 class->gc_descr_inited = TRUE;
332 class->gc_descr = GC_NO_DESCRIPTOR;
334 if (class == mono_defaults.string_class) {
335 bitmap = GC_HEADER_BITMAP;
336 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
338 else if (class->rank) {
339 mono_class_compute_gc_descriptor (class->element_class);
341 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
342 bitmap = GC_HEADER_BITMAP;
344 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
345 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
349 static int count = 0;
353 /* GC 6.1 has trouble handling 64 bit descriptors... */
354 if ((class->instance_size / sizeof (gpointer)) > 30) {
355 // printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer));
359 bitmap = GC_HEADER_BITMAP;
366 // printf("KLASS: %s.\n", class->name);
368 for (p = class; p != NULL; p = p->parent) {
369 for (i = 0; i < p->field.count; ++i) {
370 field = &p->fields [i];
371 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
373 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
376 pos = field->offset / sizeof (gpointer);
378 if (field->type->byref)
381 switch (field->type->type) {
382 case MONO_TYPE_BOOLEAN:
394 // printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap);
397 case MONO_TYPE_STRING:
398 case MONO_TYPE_SZARRAY:
399 case MONO_TYPE_CLASS:
400 case MONO_TYPE_OBJECT:
401 case MONO_TYPE_ARRAY:
403 g_assert ((field->offset % sizeof(gpointer)) == 0);
405 bitmap |= ((guint64)1) << pos;
406 // printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap);
408 case MONO_TYPE_VALUETYPE: {
409 MonoClass *fclass = field->type->data.klass;
410 if (!fclass->enumtype) {
411 mono_class_compute_gc_descriptor (fclass);
412 bitmap |= (fclass->gc_bitmap >> (sizeof (MonoObject) / sizeof (gpointer))) << pos;
422 // printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap);
423 class->gc_bitmap = bitmap;
424 /* Convert to the format expected by GC_make_descriptor */
425 bm [0] = (guint32)bitmap;
426 bm [1] = (guint32)(bitmap >> 32);
427 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bm, class->instance_size / sizeof (gpointer));
430 #endif /* CREATION_SPEEDUP */
433 * field_is_special_static:
435 * Returns SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
436 * SPECIAL_STATIC_NONE otherwise.
439 field_is_special_static (MonoClass *fklass, MonoClassField *field)
441 MonoCustomAttrInfo *ainfo;
443 ainfo = mono_custom_attrs_from_field (fklass, field);
446 for (i = 0; i < ainfo->num_attrs; ++i) {
447 MonoClass *klass = ainfo->attrs [i].ctor->klass;
448 if (klass->image == mono_defaults.corlib) {
449 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
450 mono_custom_attrs_free (ainfo);
451 return SPECIAL_STATIC_THREAD;
453 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
454 mono_custom_attrs_free (ainfo);
455 return SPECIAL_STATIC_CONTEXT;
459 mono_custom_attrs_free (ainfo);
460 return SPECIAL_STATIC_NONE;
465 * @domain: the application domain
466 * @class: the class to initialize
468 * VTables are domain specific because we create domain specific code, and
469 * they contain the domain specific static class data.
472 mono_class_vtable (MonoDomain *domain, MonoClass *class)
474 MonoVTable *vt = NULL;
475 MonoClassField *field;
481 guint32 constant_cols [MONO_CONSTANT_SIZE];
485 vt = class->cached_vtable;
486 if (vt && vt->domain == domain)
489 mono_domain_lock (domain);
490 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
491 mono_domain_unlock (domain);
496 mono_class_init (class);
498 mono_stats.used_class_count++;
499 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
501 vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
503 vt = mono_mempool_alloc0 (domain->mp, vtable_size);
509 mono_class_compute_gc_descriptor (class);
510 if (domain != mono_root_domain)
512 * We can't use typed allocation in the non-root domains, since the
513 * collector needs the GC descriptor stored in the vtable even after
514 * the mempool containing the vtable is destroyed when the domain is
515 * unloaded. An alternative might be to allocate vtables in the GC
516 * heap, but this does not seem to work (it leads to crashes inside
517 * libgc). If that approach is tried, two gc descriptors need to be
518 * allocated for each class: one for the root domain, and one for all
519 * other domains. The second descriptor should contain a bit for the
520 * vtable field in MonoObject, since we can no longer assume the
521 * vtable is reachable by other roots after the appdomain is unloaded.
523 vt->gc_descr = GC_NO_DESCRIPTOR;
525 vt->gc_descr = class->gc_descr;
528 if (class->class_size) {
530 vt->data = GC_MALLOC (class->class_size + 8);
531 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
532 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
533 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
535 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
538 mono_stats.class_static_data_size += class->class_size + 8;
542 for (i = class->field.first; i < class->field.last; ++i) {
543 field = &class->fields [i - class->field.first];
544 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
546 if (mono_field_is_deleted (field))
548 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
549 gint32 special_static = field_is_special_static (class, field);
550 if (special_static != SPECIAL_STATIC_NONE) {
551 guint32 size, align, offset;
552 size = mono_type_size (field->type, &align);
553 offset = mono_alloc_special_static_data (special_static, size, align);
554 if (!domain->special_static_fields)
555 domain->special_static_fields = g_hash_table_new (NULL, NULL);
556 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
560 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
561 MonoClass *fklass = mono_class_from_mono_type (field->type);
562 t = (char*)vt->data + field->offset;
563 if (fklass->valuetype) {
564 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
566 /* it's a pointer type: add check */
567 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
568 *t = *(char *)field->data;
572 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
575 if (!field->def_value) {
576 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1), cindex + 1);
579 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
580 field->def_value = g_new0 (MonoConstant, 1);
581 field->def_value->type = constant_cols [MONO_CONSTANT_TYPE];
582 field->def_value->value = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
585 p = field->def_value->value;
586 len = mono_metadata_decode_blob_size (p, &p);
587 t = (char*)vt->data + field->offset;
588 /* should we check that the type matches? */
589 switch (field->def_value->type) {
590 case MONO_TYPE_BOOLEAN:
598 guint16 *val = (guint16*)t;
604 guint32 *val = (guint32*)t;
610 guint64 *val = (guint64*)t;
615 float *val = (float*)t;
620 double *val = (double*)t;
624 case MONO_TYPE_STRING: {
625 gpointer *val = (gpointer*)t;
626 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
627 gunichar2 *copy = g_malloc (len);
629 for (j = 0; j < len/2; j++) {
630 copy [j] = read16 (p);
633 *val = mono_string_new_utf16 (domain, copy, len/2);
636 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
640 case MONO_TYPE_CLASS:
641 /* nothing to do, we malloc0 the data and the value can be 0 only */
644 g_warning ("type 0x%02x should not be in constant table", field->def_value->type);
648 vt->max_interface_id = class->max_interface_id;
650 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
651 sizeof (gpointer) * (class->max_interface_id + 1));
653 /* initialize interface offsets */
654 for (i = 0; i <= class->max_interface_id; ++i) {
655 int slot = class->interface_offsets [i];
657 vt->interface_offsets [i] = &(vt->vtable [slot]);
661 * arch_create_jit_trampoline () can recursively call this function again
662 * because it compiles icall methods right away.
664 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
665 if (!class->cached_vtable)
666 class->cached_vtable = vt;
668 /* initialize vtable */
669 for (i = 0; i < class->vtable_size; ++i) {
672 if ((cm = class->vtable [i]))
673 vt->vtable [i] = arch_create_jit_trampoline (cm);
676 mono_domain_unlock (domain);
678 /* make sure the the parent is initialized */
680 mono_class_vtable (domain, class->parent);
682 vt->type = mono_type_get_object (domain, &class->byval_arg);
683 if (class->contextbound)
692 * mono_class_proxy_vtable:
693 * @domain: the application domain
694 * @remove_class: the remote class
696 * Creates a vtable for transparent proxies. It is basically
697 * a copy of the real vtable of the class wrapped in @remote_class,
698 * but all function pointers invoke the remoting functions, and
699 * vtable->klass points to the transparent proxy class, and not to @class.
702 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class)
704 MonoVTable *vt, *pvt;
705 int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
707 MonoClass *class = remote_class->proxy_class;
709 vt = mono_class_vtable (domain, class);
710 max_interface_id = vt->max_interface_id;
712 /* Calculate vtable space for extra interfaces */
713 for (j = 0; j < remote_class->interface_count; j++) {
714 MonoClass* iclass = remote_class->interfaces[j];
715 int method_count = iclass->method.count;
717 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
718 continue; /* interface implemented by the class */
720 for (i = 0; i < iclass->interface_count; i++)
721 method_count += iclass->interfaces[i]->method.count;
723 extra_interface_vtsize += method_count * sizeof (gpointer);
724 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
727 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
729 mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
731 pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
732 memcpy (pvt, vt, vtsize);
734 pvt->klass = mono_defaults.transparent_proxy_class;
736 /* initialize vtable */
737 for (i = 0; i < class->vtable_size; ++i) {
740 if ((cm = class->vtable [i]))
741 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
744 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
746 /* create trampolines for abstract methods */
747 for (k = class; k; k = k->parent) {
748 for (i = 0; i < k->method.count; i++) {
749 int slot = k->methods [i]->slot;
750 if (!pvt->vtable [slot])
751 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
756 pvt->max_interface_id = max_interface_id;
757 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
758 sizeof (gpointer) * (max_interface_id + 1));
760 /* initialize interface offsets */
761 for (i = 0; i <= class->max_interface_id; ++i) {
762 int slot = class->interface_offsets [i];
764 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
767 if (remote_class->interface_count > 0)
769 int slot = class->vtable_size;
774 /* Create trampolines for the methods of the interfaces */
775 for (n = 0; n < remote_class->interface_count; n++)
777 iclass = remote_class->interfaces[n];
778 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
779 continue; /* interface implemented by the class */
784 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
786 for (j = 0; j < interf->method.count; ++j) {
787 MonoMethod *cm = interf->methods [j];
788 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
790 slot += interf->method.count;
791 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
803 * @domain: the application domain
804 * @class_name: name of the remote class
806 * Creates and initializes a MonoRemoteClass object for a remote type.
810 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
814 mono_domain_lock (domain);
815 rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class_name);
818 mono_domain_unlock (domain);
822 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
824 rc->interface_count = 0;
825 rc->interfaces = NULL;
826 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
827 rc->proxy_class_name = mono_string_to_utf8 (class_name);
829 mono_g_hash_table_insert (domain->proxy_vtable_hash, class_name, rc);
830 mono_upgrade_remote_class (domain, rc, proxy_class);
832 if (rc->vtable == NULL)
833 rc->vtable = mono_class_proxy_vtable (domain, rc);
835 mono_domain_unlock (domain);
841 extend_interface_array (MonoDomain *domain, MonoRemoteClass *remote_class, int amount)
843 /* Extends the array of interfaces. Memory is extended using blocks of 5 pointers */
845 int current_size = ((remote_class->interface_count / 5) + 1) * 5;
846 remote_class->interface_count += amount;
848 if (remote_class->interface_count > current_size || remote_class->interfaces == NULL)
850 int new_size = ((remote_class->interface_count / 5) + 1) * 5;
851 MonoClass **new_array = mono_mempool_alloc (domain->mp, new_size * sizeof (MonoClass*));
853 if (remote_class->interfaces != NULL)
854 memcpy (new_array, remote_class->interfaces, current_size * sizeof (MonoClass*));
856 remote_class->interfaces = new_array;
862 * mono_upgrade_remote_class:
863 * @domain: the application domain
864 * @remote_class: the remote class
865 * @klass: class to which the remote class can be casted.
867 * Updates the vtable of the remote class by adding the necessary method slots
868 * and interface offsets so it can be safely casted to klass. klass can be a
869 * class or an interface.
871 void mono_upgrade_remote_class (MonoDomain *domain, MonoRemoteClass *remote_class, MonoClass *klass)
873 gboolean redo_vtable;
875 mono_domain_lock (domain);
877 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
880 for (i = 0; i < remote_class->interface_count; i++)
881 if (remote_class->interfaces[i] == klass) redo_vtable = FALSE;
884 extend_interface_array (domain, remote_class, 1);
885 remote_class->interfaces [remote_class->interface_count-1] = klass;
889 redo_vtable = (remote_class->proxy_class != klass);
890 remote_class->proxy_class = klass;
894 remote_class->vtable = mono_class_proxy_vtable (domain, remote_class);
897 printf ("remote class upgrade - class:%s num-interfaces:%d\n", remote_class->proxy_class_name, remote_class->interface_count);
899 for (n=0; n<remote_class->interface_count; n++)
900 printf (" I:%s\n", remote_class->interfaces[n]->name);
903 mono_domain_unlock (domain);
907 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
908 * the instance of a callvirt of method.
911 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
915 MonoMethod *res = NULL;
917 klass = mono_object_class (obj);
918 if (klass == mono_defaults.transparent_proxy_class) {
919 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
925 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
928 vtable = klass->vtable;
930 /* check method->slot is a valid index: perform isinstance? */
931 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
933 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
935 if (method->slot != -1)
936 res = vtable [method->slot];
940 if (!res) res = method; /* It may be an interface or abstract class method */
941 res = mono_marshal_get_remoting_invoke (res);
950 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
952 g_error ("runtime invoke called on uninitialized runtime");
956 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
959 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
961 return default_mono_runtime_invoke (method, obj, params, exc);
965 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
968 gpointer *p = (gpointer*)dest;
975 case MONO_TYPE_BOOLEAN:
978 guint8 *p = (guint8*)dest;
979 *p = *(guint8*)value;
984 case MONO_TYPE_CHAR: {
985 guint16 *p = (guint16*)dest;
986 *p = *(guint16*)value;
989 #if SIZEOF_VOID_P == 4
995 gint32 *p = (gint32*)dest;
996 *p = *(gint32*)value;
999 #if SIZEOF_VOID_P == 8
1004 case MONO_TYPE_U8: {
1005 gint64 *p = (gint64*)dest;
1006 *p = *(gint64*)value;
1009 case MONO_TYPE_R4: {
1010 float *p = (float*)dest;
1011 *p = *(float*)value;
1014 case MONO_TYPE_R8: {
1015 double *p = (double*)dest;
1016 *p = *(double*)value;
1019 case MONO_TYPE_STRING:
1020 case MONO_TYPE_SZARRAY:
1021 case MONO_TYPE_CLASS:
1022 case MONO_TYPE_OBJECT:
1023 case MONO_TYPE_ARRAY:
1024 case MONO_TYPE_PTR: {
1025 gpointer *p = (gpointer*)dest;
1026 *p = deref_pointer? *(gpointer*)value: value;
1029 case MONO_TYPE_VALUETYPE:
1030 if (type->data.klass->enumtype) {
1031 t = type->data.klass->enum_basetype->type;
1035 size = mono_class_value_size (type->data.klass, NULL);
1036 memcpy (dest, value, size);
1040 g_warning ("got type %x", type->type);
1041 g_assert_not_reached ();
1046 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
1050 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1052 dest = (char*)obj + field->offset;
1053 set_value (field->type, dest, value, FALSE);
1057 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
1061 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1063 dest = (char*)vt->data + field->offset;
1064 set_value (field->type, dest, value, FALSE);
1068 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
1072 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1074 src = (char*)obj + field->offset;
1075 set_value (field->type, value, src, TRUE);
1079 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
1083 MonoVTable *vtable = NULL;
1085 gboolean is_static = FALSE;
1086 gboolean is_ref = FALSE;
1088 switch (field->type->type) {
1089 case MONO_TYPE_STRING:
1090 case MONO_TYPE_OBJECT:
1091 case MONO_TYPE_CLASS:
1092 case MONO_TYPE_ARRAY:
1093 case MONO_TYPE_SZARRAY:
1098 case MONO_TYPE_BOOLEAN:
1101 case MONO_TYPE_CHAR:
1110 case MONO_TYPE_VALUETYPE:
1111 is_ref = field->type->byref;
1114 g_error ("type 0x%x not handled in "
1115 "mono_field_get_value_object", field->type->type);
1119 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1121 vtable = mono_class_vtable (domain, field->parent);
1122 if (!vtable->initialized)
1123 mono_runtime_class_init (vtable);
1128 mono_field_static_get_value (vtable, field, &o);
1130 mono_field_get_value (obj, field, &o);
1135 /* boxed value type */
1136 klass = mono_class_from_mono_type (field->type);
1137 o = mono_object_new (domain, klass);
1138 v = ((gchar *) o) + sizeof (MonoObject);
1140 mono_field_static_get_value (vtable, field, v);
1142 mono_field_get_value (obj, field, v);
1150 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1154 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1156 src = (char*)vt->data + field->offset;
1157 set_value (field->type, value, src, TRUE);
1161 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1163 default_mono_runtime_invoke (prop->set, obj, params, exc);
1167 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1169 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1174 mono_get_delegate_invoke (MonoClass *klass)
1181 for (i = 0; i < klass->method.count; ++i) {
1182 if (klass->methods [i]->name[0] == 'I' &&
1183 !strcmp ("Invoke", klass->methods [i]->name)) {
1184 im = klass->methods [i];
1194 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1198 im = mono_get_delegate_invoke (delegate->vtable->klass);
1201 return mono_runtime_invoke (im, delegate, params, exc);
1204 static MonoArray* main_args;
1207 mono_runtime_get_main_args (void)
1213 fire_process_exit_event (void)
1215 MonoClassField *field;
1216 MonoDomain *domain = mono_domain_get ();
1218 MonoObject *delegate, *exc;
1220 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1223 if (domain != mono_root_domain)
1226 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1227 if (delegate == NULL)
1232 mono_runtime_delegate_invoke (delegate, pa, &exc);
1236 * Execute a standard Main() method (argc/argv contains the
1237 * executable name). This method also sets the command line argument value
1238 * needed by System.Environment.
1241 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1245 MonoArray *args = NULL;
1246 MonoDomain *domain = mono_domain_get ();
1247 gchar *utf8_fullpath;
1250 main_thread = mono_thread_current ();
1252 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1254 if (!g_path_is_absolute (argv [0])) {
1255 gchar *basename = g_path_get_basename (argv [0]);
1256 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1260 utf8_fullpath = mono_utf8_from_external (fullpath);
1261 if(utf8_fullpath == NULL) {
1262 /* Printing the arg text will cause glib to
1263 * whinge about "Invalid UTF-8", but at least
1264 * its relevant, and shows the problem text
1267 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1268 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1275 utf8_fullpath = mono_utf8_from_external (argv[0]);
1276 if(utf8_fullpath == NULL) {
1277 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1278 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1283 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1284 g_free (utf8_fullpath);
1286 for (i = 1; i < argc; ++i) {
1290 utf8_arg=mono_utf8_from_external (argv[i]);
1291 if(utf8_arg==NULL) {
1292 /* Ditto the comment about Invalid UTF-8 here */
1293 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1294 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1298 arg = mono_string_new (domain, utf8_arg);
1299 mono_array_set (main_args, gpointer, i, arg);
1303 if (method->signature->param_count) {
1304 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1305 for (i = 0; i < argc; ++i) {
1306 /* The encodings should all work, given that
1307 * we've checked all these args for the
1310 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1311 mono_array_set (args, gpointer, i, arg);
1314 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1317 mono_assembly_set_main (method->klass->image->assembly);
1319 result = mono_runtime_exec_main (method, args, exc);
1320 fire_process_exit_event ();
1324 /* Used in mono_unhandled_exception */
1326 create_unhandled_exception_eventargs (MonoObject *exc)
1330 MonoMethod *method = NULL;
1331 MonoBoolean is_terminating = TRUE;
1335 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1338 mono_class_init (klass);
1340 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1341 for (i = 0; i < klass->method.count; ++i) {
1342 method = klass->methods [i];
1343 if (!strcmp (".ctor", method->name) &&
1344 method->signature->param_count == 2 &&
1345 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1353 args [1] = &is_terminating;
1355 obj = mono_object_new (mono_domain_get (), klass);
1356 mono_runtime_invoke (method, obj, args, NULL);
1362 * We call this function when we detect an unhandled exception
1363 * in the default domain.
1364 * It invokes the * UnhandledException event in AppDomain or prints
1365 * a warning to the console
1368 mono_unhandled_exception (MonoObject *exc)
1370 MonoDomain *domain = mono_domain_get ();
1371 MonoClassField *field;
1372 MonoObject *delegate;
1374 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1375 "UnhandledException");
1378 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1379 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1381 /* set exitcode only in the main thread */
1382 if (mono_thread_current () == main_thread)
1383 mono_environment_exitcode_set (1);
1384 if (domain != mono_root_domain || !delegate) {
1385 mono_print_unhandled_exception (exc);
1387 MonoObject *e = NULL;
1390 pa [0] = domain->domain;
1391 pa [1] = create_unhandled_exception_eventargs (exc);
1392 mono_runtime_delegate_invoke (delegate, pa, &e);
1395 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1396 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1404 * Launch a new thread to start all setup that requires managed code
1407 * main_func is called back from the thread with main_args as the
1408 * parameter. The callback function is expected to start Main()
1409 * eventually. This function then waits for all managed threads to
1413 mono_runtime_exec_managed_code (MonoDomain *domain,
1414 MonoMainThreadFunc main_func,
1417 mono_thread_create (domain, main_func, main_args);
1419 mono_thread_manage ();
1423 * Execute a standard Main() method (args doesn't contain the
1427 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1437 domain = mono_object_domain (args);
1438 if (!domain->entry_assembly) {
1440 gchar *config_suffix;
1441 MonoAssembly *assembly;
1443 assembly = method->klass->image->assembly;
1444 domain->entry_assembly = assembly;
1445 domain->setup->application_base = mono_string_new (domain, assembly->basedir);
1447 config_suffix = g_strconcat (assembly->aname.name, ".exe.config", NULL);
1448 str = g_build_filename (assembly->basedir, config_suffix, NULL);
1449 g_free (config_suffix);
1450 domain->setup->configuration_file = mono_string_new (domain, str);
1454 /* FIXME: check signature of method */
1455 if (method->signature->ret->type == MONO_TYPE_I4) {
1457 res = mono_runtime_invoke (method, NULL, pa, exc);
1459 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1463 mono_environment_exitcode_set (rval);
1465 mono_runtime_invoke (method, NULL, pa, exc);
1469 /* If the return type of Main is void, only
1470 * set the exitcode if an exception was thrown
1471 * (we don't want to blow away an
1472 * explicitly-set exit code)
1475 mono_environment_exitcode_set (rval);
1483 mono_install_runtime_invoke (MonoInvokeFunc func)
1485 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1489 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1492 MonoMethodSignature *sig = method->signature;
1493 gpointer *pa = NULL;
1496 if (NULL != params) {
1497 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1498 for (i = 0; i < mono_array_length (params); i++) {
1499 if (sig->params [i]->byref) {
1503 switch (sig->params [i]->type) {
1506 case MONO_TYPE_BOOLEAN:
1509 case MONO_TYPE_CHAR:
1518 case MONO_TYPE_VALUETYPE:
1519 if (sig->params [i]->byref) {
1520 /* MS seems to create the objects if a null is passed in */
1521 if (! ((gpointer *)params->vector)[i])
1522 ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
1525 g_assert (((gpointer*)params->vector) [i]);
1526 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1528 case MONO_TYPE_STRING:
1529 case MONO_TYPE_OBJECT:
1530 case MONO_TYPE_CLASS:
1531 case MONO_TYPE_ARRAY:
1532 case MONO_TYPE_SZARRAY:
1533 if (sig->params [i]->byref)
1534 pa [i] = &(((gpointer *)params->vector)[i]);
1536 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1539 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1544 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1546 obj = mono_object_new (mono_domain_get (), method->klass);
1547 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1548 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
1551 mono_runtime_invoke (method, obj, pa, exc);
1554 return mono_runtime_invoke (method, obj, pa, exc);
1558 out_of_memory (size_t size)
1561 * we could allocate at program startup some memory that we could release
1562 * back to the system at this point if we're really low on memory (ie, size is
1563 * lower than the memory we set apart)
1565 mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
1569 * mono_object_allocate:
1570 * @size: number of bytes to allocate
1572 * This is a very simplistic routine until we have our GC-aware
1575 * Returns: an allocated object of size @size, or NULL on failure.
1577 static inline void *
1578 mono_object_allocate (size_t size)
1581 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1582 void *o = GC_MALLOC (size);
1584 void *o = calloc (1, size);
1586 mono_stats.new_object_count++;
1589 out_of_memory (size);
1593 #if CREATION_SPEEDUP
1594 static inline void *
1595 mono_object_allocate_spec (size_t size, void *gcdescr)
1597 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1598 void *o = GC_GCJ_MALLOC (size, gcdescr);
1599 mono_stats.new_object_count++;
1602 out_of_memory (size);
1610 * Frees the memory used by the object. Debugging purposes
1611 * only, as we will have our GC system.
1614 mono_object_free (MonoObject *o)
1617 g_error ("mono_object_free called with boehm gc.");
1619 MonoClass *c = o->vtable->klass;
1621 memset (o, 0, c->instance_size);
1628 * @klass: the class of the object that we want to create
1630 * Returns: A newly created object whose definition is
1631 * looked up using @klass
1634 mono_object_new (MonoDomain *domain, MonoClass *klass)
1636 MONO_ARCH_SAVE_REGS;
1637 return mono_object_new_specific (mono_class_vtable (domain, klass));
1641 * mono_object_new_specific:
1642 * @vtable: the vtable of the object that we want to create
1644 * Returns: A newly created object with class and domain specified
1648 mono_object_new_specific (MonoVTable *vtable)
1652 MONO_ARCH_SAVE_REGS;
1657 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1660 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1664 mono_class_init (klass);
1666 for (i = 0; i < klass->method.count; ++i) {
1667 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1668 klass->methods [i]->signature->param_count == 1) {
1669 im = klass->methods [i];
1674 vtable->domain->create_proxy_for_type_method = im;
1677 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1679 o = mono_runtime_invoke (im, NULL, pa, NULL);
1680 if (o != NULL) return o;
1683 return mono_object_new_alloc_specific (vtable);
1687 mono_object_new_fast (MonoVTable *vtable)
1690 MONO_ARCH_SAVE_REGS;
1692 #if CREATION_SPEEDUP
1693 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1694 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1696 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1697 o = mono_object_allocate (vtable->klass->instance_size);
1701 o = mono_object_allocate (vtable->klass->instance_size);
1708 mono_object_new_alloc_specific (MonoVTable *vtable)
1712 #if CREATION_SPEEDUP
1713 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1714 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1716 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1717 o = mono_object_allocate (vtable->klass->instance_size);
1721 o = mono_object_allocate (vtable->klass->instance_size);
1724 if (vtable->klass->has_finalize)
1725 mono_object_register_finalizer (o);
1727 mono_profiler_allocation (o, vtable->klass);
1732 * mono_object_new_from_token:
1733 * @image: Context where the type_token is hosted
1734 * @token: a token of the type that we want to create
1736 * Returns: A newly created object whose definition is
1737 * looked up using @token in the @image image
1740 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1744 class = mono_class_get (image, token);
1746 return mono_object_new (domain, class);
1751 * mono_object_clone:
1752 * @obj: the object to clone
1754 * Returns: A newly created object who is a shallow copy of @obj
1757 mono_object_clone (MonoObject *obj)
1762 size = obj->vtable->klass->instance_size;
1763 o = mono_object_allocate (size);
1764 mono_profiler_allocation (o, obj->vtable->klass);
1766 memcpy (o, obj, size);
1768 if (obj->vtable->klass->has_finalize)
1769 mono_object_register_finalizer (o);
1775 * @array: the array to clone
1777 * Returns: A newly created array who is a shallow copy of @array
1780 mono_array_clone (MonoArray *array)
1785 MonoClass *klass = array->obj.vtable->klass;
1787 MONO_ARCH_SAVE_REGS;
1789 if (array->bounds == NULL) {
1790 size = mono_array_length (array);
1791 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1792 klass, &size, NULL);
1794 size *= mono_array_element_size (klass);
1795 memcpy (o, array, sizeof (MonoArray) + size);
1800 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1801 size = mono_array_element_size (klass);
1802 for (i = 0; i < klass->rank; ++i) {
1803 sizes [i] = array->bounds [i].length;
1804 size *= array->bounds [i].length;
1805 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1807 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1808 klass, sizes, sizes + klass->rank);
1809 memcpy (o, array, sizeof(MonoArray) + size);
1814 /* helper macros to check for overflow when calculating the size of arrays */
1815 #define MYGUINT32_MAX 4294967295U
1816 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1817 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1818 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1819 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1820 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1823 * mono_array_new_full:
1824 * @domain: domain where the object is created
1825 * @array_class: array class
1826 * @lengths: lengths for each dimension in the array
1827 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1829 * This routine creates a new array objects with the given dimensions,
1830 * lower bounds and type.
1833 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1834 guint32 *lengths, guint32 *lower_bounds)
1836 guint32 byte_len, len;
1839 MonoArrayBounds *bounds;
1843 if (!array_class->inited)
1844 mono_class_init (array_class);
1846 byte_len = mono_array_element_size (array_class);
1849 if (array_class->rank == 1 &&
1850 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1855 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1857 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1859 for (i = 0; i < array_class->rank; ++i) {
1860 bounds [i].length = lengths [i];
1861 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1862 out_of_memory (MYGUINT32_MAX);
1867 for (i = 0; i < array_class->rank; ++i)
1868 bounds [i].lower_bound = lower_bounds [i];
1871 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1872 out_of_memory (MYGUINT32_MAX);
1874 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1875 out_of_memory (MYGUINT32_MAX);
1876 byte_len += sizeof (MonoArray);
1878 * Following three lines almost taken from mono_object_new ():
1879 * they need to be kept in sync.
1881 vtable = mono_class_vtable (domain, array_class);
1882 #if CREATION_SPEEDUP
1883 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1884 o = mono_object_allocate_spec (byte_len, vtable);
1886 o = mono_object_allocate (byte_len);
1890 o = mono_object_allocate (byte_len);
1894 array = (MonoArray*)o;
1896 array->bounds = bounds;
1897 array->max_length = len;
1899 mono_profiler_allocation (o, array_class);
1906 * @domain: domain where the object is created
1907 * @eclass: element class
1908 * @n: number of array elements
1910 * This routine creates a new szarray with @n elements of type @eclass.
1913 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1917 MONO_ARCH_SAVE_REGS;
1919 ac = mono_array_class_get (eclass, 1);
1920 g_assert (ac != NULL);
1922 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1926 * mono_array_new_specific:
1927 * @vtable: a vtable in the appropriate domain for an initialized class
1928 * @n: number of array elements
1930 * This routine is a fast alternative to mono_array_new() for code which
1931 * can be sure about the domain it operates in.
1934 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1938 guint32 byte_len, elem_size;
1940 MONO_ARCH_SAVE_REGS;
1942 elem_size = mono_array_element_size (vtable->klass);
1943 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1944 out_of_memory (MYGUINT32_MAX);
1945 byte_len = n * elem_size;
1946 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1947 out_of_memory (MYGUINT32_MAX);
1948 byte_len += sizeof (MonoArray);
1949 #if CREATION_SPEEDUP
1950 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1951 o = mono_object_allocate_spec (byte_len, vtable);
1953 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1954 o = mono_object_allocate (byte_len);
1958 o = mono_object_allocate (byte_len);
1962 ao = (MonoArray *)o;
1965 mono_profiler_allocation (o, vtable->klass);
1971 * mono_string_new_utf16:
1972 * @text: a pointer to an utf16 string
1973 * @len: the length of the string
1975 * Returns: A newly created string object which contains @text.
1978 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1982 s = mono_string_new_size (domain, len);
1983 g_assert (s != NULL);
1985 memcpy (mono_string_chars (s), text, len * 2);
1991 * mono_string_new_size:
1992 * @text: a pointer to an utf16 string
1993 * @len: the length of the string
1995 * Returns: A newly created string object of @len
1998 mono_string_new_size (MonoDomain *domain, gint32 len)
2003 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2005 #if CREATION_SPEEDUP
2006 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2007 s = mono_object_allocate_spec (sizeof (MonoString) + ((len + 1) * 2), vtable);
2009 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
2010 s->object.vtable = vtable;
2013 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
2014 s->object.vtable = vtable;
2018 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2024 * mono_string_new_len:
2025 * @text: a pointer to an utf8 string
2026 * @length: number of bytes in @text to consider
2028 * Returns: A newly created string object which contains @text.
2031 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2033 GError *error = NULL;
2034 MonoString *o = NULL;
2036 glong items_written;
2038 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2041 o = mono_string_new_utf16 (domain, ut, items_written);
2043 g_error_free (error);
2052 * @text: a pointer to an utf8 string
2054 * Returns: A newly created string object which contains @text.
2057 mono_string_new (MonoDomain *domain, const char *text)
2059 GError *error = NULL;
2060 MonoString *o = NULL;
2062 glong items_written;
2067 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2070 o = mono_string_new_utf16 (domain, ut, items_written);
2072 g_error_free (error);
2080 * mono_string_new_wrapper:
2081 * @text: pointer to utf8 characters.
2083 * Helper function to create a string object from @text in the current domain.
2086 mono_string_new_wrapper (const char *text)
2088 MonoDomain *domain = mono_domain_get ();
2090 MONO_ARCH_SAVE_REGS;
2093 return mono_string_new (domain, text);
2100 * @class: the class of the value
2101 * @value: a pointer to the unboxed data
2103 * Returns: A newly created object which contains @value.
2106 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2112 g_assert (class->valuetype);
2114 vtable = mono_class_vtable (domain, class);
2115 size = mono_class_instance_size (class);
2116 res = mono_object_allocate (size);
2117 res->vtable = vtable;
2118 mono_profiler_allocation (res, class);
2120 size = size - sizeof (MonoObject);
2122 #if NO_UNALIGNED_ACCESS
2123 memcpy ((char *)res + sizeof (MonoObject), value, size);
2127 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2130 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2133 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2136 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2139 memcpy ((char *)res + sizeof (MonoObject), value, size);
2142 if (class->has_finalize)
2143 mono_object_register_finalizer (res);
2148 mono_object_unbox (MonoObject *obj)
2150 /* add assert for valuetypes? */
2151 return ((char*)obj) + sizeof (MonoObject);
2155 * mono_object_isinst:
2157 * @klass: a pointer to a class
2159 * Returns: @obj if @obj is derived from @klass
2162 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2165 mono_class_init (klass);
2167 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2168 return mono_object_isinst_mbyref (obj, klass);
2173 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2177 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2186 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2187 if ((klass->interface_id <= vt->max_interface_id) &&
2188 (vt->interface_offsets [klass->interface_id] != 0))
2192 MonoClass *oklass = vt->klass;
2193 if ((oklass == mono_defaults.transparent_proxy_class))
2194 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2196 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2200 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2202 MonoDomain *domain = mono_domain_get ();
2204 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2205 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2206 MonoMethod *im = NULL;
2210 for (i = 0; i < rpklass->method.count; ++i) {
2211 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2212 im = rpklass->methods [i];
2217 im = mono_object_get_virtual_method (rp, im);
2220 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2223 res = mono_runtime_invoke (im, rp, pa, NULL);
2225 if (*(MonoBoolean *) mono_object_unbox(res)) {
2226 /* Update the vtable of the remote type, so it can safely cast to this new type */
2227 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2228 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2237 * mono_object_castclass_mbyref:
2239 * @klass: a pointer to a class
2241 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2244 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2246 if (!obj) return NULL;
2247 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2249 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2251 "InvalidCastException"));
2256 MonoDomain *orig_domain;
2262 str_lookup (MonoDomain *domain, gpointer user_data)
2264 LDStrInfo *info = user_data;
2265 if (info->res || domain == info->orig_domain)
2267 mono_domain_lock (domain);
2268 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2269 mono_domain_unlock (domain);
2273 mono_string_is_interned_lookup (MonoString *str, int insert)
2275 MonoGHashTable *ldstr_table;
2278 char *ins = g_malloc (4 + str->length * 2);
2281 /* Encode the length */
2282 /* Same code as in mono_image_insert_string () */
2284 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2287 * ins is stored in the hash table as a key and needs to have the same
2288 * representation as in the metadata: we swap the character bytes on big
2291 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2294 char *p2 = (char *)mono_string_chars (str);
2295 for (i = 0; i < str->length; ++i) {
2302 memcpy (p, mono_string_chars (str), str->length * 2);
2304 domain = ((MonoObject *)str)->vtable->domain;
2305 ldstr_table = domain->ldstr_table;
2306 mono_domain_lock (domain);
2307 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2308 mono_domain_unlock (domain);
2313 mono_g_hash_table_insert (ldstr_table, ins, str);
2314 mono_domain_unlock (domain);
2317 LDStrInfo ldstr_info;
2318 ldstr_info.orig_domain = domain;
2319 ldstr_info.ins = ins;
2320 ldstr_info.res = NULL;
2322 mono_domain_foreach (str_lookup, &ldstr_info);
2323 if (ldstr_info.res) {
2325 * the string was already interned in some other domain:
2326 * intern it in the current one as well.
2328 mono_g_hash_table_insert (ldstr_table, ins, str);
2329 mono_domain_unlock (domain);
2333 mono_domain_unlock (domain);
2339 mono_string_is_interned (MonoString *o)
2341 return mono_string_is_interned_lookup (o, FALSE);
2345 mono_string_intern (MonoString *str)
2347 return mono_string_is_interned_lookup (str, TRUE);
2352 * @domain: the domain where the string will be used.
2353 * @image: a metadata context
2354 * @idx: index into the user string table.
2356 * Implementation for the ldstr opcode.
2359 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2361 const char *str, *sig;
2365 MONO_ARCH_SAVE_REGS;
2368 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2370 sig = str = mono_metadata_user_string (image, idx);
2372 mono_domain_lock (domain);
2373 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2374 mono_domain_unlock (domain);
2378 len2 = mono_metadata_decode_blob_size (str, &str);
2381 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2382 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2385 guint16 *p2 = (guint16*)mono_string_chars (o);
2386 for (i = 0; i < len2; ++i) {
2387 *p2 = GUINT16_FROM_LE (*p2);
2392 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2393 mono_domain_unlock (domain);
2399 * mono_string_to_utf8:
2400 * @s: a System.String
2402 * Return the UTF8 representation for @s.
2403 * the resulting buffer nedds to be freed with g_free().
2406 mono_string_to_utf8 (MonoString *s)
2409 GError *error = NULL;
2415 return g_strdup ("");
2417 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2419 g_warning (error->message);
2420 g_error_free (error);
2427 * mono_string_to_utf16:
2430 * Return an null-terminated array of the utf-16 chars
2431 * contained in @s. The result must be freed with g_free().
2432 * This is a temporary helper until our string implementation
2433 * is reworked to always include the null terminating char.
2436 mono_string_to_utf16 (MonoString *s)
2443 as = g_malloc ((s->length * 2) + 2);
2444 as [(s->length * 2)] = '\0';
2445 as [(s->length * 2) + 1] = '\0';
2448 return (gunichar2 *)(as);
2451 memcpy (as, mono_string_chars(s), s->length * 2);
2452 return (gunichar2 *)(as);
2456 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2459 mono_string_from_utf16 (gunichar2 *data)
2461 MonoDomain *domain = mono_domain_get ();
2467 while (data [len]) len++;
2469 return mono_string_new_utf16 (domain, data, len);
2473 default_ex_handler (MonoException *ex)
2475 MonoObject *o = (MonoObject*)ex;
2476 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2480 static MonoExceptionFunc ex_handler = default_ex_handler;
2483 mono_install_handler (MonoExceptionFunc func)
2485 ex_handler = func? func: default_ex_handler;
2489 * mono_raise_exception:
2490 * @ex: exception object
2492 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2495 mono_raise_exception (MonoException *ex)
2498 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2499 * that will cause gcc to omit the function epilog, causing problems when
2500 * the JIT tries to walk the stack, since the return address on the stack
2501 * will point into the next function in the executable, not this one.
2508 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2510 MonoWaitHandle *res;
2512 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2514 res->handle = handle;
2520 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2522 MonoAsyncResult *res;
2524 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2527 res->async_state = state;
2529 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2531 res->sync_completed = FALSE;
2532 res->completed = FALSE;
2538 mono_message_init (MonoDomain *domain,
2539 MonoMethodMessage *this,
2540 MonoReflectionMethod *method,
2541 MonoArray *out_args)
2543 MonoMethodSignature *sig = method->method->signature;
2549 this->method = method;
2551 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2552 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2553 this->async_result = NULL;
2554 this->call_type = CallType_Sync;
2556 names = g_new (char *, sig->param_count);
2557 mono_method_get_param_names (method->method, (const char **) names);
2558 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2560 for (i = 0; i < sig->param_count; i++) {
2561 name = mono_string_new (domain, names [i]);
2562 mono_array_set (this->names, gpointer, i, name);
2566 for (i = 0, j = 0; i < sig->param_count; i++) {
2568 if (sig->params [i]->byref) {
2570 gpointer arg = mono_array_get (out_args, gpointer, j);
2571 mono_array_set (this->args, gpointer, i, arg);
2575 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2580 mono_array_set (this->arg_types, guint8, i, arg_type);
2585 * mono_remoting_invoke:
2586 * @real_proxy: pointer to a RealProxy object
2587 * @msg: The MonoMethodMessage to execute
2588 * @exc: used to store exceptions
2589 * @out_args: used to store output arguments
2591 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2592 * IMessage interface and it is not trivial to extract results from there. So
2593 * we call an helper method PrivateInvoke instead of calling
2594 * RealProxy::Invoke() directly.
2596 * Returns: the result object.
2599 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2600 MonoObject **exc, MonoArray **out_args)
2602 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2605 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2611 klass = mono_defaults.real_proxy_class;
2613 for (i = 0; i < klass->method.count; ++i) {
2614 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2615 klass->methods [i]->signature->param_count == 4) {
2616 im = klass->methods [i];
2622 real_proxy->vtable->domain->private_invoke_method = im;
2625 pa [0] = real_proxy;
2630 return mono_runtime_invoke (im, NULL, pa, exc);
2634 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2635 MonoObject **exc, MonoArray **out_args)
2639 MonoMethodSignature *sig;
2640 int i, j, outarg_count = 0;
2642 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2644 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2645 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2646 target = tp->rp->unwrapped_server;
2648 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2652 domain = mono_domain_get ();
2653 method = msg->method->method;
2654 sig = method->signature;
2656 for (i = 0; i < sig->param_count; i++) {
2657 if (sig->params [i]->byref)
2661 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2664 for (i = 0, j = 0; i < sig->param_count; i++) {
2665 if (sig->params [i]->byref) {
2667 arg = mono_array_get (msg->args, gpointer, i);
2668 mono_array_set (*out_args, gpointer, j, arg);
2673 return mono_runtime_invoke_array (method, target, msg->args, exc);
2677 mono_print_unhandled_exception (MonoObject *exc)
2679 char *message = (char *) "";
2683 gboolean free_message = FALSE;
2686 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2687 klass = exc->vtable->klass;
2689 while (klass && method == NULL) {
2690 for (i = 0; i < klass->method.count; ++i) {
2691 method = klass->methods [i];
2692 if (!strcmp ("ToString", method->name) &&
2693 method->signature->param_count == 0 &&
2694 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2695 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2702 klass = klass->parent;
2707 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2709 message = mono_string_to_utf8 (str);
2710 free_message = TRUE;
2715 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2716 * exc->vtable->klass->name, message);
2718 g_printerr ("\nUnhandled Exception: %s\n", message);
2725 * mono_delegate_ctor:
2726 * @this: pointer to an uninitialized delegate object
2727 * @target: target object
2728 * @addr: pointer to native code
2730 * This is used to initialize a delegate. We also insert the method_info if
2731 * we find the info with mono_jit_info_table_find().
2734 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2736 MonoDomain *domain = mono_domain_get ();
2737 MonoDelegate *delegate = (MonoDelegate *)this;
2738 MonoMethod *method = NULL;
2745 class = this->vtable->klass;
2747 if ((ji = mono_jit_info_table_find (domain, addr))) {
2748 method = ji->method;
2749 delegate->method_info = mono_method_get_object (domain, method, NULL);
2752 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2754 method = mono_marshal_get_remoting_invoke (method);
2755 delegate->method_ptr = mono_compile_method (method);
2756 delegate->target = target;
2758 delegate->method_ptr = addr;
2759 delegate->target = target;
2764 * mono_method_call_message_new:
2766 * Translates arguments pointers into a Message.
2769 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2770 MonoDelegate **cb, MonoObject **state)
2772 MonoDomain *domain = mono_domain_get ();
2773 MonoMethodSignature *sig = method->signature;
2774 MonoMethodMessage *msg;
2777 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2780 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2781 count = sig->param_count - 2;
2783 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2784 count = sig->param_count;
2787 for (i = 0; i < count; i++) {
2792 if (sig->params [i]->byref)
2793 vpos = *((gpointer *)params [i]);
2797 type = sig->params [i]->type;
2798 class = mono_class_from_mono_type (sig->params [i]);
2800 if (class->valuetype)
2801 arg = mono_value_box (domain, class, vpos);
2803 arg = *((MonoObject **)vpos);
2805 mono_array_set (msg->args, gpointer, i, arg);
2808 if (cb != NULL && state != NULL) {
2809 *cb = *((MonoDelegate **)params [i]);
2811 *state = *((MonoObject **)params [i]);
2818 * mono_method_return_message_restore:
2820 * Restore results from message based processing back to arguments pointers
2823 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2825 MonoMethodSignature *sig = method->signature;
2826 int i, j, type, size;
2827 for (i = 0, j = 0; i < sig->param_count; i++) {
2828 MonoType *pt = sig->params [i];
2831 char *arg = mono_array_get (out_args, gpointer, j);
2835 case MONO_TYPE_VOID:
2836 g_assert_not_reached ();
2840 case MONO_TYPE_BOOLEAN:
2843 case MONO_TYPE_CHAR:
2850 case MONO_TYPE_VALUETYPE: {
2851 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2852 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2855 case MONO_TYPE_STRING:
2856 case MONO_TYPE_CLASS:
2857 case MONO_TYPE_ARRAY:
2858 case MONO_TYPE_SZARRAY:
2859 case MONO_TYPE_OBJECT:
2860 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2863 g_assert_not_reached ();
2872 * mono_load_remote_field:
2873 * @this: pointer to an object
2874 * @klass: klass of the object containing @field
2875 * @field: the field to load
2876 * @res: a storage to store the result
2878 * This method is called by the runtime on attempts to load fields of
2879 * transparent proxy objects. @this points to such TP, @klass is the class of
2880 * the object containing @field. @res is a storage location which can be
2881 * used to store the result.
2883 * Returns: an address pointing to the value of field.
2886 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2888 static MonoMethod *getter = NULL;
2889 MonoDomain *domain = mono_domain_get ();
2890 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2891 MonoClass *field_class;
2892 MonoMethodMessage *msg;
2893 MonoArray *out_args;
2897 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2902 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2903 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2910 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2911 MonoMethod *cm = mono_defaults.object_class->methods [i];
2913 if (!strcmp (cm->name, "FieldGetter")) {
2921 field_class = mono_class_from_mono_type (field->type);
2923 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2924 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2925 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2927 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2928 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2930 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2932 if (exc) mono_raise_exception ((MonoException *)exc);
2934 *res = mono_array_get (out_args, MonoObject *, 0);
2936 if (field_class->valuetype) {
2937 return ((char *)*res) + sizeof (MonoObject);
2943 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2945 static MonoMethod *getter = NULL;
2946 MonoDomain *domain = mono_domain_get ();
2947 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2948 MonoClass *field_class;
2949 MonoMethodMessage *msg;
2950 MonoArray *out_args;
2951 MonoObject *exc, *res;
2953 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2955 field_class = mono_class_from_mono_type (field->type);
2957 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2959 if (field_class->valuetype) {
2960 res = mono_object_new (domain, field_class);
2961 val = ((gchar *) res) + sizeof (MonoObject);
2965 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2972 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2973 MonoMethod *cm = mono_defaults.object_class->methods [i];
2975 if (!strcmp (cm->name, "FieldGetter")) {
2983 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2984 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2985 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2987 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2988 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2990 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2992 if (exc) mono_raise_exception ((MonoException *)exc);
2994 res = mono_array_get (out_args, MonoObject *, 0);
3000 * mono_store_remote_field:
3001 * @this: pointer to an object
3002 * @klass: klass of the object containing @field
3003 * @field: the field to load
3004 * @val: the value/object to store
3006 * This method is called by the runtime on attempts to store fields of
3007 * transparent proxy objects. @this points to such TP, @klass is the class of
3008 * the object containing @field. @val is the new value to store in @field.
3011 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3013 static MonoMethod *setter = NULL;
3014 MonoDomain *domain = mono_domain_get ();
3015 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3016 MonoClass *field_class;
3017 MonoMethodMessage *msg;
3018 MonoArray *out_args;
3022 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3024 field_class = mono_class_from_mono_type (field->type);
3026 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3027 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3028 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3035 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3036 MonoMethod *cm = mono_defaults.object_class->methods [i];
3038 if (!strcmp (cm->name, "FieldSetter")) {
3046 if (field_class->valuetype)
3047 arg = mono_value_box (domain, field_class, val);
3049 arg = *((MonoObject **)val);
3052 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3053 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3055 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3056 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3057 mono_array_set (msg->args, gpointer, 2, arg);
3059 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3061 if (exc) mono_raise_exception ((MonoException *)exc);
3065 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3067 static MonoMethod *setter = NULL;
3068 MonoDomain *domain = mono_domain_get ();
3069 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3070 MonoClass *field_class;
3071 MonoMethodMessage *msg;
3072 MonoArray *out_args;
3075 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3077 field_class = mono_class_from_mono_type (field->type);
3079 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3080 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3081 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3088 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3089 MonoMethod *cm = mono_defaults.object_class->methods [i];
3091 if (!strcmp (cm->name, "FieldSetter")) {
3099 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3100 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3102 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3103 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3104 mono_array_set (msg->args, gpointer, 2, arg);
3106 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3108 if (exc) mono_raise_exception ((MonoException *)exc);