2 * object.c: Object creation for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2001-2004 Ximian, Inc.
15 #include <mono/metadata/mono-endian.h>
16 #include <mono/metadata/tabledefs.h>
17 #include <mono/metadata/tokentype.h>
18 #include <mono/metadata/loader.h>
19 #include <mono/metadata/object.h>
20 #include <mono/metadata/gc-internal.h>
21 #include <mono/metadata/exception.h>
22 #include <mono/metadata/domain-internals.h>
23 #include "mono/metadata/metadata-internals.h"
24 #include <mono/metadata/assembly.h>
25 #include <mono/metadata/threadpool.h>
26 #include <mono/metadata/marshal.h>
27 #include "mono/metadata/debug-helpers.h"
28 #include "mono/metadata/marshal.h"
29 #include <mono/metadata/threads.h>
30 #include <mono/metadata/environment.h>
31 #include "mono/metadata/profiler-private.h"
32 #include <mono/os/gc_wrapper.h>
33 #include <mono/utils/strenc.h>
36 * Enable experimental typed allocation using the GC_gcj_malloc function.
38 #ifdef HAVE_GC_GCJ_MALLOC
39 #define CREATION_SPEEDUP 1
43 mono_runtime_object_init (MonoObject *this)
46 MonoMethod *method = NULL;
47 MonoClass *klass = this->vtable->klass;
49 for (i = 0; i < klass->method.count; ++i) {
50 if (!strcmp (".ctor", klass->methods [i]->name) &&
51 klass->methods [i]->signature->param_count == 0) {
52 method = klass->methods [i];
59 mono_runtime_invoke (method, this, NULL, NULL);
62 /* The pseudo algorithm for type initialization from the spec
63 Note it doesn't say anything about domains - only threads.
65 2. If the type is initialized you are done.
66 2.1. If the type is not yet initialized, try to take an
68 2.2. If successful, record this thread as responsible for
69 initializing the type and proceed to step 2.3.
70 2.2.1. If not, see whether this thread or any thread
71 waiting for this thread to complete already holds the lock.
72 2.2.2. If so, return since blocking would create a deadlock. This thread
73 will now see an incompletely initialized state for the type,
74 but no deadlock will arise.
75 2.2.3 If not, block until the type is initialized then return.
76 2.3 Initialize the parent type and then all interfaces implemented
78 2.4 Execute the type initialization code for this type.
79 2.5 Mark the type as initialized, release the initialization lock,
80 awaken any threads waiting for this type to be initialized,
87 guint32 initializing_tid;
88 guint32 waiting_count;
89 CRITICAL_SECTION initialization_section;
90 } TypeInitializationLock;
92 /* for locking access to type_initialization_hash and blocked_thread_hash */
93 static CRITICAL_SECTION type_initialization_section;
95 /* from vtable to lock */
96 static GHashTable *type_initialization_hash;
98 /* from thread id to thread id being waited on */
99 static GHashTable *blocked_thread_hash;
102 static MonoThread *main_thread;
105 mono_type_initialization_init (void)
107 InitializeCriticalSection (&type_initialization_section);
108 type_initialization_hash = g_hash_table_new (NULL, NULL);
109 blocked_thread_hash = g_hash_table_new (NULL, NULL);
113 * mono_runtime_class_init:
114 * @vtable: vtable that needs to be initialized
116 * This routine calls the class constructor for @vtable.
119 mono_runtime_class_init (MonoVTable *vtable)
123 MonoException *exc_to_throw;
124 MonoMethod *method = NULL;
131 if (vtable->initialized)
136 klass = vtable->klass;
138 for (i = 0; i < klass->method.count; ++i) {
139 method = klass->methods [i];
140 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
141 (strcmp (".cctor", method->name) == 0)) {
148 MonoDomain *domain = vtable->domain;
149 TypeInitializationLock *lock;
150 guint32 tid = GetCurrentThreadId();
151 int do_initialization = 0;
152 MonoDomain *last_domain = NULL;
154 EnterCriticalSection (&type_initialization_section);
155 /* double check... */
156 if (vtable->initialized) {
157 LeaveCriticalSection (&type_initialization_section);
160 lock = g_hash_table_lookup (type_initialization_hash, vtable);
162 /* This thread will get to do the initialization */
163 if (mono_domain_get () != domain) {
164 /* Transfer into the target domain */
165 last_domain = mono_domain_get ();
166 if (!mono_domain_set (domain, FALSE)) {
167 vtable->initialized = 1;
168 LeaveCriticalSection (&type_initialization_section);
169 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
172 lock = g_malloc (sizeof(TypeInitializationLock));
173 InitializeCriticalSection (&lock->initialization_section);
174 lock->initializing_tid = tid;
175 lock->waiting_count = 1;
176 /* grab the vtable lock while this thread still owns type_initialization_section */
177 EnterCriticalSection (&lock->initialization_section);
178 g_hash_table_insert (type_initialization_hash, vtable, lock);
179 do_initialization = 1;
183 if (lock->initializing_tid == tid) {
184 LeaveCriticalSection (&type_initialization_section);
187 /* see if the thread doing the initialization is already blocked on this thread */
188 blocked = GUINT_TO_POINTER (lock->initializing_tid);
189 while ((blocked = g_hash_table_lookup (blocked_thread_hash, blocked))) {
190 if (blocked == GUINT_TO_POINTER (tid)) {
191 LeaveCriticalSection (&type_initialization_section);
195 ++lock->waiting_count;
196 /* record the fact that we are waiting on the initializing thread */
197 g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), GUINT_TO_POINTER (lock->initializing_tid));
199 LeaveCriticalSection (&type_initialization_section);
201 if (do_initialization) {
202 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
204 mono_domain_set (last_domain, TRUE);
205 LeaveCriticalSection (&lock->initialization_section);
207 /* this just blocks until the initializing thread is done */
208 EnterCriticalSection (&lock->initialization_section);
209 LeaveCriticalSection (&lock->initialization_section);
212 EnterCriticalSection (&type_initialization_section);
213 if (lock->initializing_tid != tid)
214 g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
215 --lock->waiting_count;
216 if (lock->waiting_count == 0) {
217 DeleteCriticalSection (&lock->initialization_section);
218 g_hash_table_remove (type_initialization_hash, vtable);
221 vtable->initialized = 1;
222 /* FIXME: if the cctor fails, the type must be marked as unusable */
223 LeaveCriticalSection (&type_initialization_section);
225 vtable->initialized = 1;
230 (klass->image == mono_defaults.corlib &&
231 !strcmp (klass->name_space, "System") &&
232 !strcmp (klass->name, "TypeInitializationException")))
233 return; /* No static constructor found or avoid infinite loop */
235 if (klass->name_space && *klass->name_space)
236 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
238 full_name = g_strdup (klass->name);
240 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
243 mono_raise_exception (exc_to_throw);
247 default_trampoline (MonoMethod *method)
253 default_remoting_trampoline (MonoMethod *method)
255 g_error ("remoting not installed");
259 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
260 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
263 mono_install_trampoline (MonoTrampoline func)
265 arch_create_jit_trampoline = func? func: default_trampoline;
269 mono_install_remoting_trampoline (MonoTrampoline func)
271 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
274 static MonoCompileFunc default_mono_compile_method = NULL;
277 mono_install_compile_method (MonoCompileFunc func)
279 default_mono_compile_method = func;
283 mono_compile_method (MonoMethod *method)
285 if (!default_mono_compile_method) {
286 g_error ("compile method called on uninitialized runtime");
289 return default_mono_compile_method (method);
293 #if 0 && HAVE_BOEHM_GC
295 vtable_finalizer (void *obj, void *data) {
296 g_print ("%s finalized (%p)\n", (char*)data, obj);
302 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
305 * The vtables in the root appdomain are assumed to be reachable by other
306 * roots, and we don't use typed allocation in the other domains.
309 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
312 mono_class_compute_gc_descriptor (MonoClass *class)
314 MonoClassField *field;
318 static gboolean gcj_inited = FALSE;
323 GC_init_gcj_malloc (5, NULL);
327 mono_class_init (class);
329 if (class->gc_descr_inited)
332 class->gc_descr_inited = TRUE;
333 class->gc_descr = GC_NO_DESCRIPTOR;
335 if (class == mono_defaults.string_class) {
336 bitmap = GC_HEADER_BITMAP;
337 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
339 else if (class->rank) {
340 mono_class_compute_gc_descriptor (class->element_class);
342 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
343 bitmap = GC_HEADER_BITMAP;
345 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
346 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
350 static int count = 0;
354 /* GC 6.1 has trouble handling 64 bit descriptors... */
355 if ((class->instance_size / sizeof (gpointer)) > 30) {
356 // printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer));
360 bitmap = GC_HEADER_BITMAP;
367 // printf("KLASS: %s.\n", class->name);
369 for (p = class; p != NULL; p = p->parent) {
370 for (i = 0; i < p->field.count; ++i) {
371 field = &p->fields [i];
372 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
374 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
377 pos = field->offset / sizeof (gpointer);
379 if (field->type->byref)
382 switch (field->type->type) {
383 case MONO_TYPE_BOOLEAN:
395 // printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap);
398 case MONO_TYPE_STRING:
399 case MONO_TYPE_SZARRAY:
400 case MONO_TYPE_CLASS:
401 case MONO_TYPE_OBJECT:
402 case MONO_TYPE_ARRAY:
404 g_assert ((field->offset % sizeof(gpointer)) == 0);
406 bitmap |= ((guint64)1) << pos;
407 // printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap);
409 case MONO_TYPE_VALUETYPE: {
410 MonoClass *fclass = field->type->data.klass;
411 if (!fclass->enumtype) {
412 mono_class_compute_gc_descriptor (fclass);
413 bitmap |= (fclass->gc_bitmap >> (sizeof (MonoObject) / sizeof (gpointer))) << pos;
423 // printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap);
424 class->gc_bitmap = bitmap;
425 /* Convert to the format expected by GC_make_descriptor */
426 bm [0] = (guint32)bitmap;
427 bm [1] = (guint32)(bitmap >> 32);
428 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bm, class->instance_size / sizeof (gpointer));
431 #endif /* CREATION_SPEEDUP */
434 * field_is_special_static:
436 * Returns SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
437 * SPECIAL_STATIC_NONE otherwise.
440 field_is_special_static (MonoClass *fklass, MonoClassField *field)
442 MonoCustomAttrInfo *ainfo;
444 ainfo = mono_custom_attrs_from_field (fklass, field);
447 for (i = 0; i < ainfo->num_attrs; ++i) {
448 MonoClass *klass = ainfo->attrs [i].ctor->klass;
449 if (klass->image == mono_defaults.corlib) {
450 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
451 mono_custom_attrs_free (ainfo);
452 return SPECIAL_STATIC_THREAD;
454 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
455 mono_custom_attrs_free (ainfo);
456 return SPECIAL_STATIC_CONTEXT;
460 mono_custom_attrs_free (ainfo);
461 return SPECIAL_STATIC_NONE;
466 * @domain: the application domain
467 * @class: the class to initialize
469 * VTables are domain specific because we create domain specific code, and
470 * they contain the domain specific static class data.
473 mono_class_vtable (MonoDomain *domain, MonoClass *class)
475 MonoVTable *vt = NULL;
476 MonoClassField *field;
482 guint32 constant_cols [MONO_CONSTANT_SIZE];
486 vt = class->cached_vtable;
487 if (vt && vt->domain == domain)
490 mono_domain_lock (domain);
491 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
492 mono_domain_unlock (domain);
497 mono_class_init (class);
499 mono_stats.used_class_count++;
500 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
502 vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
504 vt = mono_mempool_alloc0 (domain->mp, vtable_size);
510 mono_class_compute_gc_descriptor (class);
511 if (domain != mono_get_root_domain ())
513 * We can't use typed allocation in the non-root domains, since the
514 * collector needs the GC descriptor stored in the vtable even after
515 * the mempool containing the vtable is destroyed when the domain is
516 * unloaded. An alternative might be to allocate vtables in the GC
517 * heap, but this does not seem to work (it leads to crashes inside
518 * libgc). If that approach is tried, two gc descriptors need to be
519 * allocated for each class: one for the root domain, and one for all
520 * other domains. The second descriptor should contain a bit for the
521 * vtable field in MonoObject, since we can no longer assume the
522 * vtable is reachable by other roots after the appdomain is unloaded.
524 vt->gc_descr = GC_NO_DESCRIPTOR;
526 vt->gc_descr = class->gc_descr;
529 if (class->class_size) {
531 vt->data = GC_MALLOC (class->class_size + 8);
532 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
533 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
534 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
536 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
539 mono_stats.class_static_data_size += class->class_size + 8;
543 for (i = class->field.first; i < class->field.last; ++i) {
544 field = &class->fields [i - class->field.first];
545 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
547 if (mono_field_is_deleted (field))
549 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
550 gint32 special_static = field_is_special_static (class, field);
551 if (special_static != SPECIAL_STATIC_NONE) {
552 guint32 size, align, offset;
553 size = mono_type_size (field->type, &align);
554 offset = mono_alloc_special_static_data (special_static, size, align);
555 if (!domain->special_static_fields)
556 domain->special_static_fields = g_hash_table_new (NULL, NULL);
557 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
561 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
562 MonoClass *fklass = mono_class_from_mono_type (field->type);
563 t = (char*)vt->data + field->offset;
564 if (fklass->valuetype) {
565 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
567 /* it's a pointer type: add check */
568 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
569 *t = *(char *)field->data;
573 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
576 if (!field->def_value) {
577 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1), cindex + 1);
580 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
581 field->def_value = g_new0 (MonoConstant, 1);
582 field->def_value->type = constant_cols [MONO_CONSTANT_TYPE];
583 field->def_value->value = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
586 p = field->def_value->value;
587 len = mono_metadata_decode_blob_size (p, &p);
588 t = (char*)vt->data + field->offset;
589 /* should we check that the type matches? */
590 switch (field->def_value->type) {
591 case MONO_TYPE_BOOLEAN:
599 guint16 *val = (guint16*)t;
605 guint32 *val = (guint32*)t;
611 guint64 *val = (guint64*)t;
616 float *val = (float*)t;
621 double *val = (double*)t;
625 case MONO_TYPE_STRING: {
626 gpointer *val = (gpointer*)t;
627 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
628 gunichar2 *copy = g_malloc (len);
630 for (j = 0; j < len/2; j++) {
631 copy [j] = read16 (p);
634 *val = mono_string_new_utf16 (domain, copy, len/2);
637 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
641 case MONO_TYPE_CLASS:
642 /* nothing to do, we malloc0 the data and the value can be 0 only */
645 g_warning ("type 0x%02x should not be in constant table", field->def_value->type);
649 vt->max_interface_id = class->max_interface_id;
651 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
652 sizeof (gpointer) * (class->max_interface_id + 1));
654 /* initialize interface offsets */
655 for (i = 0; i <= class->max_interface_id; ++i) {
656 int slot = class->interface_offsets [i];
658 vt->interface_offsets [i] = &(vt->vtable [slot]);
662 * arch_create_jit_trampoline () can recursively call this function again
663 * because it compiles icall methods right away.
665 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
666 if (!class->cached_vtable)
667 class->cached_vtable = vt;
669 /* initialize vtable */
670 for (i = 0; i < class->vtable_size; ++i) {
673 if ((cm = class->vtable [i]))
674 vt->vtable [i] = arch_create_jit_trampoline (cm);
677 mono_domain_unlock (domain);
679 /* make sure the the parent is initialized */
681 mono_class_vtable (domain, class->parent);
683 vt->type = mono_type_get_object (domain, &class->byval_arg);
684 if (class->contextbound)
693 * mono_class_proxy_vtable:
694 * @domain: the application domain
695 * @remove_class: the remote class
697 * Creates a vtable for transparent proxies. It is basically
698 * a copy of the real vtable of the class wrapped in @remote_class,
699 * but all function pointers invoke the remoting functions, and
700 * vtable->klass points to the transparent proxy class, and not to @class.
703 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class)
705 MonoVTable *vt, *pvt;
706 int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
708 MonoClass *class = remote_class->proxy_class;
710 vt = mono_class_vtable (domain, class);
711 max_interface_id = vt->max_interface_id;
713 /* Calculate vtable space for extra interfaces */
714 for (j = 0; j < remote_class->interface_count; j++) {
715 MonoClass* iclass = remote_class->interfaces[j];
716 int method_count = iclass->method.count;
718 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
719 continue; /* interface implemented by the class */
721 for (i = 0; i < iclass->interface_count; i++)
722 method_count += iclass->interfaces[i]->method.count;
724 extra_interface_vtsize += method_count * sizeof (gpointer);
725 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
728 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
730 mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
732 pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
733 memcpy (pvt, vt, vtsize);
735 pvt->klass = mono_defaults.transparent_proxy_class;
737 /* initialize vtable */
738 for (i = 0; i < class->vtable_size; ++i) {
741 if ((cm = class->vtable [i]))
742 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
745 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
747 /* create trampolines for abstract methods */
748 for (k = class; k; k = k->parent) {
749 for (i = 0; i < k->method.count; i++) {
750 int slot = k->methods [i]->slot;
751 if (!pvt->vtable [slot])
752 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
757 pvt->max_interface_id = max_interface_id;
758 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
759 sizeof (gpointer) * (max_interface_id + 1));
761 /* initialize interface offsets */
762 for (i = 0; i <= class->max_interface_id; ++i) {
763 int slot = class->interface_offsets [i];
765 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
768 if (remote_class->interface_count > 0)
770 int slot = class->vtable_size;
775 /* Create trampolines for the methods of the interfaces */
776 for (n = 0; n < remote_class->interface_count; n++)
778 iclass = remote_class->interfaces[n];
779 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
780 continue; /* interface implemented by the class */
785 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
787 for (j = 0; j < interf->method.count; ++j) {
788 MonoMethod *cm = interf->methods [j];
789 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
791 slot += interf->method.count;
792 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
804 * @domain: the application domain
805 * @class_name: name of the remote class
807 * Creates and initializes a MonoRemoteClass object for a remote type.
811 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
815 mono_domain_lock (domain);
816 rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class_name);
819 mono_domain_unlock (domain);
823 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
825 rc->interface_count = 0;
826 rc->interfaces = NULL;
827 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
828 rc->proxy_class_name = mono_string_to_utf8 (class_name);
830 mono_g_hash_table_insert (domain->proxy_vtable_hash, class_name, rc);
831 mono_upgrade_remote_class (domain, rc, proxy_class);
833 if (rc->vtable == NULL)
834 rc->vtable = mono_class_proxy_vtable (domain, rc);
836 mono_domain_unlock (domain);
842 extend_interface_array (MonoDomain *domain, MonoRemoteClass *remote_class, int amount)
844 /* Extends the array of interfaces. Memory is extended using blocks of 5 pointers */
846 int current_size = ((remote_class->interface_count / 5) + 1) * 5;
847 remote_class->interface_count += amount;
849 if (remote_class->interface_count > current_size || remote_class->interfaces == NULL)
851 int new_size = ((remote_class->interface_count / 5) + 1) * 5;
852 MonoClass **new_array = mono_mempool_alloc (domain->mp, new_size * sizeof (MonoClass*));
854 if (remote_class->interfaces != NULL)
855 memcpy (new_array, remote_class->interfaces, current_size * sizeof (MonoClass*));
857 remote_class->interfaces = new_array;
863 * mono_upgrade_remote_class:
864 * @domain: the application domain
865 * @remote_class: the remote class
866 * @klass: class to which the remote class can be casted.
868 * Updates the vtable of the remote class by adding the necessary method slots
869 * and interface offsets so it can be safely casted to klass. klass can be a
870 * class or an interface.
872 void mono_upgrade_remote_class (MonoDomain *domain, MonoRemoteClass *remote_class, MonoClass *klass)
874 gboolean redo_vtable;
876 mono_domain_lock (domain);
878 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
881 for (i = 0; i < remote_class->interface_count; i++)
882 if (remote_class->interfaces[i] == klass) redo_vtable = FALSE;
885 extend_interface_array (domain, remote_class, 1);
886 remote_class->interfaces [remote_class->interface_count-1] = klass;
890 redo_vtable = (remote_class->proxy_class != klass);
891 remote_class->proxy_class = klass;
895 remote_class->vtable = mono_class_proxy_vtable (domain, remote_class);
898 printf ("remote class upgrade - class:%s num-interfaces:%d\n", remote_class->proxy_class_name, remote_class->interface_count);
900 for (n=0; n<remote_class->interface_count; n++)
901 printf (" I:%s\n", remote_class->interfaces[n]->name);
904 mono_domain_unlock (domain);
908 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
909 * the instance of a callvirt of method.
912 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
916 MonoMethod *res = NULL;
918 klass = mono_object_class (obj);
919 if (klass == mono_defaults.transparent_proxy_class) {
920 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
926 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
929 vtable = klass->vtable;
931 /* check method->slot is a valid index: perform isinstance? */
932 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
934 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
936 if (method->slot != -1)
937 res = vtable [method->slot];
941 if (!res) res = method; /* It may be an interface or abstract class method */
942 res = mono_marshal_get_remoting_invoke (res);
951 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
953 g_error ("runtime invoke called on uninitialized runtime");
957 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
960 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
962 return default_mono_runtime_invoke (method, obj, params, exc);
966 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
969 gpointer *p = (gpointer*)dest;
976 case MONO_TYPE_BOOLEAN:
979 guint8 *p = (guint8*)dest;
980 *p = *(guint8*)value;
985 case MONO_TYPE_CHAR: {
986 guint16 *p = (guint16*)dest;
987 *p = *(guint16*)value;
990 #if SIZEOF_VOID_P == 4
996 gint32 *p = (gint32*)dest;
997 *p = *(gint32*)value;
1000 #if SIZEOF_VOID_P == 8
1005 case MONO_TYPE_U8: {
1006 gint64 *p = (gint64*)dest;
1007 *p = *(gint64*)value;
1010 case MONO_TYPE_R4: {
1011 float *p = (float*)dest;
1012 *p = *(float*)value;
1015 case MONO_TYPE_R8: {
1016 double *p = (double*)dest;
1017 *p = *(double*)value;
1020 case MONO_TYPE_STRING:
1021 case MONO_TYPE_SZARRAY:
1022 case MONO_TYPE_CLASS:
1023 case MONO_TYPE_OBJECT:
1024 case MONO_TYPE_ARRAY:
1025 case MONO_TYPE_PTR: {
1026 gpointer *p = (gpointer*)dest;
1027 *p = deref_pointer? *(gpointer*)value: value;
1030 case MONO_TYPE_VALUETYPE:
1031 if (type->data.klass->enumtype) {
1032 t = type->data.klass->enum_basetype->type;
1036 size = mono_class_value_size (type->data.klass, NULL);
1037 memcpy (dest, value, size);
1041 g_warning ("got type %x", type->type);
1042 g_assert_not_reached ();
1047 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
1051 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1053 dest = (char*)obj + field->offset;
1054 set_value (field->type, dest, value, FALSE);
1058 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
1062 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1064 dest = (char*)vt->data + field->offset;
1065 set_value (field->type, dest, value, FALSE);
1069 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
1073 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1075 src = (char*)obj + field->offset;
1076 set_value (field->type, value, src, TRUE);
1080 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
1084 MonoVTable *vtable = NULL;
1086 gboolean is_static = FALSE;
1087 gboolean is_ref = FALSE;
1089 switch (field->type->type) {
1090 case MONO_TYPE_STRING:
1091 case MONO_TYPE_OBJECT:
1092 case MONO_TYPE_CLASS:
1093 case MONO_TYPE_ARRAY:
1094 case MONO_TYPE_SZARRAY:
1099 case MONO_TYPE_BOOLEAN:
1102 case MONO_TYPE_CHAR:
1111 case MONO_TYPE_VALUETYPE:
1112 is_ref = field->type->byref;
1115 g_error ("type 0x%x not handled in "
1116 "mono_field_get_value_object", field->type->type);
1120 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1122 vtable = mono_class_vtable (domain, field->parent);
1123 if (!vtable->initialized)
1124 mono_runtime_class_init (vtable);
1129 mono_field_static_get_value (vtable, field, &o);
1131 mono_field_get_value (obj, field, &o);
1136 /* boxed value type */
1137 klass = mono_class_from_mono_type (field->type);
1138 o = mono_object_new (domain, klass);
1139 v = ((gchar *) o) + sizeof (MonoObject);
1141 mono_field_static_get_value (vtable, field, v);
1143 mono_field_get_value (obj, field, v);
1151 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1155 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1157 src = (char*)vt->data + field->offset;
1158 set_value (field->type, value, src, TRUE);
1162 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1164 default_mono_runtime_invoke (prop->set, obj, params, exc);
1168 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1170 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1175 mono_get_delegate_invoke (MonoClass *klass)
1182 for (i = 0; i < klass->method.count; ++i) {
1183 if (klass->methods [i]->name[0] == 'I' &&
1184 !strcmp ("Invoke", klass->methods [i]->name)) {
1185 im = klass->methods [i];
1195 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1199 im = mono_get_delegate_invoke (delegate->vtable->klass);
1202 return mono_runtime_invoke (im, delegate, params, exc);
1205 static MonoArray* main_args;
1208 mono_runtime_get_main_args (void)
1214 fire_process_exit_event (void)
1216 MonoClassField *field;
1217 MonoDomain *domain = mono_domain_get ();
1219 MonoObject *delegate, *exc;
1221 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1224 if (domain != mono_get_root_domain ())
1227 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1228 if (delegate == NULL)
1233 mono_runtime_delegate_invoke (delegate, pa, &exc);
1237 * Execute a standard Main() method (argc/argv contains the
1238 * executable name). This method also sets the command line argument value
1239 * needed by System.Environment.
1242 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1246 MonoArray *args = NULL;
1247 MonoDomain *domain = mono_domain_get ();
1248 gchar *utf8_fullpath;
1251 main_thread = mono_thread_current ();
1253 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1255 if (!g_path_is_absolute (argv [0])) {
1256 gchar *basename = g_path_get_basename (argv [0]);
1257 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1261 utf8_fullpath = mono_utf8_from_external (fullpath);
1262 if(utf8_fullpath == NULL) {
1263 /* Printing the arg text will cause glib to
1264 * whinge about "Invalid UTF-8", but at least
1265 * its relevant, and shows the problem text
1268 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1269 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1276 utf8_fullpath = mono_utf8_from_external (argv[0]);
1277 if(utf8_fullpath == NULL) {
1278 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1279 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1284 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1285 g_free (utf8_fullpath);
1287 for (i = 1; i < argc; ++i) {
1291 utf8_arg=mono_utf8_from_external (argv[i]);
1292 if(utf8_arg==NULL) {
1293 /* Ditto the comment about Invalid UTF-8 here */
1294 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1295 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1299 arg = mono_string_new (domain, utf8_arg);
1300 mono_array_set (main_args, gpointer, i, arg);
1304 if (method->signature->param_count) {
1305 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1306 for (i = 0; i < argc; ++i) {
1307 /* The encodings should all work, given that
1308 * we've checked all these args for the
1311 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1312 mono_array_set (args, gpointer, i, arg);
1315 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1318 mono_assembly_set_main (method->klass->image->assembly);
1320 result = mono_runtime_exec_main (method, args, exc);
1321 fire_process_exit_event ();
1325 /* Used in mono_unhandled_exception */
1327 create_unhandled_exception_eventargs (MonoObject *exc)
1331 MonoMethod *method = NULL;
1332 MonoBoolean is_terminating = TRUE;
1336 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1339 mono_class_init (klass);
1341 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1342 for (i = 0; i < klass->method.count; ++i) {
1343 method = klass->methods [i];
1344 if (!strcmp (".ctor", method->name) &&
1345 method->signature->param_count == 2 &&
1346 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1354 args [1] = &is_terminating;
1356 obj = mono_object_new (mono_domain_get (), klass);
1357 mono_runtime_invoke (method, obj, args, NULL);
1363 * We call this function when we detect an unhandled exception
1364 * in the default domain.
1365 * It invokes the * UnhandledException event in AppDomain or prints
1366 * a warning to the console
1369 mono_unhandled_exception (MonoObject *exc)
1371 MonoDomain *domain = mono_domain_get ();
1372 MonoClassField *field;
1373 MonoObject *delegate;
1375 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1376 "UnhandledException");
1379 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1380 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1382 /* set exitcode only in the main thread */
1383 if (mono_thread_current () == main_thread)
1384 mono_environment_exitcode_set (1);
1385 if (domain != mono_get_root_domain () || !delegate) {
1386 mono_print_unhandled_exception (exc);
1388 MonoObject *e = NULL;
1391 pa [0] = domain->domain;
1392 pa [1] = create_unhandled_exception_eventargs (exc);
1393 mono_runtime_delegate_invoke (delegate, pa, &e);
1396 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1397 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1405 * Launch a new thread to start all setup that requires managed code
1408 * main_func is called back from the thread with main_args as the
1409 * parameter. The callback function is expected to start Main()
1410 * eventually. This function then waits for all managed threads to
1414 mono_runtime_exec_managed_code (MonoDomain *domain,
1415 MonoMainThreadFunc main_func,
1418 mono_thread_create (domain, main_func, main_args);
1420 mono_thread_manage ();
1424 * Execute a standard Main() method (args doesn't contain the
1428 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1438 domain = mono_object_domain (args);
1439 if (!domain->entry_assembly) {
1441 gchar *config_suffix;
1442 MonoAssembly *assembly;
1444 assembly = method->klass->image->assembly;
1445 domain->entry_assembly = assembly;
1446 domain->setup->application_base = mono_string_new (domain, assembly->basedir);
1448 config_suffix = g_strconcat (assembly->aname.name, ".exe.config", NULL);
1449 str = g_build_filename (assembly->basedir, config_suffix, NULL);
1450 g_free (config_suffix);
1451 domain->setup->configuration_file = mono_string_new (domain, str);
1455 /* FIXME: check signature of method */
1456 if (method->signature->ret->type == MONO_TYPE_I4) {
1458 res = mono_runtime_invoke (method, NULL, pa, exc);
1460 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1464 mono_environment_exitcode_set (rval);
1466 mono_runtime_invoke (method, NULL, pa, exc);
1470 /* If the return type of Main is void, only
1471 * set the exitcode if an exception was thrown
1472 * (we don't want to blow away an
1473 * explicitly-set exit code)
1476 mono_environment_exitcode_set (rval);
1484 mono_install_runtime_invoke (MonoInvokeFunc func)
1486 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1490 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1493 MonoMethodSignature *sig = method->signature;
1494 gpointer *pa = NULL;
1497 if (NULL != params) {
1498 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1499 for (i = 0; i < mono_array_length (params); i++) {
1500 if (sig->params [i]->byref) {
1504 switch (sig->params [i]->type) {
1507 case MONO_TYPE_BOOLEAN:
1510 case MONO_TYPE_CHAR:
1519 case MONO_TYPE_VALUETYPE:
1520 if (sig->params [i]->byref) {
1521 /* MS seems to create the objects if a null is passed in */
1522 if (! ((gpointer *)params->vector)[i])
1523 ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
1526 g_assert (((gpointer*)params->vector) [i]);
1527 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1529 case MONO_TYPE_STRING:
1530 case MONO_TYPE_OBJECT:
1531 case MONO_TYPE_CLASS:
1532 case MONO_TYPE_ARRAY:
1533 case MONO_TYPE_SZARRAY:
1534 if (sig->params [i]->byref)
1535 pa [i] = &(((gpointer *)params->vector)[i]);
1537 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1540 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1545 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1547 obj = mono_object_new (mono_domain_get (), method->klass);
1548 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1549 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
1552 mono_runtime_invoke (method, obj, pa, exc);
1555 return mono_runtime_invoke (method, obj, pa, exc);
1559 out_of_memory (size_t size)
1562 * we could allocate at program startup some memory that we could release
1563 * back to the system at this point if we're really low on memory (ie, size is
1564 * lower than the memory we set apart)
1566 mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
1570 * mono_object_allocate:
1571 * @size: number of bytes to allocate
1573 * This is a very simplistic routine until we have our GC-aware
1576 * Returns: an allocated object of size @size, or NULL on failure.
1578 static inline void *
1579 mono_object_allocate (size_t size)
1582 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1583 void *o = GC_MALLOC (size);
1585 void *o = calloc (1, size);
1587 mono_stats.new_object_count++;
1590 out_of_memory (size);
1594 #if CREATION_SPEEDUP
1595 static inline void *
1596 mono_object_allocate_spec (size_t size, void *gcdescr)
1598 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1599 void *o = GC_GCJ_MALLOC (size, gcdescr);
1600 mono_stats.new_object_count++;
1603 out_of_memory (size);
1611 * Frees the memory used by the object. Debugging purposes
1612 * only, as we will have our GC system.
1615 mono_object_free (MonoObject *o)
1618 g_error ("mono_object_free called with boehm gc.");
1620 MonoClass *c = o->vtable->klass;
1622 memset (o, 0, c->instance_size);
1629 * @klass: the class of the object that we want to create
1631 * Returns: A newly created object whose definition is
1632 * looked up using @klass
1635 mono_object_new (MonoDomain *domain, MonoClass *klass)
1637 MONO_ARCH_SAVE_REGS;
1638 return mono_object_new_specific (mono_class_vtable (domain, klass));
1642 * mono_object_new_specific:
1643 * @vtable: the vtable of the object that we want to create
1645 * Returns: A newly created object with class and domain specified
1649 mono_object_new_specific (MonoVTable *vtable)
1653 MONO_ARCH_SAVE_REGS;
1658 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1661 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1665 mono_class_init (klass);
1667 for (i = 0; i < klass->method.count; ++i) {
1668 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1669 klass->methods [i]->signature->param_count == 1) {
1670 im = klass->methods [i];
1675 vtable->domain->create_proxy_for_type_method = im;
1678 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1680 o = mono_runtime_invoke (im, NULL, pa, NULL);
1681 if (o != NULL) return o;
1684 return mono_object_new_alloc_specific (vtable);
1688 mono_object_new_fast (MonoVTable *vtable)
1691 MONO_ARCH_SAVE_REGS;
1693 #if CREATION_SPEEDUP
1694 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1695 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1697 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1698 o = mono_object_allocate (vtable->klass->instance_size);
1702 o = mono_object_allocate (vtable->klass->instance_size);
1709 mono_object_new_alloc_specific (MonoVTable *vtable)
1713 #if CREATION_SPEEDUP
1714 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1715 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1717 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1718 o = mono_object_allocate (vtable->klass->instance_size);
1722 o = mono_object_allocate (vtable->klass->instance_size);
1725 if (vtable->klass->has_finalize)
1726 mono_object_register_finalizer (o);
1728 mono_profiler_allocation (o, vtable->klass);
1733 * mono_object_new_from_token:
1734 * @image: Context where the type_token is hosted
1735 * @token: a token of the type that we want to create
1737 * Returns: A newly created object whose definition is
1738 * looked up using @token in the @image image
1741 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1745 class = mono_class_get (image, token);
1747 return mono_object_new (domain, class);
1752 * mono_object_clone:
1753 * @obj: the object to clone
1755 * Returns: A newly created object who is a shallow copy of @obj
1758 mono_object_clone (MonoObject *obj)
1763 size = obj->vtable->klass->instance_size;
1764 o = mono_object_allocate (size);
1765 mono_profiler_allocation (o, obj->vtable->klass);
1767 memcpy (o, obj, size);
1769 if (obj->vtable->klass->has_finalize)
1770 mono_object_register_finalizer (o);
1776 * @array: the array to clone
1778 * Returns: A newly created array who is a shallow copy of @array
1781 mono_array_clone (MonoArray *array)
1786 MonoClass *klass = array->obj.vtable->klass;
1788 MONO_ARCH_SAVE_REGS;
1790 if (array->bounds == NULL) {
1791 size = mono_array_length (array);
1792 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1793 klass, &size, NULL);
1795 size *= mono_array_element_size (klass);
1796 memcpy (o, array, sizeof (MonoArray) + size);
1801 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1802 size = mono_array_element_size (klass);
1803 for (i = 0; i < klass->rank; ++i) {
1804 sizes [i] = array->bounds [i].length;
1805 size *= array->bounds [i].length;
1806 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1808 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1809 klass, sizes, sizes + klass->rank);
1810 memcpy (o, array, sizeof(MonoArray) + size);
1815 /* helper macros to check for overflow when calculating the size of arrays */
1816 #define MYGUINT32_MAX 4294967295U
1817 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1818 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1819 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1820 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1821 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1824 * mono_array_new_full:
1825 * @domain: domain where the object is created
1826 * @array_class: array class
1827 * @lengths: lengths for each dimension in the array
1828 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1830 * This routine creates a new array objects with the given dimensions,
1831 * lower bounds and type.
1834 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1835 guint32 *lengths, guint32 *lower_bounds)
1837 guint32 byte_len, len;
1840 MonoArrayBounds *bounds;
1844 if (!array_class->inited)
1845 mono_class_init (array_class);
1847 byte_len = mono_array_element_size (array_class);
1850 if (array_class->rank == 1 &&
1851 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1856 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1858 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1860 for (i = 0; i < array_class->rank; ++i) {
1861 bounds [i].length = lengths [i];
1862 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1863 out_of_memory (MYGUINT32_MAX);
1868 for (i = 0; i < array_class->rank; ++i)
1869 bounds [i].lower_bound = lower_bounds [i];
1872 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1873 out_of_memory (MYGUINT32_MAX);
1875 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1876 out_of_memory (MYGUINT32_MAX);
1877 byte_len += sizeof (MonoArray);
1879 * Following three lines almost taken from mono_object_new ():
1880 * they need to be kept in sync.
1882 vtable = mono_class_vtable (domain, array_class);
1883 #if CREATION_SPEEDUP
1884 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1885 o = mono_object_allocate_spec (byte_len, vtable);
1887 o = mono_object_allocate (byte_len);
1891 o = mono_object_allocate (byte_len);
1895 array = (MonoArray*)o;
1897 array->bounds = bounds;
1898 array->max_length = len;
1900 mono_profiler_allocation (o, array_class);
1907 * @domain: domain where the object is created
1908 * @eclass: element class
1909 * @n: number of array elements
1911 * This routine creates a new szarray with @n elements of type @eclass.
1914 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1918 MONO_ARCH_SAVE_REGS;
1920 ac = mono_array_class_get (eclass, 1);
1921 g_assert (ac != NULL);
1923 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1927 * mono_array_new_specific:
1928 * @vtable: a vtable in the appropriate domain for an initialized class
1929 * @n: number of array elements
1931 * This routine is a fast alternative to mono_array_new() for code which
1932 * can be sure about the domain it operates in.
1935 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1939 guint32 byte_len, elem_size;
1941 MONO_ARCH_SAVE_REGS;
1943 elem_size = mono_array_element_size (vtable->klass);
1944 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1945 out_of_memory (MYGUINT32_MAX);
1946 byte_len = n * elem_size;
1947 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1948 out_of_memory (MYGUINT32_MAX);
1949 byte_len += sizeof (MonoArray);
1950 #if CREATION_SPEEDUP
1951 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1952 o = mono_object_allocate_spec (byte_len, vtable);
1954 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1955 o = mono_object_allocate (byte_len);
1959 o = mono_object_allocate (byte_len);
1963 ao = (MonoArray *)o;
1966 mono_profiler_allocation (o, vtable->klass);
1972 * mono_string_new_utf16:
1973 * @text: a pointer to an utf16 string
1974 * @len: the length of the string
1976 * Returns: A newly created string object which contains @text.
1979 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1983 s = mono_string_new_size (domain, len);
1984 g_assert (s != NULL);
1986 memcpy (mono_string_chars (s), text, len * 2);
1992 * mono_string_new_size:
1993 * @text: a pointer to an utf16 string
1994 * @len: the length of the string
1996 * Returns: A newly created string object of @len
1999 mono_string_new_size (MonoDomain *domain, gint32 len)
2003 size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2005 /* overflow ? can't fit it, can't allocate it! */
2009 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2011 #if CREATION_SPEEDUP
2012 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2013 s = mono_object_allocate_spec (size, vtable);
2015 s = (MonoString*)mono_object_allocate (size);
2016 s->object.vtable = vtable;
2019 s = (MonoString*)mono_object_allocate (size);
2020 s->object.vtable = vtable;
2024 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2030 * mono_string_new_len:
2031 * @text: a pointer to an utf8 string
2032 * @length: number of bytes in @text to consider
2034 * Returns: A newly created string object which contains @text.
2037 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2039 GError *error = NULL;
2040 MonoString *o = NULL;
2042 glong items_written;
2044 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2047 o = mono_string_new_utf16 (domain, ut, items_written);
2049 g_error_free (error);
2058 * @text: a pointer to an utf8 string
2060 * Returns: A newly created string object which contains @text.
2063 mono_string_new (MonoDomain *domain, const char *text)
2065 GError *error = NULL;
2066 MonoString *o = NULL;
2068 glong items_written;
2073 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2076 o = mono_string_new_utf16 (domain, ut, items_written);
2078 g_error_free (error);
2086 * mono_string_new_wrapper:
2087 * @text: pointer to utf8 characters.
2089 * Helper function to create a string object from @text in the current domain.
2092 mono_string_new_wrapper (const char *text)
2094 MonoDomain *domain = mono_domain_get ();
2096 MONO_ARCH_SAVE_REGS;
2099 return mono_string_new (domain, text);
2106 * @class: the class of the value
2107 * @value: a pointer to the unboxed data
2109 * Returns: A newly created object which contains @value.
2112 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2118 g_assert (class->valuetype);
2120 vtable = mono_class_vtable (domain, class);
2121 size = mono_class_instance_size (class);
2122 res = mono_object_allocate (size);
2123 res->vtable = vtable;
2124 mono_profiler_allocation (res, class);
2126 size = size - sizeof (MonoObject);
2128 #if NO_UNALIGNED_ACCESS
2129 memcpy ((char *)res + sizeof (MonoObject), value, size);
2133 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2136 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2139 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2142 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2145 memcpy ((char *)res + sizeof (MonoObject), value, size);
2148 if (class->has_finalize)
2149 mono_object_register_finalizer (res);
2154 mono_object_unbox (MonoObject *obj)
2156 /* add assert for valuetypes? */
2157 return ((char*)obj) + sizeof (MonoObject);
2161 * mono_object_isinst:
2163 * @klass: a pointer to a class
2165 * Returns: @obj if @obj is derived from @klass
2168 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2171 mono_class_init (klass);
2173 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2174 return mono_object_isinst_mbyref (obj, klass);
2179 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2183 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2192 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2193 if ((klass->interface_id <= vt->max_interface_id) &&
2194 (vt->interface_offsets [klass->interface_id] != 0))
2198 MonoClass *oklass = vt->klass;
2199 if ((oklass == mono_defaults.transparent_proxy_class))
2200 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2202 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2206 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2208 MonoDomain *domain = mono_domain_get ();
2210 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2211 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2212 MonoMethod *im = NULL;
2216 for (i = 0; i < rpklass->method.count; ++i) {
2217 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2218 im = rpklass->methods [i];
2223 im = mono_object_get_virtual_method (rp, im);
2226 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2229 res = mono_runtime_invoke (im, rp, pa, NULL);
2231 if (*(MonoBoolean *) mono_object_unbox(res)) {
2232 /* Update the vtable of the remote type, so it can safely cast to this new type */
2233 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2234 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2243 * mono_object_castclass_mbyref:
2245 * @klass: a pointer to a class
2247 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2250 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2252 if (!obj) return NULL;
2253 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2255 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2257 "InvalidCastException"));
2262 MonoDomain *orig_domain;
2268 str_lookup (MonoDomain *domain, gpointer user_data)
2270 LDStrInfo *info = user_data;
2271 if (info->res || domain == info->orig_domain)
2273 mono_domain_lock (domain);
2274 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2275 mono_domain_unlock (domain);
2279 mono_string_is_interned_lookup (MonoString *str, int insert)
2281 MonoGHashTable *ldstr_table;
2284 char *ins = g_malloc (4 + str->length * 2);
2287 /* Encode the length */
2288 /* Same code as in mono_image_insert_string () */
2290 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2293 * ins is stored in the hash table as a key and needs to have the same
2294 * representation as in the metadata: we swap the character bytes on big
2297 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2300 char *p2 = (char *)mono_string_chars (str);
2301 for (i = 0; i < str->length; ++i) {
2308 memcpy (p, mono_string_chars (str), str->length * 2);
2310 domain = ((MonoObject *)str)->vtable->domain;
2311 ldstr_table = domain->ldstr_table;
2312 mono_domain_lock (domain);
2313 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2314 mono_domain_unlock (domain);
2319 mono_g_hash_table_insert (ldstr_table, ins, str);
2320 mono_domain_unlock (domain);
2323 LDStrInfo ldstr_info;
2324 ldstr_info.orig_domain = domain;
2325 ldstr_info.ins = ins;
2326 ldstr_info.res = NULL;
2328 mono_domain_foreach (str_lookup, &ldstr_info);
2329 if (ldstr_info.res) {
2331 * the string was already interned in some other domain:
2332 * intern it in the current one as well.
2334 mono_g_hash_table_insert (ldstr_table, ins, str);
2335 mono_domain_unlock (domain);
2339 mono_domain_unlock (domain);
2345 mono_string_is_interned (MonoString *o)
2347 return mono_string_is_interned_lookup (o, FALSE);
2351 mono_string_intern (MonoString *str)
2353 return mono_string_is_interned_lookup (str, TRUE);
2358 * @domain: the domain where the string will be used.
2359 * @image: a metadata context
2360 * @idx: index into the user string table.
2362 * Implementation for the ldstr opcode.
2365 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2367 const char *str, *sig;
2371 MONO_ARCH_SAVE_REGS;
2374 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2376 sig = str = mono_metadata_user_string (image, idx);
2378 mono_domain_lock (domain);
2379 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2380 mono_domain_unlock (domain);
2384 len2 = mono_metadata_decode_blob_size (str, &str);
2387 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2388 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2391 guint16 *p2 = (guint16*)mono_string_chars (o);
2392 for (i = 0; i < len2; ++i) {
2393 *p2 = GUINT16_FROM_LE (*p2);
2398 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2399 mono_domain_unlock (domain);
2405 * mono_string_to_utf8:
2406 * @s: a System.String
2408 * Return the UTF8 representation for @s.
2409 * the resulting buffer nedds to be freed with g_free().
2412 mono_string_to_utf8 (MonoString *s)
2415 GError *error = NULL;
2421 return g_strdup ("");
2423 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2425 g_warning (error->message);
2426 g_error_free (error);
2433 * mono_string_to_utf16:
2436 * Return an null-terminated array of the utf-16 chars
2437 * contained in @s. The result must be freed with g_free().
2438 * This is a temporary helper until our string implementation
2439 * is reworked to always include the null terminating char.
2442 mono_string_to_utf16 (MonoString *s)
2449 as = g_malloc ((s->length * 2) + 2);
2450 as [(s->length * 2)] = '\0';
2451 as [(s->length * 2) + 1] = '\0';
2454 return (gunichar2 *)(as);
2457 memcpy (as, mono_string_chars(s), s->length * 2);
2458 return (gunichar2 *)(as);
2462 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2465 mono_string_from_utf16 (gunichar2 *data)
2467 MonoDomain *domain = mono_domain_get ();
2473 while (data [len]) len++;
2475 return mono_string_new_utf16 (domain, data, len);
2479 default_ex_handler (MonoException *ex)
2481 MonoObject *o = (MonoObject*)ex;
2482 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2486 static MonoExceptionFunc ex_handler = default_ex_handler;
2489 mono_install_handler (MonoExceptionFunc func)
2491 ex_handler = func? func: default_ex_handler;
2495 * mono_raise_exception:
2496 * @ex: exception object
2498 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2501 mono_raise_exception (MonoException *ex)
2504 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2505 * that will cause gcc to omit the function epilog, causing problems when
2506 * the JIT tries to walk the stack, since the return address on the stack
2507 * will point into the next function in the executable, not this one.
2514 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2516 MonoWaitHandle *res;
2518 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2520 res->handle = handle;
2526 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2528 MonoAsyncResult *res;
2530 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2533 res->async_state = state;
2535 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2537 res->sync_completed = FALSE;
2538 res->completed = FALSE;
2544 mono_message_init (MonoDomain *domain,
2545 MonoMethodMessage *this,
2546 MonoReflectionMethod *method,
2547 MonoArray *out_args)
2549 MonoMethodSignature *sig = method->method->signature;
2555 this->method = method;
2557 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2558 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2559 this->async_result = NULL;
2560 this->call_type = CallType_Sync;
2562 names = g_new (char *, sig->param_count);
2563 mono_method_get_param_names (method->method, (const char **) names);
2564 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2566 for (i = 0; i < sig->param_count; i++) {
2567 name = mono_string_new (domain, names [i]);
2568 mono_array_set (this->names, gpointer, i, name);
2572 for (i = 0, j = 0; i < sig->param_count; i++) {
2574 if (sig->params [i]->byref) {
2576 gpointer arg = mono_array_get (out_args, gpointer, j);
2577 mono_array_set (this->args, gpointer, i, arg);
2581 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2586 mono_array_set (this->arg_types, guint8, i, arg_type);
2591 * mono_remoting_invoke:
2592 * @real_proxy: pointer to a RealProxy object
2593 * @msg: The MonoMethodMessage to execute
2594 * @exc: used to store exceptions
2595 * @out_args: used to store output arguments
2597 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2598 * IMessage interface and it is not trivial to extract results from there. So
2599 * we call an helper method PrivateInvoke instead of calling
2600 * RealProxy::Invoke() directly.
2602 * Returns: the result object.
2605 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2606 MonoObject **exc, MonoArray **out_args)
2608 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2611 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2617 klass = mono_defaults.real_proxy_class;
2619 for (i = 0; i < klass->method.count; ++i) {
2620 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2621 klass->methods [i]->signature->param_count == 4) {
2622 im = klass->methods [i];
2628 real_proxy->vtable->domain->private_invoke_method = im;
2631 pa [0] = real_proxy;
2636 return mono_runtime_invoke (im, NULL, pa, exc);
2640 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2641 MonoObject **exc, MonoArray **out_args)
2645 MonoMethodSignature *sig;
2646 int i, j, outarg_count = 0;
2648 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2650 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2651 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2652 target = tp->rp->unwrapped_server;
2654 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2658 domain = mono_domain_get ();
2659 method = msg->method->method;
2660 sig = method->signature;
2662 for (i = 0; i < sig->param_count; i++) {
2663 if (sig->params [i]->byref)
2667 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2670 for (i = 0, j = 0; i < sig->param_count; i++) {
2671 if (sig->params [i]->byref) {
2673 arg = mono_array_get (msg->args, gpointer, i);
2674 mono_array_set (*out_args, gpointer, j, arg);
2679 return mono_runtime_invoke_array (method, target, msg->args, exc);
2683 mono_print_unhandled_exception (MonoObject *exc)
2685 char *message = (char *) "";
2689 gboolean free_message = FALSE;
2692 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2693 klass = exc->vtable->klass;
2695 while (klass && method == NULL) {
2696 for (i = 0; i < klass->method.count; ++i) {
2697 method = klass->methods [i];
2698 if (!strcmp ("ToString", method->name) &&
2699 method->signature->param_count == 0 &&
2700 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2701 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2708 klass = klass->parent;
2713 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2715 message = mono_string_to_utf8 (str);
2716 free_message = TRUE;
2721 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2722 * exc->vtable->klass->name, message);
2724 g_printerr ("\nUnhandled Exception: %s\n", message);
2731 * mono_delegate_ctor:
2732 * @this: pointer to an uninitialized delegate object
2733 * @target: target object
2734 * @addr: pointer to native code
2736 * This is used to initialize a delegate. We also insert the method_info if
2737 * we find the info with mono_jit_info_table_find().
2740 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2742 MonoDomain *domain = mono_domain_get ();
2743 MonoDelegate *delegate = (MonoDelegate *)this;
2744 MonoMethod *method = NULL;
2751 class = this->vtable->klass;
2753 if ((ji = mono_jit_info_table_find (domain, addr))) {
2754 method = ji->method;
2755 delegate->method_info = mono_method_get_object (domain, method, NULL);
2758 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2760 method = mono_marshal_get_remoting_invoke (method);
2761 delegate->method_ptr = mono_compile_method (method);
2762 delegate->target = target;
2764 delegate->method_ptr = addr;
2765 delegate->target = target;
2770 * mono_method_call_message_new:
2772 * Translates arguments pointers into a Message.
2775 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2776 MonoDelegate **cb, MonoObject **state)
2778 MonoDomain *domain = mono_domain_get ();
2779 MonoMethodSignature *sig = method->signature;
2780 MonoMethodMessage *msg;
2783 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2786 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2787 count = sig->param_count - 2;
2789 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2790 count = sig->param_count;
2793 for (i = 0; i < count; i++) {
2798 if (sig->params [i]->byref)
2799 vpos = *((gpointer *)params [i]);
2803 type = sig->params [i]->type;
2804 class = mono_class_from_mono_type (sig->params [i]);
2806 if (class->valuetype)
2807 arg = mono_value_box (domain, class, vpos);
2809 arg = *((MonoObject **)vpos);
2811 mono_array_set (msg->args, gpointer, i, arg);
2814 if (cb != NULL && state != NULL) {
2815 *cb = *((MonoDelegate **)params [i]);
2817 *state = *((MonoObject **)params [i]);
2824 * mono_method_return_message_restore:
2826 * Restore results from message based processing back to arguments pointers
2829 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2831 MonoMethodSignature *sig = method->signature;
2832 int i, j, type, size;
2833 for (i = 0, j = 0; i < sig->param_count; i++) {
2834 MonoType *pt = sig->params [i];
2837 char *arg = mono_array_get (out_args, gpointer, j);
2841 case MONO_TYPE_VOID:
2842 g_assert_not_reached ();
2846 case MONO_TYPE_BOOLEAN:
2849 case MONO_TYPE_CHAR:
2856 case MONO_TYPE_VALUETYPE: {
2857 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2858 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2861 case MONO_TYPE_STRING:
2862 case MONO_TYPE_CLASS:
2863 case MONO_TYPE_ARRAY:
2864 case MONO_TYPE_SZARRAY:
2865 case MONO_TYPE_OBJECT:
2866 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2869 g_assert_not_reached ();
2878 * mono_load_remote_field:
2879 * @this: pointer to an object
2880 * @klass: klass of the object containing @field
2881 * @field: the field to load
2882 * @res: a storage to store the result
2884 * This method is called by the runtime on attempts to load fields of
2885 * transparent proxy objects. @this points to such TP, @klass is the class of
2886 * the object containing @field. @res is a storage location which can be
2887 * used to store the result.
2889 * Returns: an address pointing to the value of field.
2892 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2894 static MonoMethod *getter = NULL;
2895 MonoDomain *domain = mono_domain_get ();
2896 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2897 MonoClass *field_class;
2898 MonoMethodMessage *msg;
2899 MonoArray *out_args;
2903 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2908 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2909 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2916 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2917 MonoMethod *cm = mono_defaults.object_class->methods [i];
2919 if (!strcmp (cm->name, "FieldGetter")) {
2927 field_class = mono_class_from_mono_type (field->type);
2929 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2930 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2931 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2933 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2934 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2936 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2938 if (exc) mono_raise_exception ((MonoException *)exc);
2940 *res = mono_array_get (out_args, MonoObject *, 0);
2942 if (field_class->valuetype) {
2943 return ((char *)*res) + sizeof (MonoObject);
2949 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2951 static MonoMethod *getter = NULL;
2952 MonoDomain *domain = mono_domain_get ();
2953 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2954 MonoClass *field_class;
2955 MonoMethodMessage *msg;
2956 MonoArray *out_args;
2957 MonoObject *exc, *res;
2959 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2961 field_class = mono_class_from_mono_type (field->type);
2963 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2965 if (field_class->valuetype) {
2966 res = mono_object_new (domain, field_class);
2967 val = ((gchar *) res) + sizeof (MonoObject);
2971 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2978 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2979 MonoMethod *cm = mono_defaults.object_class->methods [i];
2981 if (!strcmp (cm->name, "FieldGetter")) {
2989 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2990 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2991 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2993 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2994 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2996 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2998 if (exc) mono_raise_exception ((MonoException *)exc);
3000 res = mono_array_get (out_args, MonoObject *, 0);
3006 * mono_store_remote_field:
3007 * @this: pointer to an object
3008 * @klass: klass of the object containing @field
3009 * @field: the field to load
3010 * @val: the value/object to store
3012 * This method is called by the runtime on attempts to store fields of
3013 * transparent proxy objects. @this points to such TP, @klass is the class of
3014 * the object containing @field. @val is the new value to store in @field.
3017 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3019 static MonoMethod *setter = NULL;
3020 MonoDomain *domain = mono_domain_get ();
3021 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3022 MonoClass *field_class;
3023 MonoMethodMessage *msg;
3024 MonoArray *out_args;
3028 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3030 field_class = mono_class_from_mono_type (field->type);
3032 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3033 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3034 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3041 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3042 MonoMethod *cm = mono_defaults.object_class->methods [i];
3044 if (!strcmp (cm->name, "FieldSetter")) {
3052 if (field_class->valuetype)
3053 arg = mono_value_box (domain, field_class, val);
3055 arg = *((MonoObject **)val);
3058 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3059 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3061 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3062 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3063 mono_array_set (msg->args, gpointer, 2, arg);
3065 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3067 if (exc) mono_raise_exception ((MonoException *)exc);
3071 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3073 static MonoMethod *setter = NULL;
3074 MonoDomain *domain = mono_domain_get ();
3075 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3076 MonoClass *field_class;
3077 MonoMethodMessage *msg;
3078 MonoArray *out_args;
3081 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3083 field_class = mono_class_from_mono_type (field->type);
3085 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3086 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3087 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3094 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3095 MonoMethod *cm = mono_defaults.object_class->methods [i];
3097 if (!strcmp (cm->name, "FieldSetter")) {
3105 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3106 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3108 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3109 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3110 mono_array_set (msg->args, gpointer, 2, arg);
3112 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3114 if (exc) mono_raise_exception ((MonoException *)exc);