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;
100 CRITICAL_SECTION initialization_section;
101 } TypeInitializationLock;
103 /* for locking access to type_initialization_hash and blocked_thread_hash */
104 static CRITICAL_SECTION type_initialization_section;
106 /* from vtable to lock */
107 static GHashTable *type_initialization_hash;
109 /* from thread id to thread id being waited on */
110 static GHashTable *blocked_thread_hash;
113 static MonoThread *main_thread;
116 mono_type_initialization_init (void)
118 InitializeCriticalSection (&type_initialization_section);
119 type_initialization_hash = g_hash_table_new (NULL, NULL);
120 blocked_thread_hash = g_hash_table_new (NULL, NULL);
124 * mono_runtime_class_init:
125 * @vtable: vtable that needs to be initialized
127 * This routine calls the class constructor for @vtable.
130 mono_runtime_class_init (MonoVTable *vtable)
134 MonoException *exc_to_throw;
135 MonoMethod *method = NULL;
142 if (vtable->initialized)
147 klass = vtable->klass;
149 for (i = 0; i < klass->method.count; ++i) {
150 method = klass->methods [i];
151 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
152 (strcmp (".cctor", method->name) == 0)) {
159 MonoDomain *domain = vtable->domain;
160 TypeInitializationLock *lock;
161 guint32 tid = GetCurrentThreadId();
162 int do_initialization = 0;
163 MonoDomain *last_domain = NULL;
165 EnterCriticalSection (&type_initialization_section);
166 /* double check... */
167 if (vtable->initialized) {
168 LeaveCriticalSection (&type_initialization_section);
171 lock = g_hash_table_lookup (type_initialization_hash, vtable);
173 /* This thread will get to do the initialization */
174 if (mono_domain_get () != domain) {
175 /* Transfer into the target domain */
176 last_domain = mono_domain_get ();
177 if (!mono_domain_set (domain, FALSE)) {
178 vtable->initialized = 1;
179 LeaveCriticalSection (&type_initialization_section);
180 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
183 lock = g_malloc (sizeof(TypeInitializationLock));
184 InitializeCriticalSection (&lock->initialization_section);
185 lock->initializing_tid = tid;
186 lock->waiting_count = 1;
188 /* grab the vtable lock while this thread still owns type_initialization_section */
189 EnterCriticalSection (&lock->initialization_section);
190 g_hash_table_insert (type_initialization_hash, vtable, lock);
191 do_initialization = 1;
194 TypeInitializationLock *pending_lock;
196 if (lock->initializing_tid == tid || lock->done) {
197 LeaveCriticalSection (&type_initialization_section);
200 /* see if the thread doing the initialization is already blocked on this thread */
201 blocked = GUINT_TO_POINTER (lock->initializing_tid);
202 while ((pending_lock = (TypeInitializationLock*) g_hash_table_lookup (blocked_thread_hash, blocked))) {
203 if (pending_lock->initializing_tid == tid) {
204 if (!pending_lock->done) {
205 LeaveCriticalSection (&type_initialization_section);
208 /* the thread doing the initialization is blocked on this thread,
209 but on a lock that has already been freed. It just hasn't got
214 blocked = GUINT_TO_POINTER (pending_lock->initializing_tid);
216 ++lock->waiting_count;
217 /* record the fact that we are waiting on the initializing thread */
218 g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), lock);
220 LeaveCriticalSection (&type_initialization_section);
222 if (do_initialization) {
223 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
225 mono_domain_set (last_domain, TRUE);
227 LeaveCriticalSection (&lock->initialization_section);
229 /* this just blocks until the initializing thread is done */
230 EnterCriticalSection (&lock->initialization_section);
231 LeaveCriticalSection (&lock->initialization_section);
234 EnterCriticalSection (&type_initialization_section);
235 if (lock->initializing_tid != tid)
236 g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
237 --lock->waiting_count;
238 if (lock->waiting_count == 0) {
239 DeleteCriticalSection (&lock->initialization_section);
240 g_hash_table_remove (type_initialization_hash, vtable);
243 vtable->initialized = 1;
244 /* FIXME: if the cctor fails, the type must be marked as unusable */
245 LeaveCriticalSection (&type_initialization_section);
247 vtable->initialized = 1;
252 (klass->image == mono_defaults.corlib &&
253 !strcmp (klass->name_space, "System") &&
254 !strcmp (klass->name, "TypeInitializationException")))
255 return; /* No static constructor found or avoid infinite loop */
257 if (klass->name_space && *klass->name_space)
258 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
260 full_name = g_strdup (klass->name);
262 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
265 mono_raise_exception (exc_to_throw);
269 gboolean release_type_locks (gpointer key, gpointer value, gpointer user)
271 TypeInitializationLock *lock = (TypeInitializationLock*) value;
272 if (lock->initializing_tid == GPOINTER_TO_UINT (user)) {
274 LeaveCriticalSection (&lock->initialization_section);
275 --lock->waiting_count;
276 if (lock->waiting_count == 0) {
277 DeleteCriticalSection (&lock->initialization_section);
286 mono_release_type_locks (MonoThread *thread)
288 EnterCriticalSection (&type_initialization_section);
289 g_hash_table_foreach_remove (type_initialization_hash, release_type_locks, GUINT_TO_POINTER (thread->tid));
290 LeaveCriticalSection (&type_initialization_section);
294 default_trampoline (MonoMethod *method)
300 default_remoting_trampoline (MonoMethod *method, MonoRemotingTarget target)
302 g_error ("remoting not installed");
306 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
307 static MonoRemotingTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
310 mono_install_trampoline (MonoTrampoline func)
312 arch_create_jit_trampoline = func? func: default_trampoline;
316 mono_install_remoting_trampoline (MonoRemotingTrampoline func)
318 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
321 static MonoCompileFunc default_mono_compile_method = NULL;
324 * mono_install_compile_method:
325 * @func: function to install
327 * This is a VM internal routine
330 mono_install_compile_method (MonoCompileFunc func)
332 default_mono_compile_method = func;
336 * mono_compile_method:
337 * @method: The method to compile.
339 * This JIT-compiles the method, and returns the pointer to the native code
343 mono_compile_method (MonoMethod *method)
345 if (!default_mono_compile_method) {
346 g_error ("compile method called on uninitialized runtime");
349 return default_mono_compile_method (method);
352 static MonoFreeMethodFunc default_mono_free_method = NULL;
355 * mono_install_free_method:
356 * @func: pointer to the MonoFreeMethodFunc used to release a method
358 * This is an internal VM routine, it is used for the engines to
359 * register a handler to release the resources associated with a method.
361 * Methods are freed when no more references to the delegate that holds
365 mono_install_free_method (MonoFreeMethodFunc func)
367 default_mono_free_method = func;
371 * mono_runtime_free_method:
372 * @domain; domain where the method is hosted
373 * @method: method to release
375 * This routine is invoked to free the resources associated with
376 * a method that has been JIT compiled. This is used to discard
377 * methods that were used only temporarily (for example, used in marshalling)
381 mono_runtime_free_method (MonoDomain *domain, MonoMethod *method)
383 if (default_mono_free_method != NULL)
384 default_mono_free_method (domain, method);
387 * FIXME: This causes crashes because the types inside signatures and
390 /* mono_free_method (method); */
393 #if 0 && HAVE_BOEHM_GC
395 vtable_finalizer (void *obj, void *data) {
396 g_print ("%s finalized (%p)\n", (char*)data, obj);
402 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
405 * The vtables in the root appdomain are assumed to be reachable by other
406 * roots, and we don't use typed allocation in the other domains.
409 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
412 mono_class_compute_gc_descriptor (MonoClass *class)
414 MonoClassField *field;
418 static gboolean gcj_inited = FALSE;
423 GC_init_gcj_malloc (5, NULL);
425 mono_register_jit_icall (mono_object_new_fast, "mono_object_new_fast", mono_create_icall_signature ("object ptr"), FALSE);
427 #ifdef GC_REDIRECT_TO_LOCAL
428 mono_register_jit_icall (GC_local_gcj_malloc, "GC_local_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
429 mono_register_jit_icall (GC_local_gcj_fast_malloc, "GC_local_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
431 mono_register_jit_icall (GC_gcj_malloc, "GC_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
432 mono_register_jit_icall (GC_gcj_fast_malloc, "GC_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
436 mono_class_init (class);
438 if (class->gc_descr_inited)
441 class->gc_descr_inited = TRUE;
442 class->gc_descr = GC_NO_DESCRIPTOR;
444 if (class == mono_defaults.string_class) {
445 bitmap = GC_HEADER_BITMAP;
446 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
448 else if (class->rank) {
449 mono_class_compute_gc_descriptor (class->element_class);
451 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
452 bitmap = GC_HEADER_BITMAP;
454 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
455 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
459 static int count = 0;
463 /* GC 6.1 has trouble handling 64 bit descriptors... */
464 if ((class->instance_size / sizeof (gpointer)) > 30) {
465 /* printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer)); */
469 bitmap = GC_HEADER_BITMAP;
473 /* if (count > 442) */
476 /* printf("KLASS: %s.\n", class->name); */
478 for (p = class; p != NULL; p = p->parent) {
479 for (i = 0; i < p->field.count; ++i) {
480 field = &p->fields [i];
481 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
483 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
486 pos = field->offset / sizeof (gpointer);
488 if (field->type->byref)
491 switch (field->type->type) {
492 case MONO_TYPE_BOOLEAN:
504 /* printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap); */
507 case MONO_TYPE_STRING:
508 case MONO_TYPE_SZARRAY:
509 case MONO_TYPE_CLASS:
510 case MONO_TYPE_OBJECT:
511 case MONO_TYPE_ARRAY:
513 g_assert ((field->offset % sizeof(gpointer)) == 0);
515 bitmap |= ((guint64)1) << pos;
516 /* printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap); */
518 case MONO_TYPE_VALUETYPE: {
519 MonoClass *fclass = field->type->data.klass;
520 if (!fclass->enumtype) {
521 mono_class_compute_gc_descriptor (fclass);
522 bitmap |= (fclass->gc_bitmap >> (sizeof (MonoObject) / sizeof (gpointer))) << pos;
532 /* printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap); */
533 class->gc_bitmap = bitmap;
534 /* Convert to the format expected by GC_make_descriptor */
535 bm [0] = (guint32)bitmap;
536 bm [1] = (guint32)(bitmap >> 32);
537 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bm, class->instance_size / sizeof (gpointer));
540 #endif /* CREATION_SPEEDUP */
543 * field_is_special_static:
544 * @fklass: The MonoClass to look up.
545 * @field: The MonoClassField describing the field.
547 * Returns: SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
548 * SPECIAL_STATIC_NONE otherwise.
551 field_is_special_static (MonoClass *fklass, MonoClassField *field)
553 MonoCustomAttrInfo *ainfo;
555 ainfo = mono_custom_attrs_from_field (fklass, field);
558 for (i = 0; i < ainfo->num_attrs; ++i) {
559 MonoClass *klass = ainfo->attrs [i].ctor->klass;
560 if (klass->image == mono_defaults.corlib) {
561 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
562 mono_custom_attrs_free (ainfo);
563 return SPECIAL_STATIC_THREAD;
565 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
566 mono_custom_attrs_free (ainfo);
567 return SPECIAL_STATIC_CONTEXT;
571 mono_custom_attrs_free (ainfo);
572 return SPECIAL_STATIC_NONE;
577 * @domain: the application domain
578 * @class: the class to initialize
580 * VTables are domain specific because we create domain specific code, and
581 * they contain the domain specific static class data.
584 mono_class_vtable (MonoDomain *domain, MonoClass *class)
586 MonoVTable *vt = NULL;
587 MonoClassField *field;
592 guint32 constant_cols [MONO_CONSTANT_SIZE];
596 vt = class->cached_vtable;
597 if (vt && vt->domain == domain)
600 mono_domain_lock (domain);
601 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
602 mono_domain_unlock (domain);
607 mono_class_init (class);
609 mono_stats.used_class_count++;
610 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
612 vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
614 vt = mono_mempool_alloc0 (domain->mp, vtable_size);
620 mono_class_compute_gc_descriptor (class);
621 if (domain != mono_get_root_domain ())
623 * We can't use typed allocation in the non-root domains, since the
624 * collector needs the GC descriptor stored in the vtable even after
625 * the mempool containing the vtable is destroyed when the domain is
626 * unloaded. An alternative might be to allocate vtables in the GC
627 * heap, but this does not seem to work (it leads to crashes inside
628 * libgc). If that approach is tried, two gc descriptors need to be
629 * allocated for each class: one for the root domain, and one for all
630 * other domains. The second descriptor should contain a bit for the
631 * vtable field in MonoObject, since we can no longer assume the
632 * vtable is reachable by other roots after the appdomain is unloaded.
634 vt->gc_descr = GC_NO_DESCRIPTOR;
636 vt->gc_descr = class->gc_descr;
639 if (class->class_size) {
641 vt->data = GC_MALLOC (class->class_size + 8);
642 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
643 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
644 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
646 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
649 mono_stats.class_static_data_size += class->class_size + 8;
653 for (i = class->field.first; i < class->field.last; ++i) {
654 field = &class->fields [i - class->field.first];
655 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
657 if (mono_field_is_deleted (field))
659 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
660 gint32 special_static = field_is_special_static (class, field);
661 if (special_static != SPECIAL_STATIC_NONE) {
662 guint32 size, align, offset;
663 size = mono_type_size (field->type, &align);
664 offset = mono_alloc_special_static_data (special_static, size, align);
665 if (!domain->special_static_fields)
666 domain->special_static_fields = g_hash_table_new (NULL, NULL);
667 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
671 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
672 MonoClass *fklass = mono_class_from_mono_type (field->type);
673 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT));
674 t = (char*)vt->data + field->offset;
675 if (fklass->valuetype) {
676 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
678 /* it's a pointer type: add check */
679 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
680 *t = *(char *)field->data;
684 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
689 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1), cindex + 1);
691 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
693 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
694 field->def_type = constant_cols [MONO_CONSTANT_TYPE];
695 field->data = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
698 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL))
699 get_default_field_value (domain, field, (char*)vt->data + field->offset);
702 vt->max_interface_id = class->max_interface_id;
704 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
705 sizeof (gpointer) * (class->max_interface_id + 1));
707 /* initialize interface offsets */
708 for (i = 0; i <= class->max_interface_id; ++i) {
709 int slot = class->interface_offsets [i];
711 vt->interface_offsets [i] = &(vt->vtable [slot]);
715 * arch_create_jit_trampoline () can recursively call this function again
716 * because it compiles icall methods right away.
718 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
719 if (!class->cached_vtable)
720 class->cached_vtable = vt;
722 /* initialize vtable */
723 for (i = 0; i < class->vtable_size; ++i) {
726 if ((cm = class->vtable [i])) {
727 if (cm->signature->generic_param_count)
730 vt->vtable [i] = arch_create_jit_trampoline (cm);
734 mono_domain_unlock (domain);
736 /* make sure the the parent is initialized */
738 mono_class_vtable (domain, class->parent);
740 vt->type = mono_type_get_object (domain, &class->byval_arg);
741 if (class->contextbound)
750 * mono_class_proxy_vtable:
751 * @domain: the application domain
752 * @remove_class: the remote class
754 * Creates a vtable for transparent proxies. It is basically
755 * a copy of the real vtable of the class wrapped in @remote_class,
756 * but all function pointers invoke the remoting functions, and
757 * vtable->klass points to the transparent proxy class, and not to @class.
760 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRemotingTarget target_type)
762 MonoVTable *vt, *pvt;
763 int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
765 MonoClass *class = remote_class->proxy_class;
767 vt = mono_class_vtable (domain, class);
768 max_interface_id = vt->max_interface_id;
770 /* Calculate vtable space for extra interfaces */
771 for (j = 0; j < remote_class->interface_count; j++) {
772 MonoClass* iclass = remote_class->interfaces[j];
773 int method_count = iclass->method.count;
775 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
776 continue; /* interface implemented by the class */
778 for (i = 0; i < iclass->interface_count; i++)
779 method_count += iclass->interfaces[i]->method.count;
781 extra_interface_vtsize += method_count * sizeof (gpointer);
782 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
785 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
787 mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
789 pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
790 memcpy (pvt, vt, vtsize);
792 pvt->klass = mono_defaults.transparent_proxy_class;
794 /* initialize vtable */
795 for (i = 0; i < class->vtable_size; ++i) {
798 if ((cm = class->vtable [i]))
799 pvt->vtable [i] = arch_create_remoting_trampoline (cm, target_type);
802 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
804 /* create trampolines for abstract methods */
805 for (k = class; k; k = k->parent) {
806 for (i = 0; i < k->method.count; i++) {
807 int slot = k->methods [i]->slot;
808 if (!pvt->vtable [slot])
809 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i], target_type);
814 pvt->max_interface_id = max_interface_id;
815 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
816 sizeof (gpointer) * (max_interface_id + 1));
818 /* initialize interface offsets */
819 for (i = 0; i <= class->max_interface_id; ++i) {
820 int slot = class->interface_offsets [i];
822 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
825 if (remote_class->interface_count > 0)
827 int slot = class->vtable_size;
832 /* Create trampolines for the methods of the interfaces */
833 for (n = 0; n < remote_class->interface_count; n++)
835 iclass = remote_class->interfaces[n];
836 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
837 continue; /* interface implemented by the class */
842 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
844 for (j = 0; j < interf->method.count; ++j) {
845 MonoMethod *cm = interf->methods [j];
846 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm, target_type);
848 slot += interf->method.count;
849 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
861 * @domain: the application domain
862 * @class_name: name of the remote class
864 * Creates and initializes a MonoRemoteClass object for a remote type.
868 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
872 mono_domain_lock (domain);
873 rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class_name);
876 mono_domain_unlock (domain);
880 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
881 rc->default_vtable = NULL;
882 rc->xdomain_vtable = NULL;
883 rc->interface_count = 0;
884 rc->interfaces = NULL;
885 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
886 rc->proxy_class_name = mono_string_to_utf8 (class_name);
888 mono_g_hash_table_insert (domain->proxy_vtable_hash, class_name, rc);
889 mono_upgrade_remote_class (domain, rc, proxy_class);
891 mono_domain_unlock (domain);
897 extend_interface_array (MonoDomain *domain, MonoRemoteClass *remote_class, int amount)
899 /* Extends the array of interfaces. Memory is extended using blocks of 5 pointers */
901 int current_size = ((remote_class->interface_count / 5) + 1) * 5;
902 remote_class->interface_count += amount;
904 if (remote_class->interface_count > current_size || remote_class->interfaces == NULL)
906 int new_size = ((remote_class->interface_count / 5) + 1) * 5;
907 MonoClass **new_array = mono_mempool_alloc (domain->mp, new_size * sizeof (MonoClass*));
909 if (remote_class->interfaces != NULL)
910 memcpy (new_array, remote_class->interfaces, current_size * sizeof (MonoClass*));
912 remote_class->interfaces = new_array;
917 mono_remote_class_vtable (MonoDomain *domain, MonoRemoteClass *remote_class, MonoRealProxy *rp)
919 if (rp->target_domain_id != -1) {
920 if (remote_class->xdomain_vtable == NULL)
921 remote_class->xdomain_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_APPDOMAIN);
922 return remote_class->xdomain_vtable;
924 if (remote_class->default_vtable == NULL)
925 remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN);
927 return remote_class->default_vtable;
932 * mono_upgrade_remote_class:
933 * @domain: the application domain
934 * @remote_class: the remote class
935 * @klass: class to which the remote class can be casted.
937 * Updates the vtable of the remote class by adding the necessary method slots
938 * and interface offsets so it can be safely casted to klass. klass can be a
939 * class or an interface.
941 void mono_upgrade_remote_class (MonoDomain *domain, MonoRemoteClass *remote_class, MonoClass *klass)
943 gboolean redo_vtable;
945 mono_domain_lock (domain);
947 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
950 for (i = 0; i < remote_class->interface_count; i++)
951 if (remote_class->interfaces[i] == klass) redo_vtable = FALSE;
954 extend_interface_array (domain, remote_class, 1);
955 remote_class->interfaces [remote_class->interface_count-1] = klass;
959 redo_vtable = (remote_class->proxy_class != klass);
960 remote_class->proxy_class = klass;
964 remote_class->default_vtable = NULL;
965 remote_class->xdomain_vtable = NULL;
969 printf ("remote class upgrade - class:%s num-interfaces:%d\n", remote_class->proxy_class_name, remote_class->interface_count);
971 for (n=0; n<remote_class->interface_count; n++)
972 printf (" I:%s\n", remote_class->interfaces[n]->name);
975 mono_domain_unlock (domain);
979 * mono_object_get_virtual_method:
980 * @obj: object to operate on.
983 * Retrieves the MonoMethod that would be called on obj if obj is passed as
984 * the instance of a callvirt of method.
987 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method)
992 MonoMethod *res = NULL;
994 klass = mono_object_class (obj);
995 if (klass == mono_defaults.transparent_proxy_class) {
996 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
1002 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
1005 vtable = klass->vtable;
1007 /* check method->slot is a valid index: perform isinstance? */
1008 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1010 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
1012 if (method->slot != -1)
1013 res = vtable [method->slot];
1017 if (!res) res = method; /* It may be an interface or abstract class method */
1018 res = mono_marshal_get_remoting_invoke (res);
1027 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1029 g_error ("runtime invoke called on uninitialized runtime");
1033 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
1036 * mono_runtime_invoke:
1037 * @method: method to invoke
1038 * @obJ: object instance
1039 * @params: arguments to the method
1040 * @exc: exception information.
1042 * Invokes the method represented by @method on the object @obj.
1044 * obj is the 'this' pointer, it should be NULL for static
1045 * methods, a MonoObject* for object instances and a pointer to
1046 * the value type for value types.
1048 * The params array contains the arguments to the method with the
1049 * same convention: MonoObject* pointers for object instances and
1050 * pointers to the value type otherwise.
1052 * From unmanaged code you'll usually use the
1053 * mono_runtime_invoke() variant.
1055 * Note that this function doesn't handle virtual methods for
1056 * you, it will exec the exact method you pass: we still need to
1057 * expose a function to lookup the derived class implementation
1058 * of a virtual method (there are examples of this in the code,
1061 * You can pass NULL as the exc argument if you don't want to
1062 * catch exceptions, otherwise, *exc will be set to the exception
1063 * thrown, if any. if an exception is thrown, you can't use the
1064 * MonoObject* result from the function.
1066 * If the method returns a value type, it is boxed in an object
1070 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
1072 return default_mono_runtime_invoke (method, obj, params, exc);
1076 set_value (MonoType *type, void *dest, void *value, int deref_pointer)
1080 gpointer *p = (gpointer*)dest;
1087 case MONO_TYPE_BOOLEAN:
1089 case MONO_TYPE_U1: {
1090 guint8 *p = (guint8*)dest;
1091 *p = *(guint8*)value;
1096 case MONO_TYPE_CHAR: {
1097 guint16 *p = (guint16*)dest;
1098 *p = *(guint16*)value;
1101 #if SIZEOF_VOID_P == 4
1106 case MONO_TYPE_U4: {
1107 gint32 *p = (gint32*)dest;
1108 *p = *(gint32*)value;
1111 #if SIZEOF_VOID_P == 8
1116 case MONO_TYPE_U8: {
1117 gint64 *p = (gint64*)dest;
1118 *p = *(gint64*)value;
1121 case MONO_TYPE_R4: {
1122 float *p = (float*)dest;
1123 *p = *(float*)value;
1126 case MONO_TYPE_R8: {
1127 double *p = (double*)dest;
1128 *p = *(double*)value;
1131 case MONO_TYPE_STRING:
1132 case MONO_TYPE_SZARRAY:
1133 case MONO_TYPE_CLASS:
1134 case MONO_TYPE_OBJECT:
1135 case MONO_TYPE_ARRAY:
1136 case MONO_TYPE_PTR: {
1137 gpointer *p = (gpointer*)dest;
1138 *p = deref_pointer? *(gpointer*)value: value;
1141 case MONO_TYPE_VALUETYPE:
1142 if (type->data.klass->enumtype) {
1143 t = type->data.klass->enum_basetype->type;
1147 size = mono_class_value_size (type->data.klass, NULL);
1148 memcpy (dest, value, size);
1152 g_warning ("got type %x", type->type);
1153 g_assert_not_reached ();
1158 * mono_field_set_value:
1159 * @obj: Instance object
1160 * @field: MonoClassField describing the field to set
1161 * @value: The value to be set
1163 * Sets the value of the field described by @field in the object instance @obj
1164 * to the value passed in @value.
1166 * The value must be on the native format of the field type.
1169 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
1173 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1175 dest = (char*)obj + field->offset;
1176 set_value (field->type, dest, value, FALSE);
1180 * mono_field_static_set_value:
1181 * @field: MonoClassField describing the field to set
1182 * @value: The value to be set
1184 * Sets the value of the static field described by @field
1185 * to the value passed in @value.
1187 * The value must be on the native format of the field type.
1190 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
1194 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1195 /* you cant set a constant! */
1196 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
1198 dest = (char*)vt->data + field->offset;
1199 set_value (field->type, dest, value, FALSE);
1203 * mono_field_get_value:
1204 * @obj: Object instance
1205 * @field: MonoClassField describing the field to fetch information from
1206 * @value: pointer to the location where the value will be stored
1208 * Use this routine to get the value of the field @field in the object
1211 * The pointer provided by value must be of the field type, for reference
1212 * types this is a MonoObject*, for value types its the actual pointer to
1217 * mono_field_get_value (obj, int_field, &i);
1220 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
1224 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1226 src = (char*)obj + field->offset;
1227 set_value (field->type, value, src, TRUE);
1231 * mono_field_get_value_object:
1232 * @domain: domain where the object will be created (if boxing)
1233 * @field: MonoClassField describing the field to fetch information from
1234 * @obj: The object instance for the field.
1236 * Returns: a new MonoObject with the value from the given field. If the
1237 * field represents a value type, the value is boxed.
1241 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
1245 MonoVTable *vtable = NULL;
1247 gboolean is_static = FALSE;
1248 gboolean is_ref = FALSE;
1250 switch (field->type->type) {
1251 case MONO_TYPE_STRING:
1252 case MONO_TYPE_OBJECT:
1253 case MONO_TYPE_CLASS:
1254 case MONO_TYPE_ARRAY:
1255 case MONO_TYPE_SZARRAY:
1260 case MONO_TYPE_BOOLEAN:
1263 case MONO_TYPE_CHAR:
1272 case MONO_TYPE_VALUETYPE:
1273 is_ref = field->type->byref;
1276 g_error ("type 0x%x not handled in "
1277 "mono_field_get_value_object", field->type->type);
1281 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1283 vtable = mono_class_vtable (domain, field->parent);
1284 if (!vtable->initialized)
1285 mono_runtime_class_init (vtable);
1290 mono_field_static_get_value (vtable, field, &o);
1292 mono_field_get_value (obj, field, &o);
1297 /* boxed value type */
1298 klass = mono_class_from_mono_type (field->type);
1299 o = mono_object_new (domain, klass);
1300 v = ((gchar *) o) + sizeof (MonoObject);
1302 mono_field_static_get_value (vtable, field, v);
1304 mono_field_get_value (obj, field, v);
1311 mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, const char *blob, void *value)
1314 const char *p = blob;
1315 mono_metadata_decode_blob_size (p, &p);
1318 case MONO_TYPE_BOOLEAN:
1321 *(guint8 *) value = *p;
1323 case MONO_TYPE_CHAR:
1326 *(guint16*) value = read16 (p);
1330 *(guint32*) value = read32 (p);
1334 *(guint64*) value = read64 (p);
1337 readr4 (p, (float*) value);
1340 readr8 (p, (double*) value);
1342 case MONO_TYPE_STRING:
1343 *(gpointer*) value = mono_ldstr_metdata_sig (domain, blob);
1345 case MONO_TYPE_CLASS:
1346 *(gpointer*) value = NULL;
1350 g_warning ("type 0x%02x should not be in constant table", type);
1356 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
1358 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
1359 mono_get_constant_value_from_blob (domain, field->def_type, field->data, value);
1363 * mono_field_static_get_value:
1364 * @vt: vtable to the object
1365 * @field: MonoClassField describing the field to fetch information from
1366 * @value: where the value is returned
1368 * Use this routine to get the value of the static field @field value.
1370 * The pointer provided by value must be of the field type, for reference
1371 * types this is a MonoObject*, for value types its the actual pointer to
1376 * mono_field_static_get_value (vt, int_field, &i);
1379 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1383 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1385 if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
1386 get_default_field_value (vt->domain, field, value);
1390 src = (char*)vt->data + field->offset;
1391 set_value (field->type, value, src, TRUE);
1395 * mono_property_set_value:
1396 * @prop: MonoProperty to set
1397 * @obj: instance object on which to act
1398 * @params: parameters to pass to the propery
1399 * @exc: optional exception
1401 * Invokes the property's set method with the given arguments on the
1402 * object instance obj (or NULL for static properties).
1404 * You can pass NULL as the exc argument if you don't want to
1405 * catch exceptions, otherwise, *exc will be set to the exception
1406 * thrown, if any. if an exception is thrown, you can't use the
1407 * MonoObject* result from the function.
1410 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1412 default_mono_runtime_invoke (prop->set, obj, params, exc);
1416 * mono_property_get_value:
1417 * @prop: MonoProperty to fetch
1418 * @obj: instance object on which to act
1419 * @params: parameters to pass to the propery
1420 * @exc: optional exception
1422 * Invokes the property's get method with the given arguments on the
1423 * object instance obj (or NULL for static properties).
1425 * You can pass NULL as the exc argument if you don't want to
1426 * catch exceptions, otherwise, *exc will be set to the exception
1427 * thrown, if any. if an exception is thrown, you can't use the
1428 * MonoObject* result from the function.
1430 * Returns: the value from invoking the get method on the property.
1433 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1435 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1440 * mono_get_delegate_invoke:
1441 * @klass: The delegate class
1443 * Returns: the MonoMethod for the "Invoke" method in the delegate klass
1446 mono_get_delegate_invoke (MonoClass *klass)
1453 for (i = 0; i < klass->method.count; ++i) {
1454 if (klass->methods [i]->name[0] == 'I' &&
1455 !strcmp ("Invoke", klass->methods [i]->name)) {
1456 im = klass->methods [i];
1466 * mono_runtime_delegate_invoke:
1467 * @delegate: pointer to a delegate object.
1468 * @params: parameters for the delegate.
1469 * @exc: Pointer to the exception result.
1471 * Invokes the delegate method @delegate with the parameters provided.
1473 * You can pass NULL as the exc argument if you don't want to
1474 * catch exceptions, otherwise, *exc will be set to the exception
1475 * thrown, if any. if an exception is thrown, you can't use the
1476 * MonoObject* result from the function.
1479 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1483 im = mono_get_delegate_invoke (delegate->vtable->klass);
1486 return mono_runtime_invoke (im, delegate, params, exc);
1489 static MonoArray* main_args;
1492 * mono_runtime_get_main_args:
1494 * Returns: a MonoArray with the arguments passed to the main program
1497 mono_runtime_get_main_args (void)
1503 fire_process_exit_event (void)
1505 MonoClassField *field;
1506 MonoDomain *domain = mono_domain_get ();
1508 MonoObject *delegate, *exc;
1510 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1513 if (domain != mono_get_root_domain ())
1516 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1517 if (delegate == NULL)
1522 mono_runtime_delegate_invoke (delegate, pa, &exc);
1526 * mono_runtime_run_main:
1527 * @method: the method to start the application with (usually Main)
1528 * @argc: number of arguments from the command line
1529 * @argv: array of strings from the command line
1530 * @exc: excetption results
1532 * Execute a standard Main() method (argc/argv contains the
1533 * executable name). This method also sets the command line argument value
1534 * needed by System.Environment.
1539 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1543 MonoArray *args = NULL;
1544 MonoDomain *domain = mono_domain_get ();
1545 gchar *utf8_fullpath;
1548 main_thread = mono_thread_current ();
1550 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1552 if (!g_path_is_absolute (argv [0])) {
1553 gchar *basename = g_path_get_basename (argv [0]);
1554 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1558 utf8_fullpath = mono_utf8_from_external (fullpath);
1559 if(utf8_fullpath == NULL) {
1560 /* Printing the arg text will cause glib to
1561 * whinge about "Invalid UTF-8", but at least
1562 * its relevant, and shows the problem text
1565 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1566 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1573 utf8_fullpath = mono_utf8_from_external (argv[0]);
1574 if(utf8_fullpath == NULL) {
1575 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1576 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1581 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1582 g_free (utf8_fullpath);
1584 for (i = 1; i < argc; ++i) {
1588 utf8_arg=mono_utf8_from_external (argv[i]);
1589 if(utf8_arg==NULL) {
1590 /* Ditto the comment about Invalid UTF-8 here */
1591 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1592 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1596 arg = mono_string_new (domain, utf8_arg);
1597 mono_array_set (main_args, gpointer, i, arg);
1602 if (method->signature->param_count) {
1603 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1604 for (i = 0; i < argc; ++i) {
1605 /* The encodings should all work, given that
1606 * we've checked all these args for the
1609 gchar *str = mono_utf8_from_external (argv [i]);
1610 MonoString *arg = mono_string_new (domain, str);
1611 mono_array_set (args, gpointer, i, arg);
1615 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1618 mono_assembly_set_main (method->klass->image->assembly);
1620 result = mono_runtime_exec_main (method, args, exc);
1621 fire_process_exit_event ();
1625 /* Used in mono_unhandled_exception */
1627 create_unhandled_exception_eventargs (MonoObject *exc)
1631 MonoMethod *method = NULL;
1632 MonoBoolean is_terminating = TRUE;
1636 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1639 mono_class_init (klass);
1641 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1642 for (i = 0; i < klass->method.count; ++i) {
1643 method = klass->methods [i];
1644 if (!strcmp (".ctor", method->name) &&
1645 method->signature->param_count == 2 &&
1646 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1654 args [1] = &is_terminating;
1656 obj = mono_object_new (mono_domain_get (), klass);
1657 mono_runtime_invoke (method, obj, args, NULL);
1663 * mono_unhandled_exception:
1664 * @exc: exception thrown
1666 * This is a VM internal routine.
1668 * We call this function when we detect an unhandled exception
1669 * in the default domain.
1671 * It invokes the * UnhandledException event in AppDomain or prints
1672 * a warning to the console
1675 mono_unhandled_exception (MonoObject *exc)
1677 MonoDomain *domain = mono_domain_get ();
1678 MonoClassField *field;
1679 MonoObject *delegate;
1681 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1682 "UnhandledException");
1685 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1686 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1688 /* set exitcode only in the main thread */
1689 if (mono_thread_current () == main_thread)
1690 mono_environment_exitcode_set (1);
1691 if (domain != mono_get_root_domain () || !delegate) {
1692 mono_print_unhandled_exception (exc);
1694 MonoObject *e = NULL;
1697 pa [0] = domain->domain;
1698 pa [1] = create_unhandled_exception_eventargs (exc);
1699 mono_runtime_delegate_invoke (delegate, pa, &e);
1702 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1703 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1711 * Launch a new thread to start all setup that requires managed code
1714 * main_func is called back from the thread with main_args as the
1715 * parameter. The callback function is expected to start Main()
1716 * eventually. This function then waits for all managed threads to
1720 mono_runtime_exec_managed_code (MonoDomain *domain,
1721 MonoMainThreadFunc main_func,
1724 mono_thread_create (domain, main_func, main_args);
1726 mono_thread_manage ();
1730 * Execute a standard Main() method (args doesn't contain the
1734 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1744 domain = mono_object_domain (args);
1745 if (!domain->entry_assembly) {
1747 gchar *config_suffix;
1748 MonoAssembly *assembly;
1750 assembly = method->klass->image->assembly;
1751 domain->entry_assembly = assembly;
1752 domain->setup->application_base = mono_string_new (domain, assembly->basedir);
1754 config_suffix = g_strconcat (assembly->aname.name, ".exe.config", NULL);
1755 str = g_build_filename (assembly->basedir, config_suffix, NULL);
1756 g_free (config_suffix);
1757 domain->setup->configuration_file = mono_string_new (domain, str);
1761 /* FIXME: check signature of method */
1762 if (method->signature->ret->type == MONO_TYPE_I4) {
1764 res = mono_runtime_invoke (method, NULL, pa, exc);
1766 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1770 mono_environment_exitcode_set (rval);
1772 mono_runtime_invoke (method, NULL, pa, exc);
1776 /* If the return type of Main is void, only
1777 * set the exitcode if an exception was thrown
1778 * (we don't want to blow away an
1779 * explicitly-set exit code)
1782 mono_environment_exitcode_set (rval);
1790 * mono_install_runtime_invoke:
1791 * @func: Function to install
1793 * This is a VM internal routine
1796 mono_install_runtime_invoke (MonoInvokeFunc func)
1798 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1802 * mono_runtime_invoke_array:
1803 * @method: method to invoke
1804 * @obJ: object instance
1805 * @params: arguments to the method
1806 * @exc: exception information.
1808 * Invokes the method represented by @method on the object @obj.
1810 * obj is the 'this' pointer, it should be NULL for static
1811 * methods, a MonoObject* for object instances and a pointer to
1812 * the value type for value types.
1814 * The params array contains the arguments to the method with the
1815 * same convention: MonoObject* pointers for object instances and
1816 * pointers to the value type otherwise. The _invoke_array
1817 * variant takes a C# object[] as the params argument (MonoArray
1818 * *params): in this case the value types are boxed inside the
1819 * respective reference representation.
1821 * From unmanaged code you'll usually use the
1822 * mono_runtime_invoke() variant.
1824 * Note that this function doesn't handle virtual methods for
1825 * you, it will exec the exact method you pass: we still need to
1826 * expose a function to lookup the derived class implementation
1827 * of a virtual method (there are examples of this in the code,
1830 * You can pass NULL as the exc argument if you don't want to
1831 * catch exceptions, otherwise, *exc will be set to the exception
1832 * thrown, if any. if an exception is thrown, you can't use the
1833 * MonoObject* result from the function.
1835 * If the method returns a value type, it is boxed in an object
1839 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1842 MonoMethodSignature *sig = method->signature;
1843 gpointer *pa = NULL;
1846 if (NULL != params) {
1847 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1848 for (i = 0; i < mono_array_length (params); i++) {
1849 if (sig->params [i]->byref) {
1853 switch (sig->params [i]->type) {
1856 case MONO_TYPE_BOOLEAN:
1859 case MONO_TYPE_CHAR:
1868 case MONO_TYPE_VALUETYPE:
1869 /* MS seems to create the objects if a null is passed in */
1870 if (! ((gpointer *)params->vector)[i])
1871 ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
1872 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1874 case MONO_TYPE_STRING:
1875 case MONO_TYPE_OBJECT:
1876 case MONO_TYPE_CLASS:
1877 case MONO_TYPE_ARRAY:
1878 case MONO_TYPE_SZARRAY:
1879 if (sig->params [i]->byref)
1880 pa [i] = &(((gpointer *)params->vector)[i]);
1882 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1885 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1890 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1893 obj = mono_object_new (mono_domain_get (), method->klass);
1894 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1895 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
1897 if (method->klass->valuetype)
1898 o = mono_object_unbox (obj);
1902 mono_runtime_invoke (method, o, pa, exc);
1905 /* obj must be already unboxed if needed */
1906 return mono_runtime_invoke (method, obj, pa, exc);
1911 arith_overflow (void)
1913 mono_raise_exception (mono_get_exception_overflow ());
1917 * mono_object_allocate:
1918 * @size: number of bytes to allocate
1920 * This is a very simplistic routine until we have our GC-aware
1923 * Returns: an allocated object of size @size, or NULL on failure.
1925 static inline void *
1926 mono_object_allocate (size_t size)
1929 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1930 void *o = GC_MALLOC (size);
1932 void *o = calloc (1, size);
1934 return mono_gc_out_of_memory (size);
1936 mono_stats.new_object_count++;
1941 #if CREATION_SPEEDUP
1942 static inline void *
1943 mono_object_allocate_spec (size_t size, void *gcdescr)
1945 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1946 void *o = GC_GCJ_MALLOC (size, gcdescr);
1947 mono_stats.new_object_count++;
1955 * @klass: the class of the object that we want to create
1957 * Returns: a newly created object whose definition is
1958 * looked up using @klass. This will not invoke any constructors,
1959 * so the consumer of this routine has to invoke any constructors on
1960 * its own to initialize the object.
1963 mono_object_new (MonoDomain *domain, MonoClass *klass)
1965 MONO_ARCH_SAVE_REGS;
1966 return mono_object_new_specific (mono_class_vtable (domain, klass));
1970 * mono_object_new_specific:
1971 * @vtable: the vtable of the object that we want to create
1973 * Returns: A newly created object with class and domain specified
1977 mono_object_new_specific (MonoVTable *vtable)
1981 MONO_ARCH_SAVE_REGS;
1986 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1989 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1993 mono_class_init (klass);
1995 for (i = 0; i < klass->method.count; ++i) {
1996 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1997 klass->methods [i]->signature->param_count == 1) {
1998 im = klass->methods [i];
2003 vtable->domain->create_proxy_for_type_method = im;
2006 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
2008 o = mono_runtime_invoke (im, NULL, pa, NULL);
2009 if (o != NULL) return o;
2012 return mono_object_new_alloc_specific (vtable);
2016 mono_object_new_alloc_specific (MonoVTable *vtable)
2020 #if CREATION_SPEEDUP
2021 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2022 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
2024 /* printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2025 o = mono_object_allocate (vtable->klass->instance_size);
2029 o = mono_object_allocate (vtable->klass->instance_size);
2032 if (vtable->klass->has_finalize)
2033 mono_object_register_finalizer (o);
2035 mono_profiler_allocation (o, vtable->klass);
2039 #if CREATION_SPEEDUP
2042 mono_object_new_fast (MonoVTable *vtable)
2044 return GC_GCJ_MALLOC (vtable->klass->instance_size, vtable);
2050 * mono_class_get_allocation_ftn:
2052 * @pass_size_in_words:
2054 * Return the allocation function appropriate for the given class.
2058 mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean *pass_size_in_words)
2060 *pass_size_in_words = FALSE;
2062 if (vtable->klass->has_finalize || vtable->klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
2063 return mono_object_new_specific;
2065 #if CREATION_SPEEDUP
2066 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2068 return mono_object_new_fast;
2071 * FIXME: This is actually slower than mono_object_new_fast, because
2072 * of the overhead of parameter passing.
2075 *pass_size_in_words = TRUE;
2076 #ifdef GC_REDIRECT_TO_LOCAL
2077 return GC_local_gcj_fast_malloc;
2079 return GC_gcj_fast_malloc;
2085 return mono_object_new_specific;
2089 * mono_object_new_from_token:
2090 * @image: Context where the type_token is hosted
2091 * @token: a token of the type that we want to create
2093 * Returns: A newly created object whose definition is
2094 * looked up using @token in the @image image
2097 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
2101 class = mono_class_get (image, token);
2103 return mono_object_new (domain, class);
2108 * mono_object_clone:
2109 * @obj: the object to clone
2111 * Returns: A newly created object who is a shallow copy of @obj
2114 mono_object_clone (MonoObject *obj)
2119 size = obj->vtable->klass->instance_size;
2120 o = mono_object_allocate (size);
2121 mono_profiler_allocation (o, obj->vtable->klass);
2123 memcpy (o, obj, size);
2125 if (obj->vtable->klass->has_finalize)
2126 mono_object_register_finalizer (o);
2131 * mono_array_full_copy:
2132 * @src: source array to copy
2133 * @dest: destination array
2135 * Copies the content of one array to another with exactly the same type and size.
2138 mono_array_full_copy (MonoArray *src, MonoArray *dest)
2141 MonoClass *klass = src->obj.vtable->klass;
2143 MONO_ARCH_SAVE_REGS;
2145 g_assert (klass == dest->obj.vtable->klass);
2147 size = mono_array_length (src);
2148 g_assert (size == mono_array_length (dest));
2149 size *= mono_array_element_size (klass);
2150 memcpy (&dest->vector, &src->vector, size);
2154 * mono_array_clone_in_domain:
2155 * @domain: the domain in which the array will be cloned into
2156 * @array: the array to clone
2158 * This routine returns a copy of the array that is hosted on the
2159 * specified MonoDomain.
2162 mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
2167 MonoClass *klass = array->obj.vtable->klass;
2169 MONO_ARCH_SAVE_REGS;
2171 if (array->bounds == NULL) {
2172 size = mono_array_length (array);
2173 o = mono_array_new_full (domain, klass, &size, NULL);
2175 size *= mono_array_element_size (klass);
2176 memcpy (&o->vector, &array->vector, size);
2180 sizes = alloca (klass->rank * sizeof(guint32) * 2);
2181 size = mono_array_element_size (klass);
2182 for (i = 0; i < klass->rank; ++i) {
2183 sizes [i] = array->bounds [i].length;
2184 size *= array->bounds [i].length;
2185 sizes [i + klass->rank] = array->bounds [i].lower_bound;
2187 o = mono_array_new_full (domain, klass, sizes, sizes + klass->rank);
2188 memcpy (&o->vector, &array->vector, size);
2195 * @array: the array to clone
2197 * Returns: A newly created array who is a shallow copy of @array
2200 mono_array_clone (MonoArray *array)
2202 return mono_array_clone_in_domain (((MonoObject *)array)->vtable->domain, array);
2205 /* helper macros to check for overflow when calculating the size of arrays */
2206 #define MYGUINT32_MAX 4294967295U
2207 #define CHECK_ADD_OVERFLOW_UN(a,b) \
2208 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
2209 #define CHECK_MUL_OVERFLOW_UN(a,b) \
2210 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
2211 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
2214 * mono_array_new_full:
2215 * @domain: domain where the object is created
2216 * @array_class: array class
2217 * @lengths: lengths for each dimension in the array
2218 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
2220 * This routine creates a new array objects with the given dimensions,
2221 * lower bounds and type.
2224 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
2225 guint32 *lengths, guint32 *lower_bounds)
2227 guint32 byte_len, len;
2230 MonoArrayBounds *bounds;
2234 if (!array_class->inited)
2235 mono_class_init (array_class);
2237 byte_len = mono_array_element_size (array_class);
2240 if (array_class->rank == 1 &&
2241 (lower_bounds == NULL || lower_bounds [0] == 0)) {
2248 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
2250 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
2252 for (i = 0; i < array_class->rank; ++i)
2253 if ((int) lengths [i] < 0)
2256 for (i = 0; i < array_class->rank; ++i) {
2257 bounds [i].length = lengths [i];
2258 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
2259 mono_gc_out_of_memory (MYGUINT32_MAX);
2264 for (i = 0; i < array_class->rank; ++i)
2265 bounds [i].lower_bound = lower_bounds [i];
2268 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
2269 mono_gc_out_of_memory (MYGUINT32_MAX);
2271 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2272 mono_gc_out_of_memory (MYGUINT32_MAX);
2273 byte_len += sizeof (MonoArray);
2275 * Following three lines almost taken from mono_object_new ():
2276 * they need to be kept in sync.
2278 vtable = mono_class_vtable (domain, array_class);
2279 #if CREATION_SPEEDUP
2280 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2281 o = mono_object_allocate_spec (byte_len, vtable);
2283 o = mono_object_allocate (byte_len);
2287 o = mono_object_allocate (byte_len);
2291 array = (MonoArray*)o;
2293 array->bounds = bounds;
2294 array->max_length = len;
2296 mono_profiler_allocation (o, array_class);
2303 * @domain: domain where the object is created
2304 * @eclass: element class
2305 * @n: number of array elements
2307 * This routine creates a new szarray with @n elements of type @eclass.
2310 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
2314 MONO_ARCH_SAVE_REGS;
2316 ac = mono_array_class_get (eclass, 1);
2317 g_assert (ac != NULL);
2319 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
2323 * mono_array_new_specific:
2324 * @vtable: a vtable in the appropriate domain for an initialized class
2325 * @n: number of array elements
2327 * This routine is a fast alternative to mono_array_new() for code which
2328 * can be sure about the domain it operates in.
2331 mono_array_new_specific (MonoVTable *vtable, guint32 n)
2335 guint32 byte_len, elem_size;
2337 MONO_ARCH_SAVE_REGS;
2342 elem_size = mono_array_element_size (vtable->klass);
2343 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
2344 mono_gc_out_of_memory (MYGUINT32_MAX);
2345 byte_len = n * elem_size;
2346 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2347 mono_gc_out_of_memory (MYGUINT32_MAX);
2348 byte_len += sizeof (MonoArray);
2349 #if CREATION_SPEEDUP
2350 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2351 o = mono_object_allocate_spec (byte_len, vtable);
2353 /* printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2354 o = mono_object_allocate (byte_len);
2358 o = mono_object_allocate (byte_len);
2362 ao = (MonoArray *)o;
2365 mono_profiler_allocation (o, vtable->klass);
2371 * mono_string_new_utf16:
2372 * @text: a pointer to an utf16 string
2373 * @len: the length of the string
2375 * Returns: A newly created string object which contains @text.
2378 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
2382 s = mono_string_new_size (domain, len);
2383 g_assert (s != NULL);
2385 memcpy (mono_string_chars (s), text, len * 2);
2391 * mono_string_new_size:
2392 * @text: a pointer to an utf16 string
2393 * @len: the length of the string
2395 * Returns: A newly created string object of @len
2398 mono_string_new_size (MonoDomain *domain, gint32 len)
2402 size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2404 /* overflow ? can't fit it, can't allocate it! */
2406 mono_gc_out_of_memory (-1);
2408 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2410 #if CREATION_SPEEDUP
2411 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2412 s = mono_object_allocate_spec (size, vtable);
2414 s = (MonoString*)mono_object_allocate (size);
2415 s->object.vtable = vtable;
2418 s = (MonoString*)mono_object_allocate (size);
2419 s->object.vtable = vtable;
2423 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2429 * mono_string_new_len:
2430 * @text: a pointer to an utf8 string
2431 * @length: number of bytes in @text to consider
2433 * Returns: A newly created string object which contains @text.
2436 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2438 GError *error = NULL;
2439 MonoString *o = NULL;
2441 glong items_written;
2443 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2446 o = mono_string_new_utf16 (domain, ut, items_written);
2448 g_error_free (error);
2457 * @text: a pointer to an utf8 string
2459 * Returns: A newly created string object which contains @text.
2462 mono_string_new (MonoDomain *domain, const char *text)
2464 GError *error = NULL;
2465 MonoString *o = NULL;
2467 glong items_written;
2472 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2475 o = mono_string_new_utf16 (domain, ut, items_written);
2477 g_error_free (error);
2485 * mono_string_new_wrapper:
2486 * @text: pointer to utf8 characters.
2488 * Helper function to create a string object from @text in the current domain.
2491 mono_string_new_wrapper (const char *text)
2493 MonoDomain *domain = mono_domain_get ();
2495 MONO_ARCH_SAVE_REGS;
2498 return mono_string_new (domain, text);
2505 * @class: the class of the value
2506 * @value: a pointer to the unboxed data
2508 * Returns: A newly created object which contains @value.
2511 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2517 g_assert (class->valuetype);
2519 vtable = mono_class_vtable (domain, class);
2520 size = mono_class_instance_size (class);
2521 res = mono_object_allocate (size);
2522 res->vtable = vtable;
2523 mono_profiler_allocation (res, class);
2525 size = size - sizeof (MonoObject);
2527 #if NO_UNALIGNED_ACCESS
2528 memcpy ((char *)res + sizeof (MonoObject), value, size);
2532 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2535 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2538 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2541 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2544 memcpy ((char *)res + sizeof (MonoObject), value, size);
2547 if (class->has_finalize)
2548 mono_object_register_finalizer (res);
2553 * mono_object_get_domain:
2554 * @obj: object to query
2556 * Returns: the MonoDomain where the object is hosted
2559 mono_object_get_domain (MonoObject *obj)
2561 return mono_object_domain (obj);
2565 * mono_object_get_class:
2566 * @obj: object to query
2568 * Returns: the MonOClass of the object.
2571 mono_object_get_class (MonoObject *obj)
2573 return mono_object_class (obj);
2577 * mono_object_unbox:
2578 * @obj: object to unbox
2580 * Returns: a pointer to the start of the valuetype boxed in this
2583 * This method will assert if the object passed is not a valuetype.
2586 mono_object_unbox (MonoObject *obj)
2588 /* add assert for valuetypes? */
2589 g_assert (obj->vtable->klass->valuetype);
2590 return ((char*)obj) + sizeof (MonoObject);
2594 * mono_object_isinst:
2596 * @klass: a pointer to a class
2598 * Returns: @obj if @obj is derived from @klass
2601 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2604 mono_class_init (klass);
2606 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2607 return mono_object_isinst_mbyref (obj, klass);
2612 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2616 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2625 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2626 if ((klass->interface_id <= vt->max_interface_id) &&
2627 (vt->interface_offsets [klass->interface_id] != 0))
2631 MonoClass *oklass = vt->klass;
2632 if ((oklass == mono_defaults.transparent_proxy_class))
2633 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2635 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2639 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2641 MonoDomain *domain = mono_domain_get ();
2643 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2644 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2645 MonoMethod *im = NULL;
2649 for (i = 0; i < rpklass->method.count; ++i) {
2650 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2651 im = rpklass->methods [i];
2656 im = mono_object_get_virtual_method (rp, im);
2659 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2662 res = mono_runtime_invoke (im, rp, pa, NULL);
2664 if (*(MonoBoolean *) mono_object_unbox(res)) {
2665 /* Update the vtable of the remote type, so it can safely cast to this new type */
2666 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2667 obj->vtable = mono_remote_class_vtable (domain, ((MonoTransparentProxy *)obj)->remote_class, (MonoRealProxy *)rp);
2676 * mono_object_castclass_mbyref:
2678 * @klass: a pointer to a class
2680 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2683 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2685 if (!obj) return NULL;
2686 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2688 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2690 "InvalidCastException"));
2695 MonoDomain *orig_domain;
2701 str_lookup (MonoDomain *domain, gpointer user_data)
2703 LDStrInfo *info = user_data;
2704 if (info->res || domain == info->orig_domain)
2706 mono_domain_lock (domain);
2707 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2708 mono_domain_unlock (domain);
2712 mono_string_is_interned_lookup (MonoString *str, int insert)
2714 MonoGHashTable *ldstr_table;
2717 char *ins = g_malloc (4 + str->length * 2);
2720 /* Encode the length */
2721 /* Same code as in mono_image_insert_string () */
2723 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2726 * ins is stored in the hash table as a key and needs to have the same
2727 * representation as in the metadata: we swap the character bytes on big
2730 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2733 char *p2 = (char *)mono_string_chars (str);
2734 for (i = 0; i < str->length; ++i) {
2741 memcpy (p, mono_string_chars (str), str->length * 2);
2743 domain = ((MonoObject *)str)->vtable->domain;
2744 ldstr_table = domain->ldstr_table;
2745 mono_domain_lock (domain);
2746 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2747 mono_domain_unlock (domain);
2752 mono_g_hash_table_insert (ldstr_table, ins, str);
2753 mono_domain_unlock (domain);
2756 LDStrInfo ldstr_info;
2757 ldstr_info.orig_domain = domain;
2758 ldstr_info.ins = ins;
2759 ldstr_info.res = NULL;
2761 mono_domain_foreach (str_lookup, &ldstr_info);
2762 if (ldstr_info.res) {
2764 * the string was already interned in some other domain:
2765 * intern it in the current one as well.
2767 mono_g_hash_table_insert (ldstr_table, ins, str);
2768 mono_domain_unlock (domain);
2772 mono_domain_unlock (domain);
2778 * mono_string_is_interned:
2779 * @o: String to probe
2781 * Returns whether the string has been interned.
2784 mono_string_is_interned (MonoString *o)
2786 return mono_string_is_interned_lookup (o, FALSE);
2790 * mono_string_interne:
2791 * @o: String to intern
2793 * Interns the string passed.
2794 * Returns: The interned string.
2797 mono_string_intern (MonoString *str)
2799 return mono_string_is_interned_lookup (str, TRUE);
2804 * @domain: the domain where the string will be used.
2805 * @image: a metadata context
2806 * @idx: index into the user string table.
2808 * Implementation for the ldstr opcode.
2809 * Returns: a loaded string from the @image/@idx combination.
2812 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2814 MONO_ARCH_SAVE_REGS;
2817 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2819 return mono_ldstr_metdata_sig (domain, mono_metadata_user_string (image, idx));
2823 * mono_ldstr_metdata_sig
2824 * @domain: the domain for the string
2825 * @sig: the signature of a metadata string
2827 * Returns: a MonoString for a string stored in the metadata
2830 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig)
2832 const char *str = sig;
2836 mono_domain_lock (domain);
2837 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2838 mono_domain_unlock (domain);
2842 len2 = mono_metadata_decode_blob_size (str, &str);
2845 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2846 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2849 guint16 *p2 = (guint16*)mono_string_chars (o);
2850 for (i = 0; i < len2; ++i) {
2851 *p2 = GUINT16_FROM_LE (*p2);
2856 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2857 mono_domain_unlock (domain);
2863 * mono_string_to_utf8:
2864 * @s: a System.String
2866 * Return the UTF8 representation for @s.
2867 * the resulting buffer nedds to be freed with g_free().
2870 mono_string_to_utf8 (MonoString *s)
2873 GError *error = NULL;
2879 return g_strdup ("");
2881 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2883 g_warning (error->message);
2884 g_error_free (error);
2891 * mono_string_to_utf16:
2894 * Return an null-terminated array of the utf-16 chars
2895 * contained in @s. The result must be freed with g_free().
2896 * This is a temporary helper until our string implementation
2897 * is reworked to always include the null terminating char.
2900 mono_string_to_utf16 (MonoString *s)
2907 as = g_malloc ((s->length * 2) + 2);
2908 as [(s->length * 2)] = '\0';
2909 as [(s->length * 2) + 1] = '\0';
2912 return (gunichar2 *)(as);
2915 memcpy (as, mono_string_chars(s), s->length * 2);
2916 return (gunichar2 *)(as);
2920 * mono_string_from_utf16:
2921 * @data: the UTF16 string (LPWSTR) to convert
2923 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString.
2925 * Returns: a MonoString.
2928 mono_string_from_utf16 (gunichar2 *data)
2930 MonoDomain *domain = mono_domain_get ();
2936 while (data [len]) len++;
2938 return mono_string_new_utf16 (domain, data, len);
2942 default_ex_handler (MonoException *ex)
2944 MonoObject *o = (MonoObject*)ex;
2945 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2949 static MonoExceptionFunc ex_handler = default_ex_handler;
2952 * mono_install_handler:
2953 * @func: exception handler
2955 * This is an internal JIT routine used to install the handler for exceptions
2959 mono_install_handler (MonoExceptionFunc func)
2961 ex_handler = func? func: default_ex_handler;
2965 * mono_raise_exception:
2966 * @ex: exception object
2968 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2971 mono_raise_exception (MonoException *ex)
2974 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2975 * that will cause gcc to omit the function epilog, causing problems when
2976 * the JIT tries to walk the stack, since the return address on the stack
2977 * will point into the next function in the executable, not this one.
2980 if (((MonoObject*)ex)->vtable->klass == mono_defaults.threadabortexception_class)
2981 mono_thread_current ()->abort_exc = ex;
2987 * mono_wait_handle_new:
2988 * @domain: Domain where the object will be created
2989 * @handle: Handle for the wait handle
2991 * Returns: A new MonoWaitHandle created in the given domain for the given handle
2994 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2996 MonoWaitHandle *res;
2998 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
3000 res->handle = handle;
3006 * mono_async_result_new:
3007 * @domain:domain where the object will be created.
3008 * @handle: wait handle.
3009 * @state: state to pass to AsyncResult
3010 * @data: C closure data.
3012 * Creates a new MonoAsyncResult (AsyncResult C# class) in the given domain.
3013 * If the handle is not null, the handle is initialized to a MonOWaitHandle.
3017 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
3019 MonoAsyncResult *res;
3021 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
3024 res->async_state = state;
3026 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
3028 res->sync_completed = FALSE;
3029 res->completed = FALSE;
3035 mono_message_init (MonoDomain *domain,
3036 MonoMethodMessage *this,
3037 MonoReflectionMethod *method,
3038 MonoArray *out_args)
3040 MonoMethodSignature *sig = method->method->signature;
3046 this->method = method;
3048 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
3049 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
3050 this->async_result = NULL;
3051 this->call_type = CallType_Sync;
3053 names = g_new (char *, sig->param_count);
3054 mono_method_get_param_names (method->method, (const char **) names);
3055 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
3057 for (i = 0; i < sig->param_count; i++) {
3058 name = mono_string_new (domain, names [i]);
3059 mono_array_set (this->names, gpointer, i, name);
3063 for (i = 0, j = 0; i < sig->param_count; i++) {
3065 if (sig->params [i]->byref) {
3067 gpointer arg = mono_array_get (out_args, gpointer, j);
3068 mono_array_set (this->args, gpointer, i, arg);
3072 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
3077 mono_array_set (this->arg_types, guint8, i, arg_type);
3082 * mono_remoting_invoke:
3083 * @real_proxy: pointer to a RealProxy object
3084 * @msg: The MonoMethodMessage to execute
3085 * @exc: used to store exceptions
3086 * @out_args: used to store output arguments
3088 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
3089 * IMessage interface and it is not trivial to extract results from there. So
3090 * we call an helper method PrivateInvoke instead of calling
3091 * RealProxy::Invoke() directly.
3093 * Returns: the result object.
3096 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
3097 MonoObject **exc, MonoArray **out_args)
3099 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
3102 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
3108 klass = mono_defaults.real_proxy_class;
3110 for (i = 0; i < klass->method.count; ++i) {
3111 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
3112 klass->methods [i]->signature->param_count == 4) {
3113 im = klass->methods [i];
3119 real_proxy->vtable->domain->private_invoke_method = im;
3122 pa [0] = real_proxy;
3127 return mono_runtime_invoke (im, NULL, pa, exc);
3131 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
3132 MonoObject **exc, MonoArray **out_args)
3136 MonoMethodSignature *sig;
3138 int i, j, outarg_count = 0;
3140 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
3142 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
3143 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3144 target = tp->rp->unwrapped_server;
3146 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
3150 domain = mono_domain_get ();
3151 method = msg->method->method;
3152 sig = method->signature;
3154 for (i = 0; i < sig->param_count; i++) {
3155 if (sig->params [i]->byref)
3159 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3162 ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
3164 for (i = 0, j = 0; i < sig->param_count; i++) {
3165 if (sig->params [i]->byref) {
3167 arg = mono_array_get (msg->args, gpointer, i);
3168 mono_array_set (*out_args, gpointer, j, arg);
3177 * mono_print_unhandled_exception:
3178 * @exc: The exception
3180 * Prints the unhandled exception.
3183 mono_print_unhandled_exception (MonoObject *exc)
3185 char *message = (char *) "";
3189 gboolean free_message = FALSE;
3192 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
3193 klass = exc->vtable->klass;
3195 while (klass && method == NULL) {
3196 for (i = 0; i < klass->method.count; ++i) {
3197 method = klass->methods [i];
3198 if (!strcmp ("ToString", method->name) &&
3199 method->signature->param_count == 0 &&
3200 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
3201 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
3208 klass = klass->parent;
3213 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
3215 message = mono_string_to_utf8 (str);
3216 free_message = TRUE;
3221 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
3222 * exc->vtable->klass->name, message);
3224 g_printerr ("\nUnhandled Exception: %s\n", message);
3231 * mono_delegate_ctor:
3232 * @this: pointer to an uninitialized delegate object
3233 * @target: target object
3234 * @addr: pointer to native code
3236 * This is used to initialize a delegate. We also insert the method_info if
3237 * we find the info with mono_jit_info_table_find().
3240 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
3242 MonoDomain *domain = mono_domain_get ();
3243 MonoDelegate *delegate = (MonoDelegate *)this;
3244 MonoMethod *method = NULL;
3251 class = this->vtable->klass;
3253 if ((ji = mono_jit_info_table_find (domain, addr))) {
3254 method = ji->method;
3255 delegate->method_info = mono_method_get_object (domain, method, NULL);
3258 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
3260 method = mono_marshal_get_remoting_invoke (method);
3261 delegate->method_ptr = mono_compile_method (method);
3262 delegate->target = target;
3263 } else if (method->signature->hasthis && method->klass->valuetype) {
3264 method = mono_marshal_get_unbox_wrapper (method);
3265 delegate->method_ptr = mono_compile_method (method);
3266 delegate->target = target;
3268 delegate->method_ptr = addr;
3269 delegate->target = target;
3274 * mono_method_call_message_new:
3275 * @method: method to encapsulate
3276 * @params: parameters to the method
3277 * @invoke: optional, delegate invoke.
3278 * @cb: async callback delegate.
3279 * @state: state passed to the async callback.
3281 * Translates arguments pointers into a MonoMethodMessage.
3284 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
3285 MonoDelegate **cb, MonoObject **state)
3287 MonoDomain *domain = mono_domain_get ();
3288 MonoMethodSignature *sig = method->signature;
3289 MonoMethodMessage *msg;
3292 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3295 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
3296 count = sig->param_count - 2;
3298 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
3299 count = sig->param_count;
3302 for (i = 0; i < count; i++) {
3307 if (sig->params [i]->byref)
3308 vpos = *((gpointer *)params [i]);
3312 type = sig->params [i]->type;
3313 class = mono_class_from_mono_type (sig->params [i]);
3315 if (class->valuetype)
3316 arg = mono_value_box (domain, class, vpos);
3318 arg = *((MonoObject **)vpos);
3320 mono_array_set (msg->args, gpointer, i, arg);
3323 if (cb != NULL && state != NULL) {
3324 *cb = *((MonoDelegate **)params [i]);
3326 *state = *((MonoObject **)params [i]);
3333 * mono_method_return_message_restore:
3335 * Restore results from message based processing back to arguments pointers
3338 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
3340 MonoMethodSignature *sig = method->signature;
3341 int i, j, type, size;
3342 for (i = 0, j = 0; i < sig->param_count; i++) {
3343 MonoType *pt = sig->params [i];
3346 char *arg = mono_array_get (out_args, gpointer, j);
3350 case MONO_TYPE_VOID:
3351 g_assert_not_reached ();
3355 case MONO_TYPE_BOOLEAN:
3358 case MONO_TYPE_CHAR:
3365 case MONO_TYPE_VALUETYPE: {
3366 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
3367 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
3370 case MONO_TYPE_STRING:
3371 case MONO_TYPE_CLASS:
3372 case MONO_TYPE_ARRAY:
3373 case MONO_TYPE_SZARRAY:
3374 case MONO_TYPE_OBJECT:
3375 **((MonoObject ***)params [i]) = (MonoObject *)arg;
3378 g_assert_not_reached ();
3387 * mono_load_remote_field:
3388 * @this: pointer to an object
3389 * @klass: klass of the object containing @field
3390 * @field: the field to load
3391 * @res: a storage to store the result
3393 * This method is called by the runtime on attempts to load fields of
3394 * transparent proxy objects. @this points to such TP, @klass is the class of
3395 * the object containing @field. @res is a storage location which can be
3396 * used to store the result.
3398 * Returns: an address pointing to the value of field.
3401 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
3403 static MonoMethod *getter = NULL;
3404 MonoDomain *domain = mono_domain_get ();
3405 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3406 MonoClass *field_class;
3407 MonoMethodMessage *msg;
3408 MonoArray *out_args;
3412 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3417 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3418 mono_field_get_value (tp->rp->unwrapped_server, field, res);
3425 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3426 MonoMethod *cm = mono_defaults.object_class->methods [i];
3428 if (!strcmp (cm->name, "FieldGetter")) {
3436 field_class = mono_class_from_mono_type (field->type);
3438 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3439 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3440 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3442 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3443 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3445 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3447 if (exc) mono_raise_exception ((MonoException *)exc);
3449 *res = mono_array_get (out_args, MonoObject *, 0);
3451 if (field_class->valuetype) {
3452 return ((char *)*res) + sizeof (MonoObject);
3458 * mono_load_remote_field_new:
3463 * Missing documentation.
3466 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
3468 static MonoMethod *getter = NULL;
3469 MonoDomain *domain = mono_domain_get ();
3470 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3471 MonoClass *field_class;
3472 MonoMethodMessage *msg;
3473 MonoArray *out_args;
3474 MonoObject *exc, *res;
3476 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3478 field_class = mono_class_from_mono_type (field->type);
3480 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3482 if (field_class->valuetype) {
3483 res = mono_object_new (domain, field_class);
3484 val = ((gchar *) res) + sizeof (MonoObject);
3488 mono_field_get_value (tp->rp->unwrapped_server, field, val);
3495 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3496 MonoMethod *cm = mono_defaults.object_class->methods [i];
3498 if (!strcmp (cm->name, "FieldGetter")) {
3506 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3507 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3508 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3510 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3511 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3513 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3515 if (exc) mono_raise_exception ((MonoException *)exc);
3517 res = mono_array_get (out_args, MonoObject *, 0);
3523 * mono_store_remote_field:
3524 * @this: pointer to an object
3525 * @klass: klass of the object containing @field
3526 * @field: the field to load
3527 * @val: the value/object to store
3529 * This method is called by the runtime on attempts to store fields of
3530 * transparent proxy objects. @this points to such TP, @klass is the class of
3531 * the object containing @field. @val is the new value to store in @field.
3534 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3536 static MonoMethod *setter = NULL;
3537 MonoDomain *domain = mono_domain_get ();
3538 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3539 MonoClass *field_class;
3540 MonoMethodMessage *msg;
3541 MonoArray *out_args;
3545 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3547 field_class = mono_class_from_mono_type (field->type);
3549 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3550 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3551 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3558 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3559 MonoMethod *cm = mono_defaults.object_class->methods [i];
3561 if (!strcmp (cm->name, "FieldSetter")) {
3569 if (field_class->valuetype)
3570 arg = mono_value_box (domain, field_class, val);
3572 arg = *((MonoObject **)val);
3575 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3576 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3578 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3579 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3580 mono_array_set (msg->args, gpointer, 2, arg);
3582 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3584 if (exc) mono_raise_exception ((MonoException *)exc);
3588 * mono_store_remote_field_new:
3594 * Missing documentation
3597 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3599 static MonoMethod *setter = NULL;
3600 MonoDomain *domain = mono_domain_get ();
3601 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3602 MonoClass *field_class;
3603 MonoMethodMessage *msg;
3604 MonoArray *out_args;
3607 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3609 field_class = mono_class_from_mono_type (field->type);
3611 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3612 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3613 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3620 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3621 MonoMethod *cm = mono_defaults.object_class->methods [i];
3623 if (!strcmp (cm->name, "FieldSetter")) {
3631 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3632 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3634 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3635 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3636 mono_array_set (msg->args, gpointer, 2, arg);
3638 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3640 if (exc) mono_raise_exception ((MonoException *)exc);