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/class-internals.h"
25 #include <mono/metadata/assembly.h>
26 #include <mono/metadata/threadpool.h>
27 #include <mono/metadata/marshal.h>
28 #include "mono/metadata/debug-helpers.h"
29 #include "mono/metadata/marshal.h"
30 #include <mono/metadata/threads.h>
31 #include <mono/metadata/threads-types.h>
32 #include <mono/metadata/environment.h>
33 #include "mono/metadata/profiler-private.h"
34 #include <mono/os/gc_wrapper.h>
35 #include <mono/utils/strenc.h>
38 * Enable typed allocation using the GC_gcj_malloc function.
40 #ifdef HAVE_GC_GCJ_MALLOC
41 #define CREATION_SPEEDUP 1
45 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value);
48 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig);
51 mono_runtime_object_init (MonoObject *this)
54 MonoMethod *method = NULL;
55 MonoClass *klass = this->vtable->klass;
57 for (i = 0; i < klass->method.count; ++i) {
58 if (!strcmp (".ctor", klass->methods [i]->name) &&
59 klass->methods [i]->signature->param_count == 0) {
60 method = klass->methods [i];
67 if (method->klass->valuetype)
68 this = mono_object_unbox (this);
69 mono_runtime_invoke (method, this, NULL, NULL);
72 /* The pseudo algorithm for type initialization from the spec
73 Note it doesn't say anything about domains - only threads.
75 2. If the type is initialized you are done.
76 2.1. If the type is not yet initialized, try to take an
78 2.2. If successful, record this thread as responsible for
79 initializing the type and proceed to step 2.3.
80 2.2.1. If not, see whether this thread or any thread
81 waiting for this thread to complete already holds the lock.
82 2.2.2. If so, return since blocking would create a deadlock. This thread
83 will now see an incompletely initialized state for the type,
84 but no deadlock will arise.
85 2.2.3 If not, block until the type is initialized then return.
86 2.3 Initialize the parent type and then all interfaces implemented
88 2.4 Execute the type initialization code for this type.
89 2.5 Mark the type as initialized, release the initialization lock,
90 awaken any threads waiting for this type to be initialized,
97 guint32 initializing_tid;
98 guint32 waiting_count;
99 CRITICAL_SECTION initialization_section;
100 } TypeInitializationLock;
102 /* for locking access to type_initialization_hash and blocked_thread_hash */
103 static CRITICAL_SECTION type_initialization_section;
105 /* from vtable to lock */
106 static GHashTable *type_initialization_hash;
108 /* from thread id to thread id being waited on */
109 static GHashTable *blocked_thread_hash;
112 static MonoThread *main_thread;
115 mono_type_initialization_init (void)
117 InitializeCriticalSection (&type_initialization_section);
118 type_initialization_hash = g_hash_table_new (NULL, NULL);
119 blocked_thread_hash = g_hash_table_new (NULL, NULL);
123 * mono_runtime_class_init:
124 * @vtable: vtable that needs to be initialized
126 * This routine calls the class constructor for @vtable.
129 mono_runtime_class_init (MonoVTable *vtable)
133 MonoException *exc_to_throw;
134 MonoMethod *method = NULL;
141 if (vtable->initialized)
146 klass = vtable->klass;
148 for (i = 0; i < klass->method.count; ++i) {
149 method = klass->methods [i];
150 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
151 (strcmp (".cctor", method->name) == 0)) {
158 MonoDomain *domain = vtable->domain;
159 TypeInitializationLock *lock;
160 guint32 tid = GetCurrentThreadId();
161 int do_initialization = 0;
162 MonoDomain *last_domain = NULL;
164 EnterCriticalSection (&type_initialization_section);
165 /* double check... */
166 if (vtable->initialized) {
167 LeaveCriticalSection (&type_initialization_section);
170 lock = g_hash_table_lookup (type_initialization_hash, vtable);
172 /* This thread will get to do the initialization */
173 if (mono_domain_get () != domain) {
174 /* Transfer into the target domain */
175 last_domain = mono_domain_get ();
176 if (!mono_domain_set (domain, FALSE)) {
177 vtable->initialized = 1;
178 LeaveCriticalSection (&type_initialization_section);
179 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
182 lock = g_malloc (sizeof(TypeInitializationLock));
183 InitializeCriticalSection (&lock->initialization_section);
184 lock->initializing_tid = tid;
185 lock->waiting_count = 1;
186 /* grab the vtable lock while this thread still owns type_initialization_section */
187 EnterCriticalSection (&lock->initialization_section);
188 g_hash_table_insert (type_initialization_hash, vtable, lock);
189 do_initialization = 1;
193 if (lock->initializing_tid == tid) {
194 LeaveCriticalSection (&type_initialization_section);
197 /* see if the thread doing the initialization is already blocked on this thread */
198 blocked = GUINT_TO_POINTER (lock->initializing_tid);
199 while ((blocked = g_hash_table_lookup (blocked_thread_hash, blocked))) {
200 if (blocked == GUINT_TO_POINTER (tid)) {
201 LeaveCriticalSection (&type_initialization_section);
205 ++lock->waiting_count;
206 /* record the fact that we are waiting on the initializing thread */
207 g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), GUINT_TO_POINTER (lock->initializing_tid));
209 LeaveCriticalSection (&type_initialization_section);
211 if (do_initialization) {
212 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
214 mono_domain_set (last_domain, TRUE);
215 LeaveCriticalSection (&lock->initialization_section);
217 /* this just blocks until the initializing thread is done */
218 EnterCriticalSection (&lock->initialization_section);
219 LeaveCriticalSection (&lock->initialization_section);
222 EnterCriticalSection (&type_initialization_section);
223 if (lock->initializing_tid != tid)
224 g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
225 --lock->waiting_count;
226 if (lock->waiting_count == 0) {
227 DeleteCriticalSection (&lock->initialization_section);
228 g_hash_table_remove (type_initialization_hash, vtable);
231 vtable->initialized = 1;
232 /* FIXME: if the cctor fails, the type must be marked as unusable */
233 LeaveCriticalSection (&type_initialization_section);
235 vtable->initialized = 1;
240 (klass->image == mono_defaults.corlib &&
241 !strcmp (klass->name_space, "System") &&
242 !strcmp (klass->name, "TypeInitializationException")))
243 return; /* No static constructor found or avoid infinite loop */
245 if (klass->name_space && *klass->name_space)
246 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
248 full_name = g_strdup (klass->name);
250 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
253 mono_raise_exception (exc_to_throw);
257 default_trampoline (MonoMethod *method)
263 default_remoting_trampoline (MonoMethod *method)
265 g_error ("remoting not installed");
269 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
270 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
273 mono_install_trampoline (MonoTrampoline func)
275 arch_create_jit_trampoline = func? func: default_trampoline;
279 mono_install_remoting_trampoline (MonoTrampoline func)
281 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
284 static MonoCompileFunc default_mono_compile_method = NULL;
287 mono_install_compile_method (MonoCompileFunc func)
289 default_mono_compile_method = func;
293 mono_compile_method (MonoMethod *method)
295 if (!default_mono_compile_method) {
296 g_error ("compile method called on uninitialized runtime");
299 return default_mono_compile_method (method);
302 static MonoFreeMethodFunc default_mono_free_method = NULL;
305 mono_install_free_method (MonoFreeMethodFunc func)
307 default_mono_free_method = func;
311 mono_runtime_free_method (MonoMethod *method)
313 if (default_mono_free_method != NULL)
314 default_mono_free_method (method);
317 * FIXME: This causes crashes because the types inside signatures and
320 /* mono_free_method (method); */
323 #if 0 && HAVE_BOEHM_GC
325 vtable_finalizer (void *obj, void *data) {
326 g_print ("%s finalized (%p)\n", (char*)data, obj);
332 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
335 * The vtables in the root appdomain are assumed to be reachable by other
336 * roots, and we don't use typed allocation in the other domains.
339 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
342 mono_class_compute_gc_descriptor (MonoClass *class)
344 MonoClassField *field;
348 static gboolean gcj_inited = FALSE;
353 GC_init_gcj_malloc (5, NULL);
355 mono_register_jit_icall (mono_object_new_fast, "mono_object_new_fast", mono_create_icall_signature ("object ptr"), FALSE);
357 #ifdef GC_REDIRECT_TO_LOCAL
358 mono_register_jit_icall (GC_local_gcj_malloc, "GC_local_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
359 mono_register_jit_icall (GC_local_gcj_fast_malloc, "GC_local_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
361 mono_register_jit_icall (GC_gcj_malloc, "GC_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
362 mono_register_jit_icall (GC_gcj_fast_malloc, "GC_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
366 mono_class_init (class);
368 if (class->gc_descr_inited)
371 class->gc_descr_inited = TRUE;
372 class->gc_descr = GC_NO_DESCRIPTOR;
374 if (class == mono_defaults.string_class) {
375 bitmap = GC_HEADER_BITMAP;
376 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
378 else if (class->rank) {
379 mono_class_compute_gc_descriptor (class->element_class);
381 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
382 bitmap = GC_HEADER_BITMAP;
384 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
385 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
389 static int count = 0;
393 /* GC 6.1 has trouble handling 64 bit descriptors... */
394 if ((class->instance_size / sizeof (gpointer)) > 30) {
395 /* printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer)); */
399 bitmap = GC_HEADER_BITMAP;
403 /* if (count > 442) */
406 /* printf("KLASS: %s.\n", class->name); */
408 for (p = class; p != NULL; p = p->parent) {
409 for (i = 0; i < p->field.count; ++i) {
410 field = &p->fields [i];
411 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
413 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
416 pos = field->offset / sizeof (gpointer);
418 if (field->type->byref)
421 switch (field->type->type) {
422 case MONO_TYPE_BOOLEAN:
434 /* printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap); */
437 case MONO_TYPE_STRING:
438 case MONO_TYPE_SZARRAY:
439 case MONO_TYPE_CLASS:
440 case MONO_TYPE_OBJECT:
441 case MONO_TYPE_ARRAY:
443 g_assert ((field->offset % sizeof(gpointer)) == 0);
445 bitmap |= ((guint64)1) << pos;
446 /* printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap); */
448 case MONO_TYPE_VALUETYPE: {
449 MonoClass *fclass = field->type->data.klass;
450 if (!fclass->enumtype) {
451 mono_class_compute_gc_descriptor (fclass);
452 bitmap |= (fclass->gc_bitmap >> (sizeof (MonoObject) / sizeof (gpointer))) << pos;
462 /* printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap); */
463 class->gc_bitmap = bitmap;
464 /* Convert to the format expected by GC_make_descriptor */
465 bm [0] = (guint32)bitmap;
466 bm [1] = (guint32)(bitmap >> 32);
467 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bm, class->instance_size / sizeof (gpointer));
470 #endif /* CREATION_SPEEDUP */
473 * field_is_special_static:
475 * Returns SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
476 * SPECIAL_STATIC_NONE otherwise.
479 field_is_special_static (MonoClass *fklass, MonoClassField *field)
481 MonoCustomAttrInfo *ainfo;
483 ainfo = mono_custom_attrs_from_field (fklass, field);
486 for (i = 0; i < ainfo->num_attrs; ++i) {
487 MonoClass *klass = ainfo->attrs [i].ctor->klass;
488 if (klass->image == mono_defaults.corlib) {
489 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
490 mono_custom_attrs_free (ainfo);
491 return SPECIAL_STATIC_THREAD;
493 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
494 mono_custom_attrs_free (ainfo);
495 return SPECIAL_STATIC_CONTEXT;
499 mono_custom_attrs_free (ainfo);
500 return SPECIAL_STATIC_NONE;
505 * @domain: the application domain
506 * @class: the class to initialize
508 * VTables are domain specific because we create domain specific code, and
509 * they contain the domain specific static class data.
512 mono_class_vtable (MonoDomain *domain, MonoClass *class)
514 MonoVTable *vt = NULL;
515 MonoClassField *field;
520 guint32 constant_cols [MONO_CONSTANT_SIZE];
524 vt = class->cached_vtable;
525 if (vt && vt->domain == domain)
528 mono_domain_lock (domain);
529 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
530 mono_domain_unlock (domain);
535 mono_class_init (class);
537 mono_stats.used_class_count++;
538 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
540 vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
542 vt = mono_mempool_alloc0 (domain->mp, vtable_size);
548 mono_class_compute_gc_descriptor (class);
549 if (domain != mono_get_root_domain ())
551 * We can't use typed allocation in the non-root domains, since the
552 * collector needs the GC descriptor stored in the vtable even after
553 * the mempool containing the vtable is destroyed when the domain is
554 * unloaded. An alternative might be to allocate vtables in the GC
555 * heap, but this does not seem to work (it leads to crashes inside
556 * libgc). If that approach is tried, two gc descriptors need to be
557 * allocated for each class: one for the root domain, and one for all
558 * other domains. The second descriptor should contain a bit for the
559 * vtable field in MonoObject, since we can no longer assume the
560 * vtable is reachable by other roots after the appdomain is unloaded.
562 vt->gc_descr = GC_NO_DESCRIPTOR;
564 vt->gc_descr = class->gc_descr;
567 if (class->class_size) {
569 vt->data = GC_MALLOC (class->class_size + 8);
570 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
571 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
572 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
574 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
577 mono_stats.class_static_data_size += class->class_size + 8;
581 for (i = class->field.first; i < class->field.last; ++i) {
582 field = &class->fields [i - class->field.first];
583 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
585 if (mono_field_is_deleted (field))
587 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
588 gint32 special_static = field_is_special_static (class, field);
589 if (special_static != SPECIAL_STATIC_NONE) {
590 guint32 size, align, offset;
591 size = mono_type_size (field->type, &align);
592 offset = mono_alloc_special_static_data (special_static, size, align);
593 if (!domain->special_static_fields)
594 domain->special_static_fields = g_hash_table_new (NULL, NULL);
595 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
599 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
600 MonoClass *fklass = mono_class_from_mono_type (field->type);
601 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT));
602 t = (char*)vt->data + field->offset;
603 if (fklass->valuetype) {
604 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
606 /* it's a pointer type: add check */
607 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
608 *t = *(char *)field->data;
612 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
617 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1), cindex + 1);
619 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
621 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
622 field->def_type = constant_cols [MONO_CONSTANT_TYPE];
623 field->data = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
626 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL))
627 get_default_field_value (domain, field, (char*)vt->data + field->offset);
630 vt->max_interface_id = class->max_interface_id;
632 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
633 sizeof (gpointer) * (class->max_interface_id + 1));
635 /* initialize interface offsets */
636 for (i = 0; i <= class->max_interface_id; ++i) {
637 int slot = class->interface_offsets [i];
639 vt->interface_offsets [i] = &(vt->vtable [slot]);
643 * arch_create_jit_trampoline () can recursively call this function again
644 * because it compiles icall methods right away.
646 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
647 if (!class->cached_vtable)
648 class->cached_vtable = vt;
650 /* initialize vtable */
651 for (i = 0; i < class->vtable_size; ++i) {
654 if ((cm = class->vtable [i]))
655 vt->vtable [i] = arch_create_jit_trampoline (cm);
658 mono_domain_unlock (domain);
660 /* make sure the the parent is initialized */
662 mono_class_vtable (domain, class->parent);
664 vt->type = mono_type_get_object (domain, &class->byval_arg);
665 if (class->contextbound)
674 * mono_class_proxy_vtable:
675 * @domain: the application domain
676 * @remove_class: the remote class
678 * Creates a vtable for transparent proxies. It is basically
679 * a copy of the real vtable of the class wrapped in @remote_class,
680 * but all function pointers invoke the remoting functions, and
681 * vtable->klass points to the transparent proxy class, and not to @class.
684 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class)
686 MonoVTable *vt, *pvt;
687 int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
689 MonoClass *class = remote_class->proxy_class;
691 vt = mono_class_vtable (domain, class);
692 max_interface_id = vt->max_interface_id;
694 /* Calculate vtable space for extra interfaces */
695 for (j = 0; j < remote_class->interface_count; j++) {
696 MonoClass* iclass = remote_class->interfaces[j];
697 int method_count = iclass->method.count;
699 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
700 continue; /* interface implemented by the class */
702 for (i = 0; i < iclass->interface_count; i++)
703 method_count += iclass->interfaces[i]->method.count;
705 extra_interface_vtsize += method_count * sizeof (gpointer);
706 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
709 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
711 mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
713 pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
714 memcpy (pvt, vt, vtsize);
716 pvt->klass = mono_defaults.transparent_proxy_class;
718 /* initialize vtable */
719 for (i = 0; i < class->vtable_size; ++i) {
722 if ((cm = class->vtable [i]))
723 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
726 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
728 /* create trampolines for abstract methods */
729 for (k = class; k; k = k->parent) {
730 for (i = 0; i < k->method.count; i++) {
731 int slot = k->methods [i]->slot;
732 if (!pvt->vtable [slot])
733 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
738 pvt->max_interface_id = max_interface_id;
739 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
740 sizeof (gpointer) * (max_interface_id + 1));
742 /* initialize interface offsets */
743 for (i = 0; i <= class->max_interface_id; ++i) {
744 int slot = class->interface_offsets [i];
746 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
749 if (remote_class->interface_count > 0)
751 int slot = class->vtable_size;
756 /* Create trampolines for the methods of the interfaces */
757 for (n = 0; n < remote_class->interface_count; n++)
759 iclass = remote_class->interfaces[n];
760 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
761 continue; /* interface implemented by the class */
766 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
768 for (j = 0; j < interf->method.count; ++j) {
769 MonoMethod *cm = interf->methods [j];
770 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
772 slot += interf->method.count;
773 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
785 * @domain: the application domain
786 * @class_name: name of the remote class
788 * Creates and initializes a MonoRemoteClass object for a remote type.
792 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
796 mono_domain_lock (domain);
797 rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class_name);
800 mono_domain_unlock (domain);
804 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
806 rc->interface_count = 0;
807 rc->interfaces = NULL;
808 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
809 rc->proxy_class_name = mono_string_to_utf8 (class_name);
811 mono_g_hash_table_insert (domain->proxy_vtable_hash, class_name, rc);
812 mono_upgrade_remote_class (domain, rc, proxy_class);
814 if (rc->vtable == NULL)
815 rc->vtable = mono_class_proxy_vtable (domain, rc);
817 mono_domain_unlock (domain);
823 extend_interface_array (MonoDomain *domain, MonoRemoteClass *remote_class, int amount)
825 /* Extends the array of interfaces. Memory is extended using blocks of 5 pointers */
827 int current_size = ((remote_class->interface_count / 5) + 1) * 5;
828 remote_class->interface_count += amount;
830 if (remote_class->interface_count > current_size || remote_class->interfaces == NULL)
832 int new_size = ((remote_class->interface_count / 5) + 1) * 5;
833 MonoClass **new_array = mono_mempool_alloc (domain->mp, new_size * sizeof (MonoClass*));
835 if (remote_class->interfaces != NULL)
836 memcpy (new_array, remote_class->interfaces, current_size * sizeof (MonoClass*));
838 remote_class->interfaces = new_array;
844 * mono_upgrade_remote_class:
845 * @domain: the application domain
846 * @remote_class: the remote class
847 * @klass: class to which the remote class can be casted.
849 * Updates the vtable of the remote class by adding the necessary method slots
850 * and interface offsets so it can be safely casted to klass. klass can be a
851 * class or an interface.
853 void mono_upgrade_remote_class (MonoDomain *domain, MonoRemoteClass *remote_class, MonoClass *klass)
855 gboolean redo_vtable;
857 mono_domain_lock (domain);
859 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
862 for (i = 0; i < remote_class->interface_count; i++)
863 if (remote_class->interfaces[i] == klass) redo_vtable = FALSE;
866 extend_interface_array (domain, remote_class, 1);
867 remote_class->interfaces [remote_class->interface_count-1] = klass;
871 redo_vtable = (remote_class->proxy_class != klass);
872 remote_class->proxy_class = klass;
876 remote_class->vtable = mono_class_proxy_vtable (domain, remote_class);
879 printf ("remote class upgrade - class:%s num-interfaces:%d\n", remote_class->proxy_class_name, remote_class->interface_count);
881 for (n=0; n<remote_class->interface_count; n++)
882 printf (" I:%s\n", remote_class->interfaces[n]->name);
885 mono_domain_unlock (domain);
889 * mono_object_get_virtual_method:
891 * Retrieve the MonoMethod that would be called on obj if obj is passed as
892 * the instance of a callvirt of method.
895 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
899 MonoMethod *res = NULL;
901 klass = mono_object_class (obj);
902 if (klass == mono_defaults.transparent_proxy_class) {
903 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
909 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
912 vtable = klass->vtable;
914 /* check method->slot is a valid index: perform isinstance? */
915 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
917 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
919 if (method->slot != -1)
920 res = vtable [method->slot];
924 if (!res) res = method; /* It may be an interface or abstract class method */
925 res = mono_marshal_get_remoting_invoke (res);
934 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
936 g_error ("runtime invoke called on uninitialized runtime");
940 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
943 * mono_runtime_invoke:
945 * Invokes the method represented by `method' on the object `obj'.
947 * obj is the 'this' pointer, it should be NULL for static
948 * methods, a MonoObject* for object instances and a pointer to
949 * the value type for value types.
951 * The params array contains the arguments to the method with the
952 * same convention: MonoObject* pointers for object instances and
953 * pointers to the value type otherwise.
955 * From unmanaged code you'll usually use the
956 * mono_runtime_invoke() variant.
958 * Note that this function doesn't handle virtual methods for
959 * you, it will exec the exact method you pass: we still need to
960 * expose a function to lookup the derived class implementation
961 * of a virtual method (there are examples of this in the code,
964 * You can pass NULL as the exc argument if you don't want to
965 * catch exceptions, otherwise, *exc will be set to the exception
966 * thrown, if any. if an exception is thrown, you can't use the
967 * MonoObject* result from the function.
969 * If the method returns a value type, it is boxed in an object
973 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
975 return default_mono_runtime_invoke (method, obj, params, exc);
979 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
982 gpointer *p = (gpointer*)dest;
989 case MONO_TYPE_BOOLEAN:
992 guint8 *p = (guint8*)dest;
993 *p = *(guint8*)value;
998 case MONO_TYPE_CHAR: {
999 guint16 *p = (guint16*)dest;
1000 *p = *(guint16*)value;
1003 #if SIZEOF_VOID_P == 4
1008 case MONO_TYPE_U4: {
1009 gint32 *p = (gint32*)dest;
1010 *p = *(gint32*)value;
1013 #if SIZEOF_VOID_P == 8
1018 case MONO_TYPE_U8: {
1019 gint64 *p = (gint64*)dest;
1020 *p = *(gint64*)value;
1023 case MONO_TYPE_R4: {
1024 float *p = (float*)dest;
1025 *p = *(float*)value;
1028 case MONO_TYPE_R8: {
1029 double *p = (double*)dest;
1030 *p = *(double*)value;
1033 case MONO_TYPE_STRING:
1034 case MONO_TYPE_SZARRAY:
1035 case MONO_TYPE_CLASS:
1036 case MONO_TYPE_OBJECT:
1037 case MONO_TYPE_ARRAY:
1038 case MONO_TYPE_PTR: {
1039 gpointer *p = (gpointer*)dest;
1040 *p = deref_pointer? *(gpointer*)value: value;
1043 case MONO_TYPE_VALUETYPE:
1044 if (type->data.klass->enumtype) {
1045 t = type->data.klass->enum_basetype->type;
1049 size = mono_class_value_size (type->data.klass, NULL);
1050 memcpy (dest, value, size);
1054 g_warning ("got type %x", type->type);
1055 g_assert_not_reached ();
1060 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
1064 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1066 dest = (char*)obj + field->offset;
1067 set_value (field->type, dest, value, FALSE);
1071 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
1075 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1076 /* you cant set a constant! */
1077 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
1079 dest = (char*)vt->data + field->offset;
1080 set_value (field->type, dest, value, FALSE);
1084 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
1088 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1090 src = (char*)obj + field->offset;
1091 set_value (field->type, value, src, TRUE);
1095 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
1099 MonoVTable *vtable = NULL;
1101 gboolean is_static = FALSE;
1102 gboolean is_ref = FALSE;
1104 switch (field->type->type) {
1105 case MONO_TYPE_STRING:
1106 case MONO_TYPE_OBJECT:
1107 case MONO_TYPE_CLASS:
1108 case MONO_TYPE_ARRAY:
1109 case MONO_TYPE_SZARRAY:
1114 case MONO_TYPE_BOOLEAN:
1117 case MONO_TYPE_CHAR:
1126 case MONO_TYPE_VALUETYPE:
1127 is_ref = field->type->byref;
1130 g_error ("type 0x%x not handled in "
1131 "mono_field_get_value_object", field->type->type);
1135 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1137 vtable = mono_class_vtable (domain, field->parent);
1138 if (!vtable->initialized)
1139 mono_runtime_class_init (vtable);
1144 mono_field_static_get_value (vtable, field, &o);
1146 mono_field_get_value (obj, field, &o);
1151 /* boxed value type */
1152 klass = mono_class_from_mono_type (field->type);
1153 o = mono_object_new (domain, klass);
1154 v = ((gchar *) o) + sizeof (MonoObject);
1156 mono_field_static_get_value (vtable, field, v);
1158 mono_field_get_value (obj, field, v);
1165 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
1167 const char *p = field->data;
1168 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
1170 mono_metadata_decode_blob_size (p, &p);
1172 switch (field->def_type) {
1173 case MONO_TYPE_BOOLEAN:
1176 *(guint8 *) value = *p;
1178 case MONO_TYPE_CHAR:
1181 *(guint16*) value = read16 (p);
1185 *(guint32*) value = read32 (p);
1189 *(guint64*) value = read64 (p);
1192 readr4 (p, (float*) value);
1195 readr8 (p, (double*) value);
1197 case MONO_TYPE_STRING:
1198 *(gpointer*) value = mono_ldstr_metdata_sig (domain, field->data);
1200 case MONO_TYPE_CLASS:
1201 *(gpointer*) value = NULL;
1204 g_warning ("type 0x%02x should not be in constant table", field->def_type);
1209 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1213 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1215 if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
1216 get_default_field_value (vt->domain, field, value);
1220 src = (char*)vt->data + field->offset;
1221 set_value (field->type, value, src, TRUE);
1225 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1227 default_mono_runtime_invoke (prop->set, obj, params, exc);
1231 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1233 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1238 mono_get_delegate_invoke (MonoClass *klass)
1245 for (i = 0; i < klass->method.count; ++i) {
1246 if (klass->methods [i]->name[0] == 'I' &&
1247 !strcmp ("Invoke", klass->methods [i]->name)) {
1248 im = klass->methods [i];
1258 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1262 im = mono_get_delegate_invoke (delegate->vtable->klass);
1265 return mono_runtime_invoke (im, delegate, params, exc);
1268 static MonoArray* main_args;
1271 mono_runtime_get_main_args (void)
1277 fire_process_exit_event (void)
1279 MonoClassField *field;
1280 MonoDomain *domain = mono_domain_get ();
1282 MonoObject *delegate, *exc;
1284 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1287 if (domain != mono_get_root_domain ())
1290 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1291 if (delegate == NULL)
1296 mono_runtime_delegate_invoke (delegate, pa, &exc);
1300 * Execute a standard Main() method (argc/argv contains the
1301 * executable name). This method also sets the command line argument value
1302 * needed by System.Environment.
1305 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1309 MonoArray *args = NULL;
1310 MonoDomain *domain = mono_domain_get ();
1311 gchar *utf8_fullpath;
1314 main_thread = mono_thread_current ();
1316 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1318 if (!g_path_is_absolute (argv [0])) {
1319 gchar *basename = g_path_get_basename (argv [0]);
1320 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1324 utf8_fullpath = mono_utf8_from_external (fullpath);
1325 if(utf8_fullpath == NULL) {
1326 /* Printing the arg text will cause glib to
1327 * whinge about "Invalid UTF-8", but at least
1328 * its relevant, and shows the problem text
1331 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1332 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1339 utf8_fullpath = mono_utf8_from_external (argv[0]);
1340 if(utf8_fullpath == NULL) {
1341 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1342 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1347 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1348 g_free (utf8_fullpath);
1350 for (i = 1; i < argc; ++i) {
1354 utf8_arg=mono_utf8_from_external (argv[i]);
1355 if(utf8_arg==NULL) {
1356 /* Ditto the comment about Invalid UTF-8 here */
1357 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1358 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1362 arg = mono_string_new (domain, utf8_arg);
1363 mono_array_set (main_args, gpointer, i, arg);
1367 if (method->signature->param_count) {
1368 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1369 for (i = 0; i < argc; ++i) {
1370 /* The encodings should all work, given that
1371 * we've checked all these args for the
1374 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1375 mono_array_set (args, gpointer, i, arg);
1378 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1381 mono_assembly_set_main (method->klass->image->assembly);
1383 result = mono_runtime_exec_main (method, args, exc);
1384 fire_process_exit_event ();
1388 /* Used in mono_unhandled_exception */
1390 create_unhandled_exception_eventargs (MonoObject *exc)
1394 MonoMethod *method = NULL;
1395 MonoBoolean is_terminating = TRUE;
1399 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1402 mono_class_init (klass);
1404 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1405 for (i = 0; i < klass->method.count; ++i) {
1406 method = klass->methods [i];
1407 if (!strcmp (".ctor", method->name) &&
1408 method->signature->param_count == 2 &&
1409 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1417 args [1] = &is_terminating;
1419 obj = mono_object_new (mono_domain_get (), klass);
1420 mono_runtime_invoke (method, obj, args, NULL);
1426 * We call this function when we detect an unhandled exception
1427 * in the default domain.
1428 * It invokes the * UnhandledException event in AppDomain or prints
1429 * a warning to the console
1432 mono_unhandled_exception (MonoObject *exc)
1434 MonoDomain *domain = mono_domain_get ();
1435 MonoClassField *field;
1436 MonoObject *delegate;
1438 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1439 "UnhandledException");
1442 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1443 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1445 /* set exitcode only in the main thread */
1446 if (mono_thread_current () == main_thread)
1447 mono_environment_exitcode_set (1);
1448 if (domain != mono_get_root_domain () || !delegate) {
1449 mono_print_unhandled_exception (exc);
1451 MonoObject *e = NULL;
1454 pa [0] = domain->domain;
1455 pa [1] = create_unhandled_exception_eventargs (exc);
1456 mono_runtime_delegate_invoke (delegate, pa, &e);
1459 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1460 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1468 * Launch a new thread to start all setup that requires managed code
1471 * main_func is called back from the thread with main_args as the
1472 * parameter. The callback function is expected to start Main()
1473 * eventually. This function then waits for all managed threads to
1477 mono_runtime_exec_managed_code (MonoDomain *domain,
1478 MonoMainThreadFunc main_func,
1481 mono_thread_create (domain, main_func, main_args);
1483 mono_thread_manage ();
1487 * Execute a standard Main() method (args doesn't contain the
1491 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1501 domain = mono_object_domain (args);
1502 if (!domain->entry_assembly) {
1504 gchar *config_suffix;
1505 MonoAssembly *assembly;
1507 assembly = method->klass->image->assembly;
1508 domain->entry_assembly = assembly;
1509 domain->setup->application_base = mono_string_new (domain, assembly->basedir);
1511 config_suffix = g_strconcat (assembly->aname.name, ".exe.config", NULL);
1512 str = g_build_filename (assembly->basedir, config_suffix, NULL);
1513 g_free (config_suffix);
1514 domain->setup->configuration_file = mono_string_new (domain, str);
1518 /* FIXME: check signature of method */
1519 if (method->signature->ret->type == MONO_TYPE_I4) {
1521 res = mono_runtime_invoke (method, NULL, pa, exc);
1523 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1527 mono_environment_exitcode_set (rval);
1529 mono_runtime_invoke (method, NULL, pa, exc);
1533 /* If the return type of Main is void, only
1534 * set the exitcode if an exception was thrown
1535 * (we don't want to blow away an
1536 * explicitly-set exit code)
1539 mono_environment_exitcode_set (rval);
1547 mono_install_runtime_invoke (MonoInvokeFunc func)
1549 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1553 * mono_runtime_invoke:
1555 * Invokes the method represented by `method' on the object `obj'.
1557 * obj is the 'this' pointer, it should be NULL for static
1558 * methods, a MonoObject* for object instances and a pointer to
1559 * the value type for value types.
1561 * The params array contains the arguments to the method with the
1562 * same convention: MonoObject* pointers for object instances and
1563 * pointers to the value type otherwise. The _invoke_array
1564 * variant takes a C# object[] as the params argument (MonoArray
1565 * *params): in this case the value types are boxed inside the
1566 * respective reference representation.
1568 * From unmanaged code you'll usually use the
1569 * mono_runtime_invoke() variant.
1571 * Note that this function doesn't handle virtual methods for
1572 * you, it will exec the exact method you pass: we still need to
1573 * expose a function to lookup the derived class implementation
1574 * of a virtual method (there are examples of this in the code,
1577 * You can pass NULL as the exc argument if you don't want to
1578 * catch exceptions, otherwise, *exc will be set to the exception
1579 * thrown, if any. if an exception is thrown, you can't use the
1580 * MonoObject* result from the function.
1582 * If the method returns a value type, it is boxed in an object
1586 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1589 MonoMethodSignature *sig = method->signature;
1590 gpointer *pa = NULL;
1593 if (NULL != params) {
1594 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1595 for (i = 0; i < mono_array_length (params); i++) {
1596 if (sig->params [i]->byref) {
1600 switch (sig->params [i]->type) {
1603 case MONO_TYPE_BOOLEAN:
1606 case MONO_TYPE_CHAR:
1615 case MONO_TYPE_VALUETYPE:
1616 /* MS seems to create the objects if a null is passed in */
1617 if (! ((gpointer *)params->vector)[i])
1618 ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
1619 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1621 case MONO_TYPE_STRING:
1622 case MONO_TYPE_OBJECT:
1623 case MONO_TYPE_CLASS:
1624 case MONO_TYPE_ARRAY:
1625 case MONO_TYPE_SZARRAY:
1626 if (sig->params [i]->byref)
1627 pa [i] = &(((gpointer *)params->vector)[i]);
1629 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1632 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1637 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1640 obj = mono_object_new (mono_domain_get (), method->klass);
1641 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1642 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
1644 if (method->klass->valuetype)
1645 o = mono_object_unbox (obj);
1649 mono_runtime_invoke (method, o, pa, exc);
1652 /* obj must be already unboxed if needed */
1653 return mono_runtime_invoke (method, obj, pa, exc);
1658 arith_overflow (void)
1660 mono_raise_exception (mono_get_exception_overflow ());
1664 * mono_object_allocate:
1665 * @size: number of bytes to allocate
1667 * This is a very simplistic routine until we have our GC-aware
1670 * Returns: an allocated object of size @size, or NULL on failure.
1672 static inline void *
1673 mono_object_allocate (size_t size)
1676 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1677 void *o = GC_MALLOC (size);
1679 void *o = calloc (1, size);
1681 return mono_gc_out_of_memory (size);
1683 mono_stats.new_object_count++;
1688 #if CREATION_SPEEDUP
1689 static inline void *
1690 mono_object_allocate_spec (size_t size, void *gcdescr)
1692 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1693 void *o = GC_GCJ_MALLOC (size, gcdescr);
1694 mono_stats.new_object_count++;
1702 * @klass: the class of the object that we want to create
1704 * Returns a newly created object whose definition is
1705 * looked up using @klass. This will not invoke any constructors,
1706 * so the consumer of this routine has to invoke any constructors on
1707 * its own to initialize the object.
1710 mono_object_new (MonoDomain *domain, MonoClass *klass)
1712 MONO_ARCH_SAVE_REGS;
1713 return mono_object_new_specific (mono_class_vtable (domain, klass));
1717 * mono_object_new_specific:
1718 * @vtable: the vtable of the object that we want to create
1720 * Returns: A newly created object with class and domain specified
1724 mono_object_new_specific (MonoVTable *vtable)
1728 MONO_ARCH_SAVE_REGS;
1733 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1736 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1740 mono_class_init (klass);
1742 for (i = 0; i < klass->method.count; ++i) {
1743 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1744 klass->methods [i]->signature->param_count == 1) {
1745 im = klass->methods [i];
1750 vtable->domain->create_proxy_for_type_method = im;
1753 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1755 o = mono_runtime_invoke (im, NULL, pa, NULL);
1756 if (o != NULL) return o;
1759 return mono_object_new_alloc_specific (vtable);
1763 mono_object_new_alloc_specific (MonoVTable *vtable)
1767 #if CREATION_SPEEDUP
1768 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1769 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1771 /* printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
1772 o = mono_object_allocate (vtable->klass->instance_size);
1776 o = mono_object_allocate (vtable->klass->instance_size);
1779 if (vtable->klass->has_finalize)
1780 mono_object_register_finalizer (o);
1782 mono_profiler_allocation (o, vtable->klass);
1786 #if CREATION_SPEEDUP
1789 mono_object_new_fast (MonoVTable *vtable)
1791 return GC_GCJ_MALLOC (vtable->klass->instance_size, vtable);
1797 * Return the allocation function appropriate for the given class.
1801 mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean *pass_size_in_words)
1803 *pass_size_in_words = FALSE;
1805 if (vtable->klass->has_finalize || vtable->klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
1806 return mono_object_new_specific;
1808 #if CREATION_SPEEDUP
1809 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1811 return mono_object_new_fast;
1814 * FIXME: This is actually slower than mono_object_new_fast, because
1815 * of the overhead of parameter passing.
1818 *pass_size_in_words = TRUE;
1819 #ifdef GC_REDIRECT_TO_LOCAL
1820 return GC_local_gcj_fast_malloc;
1822 return GC_gcj_fast_malloc;
1828 return mono_object_new_specific;
1832 * mono_object_new_from_token:
1833 * @image: Context where the type_token is hosted
1834 * @token: a token of the type that we want to create
1836 * Returns: A newly created object whose definition is
1837 * looked up using @token in the @image image
1840 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1844 class = mono_class_get (image, token);
1846 return mono_object_new (domain, class);
1851 * mono_object_clone:
1852 * @obj: the object to clone
1854 * Returns: A newly created object who is a shallow copy of @obj
1857 mono_object_clone (MonoObject *obj)
1862 size = obj->vtable->klass->instance_size;
1863 o = mono_object_allocate (size);
1864 mono_profiler_allocation (o, obj->vtable->klass);
1866 memcpy (o, obj, size);
1868 if (obj->vtable->klass->has_finalize)
1869 mono_object_register_finalizer (o);
1875 * @array: the array to clone
1877 * Returns: A newly created array who is a shallow copy of @array
1880 mono_array_clone (MonoArray *array)
1885 MonoClass *klass = array->obj.vtable->klass;
1887 MONO_ARCH_SAVE_REGS;
1889 if (array->bounds == NULL) {
1890 size = mono_array_length (array);
1891 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1892 klass, &size, NULL);
1894 size *= mono_array_element_size (klass);
1895 memcpy (o, array, sizeof (MonoArray) + size);
1900 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1901 size = mono_array_element_size (klass);
1902 for (i = 0; i < klass->rank; ++i) {
1903 sizes [i] = array->bounds [i].length;
1904 size *= array->bounds [i].length;
1905 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1907 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1908 klass, sizes, sizes + klass->rank);
1909 memcpy (o, array, sizeof(MonoArray) + size);
1914 /* helper macros to check for overflow when calculating the size of arrays */
1915 #define MYGUINT32_MAX 4294967295U
1916 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1917 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1918 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1919 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1920 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1923 * mono_array_new_full:
1924 * @domain: domain where the object is created
1925 * @array_class: array class
1926 * @lengths: lengths for each dimension in the array
1927 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1929 * This routine creates a new array objects with the given dimensions,
1930 * lower bounds and type.
1933 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1934 guint32 *lengths, guint32 *lower_bounds)
1936 guint32 byte_len, len;
1939 MonoArrayBounds *bounds;
1943 if (!array_class->inited)
1944 mono_class_init (array_class);
1946 byte_len = mono_array_element_size (array_class);
1949 if (array_class->rank == 1 &&
1950 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1957 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1959 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1961 for (i = 0; i < array_class->rank; ++i)
1962 if ((int) lengths [i] < 0)
1965 for (i = 0; i < array_class->rank; ++i) {
1966 bounds [i].length = lengths [i];
1967 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1968 mono_gc_out_of_memory (MYGUINT32_MAX);
1973 for (i = 0; i < array_class->rank; ++i)
1974 bounds [i].lower_bound = lower_bounds [i];
1977 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1978 mono_gc_out_of_memory (MYGUINT32_MAX);
1980 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1981 mono_gc_out_of_memory (MYGUINT32_MAX);
1982 byte_len += sizeof (MonoArray);
1984 * Following three lines almost taken from mono_object_new ():
1985 * they need to be kept in sync.
1987 vtable = mono_class_vtable (domain, array_class);
1988 #if CREATION_SPEEDUP
1989 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1990 o = mono_object_allocate_spec (byte_len, vtable);
1992 o = mono_object_allocate (byte_len);
1996 o = mono_object_allocate (byte_len);
2000 array = (MonoArray*)o;
2002 array->bounds = bounds;
2003 array->max_length = len;
2005 mono_profiler_allocation (o, array_class);
2012 * @domain: domain where the object is created
2013 * @eclass: element class
2014 * @n: number of array elements
2016 * This routine creates a new szarray with @n elements of type @eclass.
2019 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
2023 MONO_ARCH_SAVE_REGS;
2025 ac = mono_array_class_get (eclass, 1);
2026 g_assert (ac != NULL);
2028 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
2032 * mono_array_new_specific:
2033 * @vtable: a vtable in the appropriate domain for an initialized class
2034 * @n: number of array elements
2036 * This routine is a fast alternative to mono_array_new() for code which
2037 * can be sure about the domain it operates in.
2040 mono_array_new_specific (MonoVTable *vtable, guint32 n)
2044 guint32 byte_len, elem_size;
2046 MONO_ARCH_SAVE_REGS;
2051 elem_size = mono_array_element_size (vtable->klass);
2052 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
2053 mono_gc_out_of_memory (MYGUINT32_MAX);
2054 byte_len = n * elem_size;
2055 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2056 mono_gc_out_of_memory (MYGUINT32_MAX);
2057 byte_len += sizeof (MonoArray);
2058 #if CREATION_SPEEDUP
2059 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2060 o = mono_object_allocate_spec (byte_len, vtable);
2062 /* printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2063 o = mono_object_allocate (byte_len);
2067 o = mono_object_allocate (byte_len);
2071 ao = (MonoArray *)o;
2074 mono_profiler_allocation (o, vtable->klass);
2080 * mono_string_new_utf16:
2081 * @text: a pointer to an utf16 string
2082 * @len: the length of the string
2084 * Returns: A newly created string object which contains @text.
2087 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
2091 s = mono_string_new_size (domain, len);
2092 g_assert (s != NULL);
2094 memcpy (mono_string_chars (s), text, len * 2);
2100 * mono_string_new_size:
2101 * @text: a pointer to an utf16 string
2102 * @len: the length of the string
2104 * Returns: A newly created string object of @len
2107 mono_string_new_size (MonoDomain *domain, gint32 len)
2111 size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2113 /* overflow ? can't fit it, can't allocate it! */
2115 mono_gc_out_of_memory (-1);
2117 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2119 #if CREATION_SPEEDUP
2120 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2121 s = mono_object_allocate_spec (size, vtable);
2123 s = (MonoString*)mono_object_allocate (size);
2124 s->object.vtable = vtable;
2127 s = (MonoString*)mono_object_allocate (size);
2128 s->object.vtable = vtable;
2132 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2138 * mono_string_new_len:
2139 * @text: a pointer to an utf8 string
2140 * @length: number of bytes in @text to consider
2142 * Returns: A newly created string object which contains @text.
2145 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2147 GError *error = NULL;
2148 MonoString *o = NULL;
2150 glong items_written;
2152 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2155 o = mono_string_new_utf16 (domain, ut, items_written);
2157 g_error_free (error);
2166 * @text: a pointer to an utf8 string
2168 * Returns: A newly created string object which contains @text.
2171 mono_string_new (MonoDomain *domain, const char *text)
2173 GError *error = NULL;
2174 MonoString *o = NULL;
2176 glong items_written;
2181 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2184 o = mono_string_new_utf16 (domain, ut, items_written);
2186 g_error_free (error);
2194 * mono_string_new_wrapper:
2195 * @text: pointer to utf8 characters.
2197 * Helper function to create a string object from @text in the current domain.
2200 mono_string_new_wrapper (const char *text)
2202 MonoDomain *domain = mono_domain_get ();
2204 MONO_ARCH_SAVE_REGS;
2207 return mono_string_new (domain, text);
2214 * @class: the class of the value
2215 * @value: a pointer to the unboxed data
2217 * Returns: A newly created object which contains @value.
2220 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2226 g_assert (class->valuetype);
2228 vtable = mono_class_vtable (domain, class);
2229 size = mono_class_instance_size (class);
2230 res = mono_object_allocate (size);
2231 res->vtable = vtable;
2232 mono_profiler_allocation (res, class);
2234 size = size - sizeof (MonoObject);
2236 #if NO_UNALIGNED_ACCESS
2237 memcpy ((char *)res + sizeof (MonoObject), value, size);
2241 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2244 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2247 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2250 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2253 memcpy ((char *)res + sizeof (MonoObject), value, size);
2256 if (class->has_finalize)
2257 mono_object_register_finalizer (res);
2262 mono_object_get_domain (MonoObject *obj)
2264 return mono_object_domain (obj);
2268 mono_object_get_class (MonoObject *obj)
2270 return mono_object_class (obj);
2274 mono_object_unbox (MonoObject *obj)
2276 /* add assert for valuetypes? */
2277 g_assert (obj->vtable->klass->valuetype);
2278 return ((char*)obj) + sizeof (MonoObject);
2282 * mono_object_isinst:
2284 * @klass: a pointer to a class
2286 * Returns: @obj if @obj is derived from @klass
2289 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2292 mono_class_init (klass);
2294 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2295 return mono_object_isinst_mbyref (obj, klass);
2300 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2304 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2313 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2314 if ((klass->interface_id <= vt->max_interface_id) &&
2315 (vt->interface_offsets [klass->interface_id] != 0))
2319 MonoClass *oklass = vt->klass;
2320 if ((oklass == mono_defaults.transparent_proxy_class))
2321 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2323 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2327 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2329 MonoDomain *domain = mono_domain_get ();
2331 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2332 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2333 MonoMethod *im = NULL;
2337 for (i = 0; i < rpklass->method.count; ++i) {
2338 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2339 im = rpklass->methods [i];
2344 im = mono_object_get_virtual_method (rp, im);
2347 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2350 res = mono_runtime_invoke (im, rp, pa, NULL);
2352 if (*(MonoBoolean *) mono_object_unbox(res)) {
2353 /* Update the vtable of the remote type, so it can safely cast to this new type */
2354 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2355 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2364 * mono_object_castclass_mbyref:
2366 * @klass: a pointer to a class
2368 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2371 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2373 if (!obj) return NULL;
2374 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2376 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2378 "InvalidCastException"));
2383 MonoDomain *orig_domain;
2389 str_lookup (MonoDomain *domain, gpointer user_data)
2391 LDStrInfo *info = user_data;
2392 if (info->res || domain == info->orig_domain)
2394 mono_domain_lock (domain);
2395 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2396 mono_domain_unlock (domain);
2400 mono_string_is_interned_lookup (MonoString *str, int insert)
2402 MonoGHashTable *ldstr_table;
2405 char *ins = g_malloc (4 + str->length * 2);
2408 /* Encode the length */
2409 /* Same code as in mono_image_insert_string () */
2411 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2414 * ins is stored in the hash table as a key and needs to have the same
2415 * representation as in the metadata: we swap the character bytes on big
2418 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2421 char *p2 = (char *)mono_string_chars (str);
2422 for (i = 0; i < str->length; ++i) {
2429 memcpy (p, mono_string_chars (str), str->length * 2);
2431 domain = ((MonoObject *)str)->vtable->domain;
2432 ldstr_table = domain->ldstr_table;
2433 mono_domain_lock (domain);
2434 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2435 mono_domain_unlock (domain);
2440 mono_g_hash_table_insert (ldstr_table, ins, str);
2441 mono_domain_unlock (domain);
2444 LDStrInfo ldstr_info;
2445 ldstr_info.orig_domain = domain;
2446 ldstr_info.ins = ins;
2447 ldstr_info.res = NULL;
2449 mono_domain_foreach (str_lookup, &ldstr_info);
2450 if (ldstr_info.res) {
2452 * the string was already interned in some other domain:
2453 * intern it in the current one as well.
2455 mono_g_hash_table_insert (ldstr_table, ins, str);
2456 mono_domain_unlock (domain);
2460 mono_domain_unlock (domain);
2466 mono_string_is_interned (MonoString *o)
2468 return mono_string_is_interned_lookup (o, FALSE);
2472 mono_string_intern (MonoString *str)
2474 return mono_string_is_interned_lookup (str, TRUE);
2479 * @domain: the domain where the string will be used.
2480 * @image: a metadata context
2481 * @idx: index into the user string table.
2483 * Implementation for the ldstr opcode.
2486 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2488 MONO_ARCH_SAVE_REGS;
2491 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2493 return mono_ldstr_metdata_sig (domain, mono_metadata_user_string (image, idx));
2497 * mono_ldstr_metdata_sig
2498 * @domain: the domain for the string
2499 * @sig: the signature of a metadata string
2501 * returns a MonoString for a string stored in the metadata
2504 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig)
2506 const char *str = sig;
2510 mono_domain_lock (domain);
2511 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2512 mono_domain_unlock (domain);
2516 len2 = mono_metadata_decode_blob_size (str, &str);
2519 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2520 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2523 guint16 *p2 = (guint16*)mono_string_chars (o);
2524 for (i = 0; i < len2; ++i) {
2525 *p2 = GUINT16_FROM_LE (*p2);
2530 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2531 mono_domain_unlock (domain);
2537 * mono_string_to_utf8:
2538 * @s: a System.String
2540 * Return the UTF8 representation for @s.
2541 * the resulting buffer nedds to be freed with g_free().
2544 mono_string_to_utf8 (MonoString *s)
2547 GError *error = NULL;
2553 return g_strdup ("");
2555 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2557 g_warning (error->message);
2558 g_error_free (error);
2565 * mono_string_to_utf16:
2568 * Return an null-terminated array of the utf-16 chars
2569 * contained in @s. The result must be freed with g_free().
2570 * This is a temporary helper until our string implementation
2571 * is reworked to always include the null terminating char.
2574 mono_string_to_utf16 (MonoString *s)
2581 as = g_malloc ((s->length * 2) + 2);
2582 as [(s->length * 2)] = '\0';
2583 as [(s->length * 2) + 1] = '\0';
2586 return (gunichar2 *)(as);
2589 memcpy (as, mono_string_chars(s), s->length * 2);
2590 return (gunichar2 *)(as);
2594 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2597 mono_string_from_utf16 (gunichar2 *data)
2599 MonoDomain *domain = mono_domain_get ();
2605 while (data [len]) len++;
2607 return mono_string_new_utf16 (domain, data, len);
2611 default_ex_handler (MonoException *ex)
2613 MonoObject *o = (MonoObject*)ex;
2614 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2618 static MonoExceptionFunc ex_handler = default_ex_handler;
2621 mono_install_handler (MonoExceptionFunc func)
2623 ex_handler = func? func: default_ex_handler;
2627 * mono_raise_exception:
2628 * @ex: exception object
2630 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2633 mono_raise_exception (MonoException *ex)
2636 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2637 * that will cause gcc to omit the function epilog, causing problems when
2638 * the JIT tries to walk the stack, since the return address on the stack
2639 * will point into the next function in the executable, not this one.
2646 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2648 MonoWaitHandle *res;
2650 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2652 res->handle = handle;
2658 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2660 MonoAsyncResult *res;
2662 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2665 res->async_state = state;
2667 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2669 res->sync_completed = FALSE;
2670 res->completed = FALSE;
2676 mono_message_init (MonoDomain *domain,
2677 MonoMethodMessage *this,
2678 MonoReflectionMethod *method,
2679 MonoArray *out_args)
2681 MonoMethodSignature *sig = method->method->signature;
2687 this->method = method;
2689 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2690 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2691 this->async_result = NULL;
2692 this->call_type = CallType_Sync;
2694 names = g_new (char *, sig->param_count);
2695 mono_method_get_param_names (method->method, (const char **) names);
2696 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2698 for (i = 0; i < sig->param_count; i++) {
2699 name = mono_string_new (domain, names [i]);
2700 mono_array_set (this->names, gpointer, i, name);
2704 for (i = 0, j = 0; i < sig->param_count; i++) {
2706 if (sig->params [i]->byref) {
2708 gpointer arg = mono_array_get (out_args, gpointer, j);
2709 mono_array_set (this->args, gpointer, i, arg);
2713 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2718 mono_array_set (this->arg_types, guint8, i, arg_type);
2723 * mono_remoting_invoke:
2724 * @real_proxy: pointer to a RealProxy object
2725 * @msg: The MonoMethodMessage to execute
2726 * @exc: used to store exceptions
2727 * @out_args: used to store output arguments
2729 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2730 * IMessage interface and it is not trivial to extract results from there. So
2731 * we call an helper method PrivateInvoke instead of calling
2732 * RealProxy::Invoke() directly.
2734 * Returns: the result object.
2737 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2738 MonoObject **exc, MonoArray **out_args)
2740 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2743 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2749 klass = mono_defaults.real_proxy_class;
2751 for (i = 0; i < klass->method.count; ++i) {
2752 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2753 klass->methods [i]->signature->param_count == 4) {
2754 im = klass->methods [i];
2760 real_proxy->vtable->domain->private_invoke_method = im;
2763 pa [0] = real_proxy;
2768 return mono_runtime_invoke (im, NULL, pa, exc);
2772 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2773 MonoObject **exc, MonoArray **out_args)
2777 MonoMethodSignature *sig;
2779 int i, j, outarg_count = 0;
2781 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2783 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2784 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2785 target = tp->rp->unwrapped_server;
2787 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2791 domain = mono_domain_get ();
2792 method = msg->method->method;
2793 sig = method->signature;
2795 for (i = 0; i < sig->param_count; i++) {
2796 if (sig->params [i]->byref)
2800 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2803 ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
2805 for (i = 0, j = 0; i < sig->param_count; i++) {
2806 if (sig->params [i]->byref) {
2808 arg = mono_array_get (msg->args, gpointer, i);
2809 mono_array_set (*out_args, gpointer, j, arg);
2818 mono_print_unhandled_exception (MonoObject *exc)
2820 char *message = (char *) "";
2824 gboolean free_message = FALSE;
2827 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2828 klass = exc->vtable->klass;
2830 while (klass && method == NULL) {
2831 for (i = 0; i < klass->method.count; ++i) {
2832 method = klass->methods [i];
2833 if (!strcmp ("ToString", method->name) &&
2834 method->signature->param_count == 0 &&
2835 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2836 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2843 klass = klass->parent;
2848 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2850 message = mono_string_to_utf8 (str);
2851 free_message = TRUE;
2856 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2857 * exc->vtable->klass->name, message);
2859 g_printerr ("\nUnhandled Exception: %s\n", message);
2866 * mono_delegate_ctor:
2867 * @this: pointer to an uninitialized delegate object
2868 * @target: target object
2869 * @addr: pointer to native code
2871 * This is used to initialize a delegate. We also insert the method_info if
2872 * we find the info with mono_jit_info_table_find().
2875 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2877 MonoDomain *domain = mono_domain_get ();
2878 MonoDelegate *delegate = (MonoDelegate *)this;
2879 MonoMethod *method = NULL;
2886 class = this->vtable->klass;
2888 if ((ji = mono_jit_info_table_find (domain, addr))) {
2889 method = ji->method;
2890 delegate->method_info = mono_method_get_object (domain, method, NULL);
2893 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2895 method = mono_marshal_get_remoting_invoke (method);
2896 delegate->method_ptr = mono_compile_method (method);
2897 delegate->target = target;
2899 delegate->method_ptr = addr;
2900 delegate->target = target;
2905 * mono_method_call_message_new:
2907 * Translates arguments pointers into a Message.
2910 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2911 MonoDelegate **cb, MonoObject **state)
2913 MonoDomain *domain = mono_domain_get ();
2914 MonoMethodSignature *sig = method->signature;
2915 MonoMethodMessage *msg;
2918 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2921 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2922 count = sig->param_count - 2;
2924 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2925 count = sig->param_count;
2928 for (i = 0; i < count; i++) {
2933 if (sig->params [i]->byref)
2934 vpos = *((gpointer *)params [i]);
2938 type = sig->params [i]->type;
2939 class = mono_class_from_mono_type (sig->params [i]);
2941 if (class->valuetype)
2942 arg = mono_value_box (domain, class, vpos);
2944 arg = *((MonoObject **)vpos);
2946 mono_array_set (msg->args, gpointer, i, arg);
2949 if (cb != NULL && state != NULL) {
2950 *cb = *((MonoDelegate **)params [i]);
2952 *state = *((MonoObject **)params [i]);
2959 * mono_method_return_message_restore:
2961 * Restore results from message based processing back to arguments pointers
2964 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2966 MonoMethodSignature *sig = method->signature;
2967 int i, j, type, size;
2968 for (i = 0, j = 0; i < sig->param_count; i++) {
2969 MonoType *pt = sig->params [i];
2972 char *arg = mono_array_get (out_args, gpointer, j);
2976 case MONO_TYPE_VOID:
2977 g_assert_not_reached ();
2981 case MONO_TYPE_BOOLEAN:
2984 case MONO_TYPE_CHAR:
2991 case MONO_TYPE_VALUETYPE: {
2992 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2993 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2996 case MONO_TYPE_STRING:
2997 case MONO_TYPE_CLASS:
2998 case MONO_TYPE_ARRAY:
2999 case MONO_TYPE_SZARRAY:
3000 case MONO_TYPE_OBJECT:
3001 **((MonoObject ***)params [i]) = (MonoObject *)arg;
3004 g_assert_not_reached ();
3013 * mono_load_remote_field:
3014 * @this: pointer to an object
3015 * @klass: klass of the object containing @field
3016 * @field: the field to load
3017 * @res: a storage to store the result
3019 * This method is called by the runtime on attempts to load fields of
3020 * transparent proxy objects. @this points to such TP, @klass is the class of
3021 * the object containing @field. @res is a storage location which can be
3022 * used to store the result.
3024 * Returns: an address pointing to the value of field.
3027 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
3029 static MonoMethod *getter = NULL;
3030 MonoDomain *domain = mono_domain_get ();
3031 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3032 MonoClass *field_class;
3033 MonoMethodMessage *msg;
3034 MonoArray *out_args;
3038 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3043 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3044 mono_field_get_value (tp->rp->unwrapped_server, field, res);
3051 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3052 MonoMethod *cm = mono_defaults.object_class->methods [i];
3054 if (!strcmp (cm->name, "FieldGetter")) {
3062 field_class = mono_class_from_mono_type (field->type);
3064 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3065 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3066 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3068 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3069 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3071 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3073 if (exc) mono_raise_exception ((MonoException *)exc);
3075 *res = mono_array_get (out_args, MonoObject *, 0);
3077 if (field_class->valuetype) {
3078 return ((char *)*res) + sizeof (MonoObject);
3084 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
3086 static MonoMethod *getter = NULL;
3087 MonoDomain *domain = mono_domain_get ();
3088 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3089 MonoClass *field_class;
3090 MonoMethodMessage *msg;
3091 MonoArray *out_args;
3092 MonoObject *exc, *res;
3094 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3096 field_class = mono_class_from_mono_type (field->type);
3098 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3100 if (field_class->valuetype) {
3101 res = mono_object_new (domain, field_class);
3102 val = ((gchar *) res) + sizeof (MonoObject);
3106 mono_field_get_value (tp->rp->unwrapped_server, field, val);
3113 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3114 MonoMethod *cm = mono_defaults.object_class->methods [i];
3116 if (!strcmp (cm->name, "FieldGetter")) {
3124 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3125 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3126 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3128 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3129 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3131 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3133 if (exc) mono_raise_exception ((MonoException *)exc);
3135 res = mono_array_get (out_args, MonoObject *, 0);
3141 * mono_store_remote_field:
3142 * @this: pointer to an object
3143 * @klass: klass of the object containing @field
3144 * @field: the field to load
3145 * @val: the value/object to store
3147 * This method is called by the runtime on attempts to store fields of
3148 * transparent proxy objects. @this points to such TP, @klass is the class of
3149 * the object containing @field. @val is the new value to store in @field.
3152 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3154 static MonoMethod *setter = NULL;
3155 MonoDomain *domain = mono_domain_get ();
3156 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3157 MonoClass *field_class;
3158 MonoMethodMessage *msg;
3159 MonoArray *out_args;
3163 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3165 field_class = mono_class_from_mono_type (field->type);
3167 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3168 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3169 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3176 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3177 MonoMethod *cm = mono_defaults.object_class->methods [i];
3179 if (!strcmp (cm->name, "FieldSetter")) {
3187 if (field_class->valuetype)
3188 arg = mono_value_box (domain, field_class, val);
3190 arg = *((MonoObject **)val);
3193 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3194 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3196 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3197 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3198 mono_array_set (msg->args, gpointer, 2, arg);
3200 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3202 if (exc) mono_raise_exception ((MonoException *)exc);
3206 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3208 static MonoMethod *setter = NULL;
3209 MonoDomain *domain = mono_domain_get ();
3210 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3211 MonoClass *field_class;
3212 MonoMethodMessage *msg;
3213 MonoArray *out_args;
3216 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3218 field_class = mono_class_from_mono_type (field->type);
3220 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3221 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3222 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3229 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3230 MonoMethod *cm = mono_defaults.object_class->methods [i];
3232 if (!strcmp (cm->name, "FieldSetter")) {
3240 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3241 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3243 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3244 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3245 mono_array_set (msg->args, gpointer, 2, arg);
3247 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3249 if (exc) mono_raise_exception ((MonoException *)exc);