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 g_assert (((gpointer*)params->vector) [i]);
1520 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1522 case MONO_TYPE_STRING:
1523 case MONO_TYPE_OBJECT:
1524 case MONO_TYPE_CLASS:
1525 case MONO_TYPE_ARRAY:
1526 case MONO_TYPE_SZARRAY:
1527 if (sig->params [i]->byref)
1528 pa [i] = &(((gpointer *)params->vector)[i]);
1530 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1533 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1538 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1540 obj = mono_object_new (mono_domain_get (), method->klass);
1541 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1542 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
1545 mono_runtime_invoke (method, obj, pa, exc);
1548 return mono_runtime_invoke (method, obj, pa, exc);
1552 out_of_memory (size_t size)
1555 * we could allocate at program startup some memory that we could release
1556 * back to the system at this point if we're really low on memory (ie, size is
1557 * lower than the memory we set apart)
1559 mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
1563 * mono_object_allocate:
1564 * @size: number of bytes to allocate
1566 * This is a very simplistic routine until we have our GC-aware
1569 * Returns: an allocated object of size @size, or NULL on failure.
1571 static inline void *
1572 mono_object_allocate (size_t size)
1575 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1576 void *o = GC_MALLOC (size);
1578 void *o = calloc (1, size);
1580 mono_stats.new_object_count++;
1583 out_of_memory (size);
1587 #if CREATION_SPEEDUP
1588 static inline void *
1589 mono_object_allocate_spec (size_t size, void *gcdescr)
1591 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1592 void *o = GC_GCJ_MALLOC (size, gcdescr);
1593 mono_stats.new_object_count++;
1596 out_of_memory (size);
1604 * Frees the memory used by the object. Debugging purposes
1605 * only, as we will have our GC system.
1608 mono_object_free (MonoObject *o)
1611 g_error ("mono_object_free called with boehm gc.");
1613 MonoClass *c = o->vtable->klass;
1615 memset (o, 0, c->instance_size);
1622 * @klass: the class of the object that we want to create
1624 * Returns: A newly created object whose definition is
1625 * looked up using @klass
1628 mono_object_new (MonoDomain *domain, MonoClass *klass)
1630 MONO_ARCH_SAVE_REGS;
1631 return mono_object_new_specific (mono_class_vtable (domain, klass));
1635 * mono_object_new_specific:
1636 * @vtable: the vtable of the object that we want to create
1638 * Returns: A newly created object with class and domain specified
1642 mono_object_new_specific (MonoVTable *vtable)
1646 MONO_ARCH_SAVE_REGS;
1651 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1654 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1658 mono_class_init (klass);
1660 for (i = 0; i < klass->method.count; ++i) {
1661 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1662 klass->methods [i]->signature->param_count == 1) {
1663 im = klass->methods [i];
1668 vtable->domain->create_proxy_for_type_method = im;
1671 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1673 o = mono_runtime_invoke (im, NULL, pa, NULL);
1674 if (o != NULL) return o;
1677 return mono_object_new_alloc_specific (vtable);
1681 mono_object_new_fast (MonoVTable *vtable)
1684 MONO_ARCH_SAVE_REGS;
1686 #if CREATION_SPEEDUP
1687 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1688 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1690 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1691 o = mono_object_allocate (vtable->klass->instance_size);
1695 o = mono_object_allocate (vtable->klass->instance_size);
1702 mono_object_new_alloc_specific (MonoVTable *vtable)
1706 #if CREATION_SPEEDUP
1707 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1708 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1710 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1711 o = mono_object_allocate (vtable->klass->instance_size);
1715 o = mono_object_allocate (vtable->klass->instance_size);
1718 if (vtable->klass->has_finalize)
1719 mono_object_register_finalizer (o);
1721 mono_profiler_allocation (o, vtable->klass);
1726 * mono_object_new_from_token:
1727 * @image: Context where the type_token is hosted
1728 * @token: a token of the type that we want to create
1730 * Returns: A newly created object whose definition is
1731 * looked up using @token in the @image image
1734 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1738 class = mono_class_get (image, token);
1740 return mono_object_new (domain, class);
1745 * mono_object_clone:
1746 * @obj: the object to clone
1748 * Returns: A newly created object who is a shallow copy of @obj
1751 mono_object_clone (MonoObject *obj)
1756 size = obj->vtable->klass->instance_size;
1757 o = mono_object_allocate (size);
1758 mono_profiler_allocation (o, obj->vtable->klass);
1760 memcpy (o, obj, size);
1762 if (obj->vtable->klass->has_finalize)
1763 mono_object_register_finalizer (o);
1769 * @array: the array to clone
1771 * Returns: A newly created array who is a shallow copy of @array
1774 mono_array_clone (MonoArray *array)
1779 MonoClass *klass = array->obj.vtable->klass;
1781 MONO_ARCH_SAVE_REGS;
1783 if (array->bounds == NULL) {
1784 size = mono_array_length (array);
1785 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1786 klass, &size, NULL);
1788 size *= mono_array_element_size (klass);
1789 memcpy (o, array, sizeof (MonoArray) + size);
1794 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1795 size = mono_array_element_size (klass);
1796 for (i = 0; i < klass->rank; ++i) {
1797 sizes [i] = array->bounds [i].length;
1798 size *= array->bounds [i].length;
1799 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1801 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1802 klass, sizes, sizes + klass->rank);
1803 memcpy (o, array, sizeof(MonoArray) + size);
1808 /* helper macros to check for overflow when calculating the size of arrays */
1809 #define MYGUINT32_MAX 4294967295U
1810 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1811 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1812 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1813 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1814 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1817 * mono_array_new_full:
1818 * @domain: domain where the object is created
1819 * @array_class: array class
1820 * @lengths: lengths for each dimension in the array
1821 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1823 * This routine creates a new array objects with the given dimensions,
1824 * lower bounds and type.
1827 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1828 guint32 *lengths, guint32 *lower_bounds)
1830 guint32 byte_len, len;
1833 MonoArrayBounds *bounds;
1837 if (!array_class->inited)
1838 mono_class_init (array_class);
1840 byte_len = mono_array_element_size (array_class);
1843 if (array_class->rank == 1 &&
1844 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1849 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1851 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1853 for (i = 0; i < array_class->rank; ++i) {
1854 bounds [i].length = lengths [i];
1855 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1856 out_of_memory (MYGUINT32_MAX);
1861 for (i = 0; i < array_class->rank; ++i)
1862 bounds [i].lower_bound = lower_bounds [i];
1865 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1866 out_of_memory (MYGUINT32_MAX);
1868 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1869 out_of_memory (MYGUINT32_MAX);
1870 byte_len += sizeof (MonoArray);
1872 * Following three lines almost taken from mono_object_new ():
1873 * they need to be kept in sync.
1875 vtable = mono_class_vtable (domain, array_class);
1876 #if CREATION_SPEEDUP
1877 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1878 o = mono_object_allocate_spec (byte_len, vtable);
1880 o = mono_object_allocate (byte_len);
1884 o = mono_object_allocate (byte_len);
1888 array = (MonoArray*)o;
1890 array->bounds = bounds;
1891 array->max_length = len;
1893 mono_profiler_allocation (o, array_class);
1900 * @domain: domain where the object is created
1901 * @eclass: element class
1902 * @n: number of array elements
1904 * This routine creates a new szarray with @n elements of type @eclass.
1907 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1911 MONO_ARCH_SAVE_REGS;
1913 ac = mono_array_class_get (eclass, 1);
1914 g_assert (ac != NULL);
1916 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1920 * mono_array_new_specific:
1921 * @vtable: a vtable in the appropriate domain for an initialized class
1922 * @n: number of array elements
1924 * This routine is a fast alternative to mono_array_new() for code which
1925 * can be sure about the domain it operates in.
1928 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1932 guint32 byte_len, elem_size;
1934 MONO_ARCH_SAVE_REGS;
1936 elem_size = mono_array_element_size (vtable->klass);
1937 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1938 out_of_memory (MYGUINT32_MAX);
1939 byte_len = n * elem_size;
1940 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1941 out_of_memory (MYGUINT32_MAX);
1942 byte_len += sizeof (MonoArray);
1943 #if CREATION_SPEEDUP
1944 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1945 o = mono_object_allocate_spec (byte_len, vtable);
1947 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1948 o = mono_object_allocate (byte_len);
1952 o = mono_object_allocate (byte_len);
1956 ao = (MonoArray *)o;
1959 mono_profiler_allocation (o, vtable->klass);
1965 * mono_string_new_utf16:
1966 * @text: a pointer to an utf16 string
1967 * @len: the length of the string
1969 * Returns: A newly created string object which contains @text.
1972 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1976 s = mono_string_new_size (domain, len);
1977 g_assert (s != NULL);
1979 memcpy (mono_string_chars (s), text, len * 2);
1985 * mono_string_new_size:
1986 * @text: a pointer to an utf16 string
1987 * @len: the length of the string
1989 * Returns: A newly created string object of @len
1992 mono_string_new_size (MonoDomain *domain, gint32 len)
1997 vtable = mono_class_vtable (domain, mono_defaults.string_class);
1999 #if CREATION_SPEEDUP
2000 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2001 s = mono_object_allocate_spec (sizeof (MonoString) + ((len + 1) * 2), vtable);
2003 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
2004 s->object.vtable = vtable;
2007 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
2008 s->object.vtable = vtable;
2012 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2018 * mono_string_new_len:
2019 * @text: a pointer to an utf8 string
2020 * @length: number of bytes in @text to consider
2022 * Returns: A newly created string object which contains @text.
2025 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2027 GError *error = NULL;
2028 MonoString *o = NULL;
2030 glong items_written;
2032 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2035 o = mono_string_new_utf16 (domain, ut, items_written);
2037 g_error_free (error);
2046 * @text: a pointer to an utf8 string
2048 * Returns: A newly created string object which contains @text.
2051 mono_string_new (MonoDomain *domain, const char *text)
2053 GError *error = NULL;
2054 MonoString *o = NULL;
2056 glong items_written;
2061 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2064 o = mono_string_new_utf16 (domain, ut, items_written);
2066 g_error_free (error);
2074 * mono_string_new_wrapper:
2075 * @text: pointer to utf8 characters.
2077 * Helper function to create a string object from @text in the current domain.
2080 mono_string_new_wrapper (const char *text)
2082 MonoDomain *domain = mono_domain_get ();
2084 MONO_ARCH_SAVE_REGS;
2087 return mono_string_new (domain, text);
2094 * @class: the class of the value
2095 * @value: a pointer to the unboxed data
2097 * Returns: A newly created object which contains @value.
2100 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2106 g_assert (class->valuetype);
2108 vtable = mono_class_vtable (domain, class);
2109 size = mono_class_instance_size (class);
2110 res = mono_object_allocate (size);
2111 res->vtable = vtable;
2112 mono_profiler_allocation (res, class);
2114 size = size - sizeof (MonoObject);
2116 #if NO_UNALIGNED_ACCESS
2117 memcpy ((char *)res + sizeof (MonoObject), value, size);
2121 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2124 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2127 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2130 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2133 memcpy ((char *)res + sizeof (MonoObject), value, size);
2136 if (class->has_finalize)
2137 mono_object_register_finalizer (res);
2142 mono_object_unbox (MonoObject *obj)
2144 /* add assert for valuetypes? */
2145 return ((char*)obj) + sizeof (MonoObject);
2149 * mono_object_isinst:
2151 * @klass: a pointer to a class
2153 * Returns: @obj if @obj is derived from @klass
2156 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2159 mono_class_init (klass);
2161 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2162 return mono_object_isinst_mbyref (obj, klass);
2167 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2171 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2180 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2181 if ((klass->interface_id <= vt->max_interface_id) &&
2182 (vt->interface_offsets [klass->interface_id] != 0))
2186 MonoClass *oklass = vt->klass;
2187 if ((oklass == mono_defaults.transparent_proxy_class))
2188 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2190 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2194 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2196 MonoDomain *domain = mono_domain_get ();
2198 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2199 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2200 MonoMethod *im = NULL;
2204 for (i = 0; i < rpklass->method.count; ++i) {
2205 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2206 im = rpklass->methods [i];
2211 im = mono_object_get_virtual_method (rp, im);
2214 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2217 res = mono_runtime_invoke (im, rp, pa, NULL);
2219 if (*(MonoBoolean *) mono_object_unbox(res)) {
2220 /* Update the vtable of the remote type, so it can safely cast to this new type */
2221 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2222 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2231 * mono_object_castclass_mbyref:
2233 * @klass: a pointer to a class
2235 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2238 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2240 if (!obj) return NULL;
2241 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2243 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2245 "InvalidCastException"));
2250 MonoDomain *orig_domain;
2256 str_lookup (MonoDomain *domain, gpointer user_data)
2258 LDStrInfo *info = user_data;
2259 if (info->res || domain == info->orig_domain)
2261 mono_domain_lock (domain);
2262 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2263 mono_domain_unlock (domain);
2267 mono_string_is_interned_lookup (MonoString *str, int insert)
2269 MonoGHashTable *ldstr_table;
2272 char *ins = g_malloc (4 + str->length * 2);
2275 /* Encode the length */
2276 /* Same code as in mono_image_insert_string () */
2278 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2281 * ins is stored in the hash table as a key and needs to have the same
2282 * representation as in the metadata: we swap the character bytes on big
2285 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2288 char *p2 = (char *)mono_string_chars (str);
2289 for (i = 0; i < str->length; ++i) {
2296 memcpy (p, mono_string_chars (str), str->length * 2);
2298 domain = ((MonoObject *)str)->vtable->domain;
2299 ldstr_table = domain->ldstr_table;
2300 mono_domain_lock (domain);
2301 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2302 mono_domain_unlock (domain);
2307 mono_g_hash_table_insert (ldstr_table, ins, str);
2308 mono_domain_unlock (domain);
2311 LDStrInfo ldstr_info;
2312 ldstr_info.orig_domain = domain;
2313 ldstr_info.ins = ins;
2314 ldstr_info.res = NULL;
2316 mono_domain_foreach (str_lookup, &ldstr_info);
2317 if (ldstr_info.res) {
2319 * the string was already interned in some other domain:
2320 * intern it in the current one as well.
2322 mono_g_hash_table_insert (ldstr_table, ins, str);
2323 mono_domain_unlock (domain);
2327 mono_domain_unlock (domain);
2333 mono_string_is_interned (MonoString *o)
2335 return mono_string_is_interned_lookup (o, FALSE);
2339 mono_string_intern (MonoString *str)
2341 return mono_string_is_interned_lookup (str, TRUE);
2346 * @domain: the domain where the string will be used.
2347 * @image: a metadata context
2348 * @idx: index into the user string table.
2350 * Implementation for the ldstr opcode.
2353 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2355 const char *str, *sig;
2359 MONO_ARCH_SAVE_REGS;
2362 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2364 sig = str = mono_metadata_user_string (image, idx);
2366 mono_domain_lock (domain);
2367 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2368 mono_domain_unlock (domain);
2372 len2 = mono_metadata_decode_blob_size (str, &str);
2375 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2376 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2379 guint16 *p2 = (guint16*)mono_string_chars (o);
2380 for (i = 0; i < len2; ++i) {
2381 *p2 = GUINT16_FROM_LE (*p2);
2386 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2387 mono_domain_unlock (domain);
2393 * mono_string_to_utf8:
2394 * @s: a System.String
2396 * Return the UTF8 representation for @s.
2397 * the resulting buffer nedds to be freed with g_free().
2400 mono_string_to_utf8 (MonoString *s)
2403 GError *error = NULL;
2409 return g_strdup ("");
2411 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2413 g_warning (error->message);
2414 g_error_free (error);
2421 * mono_string_to_utf16:
2424 * Return an null-terminated array of the utf-16 chars
2425 * contained in @s. The result must be freed with g_free().
2426 * This is a temporary helper until our string implementation
2427 * is reworked to always include the null terminating char.
2430 mono_string_to_utf16 (MonoString *s)
2437 as = g_malloc ((s->length * 2) + 2);
2438 as [(s->length * 2)] = '\0';
2439 as [(s->length * 2) + 1] = '\0';
2442 return (gunichar2 *)(as);
2445 memcpy (as, mono_string_chars(s), s->length * 2);
2446 return (gunichar2 *)(as);
2450 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2453 mono_string_from_utf16 (gunichar2 *data)
2455 MonoDomain *domain = mono_domain_get ();
2461 while (data [len]) len++;
2463 return mono_string_new_utf16 (domain, data, len);
2467 default_ex_handler (MonoException *ex)
2469 MonoObject *o = (MonoObject*)ex;
2470 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2474 static MonoExceptionFunc ex_handler = default_ex_handler;
2477 mono_install_handler (MonoExceptionFunc func)
2479 ex_handler = func? func: default_ex_handler;
2483 * mono_raise_exception:
2484 * @ex: exception object
2486 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2489 mono_raise_exception (MonoException *ex)
2492 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2493 * that will cause gcc to omit the function epilog, causing problems when
2494 * the JIT tries to walk the stack, since the return address on the stack
2495 * will point into the next function in the executable, not this one.
2502 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2504 MonoWaitHandle *res;
2506 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2508 res->handle = handle;
2514 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2516 MonoAsyncResult *res;
2518 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2521 res->async_state = state;
2523 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2525 res->sync_completed = FALSE;
2526 res->completed = FALSE;
2532 mono_message_init (MonoDomain *domain,
2533 MonoMethodMessage *this,
2534 MonoReflectionMethod *method,
2535 MonoArray *out_args)
2537 MonoMethodSignature *sig = method->method->signature;
2543 this->method = method;
2545 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2546 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2547 this->async_result = NULL;
2548 this->call_type = CallType_Sync;
2550 names = g_new (char *, sig->param_count);
2551 mono_method_get_param_names (method->method, (const char **) names);
2552 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2554 for (i = 0; i < sig->param_count; i++) {
2555 name = mono_string_new (domain, names [i]);
2556 mono_array_set (this->names, gpointer, i, name);
2560 for (i = 0, j = 0; i < sig->param_count; i++) {
2562 if (sig->params [i]->byref) {
2564 gpointer arg = mono_array_get (out_args, gpointer, j);
2565 mono_array_set (this->args, gpointer, i, arg);
2569 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2574 mono_array_set (this->arg_types, guint8, i, arg_type);
2579 * mono_remoting_invoke:
2580 * @real_proxy: pointer to a RealProxy object
2581 * @msg: The MonoMethodMessage to execute
2582 * @exc: used to store exceptions
2583 * @out_args: used to store output arguments
2585 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2586 * IMessage interface and it is not trivial to extract results from there. So
2587 * we call an helper method PrivateInvoke instead of calling
2588 * RealProxy::Invoke() directly.
2590 * Returns: the result object.
2593 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2594 MonoObject **exc, MonoArray **out_args)
2596 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2599 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2605 klass = mono_defaults.real_proxy_class;
2607 for (i = 0; i < klass->method.count; ++i) {
2608 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2609 klass->methods [i]->signature->param_count == 4) {
2610 im = klass->methods [i];
2616 real_proxy->vtable->domain->private_invoke_method = im;
2619 pa [0] = real_proxy;
2624 return mono_runtime_invoke (im, NULL, pa, exc);
2628 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2629 MonoObject **exc, MonoArray **out_args)
2633 MonoMethodSignature *sig;
2634 int i, j, outarg_count = 0;
2636 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2638 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2639 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2640 target = tp->rp->unwrapped_server;
2642 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2646 domain = mono_domain_get ();
2647 method = msg->method->method;
2648 sig = method->signature;
2650 for (i = 0; i < sig->param_count; i++) {
2651 if (sig->params [i]->byref)
2655 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2658 for (i = 0, j = 0; i < sig->param_count; i++) {
2659 if (sig->params [i]->byref) {
2661 arg = mono_array_get (msg->args, gpointer, i);
2662 mono_array_set (*out_args, gpointer, j, arg);
2667 return mono_runtime_invoke_array (method, target, msg->args, exc);
2671 mono_print_unhandled_exception (MonoObject *exc)
2673 char *message = (char *) "";
2677 gboolean free_message = FALSE;
2680 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2681 klass = exc->vtable->klass;
2683 while (klass && method == NULL) {
2684 for (i = 0; i < klass->method.count; ++i) {
2685 method = klass->methods [i];
2686 if (!strcmp ("ToString", method->name) &&
2687 method->signature->param_count == 0 &&
2688 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2689 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2696 klass = klass->parent;
2701 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2703 message = mono_string_to_utf8 (str);
2704 free_message = TRUE;
2709 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2710 * exc->vtable->klass->name, message);
2712 g_printerr ("\nUnhandled Exception: %s\n", message);
2719 * mono_delegate_ctor:
2720 * @this: pointer to an uninitialized delegate object
2721 * @target: target object
2722 * @addr: pointer to native code
2724 * This is used to initialize a delegate. We also insert the method_info if
2725 * we find the info with mono_jit_info_table_find().
2728 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2730 MonoDomain *domain = mono_domain_get ();
2731 MonoDelegate *delegate = (MonoDelegate *)this;
2732 MonoMethod *method = NULL;
2739 class = this->vtable->klass;
2741 if ((ji = mono_jit_info_table_find (domain, addr))) {
2742 method = ji->method;
2743 delegate->method_info = mono_method_get_object (domain, method, NULL);
2746 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2748 method = mono_marshal_get_remoting_invoke (method);
2749 delegate->method_ptr = mono_compile_method (method);
2750 delegate->target = target;
2752 delegate->method_ptr = addr;
2753 delegate->target = target;
2758 * mono_method_call_message_new:
2760 * Translates arguments pointers into a Message.
2763 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2764 MonoDelegate **cb, MonoObject **state)
2766 MonoDomain *domain = mono_domain_get ();
2767 MonoMethodSignature *sig = method->signature;
2768 MonoMethodMessage *msg;
2771 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2774 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2775 count = sig->param_count - 2;
2777 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2778 count = sig->param_count;
2781 for (i = 0; i < count; i++) {
2786 if (sig->params [i]->byref)
2787 vpos = *((gpointer *)params [i]);
2791 type = sig->params [i]->type;
2792 class = mono_class_from_mono_type (sig->params [i]);
2794 if (class->valuetype)
2795 arg = mono_value_box (domain, class, vpos);
2797 arg = *((MonoObject **)vpos);
2799 mono_array_set (msg->args, gpointer, i, arg);
2802 if (cb != NULL && state != NULL) {
2803 *cb = *((MonoDelegate **)params [i]);
2805 *state = *((MonoObject **)params [i]);
2812 * mono_method_return_message_restore:
2814 * Restore results from message based processing back to arguments pointers
2817 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2819 MonoMethodSignature *sig = method->signature;
2820 int i, j, type, size;
2821 for (i = 0, j = 0; i < sig->param_count; i++) {
2822 MonoType *pt = sig->params [i];
2825 char *arg = mono_array_get (out_args, gpointer, j);
2829 case MONO_TYPE_VOID:
2830 g_assert_not_reached ();
2834 case MONO_TYPE_BOOLEAN:
2837 case MONO_TYPE_CHAR:
2844 case MONO_TYPE_VALUETYPE: {
2845 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2846 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2849 case MONO_TYPE_STRING:
2850 case MONO_TYPE_CLASS:
2851 case MONO_TYPE_ARRAY:
2852 case MONO_TYPE_SZARRAY:
2853 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2856 g_assert_not_reached ();
2865 * mono_load_remote_field:
2866 * @this: pointer to an object
2867 * @klass: klass of the object containing @field
2868 * @field: the field to load
2869 * @res: a storage to store the result
2871 * This method is called by the runtime on attempts to load fields of
2872 * transparent proxy objects. @this points to such TP, @klass is the class of
2873 * the object containing @field. @res is a storage location which can be
2874 * used to store the result.
2876 * Returns: an address pointing to the value of field.
2879 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2881 static MonoMethod *getter = NULL;
2882 MonoDomain *domain = mono_domain_get ();
2883 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2884 MonoClass *field_class;
2885 MonoMethodMessage *msg;
2886 MonoArray *out_args;
2890 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2895 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2896 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2903 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2904 MonoMethod *cm = mono_defaults.object_class->methods [i];
2906 if (!strcmp (cm->name, "FieldGetter")) {
2914 field_class = mono_class_from_mono_type (field->type);
2916 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2917 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2918 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2920 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2921 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2923 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2925 if (exc) mono_raise_exception ((MonoException *)exc);
2927 *res = mono_array_get (out_args, MonoObject *, 0);
2929 if (field_class->valuetype) {
2930 return ((char *)*res) + sizeof (MonoObject);
2936 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2938 static MonoMethod *getter = NULL;
2939 MonoDomain *domain = mono_domain_get ();
2940 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2941 MonoClass *field_class;
2942 MonoMethodMessage *msg;
2943 MonoArray *out_args;
2944 MonoObject *exc, *res;
2946 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2948 field_class = mono_class_from_mono_type (field->type);
2950 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2952 if (field_class->valuetype) {
2953 res = mono_object_new (domain, field_class);
2954 val = ((gchar *) res) + sizeof (MonoObject);
2958 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2965 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2966 MonoMethod *cm = mono_defaults.object_class->methods [i];
2968 if (!strcmp (cm->name, "FieldGetter")) {
2976 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2977 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2978 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2980 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2981 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2983 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2985 if (exc) mono_raise_exception ((MonoException *)exc);
2987 res = mono_array_get (out_args, MonoObject *, 0);
2993 * mono_store_remote_field:
2994 * @this: pointer to an object
2995 * @klass: klass of the object containing @field
2996 * @field: the field to load
2997 * @val: the value/object to store
2999 * This method is called by the runtime on attempts to store fields of
3000 * transparent proxy objects. @this points to such TP, @klass is the class of
3001 * the object containing @field. @val is the new value to store in @field.
3004 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3006 static MonoMethod *setter = NULL;
3007 MonoDomain *domain = mono_domain_get ();
3008 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3009 MonoClass *field_class;
3010 MonoMethodMessage *msg;
3011 MonoArray *out_args;
3015 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3017 field_class = mono_class_from_mono_type (field->type);
3019 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3020 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3021 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3028 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3029 MonoMethod *cm = mono_defaults.object_class->methods [i];
3031 if (!strcmp (cm->name, "FieldSetter")) {
3039 if (field_class->valuetype)
3040 arg = mono_value_box (domain, field_class, val);
3042 arg = *((MonoObject **)val);
3045 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3046 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3048 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3049 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3050 mono_array_set (msg->args, gpointer, 2, arg);
3052 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3054 if (exc) mono_raise_exception ((MonoException *)exc);
3058 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3060 static MonoMethod *setter = NULL;
3061 MonoDomain *domain = mono_domain_get ();
3062 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3063 MonoClass *field_class;
3064 MonoMethodMessage *msg;
3065 MonoArray *out_args;
3068 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3070 field_class = mono_class_from_mono_type (field->type);
3072 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3073 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3074 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3081 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3082 MonoMethod *cm = mono_defaults.object_class->methods [i];
3084 if (!strcmp (cm->name, "FieldSetter")) {
3092 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3093 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3095 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3096 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3097 mono_array_set (msg->args, gpointer, 2, arg);
3099 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3101 if (exc) mono_raise_exception ((MonoException *)exc);