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) {
1439 domain->entry_assembly = method->klass->image->assembly;
1440 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
1443 /* FIXME: check signature of method */
1444 if (method->signature->ret->type == MONO_TYPE_I4) {
1446 res = mono_runtime_invoke (method, NULL, pa, exc);
1448 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1452 mono_environment_exitcode_set (rval);
1454 mono_runtime_invoke (method, NULL, pa, exc);
1458 /* If the return type of Main is void, only
1459 * set the exitcode if an exception was thrown
1460 * (we don't want to blow away an
1461 * explicitly-set exit code)
1464 mono_environment_exitcode_set (rval);
1472 mono_install_runtime_invoke (MonoInvokeFunc func)
1474 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1478 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1481 MonoMethodSignature *sig = method->signature;
1482 gpointer *pa = NULL;
1485 if (NULL != params) {
1486 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1487 for (i = 0; i < mono_array_length (params); i++) {
1488 if (sig->params [i]->byref) {
1492 switch (sig->params [i]->type) {
1495 case MONO_TYPE_BOOLEAN:
1498 case MONO_TYPE_CHAR:
1507 case MONO_TYPE_VALUETYPE:
1508 g_assert (((gpointer*)params->vector) [i]);
1509 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1511 case MONO_TYPE_STRING:
1512 case MONO_TYPE_OBJECT:
1513 case MONO_TYPE_CLASS:
1514 case MONO_TYPE_ARRAY:
1515 case MONO_TYPE_SZARRAY:
1516 if (sig->params [i]->byref)
1517 pa [i] = &(((gpointer *)params->vector)[i]);
1519 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1522 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1527 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1529 obj = mono_object_new (mono_domain_get (), method->klass);
1530 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1531 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
1534 mono_runtime_invoke (method, obj, pa, exc);
1537 return mono_runtime_invoke (method, obj, pa, exc);
1541 out_of_memory (size_t size)
1544 * we could allocate at program startup some memory that we could release
1545 * back to the system at this point if we're really low on memory (ie, size is
1546 * lower than the memory we set apart)
1548 mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
1552 * mono_object_allocate:
1553 * @size: number of bytes to allocate
1555 * This is a very simplistic routine until we have our GC-aware
1558 * Returns: an allocated object of size @size, or NULL on failure.
1560 static inline void *
1561 mono_object_allocate (size_t size)
1564 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1565 void *o = GC_MALLOC (size);
1567 void *o = calloc (1, size);
1569 mono_stats.new_object_count++;
1572 out_of_memory (size);
1576 #if CREATION_SPEEDUP
1577 static inline void *
1578 mono_object_allocate_spec (size_t size, void *gcdescr)
1580 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1581 void *o = GC_GCJ_MALLOC (size, gcdescr);
1582 mono_stats.new_object_count++;
1585 out_of_memory (size);
1593 * Frees the memory used by the object. Debugging purposes
1594 * only, as we will have our GC system.
1597 mono_object_free (MonoObject *o)
1600 g_error ("mono_object_free called with boehm gc.");
1602 MonoClass *c = o->vtable->klass;
1604 memset (o, 0, c->instance_size);
1611 * @klass: the class of the object that we want to create
1613 * Returns: A newly created object whose definition is
1614 * looked up using @klass
1617 mono_object_new (MonoDomain *domain, MonoClass *klass)
1619 MONO_ARCH_SAVE_REGS;
1620 return mono_object_new_specific (mono_class_vtable (domain, klass));
1624 * mono_object_new_specific:
1625 * @vtable: the vtable of the object that we want to create
1627 * Returns: A newly created object with class and domain specified
1631 mono_object_new_specific (MonoVTable *vtable)
1635 MONO_ARCH_SAVE_REGS;
1640 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1643 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1647 mono_class_init (klass);
1649 for (i = 0; i < klass->method.count; ++i) {
1650 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1651 klass->methods [i]->signature->param_count == 1) {
1652 im = klass->methods [i];
1657 vtable->domain->create_proxy_for_type_method = im;
1660 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1662 o = mono_runtime_invoke (im, NULL, pa, NULL);
1663 if (o != NULL) return o;
1666 return mono_object_new_alloc_specific (vtable);
1670 mono_object_new_fast (MonoVTable *vtable)
1673 MONO_ARCH_SAVE_REGS;
1675 #if CREATION_SPEEDUP
1676 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1677 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1679 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1680 o = mono_object_allocate (vtable->klass->instance_size);
1684 o = mono_object_allocate (vtable->klass->instance_size);
1691 mono_object_new_alloc_specific (MonoVTable *vtable)
1695 #if CREATION_SPEEDUP
1696 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1697 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1699 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1700 o = mono_object_allocate (vtable->klass->instance_size);
1704 o = mono_object_allocate (vtable->klass->instance_size);
1707 if (vtable->klass->has_finalize)
1708 mono_object_register_finalizer (o);
1710 mono_profiler_allocation (o, vtable->klass);
1715 * mono_object_new_from_token:
1716 * @image: Context where the type_token is hosted
1717 * @token: a token of the type that we want to create
1719 * Returns: A newly created object whose definition is
1720 * looked up using @token in the @image image
1723 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1727 class = mono_class_get (image, token);
1729 return mono_object_new (domain, class);
1734 * mono_object_clone:
1735 * @obj: the object to clone
1737 * Returns: A newly created object who is a shallow copy of @obj
1740 mono_object_clone (MonoObject *obj)
1745 size = obj->vtable->klass->instance_size;
1746 o = mono_object_allocate (size);
1747 mono_profiler_allocation (o, obj->vtable->klass);
1749 memcpy (o, obj, size);
1751 if (obj->vtable->klass->has_finalize)
1752 mono_object_register_finalizer (o);
1758 * @array: the array to clone
1760 * Returns: A newly created array who is a shallow copy of @array
1763 mono_array_clone (MonoArray *array)
1768 MonoClass *klass = array->obj.vtable->klass;
1770 MONO_ARCH_SAVE_REGS;
1772 if (array->bounds == NULL) {
1773 size = mono_array_length (array);
1774 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1775 klass, &size, NULL);
1777 size *= mono_array_element_size (klass);
1778 memcpy (o, array, sizeof (MonoArray) + size);
1783 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1784 size = mono_array_element_size (klass);
1785 for (i = 0; i < klass->rank; ++i) {
1786 sizes [i] = array->bounds [i].length;
1787 size *= array->bounds [i].length;
1788 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1790 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1791 klass, sizes, sizes + klass->rank);
1792 memcpy (o, array, sizeof(MonoArray) + size);
1797 /* helper macros to check for overflow when calculating the size of arrays */
1798 #define MYGUINT32_MAX 4294967295U
1799 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1800 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1801 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1802 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1803 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1806 * mono_array_new_full:
1807 * @domain: domain where the object is created
1808 * @array_class: array class
1809 * @lengths: lengths for each dimension in the array
1810 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1812 * This routine creates a new array objects with the given dimensions,
1813 * lower bounds and type.
1816 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1817 guint32 *lengths, guint32 *lower_bounds)
1819 guint32 byte_len, len;
1822 MonoArrayBounds *bounds;
1826 if (!array_class->inited)
1827 mono_class_init (array_class);
1829 byte_len = mono_array_element_size (array_class);
1832 if (array_class->rank == 1 &&
1833 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1838 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1840 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1842 for (i = 0; i < array_class->rank; ++i) {
1843 bounds [i].length = lengths [i];
1844 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1845 out_of_memory (MYGUINT32_MAX);
1850 for (i = 0; i < array_class->rank; ++i)
1851 bounds [i].lower_bound = lower_bounds [i];
1854 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1855 out_of_memory (MYGUINT32_MAX);
1857 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1858 out_of_memory (MYGUINT32_MAX);
1859 byte_len += sizeof (MonoArray);
1861 * Following three lines almost taken from mono_object_new ():
1862 * they need to be kept in sync.
1864 vtable = mono_class_vtable (domain, array_class);
1865 #if CREATION_SPEEDUP
1866 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1867 o = mono_object_allocate_spec (byte_len, vtable);
1869 o = mono_object_allocate (byte_len);
1873 o = mono_object_allocate (byte_len);
1877 array = (MonoArray*)o;
1879 array->bounds = bounds;
1880 array->max_length = len;
1882 mono_profiler_allocation (o, array_class);
1889 * @domain: domain where the object is created
1890 * @eclass: element class
1891 * @n: number of array elements
1893 * This routine creates a new szarray with @n elements of type @eclass.
1896 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1900 MONO_ARCH_SAVE_REGS;
1902 ac = mono_array_class_get (eclass, 1);
1903 g_assert (ac != NULL);
1905 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1909 * mono_array_new_specific:
1910 * @vtable: a vtable in the appropriate domain for an initialized class
1911 * @n: number of array elements
1913 * This routine is a fast alternative to mono_array_new() for code which
1914 * can be sure about the domain it operates in.
1917 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1921 guint32 byte_len, elem_size;
1923 MONO_ARCH_SAVE_REGS;
1925 elem_size = mono_array_element_size (vtable->klass);
1926 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1927 out_of_memory (MYGUINT32_MAX);
1928 byte_len = n * elem_size;
1929 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1930 out_of_memory (MYGUINT32_MAX);
1931 byte_len += sizeof (MonoArray);
1932 #if CREATION_SPEEDUP
1933 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1934 o = mono_object_allocate_spec (byte_len, vtable);
1936 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1937 o = mono_object_allocate (byte_len);
1941 o = mono_object_allocate (byte_len);
1945 ao = (MonoArray *)o;
1948 mono_profiler_allocation (o, vtable->klass);
1954 * mono_string_new_utf16:
1955 * @text: a pointer to an utf16 string
1956 * @len: the length of the string
1958 * Returns: A newly created string object which contains @text.
1961 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1965 s = mono_string_new_size (domain, len);
1966 g_assert (s != NULL);
1968 memcpy (mono_string_chars (s), text, len * 2);
1974 * mono_string_new_size:
1975 * @text: a pointer to an utf16 string
1976 * @len: the length of the string
1978 * Returns: A newly created string object of @len
1981 mono_string_new_size (MonoDomain *domain, gint32 len)
1986 vtable = mono_class_vtable (domain, mono_defaults.string_class);
1988 #if CREATION_SPEEDUP
1989 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1990 s = mono_object_allocate_spec (sizeof (MonoString) + ((len + 1) * 2), vtable);
1992 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1993 s->object.vtable = vtable;
1996 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1997 s->object.vtable = vtable;
2001 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2007 * mono_string_new_len:
2008 * @text: a pointer to an utf8 string
2009 * @length: number of bytes in @text to consider
2011 * Returns: A newly created string object which contains @text.
2014 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2016 GError *error = NULL;
2017 MonoString *o = NULL;
2019 glong items_written;
2021 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2024 o = mono_string_new_utf16 (domain, ut, items_written);
2026 g_error_free (error);
2035 * @text: a pointer to an utf8 string
2037 * Returns: A newly created string object which contains @text.
2040 mono_string_new (MonoDomain *domain, const char *text)
2042 GError *error = NULL;
2043 MonoString *o = NULL;
2045 glong items_written;
2050 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2053 o = mono_string_new_utf16 (domain, ut, items_written);
2055 g_error_free (error);
2063 * mono_string_new_wrapper:
2064 * @text: pointer to utf8 characters.
2066 * Helper function to create a string object from @text in the current domain.
2069 mono_string_new_wrapper (const char *text)
2071 MonoDomain *domain = mono_domain_get ();
2073 MONO_ARCH_SAVE_REGS;
2076 return mono_string_new (domain, text);
2083 * @class: the class of the value
2084 * @value: a pointer to the unboxed data
2086 * Returns: A newly created object which contains @value.
2089 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2095 g_assert (class->valuetype);
2097 vtable = mono_class_vtable (domain, class);
2098 size = mono_class_instance_size (class);
2099 res = mono_object_allocate (size);
2100 res->vtable = vtable;
2101 mono_profiler_allocation (res, class);
2103 size = size - sizeof (MonoObject);
2105 #if NO_UNALIGNED_ACCESS
2106 memcpy ((char *)res + sizeof (MonoObject), value, size);
2110 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2113 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2116 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2119 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2122 memcpy ((char *)res + sizeof (MonoObject), value, size);
2125 if (class->has_finalize)
2126 mono_object_register_finalizer (res);
2131 mono_object_unbox (MonoObject *obj)
2133 /* add assert for valuetypes? */
2134 return ((char*)obj) + sizeof (MonoObject);
2138 * mono_object_isinst:
2140 * @klass: a pointer to a class
2142 * Returns: @obj if @obj is derived from @klass
2145 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2148 mono_class_init (klass);
2150 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2151 return mono_object_isinst_mbyref (obj, klass);
2156 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2160 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2169 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2170 if ((klass->interface_id <= vt->max_interface_id) &&
2171 (vt->interface_offsets [klass->interface_id] != 0))
2175 MonoClass *oklass = vt->klass;
2176 if ((oklass == mono_defaults.transparent_proxy_class))
2177 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2179 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2183 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2185 MonoDomain *domain = mono_domain_get ();
2187 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2188 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2189 MonoMethod *im = NULL;
2193 for (i = 0; i < rpklass->method.count; ++i) {
2194 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2195 im = rpklass->methods [i];
2200 im = mono_object_get_virtual_method (rp, im);
2203 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2206 res = mono_runtime_invoke (im, rp, pa, NULL);
2208 if (*(MonoBoolean *) mono_object_unbox(res)) {
2209 /* Update the vtable of the remote type, so it can safely cast to this new type */
2210 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2211 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2220 * mono_object_castclass_mbyref:
2222 * @klass: a pointer to a class
2224 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2227 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2229 if (!obj) return NULL;
2230 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2232 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2234 "InvalidCastException"));
2239 MonoDomain *orig_domain;
2245 str_lookup (MonoDomain *domain, gpointer user_data)
2247 LDStrInfo *info = user_data;
2248 if (info->res || domain == info->orig_domain)
2250 mono_domain_lock (domain);
2251 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2252 mono_domain_unlock (domain);
2256 mono_string_is_interned_lookup (MonoString *str, int insert)
2258 MonoGHashTable *ldstr_table;
2261 char *ins = g_malloc (4 + str->length * 2);
2264 /* Encode the length */
2265 /* Same code as in mono_image_insert_string () */
2267 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2270 * ins is stored in the hash table as a key and needs to have the same
2271 * representation as in the metadata: we swap the character bytes on big
2274 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2277 char *p2 = (char *)mono_string_chars (str);
2278 for (i = 0; i < str->length; ++i) {
2285 memcpy (p, mono_string_chars (str), str->length * 2);
2287 domain = ((MonoObject *)str)->vtable->domain;
2288 ldstr_table = domain->ldstr_table;
2289 mono_domain_lock (domain);
2290 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2291 mono_domain_unlock (domain);
2296 mono_g_hash_table_insert (ldstr_table, ins, str);
2297 mono_domain_unlock (domain);
2300 LDStrInfo ldstr_info;
2301 ldstr_info.orig_domain = domain;
2302 ldstr_info.ins = ins;
2303 ldstr_info.res = NULL;
2305 mono_domain_foreach (str_lookup, &ldstr_info);
2306 if (ldstr_info.res) {
2308 * the string was already interned in some other domain:
2309 * intern it in the current one as well.
2311 mono_g_hash_table_insert (ldstr_table, ins, str);
2312 mono_domain_unlock (domain);
2316 mono_domain_unlock (domain);
2322 mono_string_is_interned (MonoString *o)
2324 return mono_string_is_interned_lookup (o, FALSE);
2328 mono_string_intern (MonoString *str)
2330 return mono_string_is_interned_lookup (str, TRUE);
2335 * @domain: the domain where the string will be used.
2336 * @image: a metadata context
2337 * @idx: index into the user string table.
2339 * Implementation for the ldstr opcode.
2342 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2344 const char *str, *sig;
2348 MONO_ARCH_SAVE_REGS;
2351 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2353 sig = str = mono_metadata_user_string (image, idx);
2355 mono_domain_lock (domain);
2356 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2357 mono_domain_unlock (domain);
2361 len2 = mono_metadata_decode_blob_size (str, &str);
2364 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2365 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2368 guint16 *p2 = (guint16*)mono_string_chars (o);
2369 for (i = 0; i < len2; ++i) {
2370 *p2 = GUINT16_FROM_LE (*p2);
2375 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2376 mono_domain_unlock (domain);
2382 * mono_string_to_utf8:
2383 * @s: a System.String
2385 * Return the UTF8 representation for @s.
2386 * the resulting buffer nedds to be freed with g_free().
2389 mono_string_to_utf8 (MonoString *s)
2392 GError *error = NULL;
2398 return g_strdup ("");
2400 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2402 g_warning (error->message);
2403 g_error_free (error);
2410 * mono_string_to_utf16:
2413 * Return an null-terminated array of the utf-16 chars
2414 * contained in @s. The result must be freed with g_free().
2415 * This is a temporary helper until our string implementation
2416 * is reworked to always include the null terminating char.
2419 mono_string_to_utf16 (MonoString *s)
2426 as = g_malloc ((s->length * 2) + 2);
2427 as [(s->length * 2)] = '\0';
2428 as [(s->length * 2) + 1] = '\0';
2431 return (gunichar2 *)(as);
2434 memcpy (as, mono_string_chars(s), s->length * 2);
2435 return (gunichar2 *)(as);
2439 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2442 mono_string_from_utf16 (gunichar2 *data)
2444 MonoDomain *domain = mono_domain_get ();
2450 while (data [len]) len++;
2452 return mono_string_new_utf16 (domain, data, len);
2456 default_ex_handler (MonoException *ex)
2458 MonoObject *o = (MonoObject*)ex;
2459 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2463 static MonoExceptionFunc ex_handler = default_ex_handler;
2466 mono_install_handler (MonoExceptionFunc func)
2468 ex_handler = func? func: default_ex_handler;
2472 * mono_raise_exception:
2473 * @ex: exception object
2475 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2478 mono_raise_exception (MonoException *ex)
2481 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2482 * that will cause gcc to omit the function epilog, causing problems when
2483 * the JIT tries to walk the stack, since the return address on the stack
2484 * will point into the next function in the executable, not this one.
2491 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2493 MonoWaitHandle *res;
2495 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2497 res->handle = handle;
2503 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2505 MonoAsyncResult *res;
2507 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2510 res->async_state = state;
2512 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2514 res->sync_completed = FALSE;
2515 res->completed = FALSE;
2521 mono_message_init (MonoDomain *domain,
2522 MonoMethodMessage *this,
2523 MonoReflectionMethod *method,
2524 MonoArray *out_args)
2526 MonoMethodSignature *sig = method->method->signature;
2532 this->method = method;
2534 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2535 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2536 this->async_result = NULL;
2537 this->call_type = CallType_Sync;
2539 names = g_new (char *, sig->param_count);
2540 mono_method_get_param_names (method->method, (const char **) names);
2541 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2543 for (i = 0; i < sig->param_count; i++) {
2544 name = mono_string_new (domain, names [i]);
2545 mono_array_set (this->names, gpointer, i, name);
2549 for (i = 0, j = 0; i < sig->param_count; i++) {
2551 if (sig->params [i]->byref) {
2553 gpointer arg = mono_array_get (out_args, gpointer, j);
2554 mono_array_set (this->args, gpointer, i, arg);
2558 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2563 mono_array_set (this->arg_types, guint8, i, arg_type);
2568 * mono_remoting_invoke:
2569 * @real_proxy: pointer to a RealProxy object
2570 * @msg: The MonoMethodMessage to execute
2571 * @exc: used to store exceptions
2572 * @out_args: used to store output arguments
2574 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2575 * IMessage interface and it is not trivial to extract results from there. So
2576 * we call an helper method PrivateInvoke instead of calling
2577 * RealProxy::Invoke() directly.
2579 * Returns: the result object.
2582 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2583 MonoObject **exc, MonoArray **out_args)
2585 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2588 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2594 klass = mono_defaults.real_proxy_class;
2596 for (i = 0; i < klass->method.count; ++i) {
2597 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2598 klass->methods [i]->signature->param_count == 4) {
2599 im = klass->methods [i];
2605 real_proxy->vtable->domain->private_invoke_method = im;
2608 pa [0] = real_proxy;
2613 return mono_runtime_invoke (im, NULL, pa, exc);
2617 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2618 MonoObject **exc, MonoArray **out_args)
2622 MonoMethodSignature *sig;
2623 int i, j, outarg_count = 0;
2625 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2627 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2628 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2629 target = tp->rp->unwrapped_server;
2631 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2635 domain = mono_domain_get ();
2636 method = msg->method->method;
2637 sig = method->signature;
2639 for (i = 0; i < sig->param_count; i++) {
2640 if (sig->params [i]->byref)
2644 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2647 for (i = 0, j = 0; i < sig->param_count; i++) {
2648 if (sig->params [i]->byref) {
2650 arg = mono_array_get (msg->args, gpointer, i);
2651 mono_array_set (*out_args, gpointer, j, arg);
2656 return mono_runtime_invoke_array (method, target, msg->args, exc);
2660 mono_print_unhandled_exception (MonoObject *exc)
2662 char *message = (char *) "";
2666 gboolean free_message = FALSE;
2669 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2670 klass = exc->vtable->klass;
2672 while (klass && method == NULL) {
2673 for (i = 0; i < klass->method.count; ++i) {
2674 method = klass->methods [i];
2675 if (!strcmp ("ToString", method->name) &&
2676 method->signature->param_count == 0 &&
2677 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2678 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2685 klass = klass->parent;
2690 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2692 message = mono_string_to_utf8 (str);
2693 free_message = TRUE;
2698 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2699 * exc->vtable->klass->name, message);
2701 g_printerr ("\nUnhandled Exception: %s\n", message);
2708 * mono_delegate_ctor:
2709 * @this: pointer to an uninitialized delegate object
2710 * @target: target object
2711 * @addr: pointer to native code
2713 * This is used to initialize a delegate. We also insert the method_info if
2714 * we find the info with mono_jit_info_table_find().
2717 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2719 MonoDomain *domain = mono_domain_get ();
2720 MonoDelegate *delegate = (MonoDelegate *)this;
2721 MonoMethod *method = NULL;
2728 class = this->vtable->klass;
2730 if ((ji = mono_jit_info_table_find (domain, addr))) {
2731 method = ji->method;
2732 delegate->method_info = mono_method_get_object (domain, method, NULL);
2735 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2737 method = mono_marshal_get_remoting_invoke (method);
2738 delegate->method_ptr = mono_compile_method (method);
2739 delegate->target = target;
2741 delegate->method_ptr = addr;
2742 delegate->target = target;
2747 * mono_method_call_message_new:
2749 * Translates arguments pointers into a Message.
2752 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2753 MonoDelegate **cb, MonoObject **state)
2755 MonoDomain *domain = mono_domain_get ();
2756 MonoMethodSignature *sig = method->signature;
2757 MonoMethodMessage *msg;
2760 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2763 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2764 count = sig->param_count - 2;
2766 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2767 count = sig->param_count;
2770 for (i = 0; i < count; i++) {
2775 if (sig->params [i]->byref)
2776 vpos = *((gpointer *)params [i]);
2780 type = sig->params [i]->type;
2781 class = mono_class_from_mono_type (sig->params [i]);
2783 if (class->valuetype)
2784 arg = mono_value_box (domain, class, vpos);
2786 arg = *((MonoObject **)vpos);
2788 mono_array_set (msg->args, gpointer, i, arg);
2791 if (cb != NULL && state != NULL) {
2792 *cb = *((MonoDelegate **)params [i]);
2794 *state = *((MonoObject **)params [i]);
2801 * mono_method_return_message_restore:
2803 * Restore results from message based processing back to arguments pointers
2806 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2808 MonoMethodSignature *sig = method->signature;
2809 int i, j, type, size;
2810 for (i = 0, j = 0; i < sig->param_count; i++) {
2811 MonoType *pt = sig->params [i];
2814 char *arg = mono_array_get (out_args, gpointer, j);
2818 case MONO_TYPE_VOID:
2819 g_assert_not_reached ();
2823 case MONO_TYPE_BOOLEAN:
2826 case MONO_TYPE_CHAR:
2833 case MONO_TYPE_VALUETYPE: {
2834 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2835 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2838 case MONO_TYPE_STRING:
2839 case MONO_TYPE_CLASS:
2840 case MONO_TYPE_ARRAY:
2841 case MONO_TYPE_SZARRAY:
2842 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2845 g_assert_not_reached ();
2854 * mono_load_remote_field:
2855 * @this: pointer to an object
2856 * @klass: klass of the object containing @field
2857 * @field: the field to load
2858 * @res: a storage to store the result
2860 * This method is called by the runtime on attempts to load fields of
2861 * transparent proxy objects. @this points to such TP, @klass is the class of
2862 * the object containing @field. @res is a storage location which can be
2863 * used to store the result.
2865 * Returns: an address pointing to the value of field.
2868 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2870 static MonoMethod *getter = NULL;
2871 MonoDomain *domain = mono_domain_get ();
2872 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2873 MonoClass *field_class;
2874 MonoMethodMessage *msg;
2875 MonoArray *out_args;
2879 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2884 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2885 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2892 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2893 MonoMethod *cm = mono_defaults.object_class->methods [i];
2895 if (!strcmp (cm->name, "FieldGetter")) {
2903 field_class = mono_class_from_mono_type (field->type);
2905 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2906 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2907 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2909 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2910 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2912 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2914 if (exc) mono_raise_exception ((MonoException *)exc);
2916 *res = mono_array_get (out_args, MonoObject *, 0);
2918 if (field_class->valuetype) {
2919 return ((char *)*res) + sizeof (MonoObject);
2925 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2927 static MonoMethod *getter = NULL;
2928 MonoDomain *domain = mono_domain_get ();
2929 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2930 MonoClass *field_class;
2931 MonoMethodMessage *msg;
2932 MonoArray *out_args;
2933 MonoObject *exc, *res;
2935 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2937 field_class = mono_class_from_mono_type (field->type);
2939 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2941 if (field_class->valuetype) {
2942 res = mono_object_new (domain, field_class);
2943 val = ((gchar *) res) + sizeof (MonoObject);
2947 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2954 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2955 MonoMethod *cm = mono_defaults.object_class->methods [i];
2957 if (!strcmp (cm->name, "FieldGetter")) {
2965 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2966 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2967 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2969 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2970 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2972 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2974 if (exc) mono_raise_exception ((MonoException *)exc);
2976 res = mono_array_get (out_args, MonoObject *, 0);
2982 * mono_store_remote_field:
2983 * @this: pointer to an object
2984 * @klass: klass of the object containing @field
2985 * @field: the field to load
2986 * @val: the value/object to store
2988 * This method is called by the runtime on attempts to store fields of
2989 * transparent proxy objects. @this points to such TP, @klass is the class of
2990 * the object containing @field. @val is the new value to store in @field.
2993 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
2995 static MonoMethod *setter = NULL;
2996 MonoDomain *domain = mono_domain_get ();
2997 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2998 MonoClass *field_class;
2999 MonoMethodMessage *msg;
3000 MonoArray *out_args;
3004 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3006 field_class = mono_class_from_mono_type (field->type);
3008 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3009 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3010 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3017 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3018 MonoMethod *cm = mono_defaults.object_class->methods [i];
3020 if (!strcmp (cm->name, "FieldSetter")) {
3028 if (field_class->valuetype)
3029 arg = mono_value_box (domain, field_class, val);
3031 arg = *((MonoObject **)val);
3034 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3035 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3037 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3038 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3039 mono_array_set (msg->args, gpointer, 2, arg);
3041 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3043 if (exc) mono_raise_exception ((MonoException *)exc);
3047 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3049 static MonoMethod *setter = NULL;
3050 MonoDomain *domain = mono_domain_get ();
3051 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3052 MonoClass *field_class;
3053 MonoMethodMessage *msg;
3054 MonoArray *out_args;
3057 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3059 field_class = mono_class_from_mono_type (field->type);
3061 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3062 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3063 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3070 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3071 MonoMethod *cm = mono_defaults.object_class->methods [i];
3073 if (!strcmp (cm->name, "FieldSetter")) {
3081 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3082 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3084 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3085 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3086 mono_array_set (msg->args, gpointer, 2, arg);
3088 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3090 if (exc) mono_raise_exception ((MonoException *)exc);