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 mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, char *blob, void *value)
1168 const char *p = blob;
1169 mono_metadata_decode_blob_size (p, &p);
1172 case MONO_TYPE_BOOLEAN:
1175 *(guint8 *) value = *p;
1177 case MONO_TYPE_CHAR:
1180 *(guint16*) value = read16 (p);
1184 *(guint32*) value = read32 (p);
1188 *(guint64*) value = read64 (p);
1191 readr4 (p, (float*) value);
1194 readr8 (p, (double*) value);
1196 case MONO_TYPE_STRING:
1197 *(gpointer*) value = mono_ldstr_metdata_sig (domain, blob);
1199 case MONO_TYPE_CLASS:
1200 *(gpointer*) value = NULL;
1204 g_warning ("type 0x%02x should not be in constant table", type);
1210 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
1212 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
1213 mono_get_constant_value_from_blob (domain, field->def_type, field->data, value);
1218 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1222 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1224 if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
1225 get_default_field_value (vt->domain, field, value);
1229 src = (char*)vt->data + field->offset;
1230 set_value (field->type, value, src, TRUE);
1234 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1236 default_mono_runtime_invoke (prop->set, obj, params, exc);
1240 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1242 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1247 mono_get_delegate_invoke (MonoClass *klass)
1254 for (i = 0; i < klass->method.count; ++i) {
1255 if (klass->methods [i]->name[0] == 'I' &&
1256 !strcmp ("Invoke", klass->methods [i]->name)) {
1257 im = klass->methods [i];
1267 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1271 im = mono_get_delegate_invoke (delegate->vtable->klass);
1274 return mono_runtime_invoke (im, delegate, params, exc);
1277 static MonoArray* main_args;
1280 mono_runtime_get_main_args (void)
1286 fire_process_exit_event (void)
1288 MonoClassField *field;
1289 MonoDomain *domain = mono_domain_get ();
1291 MonoObject *delegate, *exc;
1293 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1296 if (domain != mono_get_root_domain ())
1299 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1300 if (delegate == NULL)
1305 mono_runtime_delegate_invoke (delegate, pa, &exc);
1309 * Execute a standard Main() method (argc/argv contains the
1310 * executable name). This method also sets the command line argument value
1311 * needed by System.Environment.
1314 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1318 MonoArray *args = NULL;
1319 MonoDomain *domain = mono_domain_get ();
1320 gchar *utf8_fullpath;
1323 main_thread = mono_thread_current ();
1325 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1327 if (!g_path_is_absolute (argv [0])) {
1328 gchar *basename = g_path_get_basename (argv [0]);
1329 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1333 utf8_fullpath = mono_utf8_from_external (fullpath);
1334 if(utf8_fullpath == NULL) {
1335 /* Printing the arg text will cause glib to
1336 * whinge about "Invalid UTF-8", but at least
1337 * its relevant, and shows the problem text
1340 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1341 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1348 utf8_fullpath = mono_utf8_from_external (argv[0]);
1349 if(utf8_fullpath == NULL) {
1350 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1351 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1356 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1357 g_free (utf8_fullpath);
1359 for (i = 1; i < argc; ++i) {
1363 utf8_arg=mono_utf8_from_external (argv[i]);
1364 if(utf8_arg==NULL) {
1365 /* Ditto the comment about Invalid UTF-8 here */
1366 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1367 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1371 arg = mono_string_new (domain, utf8_arg);
1372 mono_array_set (main_args, gpointer, i, arg);
1376 if (method->signature->param_count) {
1377 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1378 for (i = 0; i < argc; ++i) {
1379 /* The encodings should all work, given that
1380 * we've checked all these args for the
1383 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1384 mono_array_set (args, gpointer, i, arg);
1387 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1390 mono_assembly_set_main (method->klass->image->assembly);
1392 result = mono_runtime_exec_main (method, args, exc);
1393 fire_process_exit_event ();
1397 /* Used in mono_unhandled_exception */
1399 create_unhandled_exception_eventargs (MonoObject *exc)
1403 MonoMethod *method = NULL;
1404 MonoBoolean is_terminating = TRUE;
1408 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1411 mono_class_init (klass);
1413 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1414 for (i = 0; i < klass->method.count; ++i) {
1415 method = klass->methods [i];
1416 if (!strcmp (".ctor", method->name) &&
1417 method->signature->param_count == 2 &&
1418 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1426 args [1] = &is_terminating;
1428 obj = mono_object_new (mono_domain_get (), klass);
1429 mono_runtime_invoke (method, obj, args, NULL);
1435 * We call this function when we detect an unhandled exception
1436 * in the default domain.
1437 * It invokes the * UnhandledException event in AppDomain or prints
1438 * a warning to the console
1441 mono_unhandled_exception (MonoObject *exc)
1443 MonoDomain *domain = mono_domain_get ();
1444 MonoClassField *field;
1445 MonoObject *delegate;
1447 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1448 "UnhandledException");
1451 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1452 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1454 /* set exitcode only in the main thread */
1455 if (mono_thread_current () == main_thread)
1456 mono_environment_exitcode_set (1);
1457 if (domain != mono_get_root_domain () || !delegate) {
1458 mono_print_unhandled_exception (exc);
1460 MonoObject *e = NULL;
1463 pa [0] = domain->domain;
1464 pa [1] = create_unhandled_exception_eventargs (exc);
1465 mono_runtime_delegate_invoke (delegate, pa, &e);
1468 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1469 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1477 * Launch a new thread to start all setup that requires managed code
1480 * main_func is called back from the thread with main_args as the
1481 * parameter. The callback function is expected to start Main()
1482 * eventually. This function then waits for all managed threads to
1486 mono_runtime_exec_managed_code (MonoDomain *domain,
1487 MonoMainThreadFunc main_func,
1490 mono_thread_create (domain, main_func, main_args);
1492 mono_thread_manage ();
1496 * Execute a standard Main() method (args doesn't contain the
1500 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1510 domain = mono_object_domain (args);
1511 if (!domain->entry_assembly) {
1513 gchar *config_suffix;
1514 MonoAssembly *assembly;
1516 assembly = method->klass->image->assembly;
1517 domain->entry_assembly = assembly;
1518 domain->setup->application_base = mono_string_new (domain, assembly->basedir);
1520 config_suffix = g_strconcat (assembly->aname.name, ".exe.config", NULL);
1521 str = g_build_filename (assembly->basedir, config_suffix, NULL);
1522 g_free (config_suffix);
1523 domain->setup->configuration_file = mono_string_new (domain, str);
1527 /* FIXME: check signature of method */
1528 if (method->signature->ret->type == MONO_TYPE_I4) {
1530 res = mono_runtime_invoke (method, NULL, pa, exc);
1532 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1536 mono_environment_exitcode_set (rval);
1538 mono_runtime_invoke (method, NULL, pa, exc);
1542 /* If the return type of Main is void, only
1543 * set the exitcode if an exception was thrown
1544 * (we don't want to blow away an
1545 * explicitly-set exit code)
1548 mono_environment_exitcode_set (rval);
1556 mono_install_runtime_invoke (MonoInvokeFunc func)
1558 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1562 * mono_runtime_invoke:
1564 * Invokes the method represented by `method' on the object `obj'.
1566 * obj is the 'this' pointer, it should be NULL for static
1567 * methods, a MonoObject* for object instances and a pointer to
1568 * the value type for value types.
1570 * The params array contains the arguments to the method with the
1571 * same convention: MonoObject* pointers for object instances and
1572 * pointers to the value type otherwise. The _invoke_array
1573 * variant takes a C# object[] as the params argument (MonoArray
1574 * *params): in this case the value types are boxed inside the
1575 * respective reference representation.
1577 * From unmanaged code you'll usually use the
1578 * mono_runtime_invoke() variant.
1580 * Note that this function doesn't handle virtual methods for
1581 * you, it will exec the exact method you pass: we still need to
1582 * expose a function to lookup the derived class implementation
1583 * of a virtual method (there are examples of this in the code,
1586 * You can pass NULL as the exc argument if you don't want to
1587 * catch exceptions, otherwise, *exc will be set to the exception
1588 * thrown, if any. if an exception is thrown, you can't use the
1589 * MonoObject* result from the function.
1591 * If the method returns a value type, it is boxed in an object
1595 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1598 MonoMethodSignature *sig = method->signature;
1599 gpointer *pa = NULL;
1602 if (NULL != params) {
1603 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1604 for (i = 0; i < mono_array_length (params); i++) {
1605 if (sig->params [i]->byref) {
1609 switch (sig->params [i]->type) {
1612 case MONO_TYPE_BOOLEAN:
1615 case MONO_TYPE_CHAR:
1624 case MONO_TYPE_VALUETYPE:
1625 /* MS seems to create the objects if a null is passed in */
1626 if (! ((gpointer *)params->vector)[i])
1627 ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
1628 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1630 case MONO_TYPE_STRING:
1631 case MONO_TYPE_OBJECT:
1632 case MONO_TYPE_CLASS:
1633 case MONO_TYPE_ARRAY:
1634 case MONO_TYPE_SZARRAY:
1635 if (sig->params [i]->byref)
1636 pa [i] = &(((gpointer *)params->vector)[i]);
1638 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1641 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1646 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1649 obj = mono_object_new (mono_domain_get (), method->klass);
1650 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1651 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
1653 if (method->klass->valuetype)
1654 o = mono_object_unbox (obj);
1658 mono_runtime_invoke (method, o, pa, exc);
1661 /* obj must be already unboxed if needed */
1662 return mono_runtime_invoke (method, obj, pa, exc);
1667 arith_overflow (void)
1669 mono_raise_exception (mono_get_exception_overflow ());
1673 * mono_object_allocate:
1674 * @size: number of bytes to allocate
1676 * This is a very simplistic routine until we have our GC-aware
1679 * Returns: an allocated object of size @size, or NULL on failure.
1681 static inline void *
1682 mono_object_allocate (size_t size)
1685 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1686 void *o = GC_MALLOC (size);
1688 void *o = calloc (1, size);
1690 return mono_gc_out_of_memory (size);
1692 mono_stats.new_object_count++;
1697 #if CREATION_SPEEDUP
1698 static inline void *
1699 mono_object_allocate_spec (size_t size, void *gcdescr)
1701 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1702 void *o = GC_GCJ_MALLOC (size, gcdescr);
1703 mono_stats.new_object_count++;
1711 * @klass: the class of the object that we want to create
1713 * Returns a newly created object whose definition is
1714 * looked up using @klass. This will not invoke any constructors,
1715 * so the consumer of this routine has to invoke any constructors on
1716 * its own to initialize the object.
1719 mono_object_new (MonoDomain *domain, MonoClass *klass)
1721 MONO_ARCH_SAVE_REGS;
1722 return mono_object_new_specific (mono_class_vtable (domain, klass));
1726 * mono_object_new_specific:
1727 * @vtable: the vtable of the object that we want to create
1729 * Returns: A newly created object with class and domain specified
1733 mono_object_new_specific (MonoVTable *vtable)
1737 MONO_ARCH_SAVE_REGS;
1742 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1745 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1749 mono_class_init (klass);
1751 for (i = 0; i < klass->method.count; ++i) {
1752 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1753 klass->methods [i]->signature->param_count == 1) {
1754 im = klass->methods [i];
1759 vtable->domain->create_proxy_for_type_method = im;
1762 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1764 o = mono_runtime_invoke (im, NULL, pa, NULL);
1765 if (o != NULL) return o;
1768 return mono_object_new_alloc_specific (vtable);
1772 mono_object_new_alloc_specific (MonoVTable *vtable)
1776 #if CREATION_SPEEDUP
1777 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1778 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1780 /* printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
1781 o = mono_object_allocate (vtable->klass->instance_size);
1785 o = mono_object_allocate (vtable->klass->instance_size);
1788 if (vtable->klass->has_finalize)
1789 mono_object_register_finalizer (o);
1791 mono_profiler_allocation (o, vtable->klass);
1795 #if CREATION_SPEEDUP
1798 mono_object_new_fast (MonoVTable *vtable)
1800 return GC_GCJ_MALLOC (vtable->klass->instance_size, vtable);
1806 * Return the allocation function appropriate for the given class.
1810 mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean *pass_size_in_words)
1812 *pass_size_in_words = FALSE;
1814 if (vtable->klass->has_finalize || vtable->klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
1815 return mono_object_new_specific;
1817 #if CREATION_SPEEDUP
1818 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1820 return mono_object_new_fast;
1823 * FIXME: This is actually slower than mono_object_new_fast, because
1824 * of the overhead of parameter passing.
1827 *pass_size_in_words = TRUE;
1828 #ifdef GC_REDIRECT_TO_LOCAL
1829 return GC_local_gcj_fast_malloc;
1831 return GC_gcj_fast_malloc;
1837 return mono_object_new_specific;
1841 * mono_object_new_from_token:
1842 * @image: Context where the type_token is hosted
1843 * @token: a token of the type that we want to create
1845 * Returns: A newly created object whose definition is
1846 * looked up using @token in the @image image
1849 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1853 class = mono_class_get (image, token);
1855 return mono_object_new (domain, class);
1860 * mono_object_clone:
1861 * @obj: the object to clone
1863 * Returns: A newly created object who is a shallow copy of @obj
1866 mono_object_clone (MonoObject *obj)
1871 size = obj->vtable->klass->instance_size;
1872 o = mono_object_allocate (size);
1873 mono_profiler_allocation (o, obj->vtable->klass);
1875 memcpy (o, obj, size);
1877 if (obj->vtable->klass->has_finalize)
1878 mono_object_register_finalizer (o);
1884 * @array: the array to clone
1886 * Returns: A newly created array who is a shallow copy of @array
1889 mono_array_clone (MonoArray *array)
1894 MonoClass *klass = array->obj.vtable->klass;
1896 MONO_ARCH_SAVE_REGS;
1898 if (array->bounds == NULL) {
1899 size = mono_array_length (array);
1900 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1901 klass, &size, NULL);
1903 size *= mono_array_element_size (klass);
1904 memcpy (o, array, sizeof (MonoArray) + size);
1909 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1910 size = mono_array_element_size (klass);
1911 for (i = 0; i < klass->rank; ++i) {
1912 sizes [i] = array->bounds [i].length;
1913 size *= array->bounds [i].length;
1914 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1916 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1917 klass, sizes, sizes + klass->rank);
1918 memcpy (o, array, sizeof(MonoArray) + size);
1923 /* helper macros to check for overflow when calculating the size of arrays */
1924 #define MYGUINT32_MAX 4294967295U
1925 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1926 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1927 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1928 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1929 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1932 * mono_array_new_full:
1933 * @domain: domain where the object is created
1934 * @array_class: array class
1935 * @lengths: lengths for each dimension in the array
1936 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1938 * This routine creates a new array objects with the given dimensions,
1939 * lower bounds and type.
1942 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1943 guint32 *lengths, guint32 *lower_bounds)
1945 guint32 byte_len, len;
1948 MonoArrayBounds *bounds;
1952 if (!array_class->inited)
1953 mono_class_init (array_class);
1955 byte_len = mono_array_element_size (array_class);
1958 if (array_class->rank == 1 &&
1959 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1966 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1968 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1970 for (i = 0; i < array_class->rank; ++i)
1971 if ((int) lengths [i] < 0)
1974 for (i = 0; i < array_class->rank; ++i) {
1975 bounds [i].length = lengths [i];
1976 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1977 mono_gc_out_of_memory (MYGUINT32_MAX);
1982 for (i = 0; i < array_class->rank; ++i)
1983 bounds [i].lower_bound = lower_bounds [i];
1986 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1987 mono_gc_out_of_memory (MYGUINT32_MAX);
1989 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1990 mono_gc_out_of_memory (MYGUINT32_MAX);
1991 byte_len += sizeof (MonoArray);
1993 * Following three lines almost taken from mono_object_new ():
1994 * they need to be kept in sync.
1996 vtable = mono_class_vtable (domain, array_class);
1997 #if CREATION_SPEEDUP
1998 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1999 o = mono_object_allocate_spec (byte_len, vtable);
2001 o = mono_object_allocate (byte_len);
2005 o = mono_object_allocate (byte_len);
2009 array = (MonoArray*)o;
2011 array->bounds = bounds;
2012 array->max_length = len;
2014 mono_profiler_allocation (o, array_class);
2021 * @domain: domain where the object is created
2022 * @eclass: element class
2023 * @n: number of array elements
2025 * This routine creates a new szarray with @n elements of type @eclass.
2028 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
2032 MONO_ARCH_SAVE_REGS;
2034 ac = mono_array_class_get (eclass, 1);
2035 g_assert (ac != NULL);
2037 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
2041 * mono_array_new_specific:
2042 * @vtable: a vtable in the appropriate domain for an initialized class
2043 * @n: number of array elements
2045 * This routine is a fast alternative to mono_array_new() for code which
2046 * can be sure about the domain it operates in.
2049 mono_array_new_specific (MonoVTable *vtable, guint32 n)
2053 guint32 byte_len, elem_size;
2055 MONO_ARCH_SAVE_REGS;
2060 elem_size = mono_array_element_size (vtable->klass);
2061 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
2062 mono_gc_out_of_memory (MYGUINT32_MAX);
2063 byte_len = n * elem_size;
2064 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2065 mono_gc_out_of_memory (MYGUINT32_MAX);
2066 byte_len += sizeof (MonoArray);
2067 #if CREATION_SPEEDUP
2068 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2069 o = mono_object_allocate_spec (byte_len, vtable);
2071 /* printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2072 o = mono_object_allocate (byte_len);
2076 o = mono_object_allocate (byte_len);
2080 ao = (MonoArray *)o;
2083 mono_profiler_allocation (o, vtable->klass);
2089 * mono_string_new_utf16:
2090 * @text: a pointer to an utf16 string
2091 * @len: the length of the string
2093 * Returns: A newly created string object which contains @text.
2096 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
2100 s = mono_string_new_size (domain, len);
2101 g_assert (s != NULL);
2103 memcpy (mono_string_chars (s), text, len * 2);
2109 * mono_string_new_size:
2110 * @text: a pointer to an utf16 string
2111 * @len: the length of the string
2113 * Returns: A newly created string object of @len
2116 mono_string_new_size (MonoDomain *domain, gint32 len)
2120 size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2122 /* overflow ? can't fit it, can't allocate it! */
2124 mono_gc_out_of_memory (-1);
2126 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2128 #if CREATION_SPEEDUP
2129 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2130 s = mono_object_allocate_spec (size, vtable);
2132 s = (MonoString*)mono_object_allocate (size);
2133 s->object.vtable = vtable;
2136 s = (MonoString*)mono_object_allocate (size);
2137 s->object.vtable = vtable;
2141 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2147 * mono_string_new_len:
2148 * @text: a pointer to an utf8 string
2149 * @length: number of bytes in @text to consider
2151 * Returns: A newly created string object which contains @text.
2154 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2156 GError *error = NULL;
2157 MonoString *o = NULL;
2159 glong items_written;
2161 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2164 o = mono_string_new_utf16 (domain, ut, items_written);
2166 g_error_free (error);
2175 * @text: a pointer to an utf8 string
2177 * Returns: A newly created string object which contains @text.
2180 mono_string_new (MonoDomain *domain, const char *text)
2182 GError *error = NULL;
2183 MonoString *o = NULL;
2185 glong items_written;
2190 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2193 o = mono_string_new_utf16 (domain, ut, items_written);
2195 g_error_free (error);
2203 * mono_string_new_wrapper:
2204 * @text: pointer to utf8 characters.
2206 * Helper function to create a string object from @text in the current domain.
2209 mono_string_new_wrapper (const char *text)
2211 MonoDomain *domain = mono_domain_get ();
2213 MONO_ARCH_SAVE_REGS;
2216 return mono_string_new (domain, text);
2223 * @class: the class of the value
2224 * @value: a pointer to the unboxed data
2226 * Returns: A newly created object which contains @value.
2229 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2235 g_assert (class->valuetype);
2237 vtable = mono_class_vtable (domain, class);
2238 size = mono_class_instance_size (class);
2239 res = mono_object_allocate (size);
2240 res->vtable = vtable;
2241 mono_profiler_allocation (res, class);
2243 size = size - sizeof (MonoObject);
2245 #if NO_UNALIGNED_ACCESS
2246 memcpy ((char *)res + sizeof (MonoObject), value, size);
2250 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2253 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2256 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2259 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2262 memcpy ((char *)res + sizeof (MonoObject), value, size);
2265 if (class->has_finalize)
2266 mono_object_register_finalizer (res);
2271 mono_object_get_domain (MonoObject *obj)
2273 return mono_object_domain (obj);
2277 mono_object_get_class (MonoObject *obj)
2279 return mono_object_class (obj);
2283 mono_object_unbox (MonoObject *obj)
2285 /* add assert for valuetypes? */
2286 g_assert (obj->vtable->klass->valuetype);
2287 return ((char*)obj) + sizeof (MonoObject);
2291 * mono_object_isinst:
2293 * @klass: a pointer to a class
2295 * Returns: @obj if @obj is derived from @klass
2298 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2301 mono_class_init (klass);
2303 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2304 return mono_object_isinst_mbyref (obj, klass);
2309 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2313 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2322 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2323 if ((klass->interface_id <= vt->max_interface_id) &&
2324 (vt->interface_offsets [klass->interface_id] != 0))
2328 MonoClass *oklass = vt->klass;
2329 if ((oklass == mono_defaults.transparent_proxy_class))
2330 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2332 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2336 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2338 MonoDomain *domain = mono_domain_get ();
2340 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2341 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2342 MonoMethod *im = NULL;
2346 for (i = 0; i < rpklass->method.count; ++i) {
2347 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2348 im = rpklass->methods [i];
2353 im = mono_object_get_virtual_method (rp, im);
2356 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2359 res = mono_runtime_invoke (im, rp, pa, NULL);
2361 if (*(MonoBoolean *) mono_object_unbox(res)) {
2362 /* Update the vtable of the remote type, so it can safely cast to this new type */
2363 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2364 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2373 * mono_object_castclass_mbyref:
2375 * @klass: a pointer to a class
2377 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2380 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2382 if (!obj) return NULL;
2383 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2385 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2387 "InvalidCastException"));
2392 MonoDomain *orig_domain;
2398 str_lookup (MonoDomain *domain, gpointer user_data)
2400 LDStrInfo *info = user_data;
2401 if (info->res || domain == info->orig_domain)
2403 mono_domain_lock (domain);
2404 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2405 mono_domain_unlock (domain);
2409 mono_string_is_interned_lookup (MonoString *str, int insert)
2411 MonoGHashTable *ldstr_table;
2414 char *ins = g_malloc (4 + str->length * 2);
2417 /* Encode the length */
2418 /* Same code as in mono_image_insert_string () */
2420 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2423 * ins is stored in the hash table as a key and needs to have the same
2424 * representation as in the metadata: we swap the character bytes on big
2427 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2430 char *p2 = (char *)mono_string_chars (str);
2431 for (i = 0; i < str->length; ++i) {
2438 memcpy (p, mono_string_chars (str), str->length * 2);
2440 domain = ((MonoObject *)str)->vtable->domain;
2441 ldstr_table = domain->ldstr_table;
2442 mono_domain_lock (domain);
2443 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2444 mono_domain_unlock (domain);
2449 mono_g_hash_table_insert (ldstr_table, ins, str);
2450 mono_domain_unlock (domain);
2453 LDStrInfo ldstr_info;
2454 ldstr_info.orig_domain = domain;
2455 ldstr_info.ins = ins;
2456 ldstr_info.res = NULL;
2458 mono_domain_foreach (str_lookup, &ldstr_info);
2459 if (ldstr_info.res) {
2461 * the string was already interned in some other domain:
2462 * intern it in the current one as well.
2464 mono_g_hash_table_insert (ldstr_table, ins, str);
2465 mono_domain_unlock (domain);
2469 mono_domain_unlock (domain);
2475 mono_string_is_interned (MonoString *o)
2477 return mono_string_is_interned_lookup (o, FALSE);
2481 mono_string_intern (MonoString *str)
2483 return mono_string_is_interned_lookup (str, TRUE);
2488 * @domain: the domain where the string will be used.
2489 * @image: a metadata context
2490 * @idx: index into the user string table.
2492 * Implementation for the ldstr opcode.
2495 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2497 MONO_ARCH_SAVE_REGS;
2500 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2502 return mono_ldstr_metdata_sig (domain, mono_metadata_user_string (image, idx));
2506 * mono_ldstr_metdata_sig
2507 * @domain: the domain for the string
2508 * @sig: the signature of a metadata string
2510 * returns a MonoString for a string stored in the metadata
2513 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig)
2515 const char *str = sig;
2519 mono_domain_lock (domain);
2520 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2521 mono_domain_unlock (domain);
2525 len2 = mono_metadata_decode_blob_size (str, &str);
2528 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2529 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2532 guint16 *p2 = (guint16*)mono_string_chars (o);
2533 for (i = 0; i < len2; ++i) {
2534 *p2 = GUINT16_FROM_LE (*p2);
2539 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2540 mono_domain_unlock (domain);
2546 * mono_string_to_utf8:
2547 * @s: a System.String
2549 * Return the UTF8 representation for @s.
2550 * the resulting buffer nedds to be freed with g_free().
2553 mono_string_to_utf8 (MonoString *s)
2556 GError *error = NULL;
2562 return g_strdup ("");
2564 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2566 g_warning (error->message);
2567 g_error_free (error);
2574 * mono_string_to_utf16:
2577 * Return an null-terminated array of the utf-16 chars
2578 * contained in @s. The result must be freed with g_free().
2579 * This is a temporary helper until our string implementation
2580 * is reworked to always include the null terminating char.
2583 mono_string_to_utf16 (MonoString *s)
2590 as = g_malloc ((s->length * 2) + 2);
2591 as [(s->length * 2)] = '\0';
2592 as [(s->length * 2) + 1] = '\0';
2595 return (gunichar2 *)(as);
2598 memcpy (as, mono_string_chars(s), s->length * 2);
2599 return (gunichar2 *)(as);
2603 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2606 mono_string_from_utf16 (gunichar2 *data)
2608 MonoDomain *domain = mono_domain_get ();
2614 while (data [len]) len++;
2616 return mono_string_new_utf16 (domain, data, len);
2620 default_ex_handler (MonoException *ex)
2622 MonoObject *o = (MonoObject*)ex;
2623 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2627 static MonoExceptionFunc ex_handler = default_ex_handler;
2630 mono_install_handler (MonoExceptionFunc func)
2632 ex_handler = func? func: default_ex_handler;
2636 * mono_raise_exception:
2637 * @ex: exception object
2639 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2642 mono_raise_exception (MonoException *ex)
2645 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2646 * that will cause gcc to omit the function epilog, causing problems when
2647 * the JIT tries to walk the stack, since the return address on the stack
2648 * will point into the next function in the executable, not this one.
2655 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2657 MonoWaitHandle *res;
2659 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2661 res->handle = handle;
2667 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2669 MonoAsyncResult *res;
2671 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2674 res->async_state = state;
2676 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2678 res->sync_completed = FALSE;
2679 res->completed = FALSE;
2685 mono_message_init (MonoDomain *domain,
2686 MonoMethodMessage *this,
2687 MonoReflectionMethod *method,
2688 MonoArray *out_args)
2690 MonoMethodSignature *sig = method->method->signature;
2696 this->method = method;
2698 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2699 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2700 this->async_result = NULL;
2701 this->call_type = CallType_Sync;
2703 names = g_new (char *, sig->param_count);
2704 mono_method_get_param_names (method->method, (const char **) names);
2705 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2707 for (i = 0; i < sig->param_count; i++) {
2708 name = mono_string_new (domain, names [i]);
2709 mono_array_set (this->names, gpointer, i, name);
2713 for (i = 0, j = 0; i < sig->param_count; i++) {
2715 if (sig->params [i]->byref) {
2717 gpointer arg = mono_array_get (out_args, gpointer, j);
2718 mono_array_set (this->args, gpointer, i, arg);
2722 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2727 mono_array_set (this->arg_types, guint8, i, arg_type);
2732 * mono_remoting_invoke:
2733 * @real_proxy: pointer to a RealProxy object
2734 * @msg: The MonoMethodMessage to execute
2735 * @exc: used to store exceptions
2736 * @out_args: used to store output arguments
2738 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2739 * IMessage interface and it is not trivial to extract results from there. So
2740 * we call an helper method PrivateInvoke instead of calling
2741 * RealProxy::Invoke() directly.
2743 * Returns: the result object.
2746 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2747 MonoObject **exc, MonoArray **out_args)
2749 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2752 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2758 klass = mono_defaults.real_proxy_class;
2760 for (i = 0; i < klass->method.count; ++i) {
2761 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2762 klass->methods [i]->signature->param_count == 4) {
2763 im = klass->methods [i];
2769 real_proxy->vtable->domain->private_invoke_method = im;
2772 pa [0] = real_proxy;
2777 return mono_runtime_invoke (im, NULL, pa, exc);
2781 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2782 MonoObject **exc, MonoArray **out_args)
2786 MonoMethodSignature *sig;
2788 int i, j, outarg_count = 0;
2790 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2792 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2793 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2794 target = tp->rp->unwrapped_server;
2796 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2800 domain = mono_domain_get ();
2801 method = msg->method->method;
2802 sig = method->signature;
2804 for (i = 0; i < sig->param_count; i++) {
2805 if (sig->params [i]->byref)
2809 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2812 ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
2814 for (i = 0, j = 0; i < sig->param_count; i++) {
2815 if (sig->params [i]->byref) {
2817 arg = mono_array_get (msg->args, gpointer, i);
2818 mono_array_set (*out_args, gpointer, j, arg);
2827 mono_print_unhandled_exception (MonoObject *exc)
2829 char *message = (char *) "";
2833 gboolean free_message = FALSE;
2836 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2837 klass = exc->vtable->klass;
2839 while (klass && method == NULL) {
2840 for (i = 0; i < klass->method.count; ++i) {
2841 method = klass->methods [i];
2842 if (!strcmp ("ToString", method->name) &&
2843 method->signature->param_count == 0 &&
2844 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2845 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2852 klass = klass->parent;
2857 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2859 message = mono_string_to_utf8 (str);
2860 free_message = TRUE;
2865 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2866 * exc->vtable->klass->name, message);
2868 g_printerr ("\nUnhandled Exception: %s\n", message);
2875 * mono_delegate_ctor:
2876 * @this: pointer to an uninitialized delegate object
2877 * @target: target object
2878 * @addr: pointer to native code
2880 * This is used to initialize a delegate. We also insert the method_info if
2881 * we find the info with mono_jit_info_table_find().
2884 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2886 MonoDomain *domain = mono_domain_get ();
2887 MonoDelegate *delegate = (MonoDelegate *)this;
2888 MonoMethod *method = NULL;
2895 class = this->vtable->klass;
2897 if ((ji = mono_jit_info_table_find (domain, addr))) {
2898 method = ji->method;
2899 delegate->method_info = mono_method_get_object (domain, method, NULL);
2902 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2904 method = mono_marshal_get_remoting_invoke (method);
2905 delegate->method_ptr = mono_compile_method (method);
2906 delegate->target = target;
2908 delegate->method_ptr = addr;
2909 delegate->target = target;
2914 * mono_method_call_message_new:
2916 * Translates arguments pointers into a Message.
2919 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2920 MonoDelegate **cb, MonoObject **state)
2922 MonoDomain *domain = mono_domain_get ();
2923 MonoMethodSignature *sig = method->signature;
2924 MonoMethodMessage *msg;
2927 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2930 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2931 count = sig->param_count - 2;
2933 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2934 count = sig->param_count;
2937 for (i = 0; i < count; i++) {
2942 if (sig->params [i]->byref)
2943 vpos = *((gpointer *)params [i]);
2947 type = sig->params [i]->type;
2948 class = mono_class_from_mono_type (sig->params [i]);
2950 if (class->valuetype)
2951 arg = mono_value_box (domain, class, vpos);
2953 arg = *((MonoObject **)vpos);
2955 mono_array_set (msg->args, gpointer, i, arg);
2958 if (cb != NULL && state != NULL) {
2959 *cb = *((MonoDelegate **)params [i]);
2961 *state = *((MonoObject **)params [i]);
2968 * mono_method_return_message_restore:
2970 * Restore results from message based processing back to arguments pointers
2973 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2975 MonoMethodSignature *sig = method->signature;
2976 int i, j, type, size;
2977 for (i = 0, j = 0; i < sig->param_count; i++) {
2978 MonoType *pt = sig->params [i];
2981 char *arg = mono_array_get (out_args, gpointer, j);
2985 case MONO_TYPE_VOID:
2986 g_assert_not_reached ();
2990 case MONO_TYPE_BOOLEAN:
2993 case MONO_TYPE_CHAR:
3000 case MONO_TYPE_VALUETYPE: {
3001 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
3002 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
3005 case MONO_TYPE_STRING:
3006 case MONO_TYPE_CLASS:
3007 case MONO_TYPE_ARRAY:
3008 case MONO_TYPE_SZARRAY:
3009 case MONO_TYPE_OBJECT:
3010 **((MonoObject ***)params [i]) = (MonoObject *)arg;
3013 g_assert_not_reached ();
3022 * mono_load_remote_field:
3023 * @this: pointer to an object
3024 * @klass: klass of the object containing @field
3025 * @field: the field to load
3026 * @res: a storage to store the result
3028 * This method is called by the runtime on attempts to load fields of
3029 * transparent proxy objects. @this points to such TP, @klass is the class of
3030 * the object containing @field. @res is a storage location which can be
3031 * used to store the result.
3033 * Returns: an address pointing to the value of field.
3036 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
3038 static MonoMethod *getter = NULL;
3039 MonoDomain *domain = mono_domain_get ();
3040 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3041 MonoClass *field_class;
3042 MonoMethodMessage *msg;
3043 MonoArray *out_args;
3047 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3052 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3053 mono_field_get_value (tp->rp->unwrapped_server, field, res);
3060 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3061 MonoMethod *cm = mono_defaults.object_class->methods [i];
3063 if (!strcmp (cm->name, "FieldGetter")) {
3071 field_class = mono_class_from_mono_type (field->type);
3073 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3074 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3075 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3077 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3078 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3080 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3082 if (exc) mono_raise_exception ((MonoException *)exc);
3084 *res = mono_array_get (out_args, MonoObject *, 0);
3086 if (field_class->valuetype) {
3087 return ((char *)*res) + sizeof (MonoObject);
3093 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
3095 static MonoMethod *getter = NULL;
3096 MonoDomain *domain = mono_domain_get ();
3097 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3098 MonoClass *field_class;
3099 MonoMethodMessage *msg;
3100 MonoArray *out_args;
3101 MonoObject *exc, *res;
3103 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3105 field_class = mono_class_from_mono_type (field->type);
3107 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3109 if (field_class->valuetype) {
3110 res = mono_object_new (domain, field_class);
3111 val = ((gchar *) res) + sizeof (MonoObject);
3115 mono_field_get_value (tp->rp->unwrapped_server, field, val);
3122 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3123 MonoMethod *cm = mono_defaults.object_class->methods [i];
3125 if (!strcmp (cm->name, "FieldGetter")) {
3133 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3134 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3135 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3137 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3138 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3140 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3142 if (exc) mono_raise_exception ((MonoException *)exc);
3144 res = mono_array_get (out_args, MonoObject *, 0);
3150 * mono_store_remote_field:
3151 * @this: pointer to an object
3152 * @klass: klass of the object containing @field
3153 * @field: the field to load
3154 * @val: the value/object to store
3156 * This method is called by the runtime on attempts to store fields of
3157 * transparent proxy objects. @this points to such TP, @klass is the class of
3158 * the object containing @field. @val is the new value to store in @field.
3161 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3163 static MonoMethod *setter = NULL;
3164 MonoDomain *domain = mono_domain_get ();
3165 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3166 MonoClass *field_class;
3167 MonoMethodMessage *msg;
3168 MonoArray *out_args;
3172 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3174 field_class = mono_class_from_mono_type (field->type);
3176 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3177 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3178 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3185 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3186 MonoMethod *cm = mono_defaults.object_class->methods [i];
3188 if (!strcmp (cm->name, "FieldSetter")) {
3196 if (field_class->valuetype)
3197 arg = mono_value_box (domain, field_class, val);
3199 arg = *((MonoObject **)val);
3202 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3203 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3205 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3206 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3207 mono_array_set (msg->args, gpointer, 2, arg);
3209 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3211 if (exc) mono_raise_exception ((MonoException *)exc);
3215 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3217 static MonoMethod *setter = NULL;
3218 MonoDomain *domain = mono_domain_get ();
3219 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3220 MonoClass *field_class;
3221 MonoMethodMessage *msg;
3222 MonoArray *out_args;
3225 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3227 field_class = mono_class_from_mono_type (field->type);
3229 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3230 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3231 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3238 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3239 MonoMethod *cm = mono_defaults.object_class->methods [i];
3241 if (!strcmp (cm->name, "FieldSetter")) {
3249 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3250 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3252 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3253 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3254 mono_array_set (msg->args, gpointer, 2, arg);
3256 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3258 if (exc) mono_raise_exception ((MonoException *)exc);