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)
2002 size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2004 /* overflow ? can't fit it, can't allocate it! */
2008 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2010 #if CREATION_SPEEDUP
2011 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2012 s = mono_object_allocate_spec (size, vtable);
2014 s = (MonoString*)mono_object_allocate (size);
2015 s->object.vtable = vtable;
2018 s = (MonoString*)mono_object_allocate (size);
2019 s->object.vtable = vtable;
2023 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2029 * mono_string_new_len:
2030 * @text: a pointer to an utf8 string
2031 * @length: number of bytes in @text to consider
2033 * Returns: A newly created string object which contains @text.
2036 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2038 GError *error = NULL;
2039 MonoString *o = NULL;
2041 glong items_written;
2043 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2046 o = mono_string_new_utf16 (domain, ut, items_written);
2048 g_error_free (error);
2057 * @text: a pointer to an utf8 string
2059 * Returns: A newly created string object which contains @text.
2062 mono_string_new (MonoDomain *domain, const char *text)
2064 GError *error = NULL;
2065 MonoString *o = NULL;
2067 glong items_written;
2072 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2075 o = mono_string_new_utf16 (domain, ut, items_written);
2077 g_error_free (error);
2085 * mono_string_new_wrapper:
2086 * @text: pointer to utf8 characters.
2088 * Helper function to create a string object from @text in the current domain.
2091 mono_string_new_wrapper (const char *text)
2093 MonoDomain *domain = mono_domain_get ();
2095 MONO_ARCH_SAVE_REGS;
2098 return mono_string_new (domain, text);
2105 * @class: the class of the value
2106 * @value: a pointer to the unboxed data
2108 * Returns: A newly created object which contains @value.
2111 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2117 g_assert (class->valuetype);
2119 vtable = mono_class_vtable (domain, class);
2120 size = mono_class_instance_size (class);
2121 res = mono_object_allocate (size);
2122 res->vtable = vtable;
2123 mono_profiler_allocation (res, class);
2125 size = size - sizeof (MonoObject);
2127 #if NO_UNALIGNED_ACCESS
2128 memcpy ((char *)res + sizeof (MonoObject), value, size);
2132 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2135 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2138 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2141 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2144 memcpy ((char *)res + sizeof (MonoObject), value, size);
2147 if (class->has_finalize)
2148 mono_object_register_finalizer (res);
2153 mono_object_unbox (MonoObject *obj)
2155 /* add assert for valuetypes? */
2156 return ((char*)obj) + sizeof (MonoObject);
2160 * mono_object_isinst:
2162 * @klass: a pointer to a class
2164 * Returns: @obj if @obj is derived from @klass
2167 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2170 mono_class_init (klass);
2172 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2173 return mono_object_isinst_mbyref (obj, klass);
2178 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2182 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2191 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2192 if ((klass->interface_id <= vt->max_interface_id) &&
2193 (vt->interface_offsets [klass->interface_id] != 0))
2197 MonoClass *oklass = vt->klass;
2198 if ((oklass == mono_defaults.transparent_proxy_class))
2199 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2201 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2205 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2207 MonoDomain *domain = mono_domain_get ();
2209 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2210 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2211 MonoMethod *im = NULL;
2215 for (i = 0; i < rpklass->method.count; ++i) {
2216 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2217 im = rpklass->methods [i];
2222 im = mono_object_get_virtual_method (rp, im);
2225 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2228 res = mono_runtime_invoke (im, rp, pa, NULL);
2230 if (*(MonoBoolean *) mono_object_unbox(res)) {
2231 /* Update the vtable of the remote type, so it can safely cast to this new type */
2232 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2233 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2242 * mono_object_castclass_mbyref:
2244 * @klass: a pointer to a class
2246 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2249 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2251 if (!obj) return NULL;
2252 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2254 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2256 "InvalidCastException"));
2261 MonoDomain *orig_domain;
2267 str_lookup (MonoDomain *domain, gpointer user_data)
2269 LDStrInfo *info = user_data;
2270 if (info->res || domain == info->orig_domain)
2272 mono_domain_lock (domain);
2273 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2274 mono_domain_unlock (domain);
2278 mono_string_is_interned_lookup (MonoString *str, int insert)
2280 MonoGHashTable *ldstr_table;
2283 char *ins = g_malloc (4 + str->length * 2);
2286 /* Encode the length */
2287 /* Same code as in mono_image_insert_string () */
2289 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2292 * ins is stored in the hash table as a key and needs to have the same
2293 * representation as in the metadata: we swap the character bytes on big
2296 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2299 char *p2 = (char *)mono_string_chars (str);
2300 for (i = 0; i < str->length; ++i) {
2307 memcpy (p, mono_string_chars (str), str->length * 2);
2309 domain = ((MonoObject *)str)->vtable->domain;
2310 ldstr_table = domain->ldstr_table;
2311 mono_domain_lock (domain);
2312 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2313 mono_domain_unlock (domain);
2318 mono_g_hash_table_insert (ldstr_table, ins, str);
2319 mono_domain_unlock (domain);
2322 LDStrInfo ldstr_info;
2323 ldstr_info.orig_domain = domain;
2324 ldstr_info.ins = ins;
2325 ldstr_info.res = NULL;
2327 mono_domain_foreach (str_lookup, &ldstr_info);
2328 if (ldstr_info.res) {
2330 * the string was already interned in some other domain:
2331 * intern it in the current one as well.
2333 mono_g_hash_table_insert (ldstr_table, ins, str);
2334 mono_domain_unlock (domain);
2338 mono_domain_unlock (domain);
2344 mono_string_is_interned (MonoString *o)
2346 return mono_string_is_interned_lookup (o, FALSE);
2350 mono_string_intern (MonoString *str)
2352 return mono_string_is_interned_lookup (str, TRUE);
2357 * @domain: the domain where the string will be used.
2358 * @image: a metadata context
2359 * @idx: index into the user string table.
2361 * Implementation for the ldstr opcode.
2364 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2366 const char *str, *sig;
2370 MONO_ARCH_SAVE_REGS;
2373 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2375 sig = str = mono_metadata_user_string (image, idx);
2377 mono_domain_lock (domain);
2378 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2379 mono_domain_unlock (domain);
2383 len2 = mono_metadata_decode_blob_size (str, &str);
2386 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2387 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2390 guint16 *p2 = (guint16*)mono_string_chars (o);
2391 for (i = 0; i < len2; ++i) {
2392 *p2 = GUINT16_FROM_LE (*p2);
2397 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2398 mono_domain_unlock (domain);
2404 * mono_string_to_utf8:
2405 * @s: a System.String
2407 * Return the UTF8 representation for @s.
2408 * the resulting buffer nedds to be freed with g_free().
2411 mono_string_to_utf8 (MonoString *s)
2414 GError *error = NULL;
2420 return g_strdup ("");
2422 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2424 g_warning (error->message);
2425 g_error_free (error);
2432 * mono_string_to_utf16:
2435 * Return an null-terminated array of the utf-16 chars
2436 * contained in @s. The result must be freed with g_free().
2437 * This is a temporary helper until our string implementation
2438 * is reworked to always include the null terminating char.
2441 mono_string_to_utf16 (MonoString *s)
2448 as = g_malloc ((s->length * 2) + 2);
2449 as [(s->length * 2)] = '\0';
2450 as [(s->length * 2) + 1] = '\0';
2453 return (gunichar2 *)(as);
2456 memcpy (as, mono_string_chars(s), s->length * 2);
2457 return (gunichar2 *)(as);
2461 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2464 mono_string_from_utf16 (gunichar2 *data)
2466 MonoDomain *domain = mono_domain_get ();
2472 while (data [len]) len++;
2474 return mono_string_new_utf16 (domain, data, len);
2478 default_ex_handler (MonoException *ex)
2480 MonoObject *o = (MonoObject*)ex;
2481 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2485 static MonoExceptionFunc ex_handler = default_ex_handler;
2488 mono_install_handler (MonoExceptionFunc func)
2490 ex_handler = func? func: default_ex_handler;
2494 * mono_raise_exception:
2495 * @ex: exception object
2497 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2500 mono_raise_exception (MonoException *ex)
2503 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2504 * that will cause gcc to omit the function epilog, causing problems when
2505 * the JIT tries to walk the stack, since the return address on the stack
2506 * will point into the next function in the executable, not this one.
2513 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2515 MonoWaitHandle *res;
2517 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2519 res->handle = handle;
2525 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2527 MonoAsyncResult *res;
2529 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2532 res->async_state = state;
2534 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2536 res->sync_completed = FALSE;
2537 res->completed = FALSE;
2543 mono_message_init (MonoDomain *domain,
2544 MonoMethodMessage *this,
2545 MonoReflectionMethod *method,
2546 MonoArray *out_args)
2548 MonoMethodSignature *sig = method->method->signature;
2554 this->method = method;
2556 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2557 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2558 this->async_result = NULL;
2559 this->call_type = CallType_Sync;
2561 names = g_new (char *, sig->param_count);
2562 mono_method_get_param_names (method->method, (const char **) names);
2563 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2565 for (i = 0; i < sig->param_count; i++) {
2566 name = mono_string_new (domain, names [i]);
2567 mono_array_set (this->names, gpointer, i, name);
2571 for (i = 0, j = 0; i < sig->param_count; i++) {
2573 if (sig->params [i]->byref) {
2575 gpointer arg = mono_array_get (out_args, gpointer, j);
2576 mono_array_set (this->args, gpointer, i, arg);
2580 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2585 mono_array_set (this->arg_types, guint8, i, arg_type);
2590 * mono_remoting_invoke:
2591 * @real_proxy: pointer to a RealProxy object
2592 * @msg: The MonoMethodMessage to execute
2593 * @exc: used to store exceptions
2594 * @out_args: used to store output arguments
2596 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2597 * IMessage interface and it is not trivial to extract results from there. So
2598 * we call an helper method PrivateInvoke instead of calling
2599 * RealProxy::Invoke() directly.
2601 * Returns: the result object.
2604 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2605 MonoObject **exc, MonoArray **out_args)
2607 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2610 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2616 klass = mono_defaults.real_proxy_class;
2618 for (i = 0; i < klass->method.count; ++i) {
2619 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2620 klass->methods [i]->signature->param_count == 4) {
2621 im = klass->methods [i];
2627 real_proxy->vtable->domain->private_invoke_method = im;
2630 pa [0] = real_proxy;
2635 return mono_runtime_invoke (im, NULL, pa, exc);
2639 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2640 MonoObject **exc, MonoArray **out_args)
2644 MonoMethodSignature *sig;
2645 int i, j, outarg_count = 0;
2647 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2649 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2650 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2651 target = tp->rp->unwrapped_server;
2653 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2657 domain = mono_domain_get ();
2658 method = msg->method->method;
2659 sig = method->signature;
2661 for (i = 0; i < sig->param_count; i++) {
2662 if (sig->params [i]->byref)
2666 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2669 for (i = 0, j = 0; i < sig->param_count; i++) {
2670 if (sig->params [i]->byref) {
2672 arg = mono_array_get (msg->args, gpointer, i);
2673 mono_array_set (*out_args, gpointer, j, arg);
2678 return mono_runtime_invoke_array (method, target, msg->args, exc);
2682 mono_print_unhandled_exception (MonoObject *exc)
2684 char *message = (char *) "";
2688 gboolean free_message = FALSE;
2691 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2692 klass = exc->vtable->klass;
2694 while (klass && method == NULL) {
2695 for (i = 0; i < klass->method.count; ++i) {
2696 method = klass->methods [i];
2697 if (!strcmp ("ToString", method->name) &&
2698 method->signature->param_count == 0 &&
2699 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2700 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2707 klass = klass->parent;
2712 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2714 message = mono_string_to_utf8 (str);
2715 free_message = TRUE;
2720 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2721 * exc->vtable->klass->name, message);
2723 g_printerr ("\nUnhandled Exception: %s\n", message);
2730 * mono_delegate_ctor:
2731 * @this: pointer to an uninitialized delegate object
2732 * @target: target object
2733 * @addr: pointer to native code
2735 * This is used to initialize a delegate. We also insert the method_info if
2736 * we find the info with mono_jit_info_table_find().
2739 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2741 MonoDomain *domain = mono_domain_get ();
2742 MonoDelegate *delegate = (MonoDelegate *)this;
2743 MonoMethod *method = NULL;
2750 class = this->vtable->klass;
2752 if ((ji = mono_jit_info_table_find (domain, addr))) {
2753 method = ji->method;
2754 delegate->method_info = mono_method_get_object (domain, method, NULL);
2757 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2759 method = mono_marshal_get_remoting_invoke (method);
2760 delegate->method_ptr = mono_compile_method (method);
2761 delegate->target = target;
2763 delegate->method_ptr = addr;
2764 delegate->target = target;
2769 * mono_method_call_message_new:
2771 * Translates arguments pointers into a Message.
2774 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2775 MonoDelegate **cb, MonoObject **state)
2777 MonoDomain *domain = mono_domain_get ();
2778 MonoMethodSignature *sig = method->signature;
2779 MonoMethodMessage *msg;
2782 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2785 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2786 count = sig->param_count - 2;
2788 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2789 count = sig->param_count;
2792 for (i = 0; i < count; i++) {
2797 if (sig->params [i]->byref)
2798 vpos = *((gpointer *)params [i]);
2802 type = sig->params [i]->type;
2803 class = mono_class_from_mono_type (sig->params [i]);
2805 if (class->valuetype)
2806 arg = mono_value_box (domain, class, vpos);
2808 arg = *((MonoObject **)vpos);
2810 mono_array_set (msg->args, gpointer, i, arg);
2813 if (cb != NULL && state != NULL) {
2814 *cb = *((MonoDelegate **)params [i]);
2816 *state = *((MonoObject **)params [i]);
2823 * mono_method_return_message_restore:
2825 * Restore results from message based processing back to arguments pointers
2828 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2830 MonoMethodSignature *sig = method->signature;
2831 int i, j, type, size;
2832 for (i = 0, j = 0; i < sig->param_count; i++) {
2833 MonoType *pt = sig->params [i];
2836 char *arg = mono_array_get (out_args, gpointer, j);
2840 case MONO_TYPE_VOID:
2841 g_assert_not_reached ();
2845 case MONO_TYPE_BOOLEAN:
2848 case MONO_TYPE_CHAR:
2855 case MONO_TYPE_VALUETYPE: {
2856 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2857 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2860 case MONO_TYPE_STRING:
2861 case MONO_TYPE_CLASS:
2862 case MONO_TYPE_ARRAY:
2863 case MONO_TYPE_SZARRAY:
2864 case MONO_TYPE_OBJECT:
2865 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2868 g_assert_not_reached ();
2877 * mono_load_remote_field:
2878 * @this: pointer to an object
2879 * @klass: klass of the object containing @field
2880 * @field: the field to load
2881 * @res: a storage to store the result
2883 * This method is called by the runtime on attempts to load fields of
2884 * transparent proxy objects. @this points to such TP, @klass is the class of
2885 * the object containing @field. @res is a storage location which can be
2886 * used to store the result.
2888 * Returns: an address pointing to the value of field.
2891 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2893 static MonoMethod *getter = NULL;
2894 MonoDomain *domain = mono_domain_get ();
2895 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2896 MonoClass *field_class;
2897 MonoMethodMessage *msg;
2898 MonoArray *out_args;
2902 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2907 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2908 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2915 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2916 MonoMethod *cm = mono_defaults.object_class->methods [i];
2918 if (!strcmp (cm->name, "FieldGetter")) {
2926 field_class = mono_class_from_mono_type (field->type);
2928 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2929 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2930 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2932 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2933 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2935 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2937 if (exc) mono_raise_exception ((MonoException *)exc);
2939 *res = mono_array_get (out_args, MonoObject *, 0);
2941 if (field_class->valuetype) {
2942 return ((char *)*res) + sizeof (MonoObject);
2948 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2950 static MonoMethod *getter = NULL;
2951 MonoDomain *domain = mono_domain_get ();
2952 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2953 MonoClass *field_class;
2954 MonoMethodMessage *msg;
2955 MonoArray *out_args;
2956 MonoObject *exc, *res;
2958 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2960 field_class = mono_class_from_mono_type (field->type);
2962 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2964 if (field_class->valuetype) {
2965 res = mono_object_new (domain, field_class);
2966 val = ((gchar *) res) + sizeof (MonoObject);
2970 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2977 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2978 MonoMethod *cm = mono_defaults.object_class->methods [i];
2980 if (!strcmp (cm->name, "FieldGetter")) {
2988 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2989 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2990 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2992 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2993 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2995 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2997 if (exc) mono_raise_exception ((MonoException *)exc);
2999 res = mono_array_get (out_args, MonoObject *, 0);
3005 * mono_store_remote_field:
3006 * @this: pointer to an object
3007 * @klass: klass of the object containing @field
3008 * @field: the field to load
3009 * @val: the value/object to store
3011 * This method is called by the runtime on attempts to store fields of
3012 * transparent proxy objects. @this points to such TP, @klass is the class of
3013 * the object containing @field. @val is the new value to store in @field.
3016 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3018 static MonoMethod *setter = NULL;
3019 MonoDomain *domain = mono_domain_get ();
3020 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3021 MonoClass *field_class;
3022 MonoMethodMessage *msg;
3023 MonoArray *out_args;
3027 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3029 field_class = mono_class_from_mono_type (field->type);
3031 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3032 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3033 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3040 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3041 MonoMethod *cm = mono_defaults.object_class->methods [i];
3043 if (!strcmp (cm->name, "FieldSetter")) {
3051 if (field_class->valuetype)
3052 arg = mono_value_box (domain, field_class, val);
3054 arg = *((MonoObject **)val);
3057 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3058 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3060 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3061 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3062 mono_array_set (msg->args, gpointer, 2, arg);
3064 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3066 if (exc) mono_raise_exception ((MonoException *)exc);
3070 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3072 static MonoMethod *setter = NULL;
3073 MonoDomain *domain = mono_domain_get ();
3074 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3075 MonoClass *field_class;
3076 MonoMethodMessage *msg;
3077 MonoArray *out_args;
3080 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3082 field_class = mono_class_from_mono_type (field->type);
3084 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3085 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3086 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3093 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3094 MonoMethod *cm = mono_defaults.object_class->methods [i];
3096 if (!strcmp (cm->name, "FieldSetter")) {
3104 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3105 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3107 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3108 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3109 mono_array_set (msg->args, gpointer, 2, arg);
3111 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3113 if (exc) mono_raise_exception ((MonoException *)exc);