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 default_trampoline (MonoMethod *method)
275 default_remoting_trampoline (MonoMethod *method)
277 g_error ("remoting not installed");
281 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
282 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
285 mono_install_trampoline (MonoTrampoline func)
287 arch_create_jit_trampoline = func? func: default_trampoline;
291 mono_install_remoting_trampoline (MonoTrampoline func)
293 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
296 static MonoCompileFunc default_mono_compile_method = NULL;
299 mono_install_compile_method (MonoCompileFunc func)
301 default_mono_compile_method = func;
305 mono_compile_method (MonoMethod *method)
307 if (!default_mono_compile_method) {
308 g_error ("compile method called on uninitialized runtime");
311 return default_mono_compile_method (method);
314 static MonoFreeMethodFunc default_mono_free_method = NULL;
317 mono_install_free_method (MonoFreeMethodFunc func)
319 default_mono_free_method = func;
323 mono_runtime_free_method (MonoMethod *method)
325 if (default_mono_free_method != NULL)
326 default_mono_free_method (method);
329 * FIXME: This causes crashes because the types inside signatures and
332 /* mono_free_method (method); */
335 #if 0 && HAVE_BOEHM_GC
337 vtable_finalizer (void *obj, void *data) {
338 g_print ("%s finalized (%p)\n", (char*)data, obj);
344 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
347 * The vtables in the root appdomain are assumed to be reachable by other
348 * roots, and we don't use typed allocation in the other domains.
351 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
354 mono_class_compute_gc_descriptor (MonoClass *class)
356 MonoClassField *field;
360 static gboolean gcj_inited = FALSE;
365 GC_init_gcj_malloc (5, NULL);
367 mono_register_jit_icall (mono_object_new_fast, "mono_object_new_fast", mono_create_icall_signature ("object ptr"), FALSE);
369 #ifdef GC_REDIRECT_TO_LOCAL
370 mono_register_jit_icall (GC_local_gcj_malloc, "GC_local_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
371 mono_register_jit_icall (GC_local_gcj_fast_malloc, "GC_local_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
373 mono_register_jit_icall (GC_gcj_malloc, "GC_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
374 mono_register_jit_icall (GC_gcj_fast_malloc, "GC_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
378 mono_class_init (class);
380 if (class->gc_descr_inited)
383 class->gc_descr_inited = TRUE;
384 class->gc_descr = GC_NO_DESCRIPTOR;
386 if (class == mono_defaults.string_class) {
387 bitmap = GC_HEADER_BITMAP;
388 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
390 else if (class->rank) {
391 mono_class_compute_gc_descriptor (class->element_class);
393 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
394 bitmap = GC_HEADER_BITMAP;
396 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
397 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
401 static int count = 0;
405 /* GC 6.1 has trouble handling 64 bit descriptors... */
406 if ((class->instance_size / sizeof (gpointer)) > 30) {
407 /* printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer)); */
411 bitmap = GC_HEADER_BITMAP;
415 /* if (count > 442) */
418 /* printf("KLASS: %s.\n", class->name); */
420 for (p = class; p != NULL; p = p->parent) {
421 for (i = 0; i < p->field.count; ++i) {
422 field = &p->fields [i];
423 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
425 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
428 pos = field->offset / sizeof (gpointer);
430 if (field->type->byref)
433 switch (field->type->type) {
434 case MONO_TYPE_BOOLEAN:
446 /* printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap); */
449 case MONO_TYPE_STRING:
450 case MONO_TYPE_SZARRAY:
451 case MONO_TYPE_CLASS:
452 case MONO_TYPE_OBJECT:
453 case MONO_TYPE_ARRAY:
455 g_assert ((field->offset % sizeof(gpointer)) == 0);
457 bitmap |= ((guint64)1) << pos;
458 /* printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap); */
460 case MONO_TYPE_VALUETYPE: {
461 MonoClass *fclass = field->type->data.klass;
462 if (!fclass->enumtype) {
463 mono_class_compute_gc_descriptor (fclass);
464 bitmap |= (fclass->gc_bitmap >> (sizeof (MonoObject) / sizeof (gpointer))) << pos;
474 /* printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap); */
475 class->gc_bitmap = bitmap;
476 /* Convert to the format expected by GC_make_descriptor */
477 bm [0] = (guint32)bitmap;
478 bm [1] = (guint32)(bitmap >> 32);
479 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bm, class->instance_size / sizeof (gpointer));
482 #endif /* CREATION_SPEEDUP */
485 * field_is_special_static:
487 * Returns SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
488 * SPECIAL_STATIC_NONE otherwise.
491 field_is_special_static (MonoClass *fklass, MonoClassField *field)
493 MonoCustomAttrInfo *ainfo;
495 ainfo = mono_custom_attrs_from_field (fklass, field);
498 for (i = 0; i < ainfo->num_attrs; ++i) {
499 MonoClass *klass = ainfo->attrs [i].ctor->klass;
500 if (klass->image == mono_defaults.corlib) {
501 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
502 mono_custom_attrs_free (ainfo);
503 return SPECIAL_STATIC_THREAD;
505 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
506 mono_custom_attrs_free (ainfo);
507 return SPECIAL_STATIC_CONTEXT;
511 mono_custom_attrs_free (ainfo);
512 return SPECIAL_STATIC_NONE;
517 * @domain: the application domain
518 * @class: the class to initialize
520 * VTables are domain specific because we create domain specific code, and
521 * they contain the domain specific static class data.
524 mono_class_vtable (MonoDomain *domain, MonoClass *class)
526 MonoVTable *vt = NULL;
527 MonoClassField *field;
532 guint32 constant_cols [MONO_CONSTANT_SIZE];
536 vt = class->cached_vtable;
537 if (vt && vt->domain == domain)
540 mono_domain_lock (domain);
541 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
542 mono_domain_unlock (domain);
547 mono_class_init (class);
549 mono_stats.used_class_count++;
550 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
552 vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
554 vt = mono_mempool_alloc0 (domain->mp, vtable_size);
560 mono_class_compute_gc_descriptor (class);
561 if (domain != mono_get_root_domain ())
563 * We can't use typed allocation in the non-root domains, since the
564 * collector needs the GC descriptor stored in the vtable even after
565 * the mempool containing the vtable is destroyed when the domain is
566 * unloaded. An alternative might be to allocate vtables in the GC
567 * heap, but this does not seem to work (it leads to crashes inside
568 * libgc). If that approach is tried, two gc descriptors need to be
569 * allocated for each class: one for the root domain, and one for all
570 * other domains. The second descriptor should contain a bit for the
571 * vtable field in MonoObject, since we can no longer assume the
572 * vtable is reachable by other roots after the appdomain is unloaded.
574 vt->gc_descr = GC_NO_DESCRIPTOR;
576 vt->gc_descr = class->gc_descr;
579 if (class->class_size) {
581 vt->data = GC_MALLOC (class->class_size + 8);
582 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
583 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
584 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
586 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
589 mono_stats.class_static_data_size += class->class_size + 8;
593 for (i = class->field.first; i < class->field.last; ++i) {
594 field = &class->fields [i - class->field.first];
595 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
597 if (mono_field_is_deleted (field))
599 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
600 gint32 special_static = field_is_special_static (class, field);
601 if (special_static != SPECIAL_STATIC_NONE) {
602 guint32 size, align, offset;
603 size = mono_type_size (field->type, &align);
604 offset = mono_alloc_special_static_data (special_static, size, align);
605 if (!domain->special_static_fields)
606 domain->special_static_fields = g_hash_table_new (NULL, NULL);
607 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
611 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
612 MonoClass *fklass = mono_class_from_mono_type (field->type);
613 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT));
614 t = (char*)vt->data + field->offset;
615 if (fklass->valuetype) {
616 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
618 /* it's a pointer type: add check */
619 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
620 *t = *(char *)field->data;
624 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
629 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1), cindex + 1);
631 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
633 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
634 field->def_type = constant_cols [MONO_CONSTANT_TYPE];
635 field->data = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
638 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL))
639 get_default_field_value (domain, field, (char*)vt->data + field->offset);
642 vt->max_interface_id = class->max_interface_id;
644 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
645 sizeof (gpointer) * (class->max_interface_id + 1));
647 /* initialize interface offsets */
648 for (i = 0; i <= class->max_interface_id; ++i) {
649 int slot = class->interface_offsets [i];
651 vt->interface_offsets [i] = &(vt->vtable [slot]);
655 * arch_create_jit_trampoline () can recursively call this function again
656 * because it compiles icall methods right away.
658 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
659 if (!class->cached_vtable)
660 class->cached_vtable = vt;
662 /* initialize vtable */
663 for (i = 0; i < class->vtable_size; ++i) {
666 if ((cm = class->vtable [i]))
667 vt->vtable [i] = arch_create_jit_trampoline (cm);
670 mono_domain_unlock (domain);
672 /* make sure the the parent is initialized */
674 mono_class_vtable (domain, class->parent);
676 vt->type = mono_type_get_object (domain, &class->byval_arg);
677 if (class->contextbound)
686 * mono_class_proxy_vtable:
687 * @domain: the application domain
688 * @remove_class: the remote class
690 * Creates a vtable for transparent proxies. It is basically
691 * a copy of the real vtable of the class wrapped in @remote_class,
692 * but all function pointers invoke the remoting functions, and
693 * vtable->klass points to the transparent proxy class, and not to @class.
696 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class)
698 MonoVTable *vt, *pvt;
699 int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
701 MonoClass *class = remote_class->proxy_class;
703 vt = mono_class_vtable (domain, class);
704 max_interface_id = vt->max_interface_id;
706 /* Calculate vtable space for extra interfaces */
707 for (j = 0; j < remote_class->interface_count; j++) {
708 MonoClass* iclass = remote_class->interfaces[j];
709 int method_count = iclass->method.count;
711 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
712 continue; /* interface implemented by the class */
714 for (i = 0; i < iclass->interface_count; i++)
715 method_count += iclass->interfaces[i]->method.count;
717 extra_interface_vtsize += method_count * sizeof (gpointer);
718 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
721 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
723 mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
725 pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
726 memcpy (pvt, vt, vtsize);
728 pvt->klass = mono_defaults.transparent_proxy_class;
730 /* initialize vtable */
731 for (i = 0; i < class->vtable_size; ++i) {
734 if ((cm = class->vtable [i]))
735 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
738 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
740 /* create trampolines for abstract methods */
741 for (k = class; k; k = k->parent) {
742 for (i = 0; i < k->method.count; i++) {
743 int slot = k->methods [i]->slot;
744 if (!pvt->vtable [slot])
745 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
750 pvt->max_interface_id = max_interface_id;
751 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
752 sizeof (gpointer) * (max_interface_id + 1));
754 /* initialize interface offsets */
755 for (i = 0; i <= class->max_interface_id; ++i) {
756 int slot = class->interface_offsets [i];
758 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
761 if (remote_class->interface_count > 0)
763 int slot = class->vtable_size;
768 /* Create trampolines for the methods of the interfaces */
769 for (n = 0; n < remote_class->interface_count; n++)
771 iclass = remote_class->interfaces[n];
772 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
773 continue; /* interface implemented by the class */
778 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
780 for (j = 0; j < interf->method.count; ++j) {
781 MonoMethod *cm = interf->methods [j];
782 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
784 slot += interf->method.count;
785 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
797 * @domain: the application domain
798 * @class_name: name of the remote class
800 * Creates and initializes a MonoRemoteClass object for a remote type.
804 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
808 mono_domain_lock (domain);
809 rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class_name);
812 mono_domain_unlock (domain);
816 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
818 rc->interface_count = 0;
819 rc->interfaces = NULL;
820 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
821 rc->proxy_class_name = mono_string_to_utf8 (class_name);
823 mono_g_hash_table_insert (domain->proxy_vtable_hash, class_name, rc);
824 mono_upgrade_remote_class (domain, rc, proxy_class);
826 if (rc->vtable == NULL)
827 rc->vtable = mono_class_proxy_vtable (domain, rc);
829 mono_domain_unlock (domain);
835 extend_interface_array (MonoDomain *domain, MonoRemoteClass *remote_class, int amount)
837 /* Extends the array of interfaces. Memory is extended using blocks of 5 pointers */
839 int current_size = ((remote_class->interface_count / 5) + 1) * 5;
840 remote_class->interface_count += amount;
842 if (remote_class->interface_count > current_size || remote_class->interfaces == NULL)
844 int new_size = ((remote_class->interface_count / 5) + 1) * 5;
845 MonoClass **new_array = mono_mempool_alloc (domain->mp, new_size * sizeof (MonoClass*));
847 if (remote_class->interfaces != NULL)
848 memcpy (new_array, remote_class->interfaces, current_size * sizeof (MonoClass*));
850 remote_class->interfaces = new_array;
856 * mono_upgrade_remote_class:
857 * @domain: the application domain
858 * @remote_class: the remote class
859 * @klass: class to which the remote class can be casted.
861 * Updates the vtable of the remote class by adding the necessary method slots
862 * and interface offsets so it can be safely casted to klass. klass can be a
863 * class or an interface.
865 void mono_upgrade_remote_class (MonoDomain *domain, MonoRemoteClass *remote_class, MonoClass *klass)
867 gboolean redo_vtable;
869 mono_domain_lock (domain);
871 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
874 for (i = 0; i < remote_class->interface_count; i++)
875 if (remote_class->interfaces[i] == klass) redo_vtable = FALSE;
878 extend_interface_array (domain, remote_class, 1);
879 remote_class->interfaces [remote_class->interface_count-1] = klass;
883 redo_vtable = (remote_class->proxy_class != klass);
884 remote_class->proxy_class = klass;
888 remote_class->vtable = mono_class_proxy_vtable (domain, remote_class);
891 printf ("remote class upgrade - class:%s num-interfaces:%d\n", remote_class->proxy_class_name, remote_class->interface_count);
893 for (n=0; n<remote_class->interface_count; n++)
894 printf (" I:%s\n", remote_class->interfaces[n]->name);
897 mono_domain_unlock (domain);
901 * mono_object_get_virtual_method:
903 * Retrieve the MonoMethod that would be called on obj if obj is passed as
904 * the instance of a callvirt of method.
907 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
911 MonoMethod *res = NULL;
913 klass = mono_object_class (obj);
914 if (klass == mono_defaults.transparent_proxy_class) {
915 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
921 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
924 vtable = klass->vtable;
926 /* check method->slot is a valid index: perform isinstance? */
927 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
929 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
931 if (method->slot != -1)
932 res = vtable [method->slot];
936 if (!res) res = method; /* It may be an interface or abstract class method */
937 res = mono_marshal_get_remoting_invoke (res);
946 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
948 g_error ("runtime invoke called on uninitialized runtime");
952 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
955 * mono_runtime_invoke:
957 * Invokes the method represented by `method' on the object `obj'.
959 * obj is the 'this' pointer, it should be NULL for static
960 * methods, a MonoObject* for object instances and a pointer to
961 * the value type for value types.
963 * The params array contains the arguments to the method with the
964 * same convention: MonoObject* pointers for object instances and
965 * pointers to the value type otherwise.
967 * From unmanaged code you'll usually use the
968 * mono_runtime_invoke() variant.
970 * Note that this function doesn't handle virtual methods for
971 * you, it will exec the exact method you pass: we still need to
972 * expose a function to lookup the derived class implementation
973 * of a virtual method (there are examples of this in the code,
976 * You can pass NULL as the exc argument if you don't want to
977 * catch exceptions, otherwise, *exc will be set to the exception
978 * thrown, if any. if an exception is thrown, you can't use the
979 * MonoObject* result from the function.
981 * If the method returns a value type, it is boxed in an object
985 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
987 return default_mono_runtime_invoke (method, obj, params, exc);
991 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
994 gpointer *p = (gpointer*)dest;
1001 case MONO_TYPE_BOOLEAN:
1003 case MONO_TYPE_U1: {
1004 guint8 *p = (guint8*)dest;
1005 *p = *(guint8*)value;
1010 case MONO_TYPE_CHAR: {
1011 guint16 *p = (guint16*)dest;
1012 *p = *(guint16*)value;
1015 #if SIZEOF_VOID_P == 4
1020 case MONO_TYPE_U4: {
1021 gint32 *p = (gint32*)dest;
1022 *p = *(gint32*)value;
1025 #if SIZEOF_VOID_P == 8
1030 case MONO_TYPE_U8: {
1031 gint64 *p = (gint64*)dest;
1032 *p = *(gint64*)value;
1035 case MONO_TYPE_R4: {
1036 float *p = (float*)dest;
1037 *p = *(float*)value;
1040 case MONO_TYPE_R8: {
1041 double *p = (double*)dest;
1042 *p = *(double*)value;
1045 case MONO_TYPE_STRING:
1046 case MONO_TYPE_SZARRAY:
1047 case MONO_TYPE_CLASS:
1048 case MONO_TYPE_OBJECT:
1049 case MONO_TYPE_ARRAY:
1050 case MONO_TYPE_PTR: {
1051 gpointer *p = (gpointer*)dest;
1052 *p = deref_pointer? *(gpointer*)value: value;
1055 case MONO_TYPE_VALUETYPE:
1056 if (type->data.klass->enumtype) {
1057 t = type->data.klass->enum_basetype->type;
1061 size = mono_class_value_size (type->data.klass, NULL);
1062 memcpy (dest, value, size);
1066 g_warning ("got type %x", type->type);
1067 g_assert_not_reached ();
1072 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
1076 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1078 dest = (char*)obj + field->offset;
1079 set_value (field->type, dest, value, FALSE);
1083 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
1087 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1088 /* you cant set a constant! */
1089 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
1091 dest = (char*)vt->data + field->offset;
1092 set_value (field->type, dest, value, FALSE);
1096 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
1100 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1102 src = (char*)obj + field->offset;
1103 set_value (field->type, value, src, TRUE);
1107 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
1111 MonoVTable *vtable = NULL;
1113 gboolean is_static = FALSE;
1114 gboolean is_ref = FALSE;
1116 switch (field->type->type) {
1117 case MONO_TYPE_STRING:
1118 case MONO_TYPE_OBJECT:
1119 case MONO_TYPE_CLASS:
1120 case MONO_TYPE_ARRAY:
1121 case MONO_TYPE_SZARRAY:
1126 case MONO_TYPE_BOOLEAN:
1129 case MONO_TYPE_CHAR:
1138 case MONO_TYPE_VALUETYPE:
1139 is_ref = field->type->byref;
1142 g_error ("type 0x%x not handled in "
1143 "mono_field_get_value_object", field->type->type);
1147 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1149 vtable = mono_class_vtable (domain, field->parent);
1150 if (!vtable->initialized)
1151 mono_runtime_class_init (vtable);
1156 mono_field_static_get_value (vtable, field, &o);
1158 mono_field_get_value (obj, field, &o);
1163 /* boxed value type */
1164 klass = mono_class_from_mono_type (field->type);
1165 o = mono_object_new (domain, klass);
1166 v = ((gchar *) o) + sizeof (MonoObject);
1168 mono_field_static_get_value (vtable, field, v);
1170 mono_field_get_value (obj, field, v);
1177 mono_get_constant_value_from_blob (MonoDomain* domain, MonoTypeEnum type, char *blob, void *value)
1180 const char *p = blob;
1181 mono_metadata_decode_blob_size (p, &p);
1184 case MONO_TYPE_BOOLEAN:
1187 *(guint8 *) value = *p;
1189 case MONO_TYPE_CHAR:
1192 *(guint16*) value = read16 (p);
1196 *(guint32*) value = read32 (p);
1200 *(guint64*) value = read64 (p);
1203 readr4 (p, (float*) value);
1206 readr8 (p, (double*) value);
1208 case MONO_TYPE_STRING:
1209 *(gpointer*) value = mono_ldstr_metdata_sig (domain, blob);
1211 case MONO_TYPE_CLASS:
1212 *(gpointer*) value = NULL;
1216 g_warning ("type 0x%02x should not be in constant table", type);
1222 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
1224 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
1225 mono_get_constant_value_from_blob (domain, field->def_type, field->data, value);
1230 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1234 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1236 if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
1237 get_default_field_value (vt->domain, field, value);
1241 src = (char*)vt->data + field->offset;
1242 set_value (field->type, value, src, TRUE);
1246 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1248 default_mono_runtime_invoke (prop->set, obj, params, exc);
1252 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1254 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1259 mono_get_delegate_invoke (MonoClass *klass)
1266 for (i = 0; i < klass->method.count; ++i) {
1267 if (klass->methods [i]->name[0] == 'I' &&
1268 !strcmp ("Invoke", klass->methods [i]->name)) {
1269 im = klass->methods [i];
1279 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1283 im = mono_get_delegate_invoke (delegate->vtable->klass);
1286 return mono_runtime_invoke (im, delegate, params, exc);
1289 static MonoArray* main_args;
1292 mono_runtime_get_main_args (void)
1298 fire_process_exit_event (void)
1300 MonoClassField *field;
1301 MonoDomain *domain = mono_domain_get ();
1303 MonoObject *delegate, *exc;
1305 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1308 if (domain != mono_get_root_domain ())
1311 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1312 if (delegate == NULL)
1317 mono_runtime_delegate_invoke (delegate, pa, &exc);
1321 * Execute a standard Main() method (argc/argv contains the
1322 * executable name). This method also sets the command line argument value
1323 * needed by System.Environment.
1326 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1330 MonoArray *args = NULL;
1331 MonoDomain *domain = mono_domain_get ();
1332 gchar *utf8_fullpath;
1335 main_thread = mono_thread_current ();
1337 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1339 if (!g_path_is_absolute (argv [0])) {
1340 gchar *basename = g_path_get_basename (argv [0]);
1341 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1345 utf8_fullpath = mono_utf8_from_external (fullpath);
1346 if(utf8_fullpath == NULL) {
1347 /* Printing the arg text will cause glib to
1348 * whinge about "Invalid UTF-8", but at least
1349 * its relevant, and shows the problem text
1352 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1353 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1360 utf8_fullpath = mono_utf8_from_external (argv[0]);
1361 if(utf8_fullpath == NULL) {
1362 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1363 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1368 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1369 g_free (utf8_fullpath);
1371 for (i = 1; i < argc; ++i) {
1375 utf8_arg=mono_utf8_from_external (argv[i]);
1376 if(utf8_arg==NULL) {
1377 /* Ditto the comment about Invalid UTF-8 here */
1378 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1379 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1383 arg = mono_string_new (domain, utf8_arg);
1384 mono_array_set (main_args, gpointer, i, arg);
1388 if (method->signature->param_count) {
1389 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1390 for (i = 0; i < argc; ++i) {
1391 /* The encodings should all work, given that
1392 * we've checked all these args for the
1395 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1396 mono_array_set (args, gpointer, i, arg);
1399 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1402 mono_assembly_set_main (method->klass->image->assembly);
1404 result = mono_runtime_exec_main (method, args, exc);
1405 fire_process_exit_event ();
1409 /* Used in mono_unhandled_exception */
1411 create_unhandled_exception_eventargs (MonoObject *exc)
1415 MonoMethod *method = NULL;
1416 MonoBoolean is_terminating = TRUE;
1420 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1423 mono_class_init (klass);
1425 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1426 for (i = 0; i < klass->method.count; ++i) {
1427 method = klass->methods [i];
1428 if (!strcmp (".ctor", method->name) &&
1429 method->signature->param_count == 2 &&
1430 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1438 args [1] = &is_terminating;
1440 obj = mono_object_new (mono_domain_get (), klass);
1441 mono_runtime_invoke (method, obj, args, NULL);
1447 * We call this function when we detect an unhandled exception
1448 * in the default domain.
1449 * It invokes the * UnhandledException event in AppDomain or prints
1450 * a warning to the console
1453 mono_unhandled_exception (MonoObject *exc)
1455 MonoDomain *domain = mono_domain_get ();
1456 MonoClassField *field;
1457 MonoObject *delegate;
1459 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1460 "UnhandledException");
1463 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1464 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1466 /* set exitcode only in the main thread */
1467 if (mono_thread_current () == main_thread)
1468 mono_environment_exitcode_set (1);
1469 if (domain != mono_get_root_domain () || !delegate) {
1470 mono_print_unhandled_exception (exc);
1472 MonoObject *e = NULL;
1475 pa [0] = domain->domain;
1476 pa [1] = create_unhandled_exception_eventargs (exc);
1477 mono_runtime_delegate_invoke (delegate, pa, &e);
1480 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1481 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1489 * Launch a new thread to start all setup that requires managed code
1492 * main_func is called back from the thread with main_args as the
1493 * parameter. The callback function is expected to start Main()
1494 * eventually. This function then waits for all managed threads to
1498 mono_runtime_exec_managed_code (MonoDomain *domain,
1499 MonoMainThreadFunc main_func,
1502 mono_thread_create (domain, main_func, main_args);
1504 mono_thread_manage ();
1508 * Execute a standard Main() method (args doesn't contain the
1512 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1522 domain = mono_object_domain (args);
1523 if (!domain->entry_assembly) {
1525 gchar *config_suffix;
1526 MonoAssembly *assembly;
1528 assembly = method->klass->image->assembly;
1529 domain->entry_assembly = assembly;
1530 domain->setup->application_base = mono_string_new (domain, assembly->basedir);
1532 config_suffix = g_strconcat (assembly->aname.name, ".exe.config", NULL);
1533 str = g_build_filename (assembly->basedir, config_suffix, NULL);
1534 g_free (config_suffix);
1535 domain->setup->configuration_file = mono_string_new (domain, str);
1539 /* FIXME: check signature of method */
1540 if (method->signature->ret->type == MONO_TYPE_I4) {
1542 res = mono_runtime_invoke (method, NULL, pa, exc);
1544 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1548 mono_environment_exitcode_set (rval);
1550 mono_runtime_invoke (method, NULL, pa, exc);
1554 /* If the return type of Main is void, only
1555 * set the exitcode if an exception was thrown
1556 * (we don't want to blow away an
1557 * explicitly-set exit code)
1560 mono_environment_exitcode_set (rval);
1568 mono_install_runtime_invoke (MonoInvokeFunc func)
1570 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1574 * mono_runtime_invoke:
1576 * Invokes the method represented by `method' on the object `obj'.
1578 * obj is the 'this' pointer, it should be NULL for static
1579 * methods, a MonoObject* for object instances and a pointer to
1580 * the value type for value types.
1582 * The params array contains the arguments to the method with the
1583 * same convention: MonoObject* pointers for object instances and
1584 * pointers to the value type otherwise. The _invoke_array
1585 * variant takes a C# object[] as the params argument (MonoArray
1586 * *params): in this case the value types are boxed inside the
1587 * respective reference representation.
1589 * From unmanaged code you'll usually use the
1590 * mono_runtime_invoke() variant.
1592 * Note that this function doesn't handle virtual methods for
1593 * you, it will exec the exact method you pass: we still need to
1594 * expose a function to lookup the derived class implementation
1595 * of a virtual method (there are examples of this in the code,
1598 * You can pass NULL as the exc argument if you don't want to
1599 * catch exceptions, otherwise, *exc will be set to the exception
1600 * thrown, if any. if an exception is thrown, you can't use the
1601 * MonoObject* result from the function.
1603 * If the method returns a value type, it is boxed in an object
1607 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1610 MonoMethodSignature *sig = method->signature;
1611 gpointer *pa = NULL;
1614 if (NULL != params) {
1615 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1616 for (i = 0; i < mono_array_length (params); i++) {
1617 if (sig->params [i]->byref) {
1621 switch (sig->params [i]->type) {
1624 case MONO_TYPE_BOOLEAN:
1627 case MONO_TYPE_CHAR:
1636 case MONO_TYPE_VALUETYPE:
1637 /* MS seems to create the objects if a null is passed in */
1638 if (! ((gpointer *)params->vector)[i])
1639 ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
1640 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1642 case MONO_TYPE_STRING:
1643 case MONO_TYPE_OBJECT:
1644 case MONO_TYPE_CLASS:
1645 case MONO_TYPE_ARRAY:
1646 case MONO_TYPE_SZARRAY:
1647 if (sig->params [i]->byref)
1648 pa [i] = &(((gpointer *)params->vector)[i]);
1650 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1653 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1658 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1661 obj = mono_object_new (mono_domain_get (), method->klass);
1662 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1663 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
1665 if (method->klass->valuetype)
1666 o = mono_object_unbox (obj);
1670 mono_runtime_invoke (method, o, pa, exc);
1673 /* obj must be already unboxed if needed */
1674 return mono_runtime_invoke (method, obj, pa, exc);
1679 arith_overflow (void)
1681 mono_raise_exception (mono_get_exception_overflow ());
1685 * mono_object_allocate:
1686 * @size: number of bytes to allocate
1688 * This is a very simplistic routine until we have our GC-aware
1691 * Returns: an allocated object of size @size, or NULL on failure.
1693 static inline void *
1694 mono_object_allocate (size_t size)
1697 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1698 void *o = GC_MALLOC (size);
1700 void *o = calloc (1, size);
1702 return mono_gc_out_of_memory (size);
1704 mono_stats.new_object_count++;
1709 #if CREATION_SPEEDUP
1710 static inline void *
1711 mono_object_allocate_spec (size_t size, void *gcdescr)
1713 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1714 void *o = GC_GCJ_MALLOC (size, gcdescr);
1715 mono_stats.new_object_count++;
1723 * @klass: the class of the object that we want to create
1725 * Returns a newly created object whose definition is
1726 * looked up using @klass. This will not invoke any constructors,
1727 * so the consumer of this routine has to invoke any constructors on
1728 * its own to initialize the object.
1731 mono_object_new (MonoDomain *domain, MonoClass *klass)
1733 MONO_ARCH_SAVE_REGS;
1734 return mono_object_new_specific (mono_class_vtable (domain, klass));
1738 * mono_object_new_specific:
1739 * @vtable: the vtable of the object that we want to create
1741 * Returns: A newly created object with class and domain specified
1745 mono_object_new_specific (MonoVTable *vtable)
1749 MONO_ARCH_SAVE_REGS;
1754 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1757 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1761 mono_class_init (klass);
1763 for (i = 0; i < klass->method.count; ++i) {
1764 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1765 klass->methods [i]->signature->param_count == 1) {
1766 im = klass->methods [i];
1771 vtable->domain->create_proxy_for_type_method = im;
1774 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1776 o = mono_runtime_invoke (im, NULL, pa, NULL);
1777 if (o != NULL) return o;
1780 return mono_object_new_alloc_specific (vtable);
1784 mono_object_new_alloc_specific (MonoVTable *vtable)
1788 #if CREATION_SPEEDUP
1789 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1790 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1792 /* printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
1793 o = mono_object_allocate (vtable->klass->instance_size);
1797 o = mono_object_allocate (vtable->klass->instance_size);
1800 if (vtable->klass->has_finalize)
1801 mono_object_register_finalizer (o);
1803 mono_profiler_allocation (o, vtable->klass);
1807 #if CREATION_SPEEDUP
1810 mono_object_new_fast (MonoVTable *vtable)
1812 return GC_GCJ_MALLOC (vtable->klass->instance_size, vtable);
1818 * Return the allocation function appropriate for the given class.
1822 mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean *pass_size_in_words)
1824 *pass_size_in_words = FALSE;
1826 if (vtable->klass->has_finalize || vtable->klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
1827 return mono_object_new_specific;
1829 #if CREATION_SPEEDUP
1830 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1832 return mono_object_new_fast;
1835 * FIXME: This is actually slower than mono_object_new_fast, because
1836 * of the overhead of parameter passing.
1839 *pass_size_in_words = TRUE;
1840 #ifdef GC_REDIRECT_TO_LOCAL
1841 return GC_local_gcj_fast_malloc;
1843 return GC_gcj_fast_malloc;
1849 return mono_object_new_specific;
1853 * mono_object_new_from_token:
1854 * @image: Context where the type_token is hosted
1855 * @token: a token of the type that we want to create
1857 * Returns: A newly created object whose definition is
1858 * looked up using @token in the @image image
1861 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1865 class = mono_class_get (image, token);
1867 return mono_object_new (domain, class);
1872 * mono_object_clone:
1873 * @obj: the object to clone
1875 * Returns: A newly created object who is a shallow copy of @obj
1878 mono_object_clone (MonoObject *obj)
1883 size = obj->vtable->klass->instance_size;
1884 o = mono_object_allocate (size);
1885 mono_profiler_allocation (o, obj->vtable->klass);
1887 memcpy (o, obj, size);
1889 if (obj->vtable->klass->has_finalize)
1890 mono_object_register_finalizer (o);
1896 * @array: the array to clone
1898 * Returns: A newly created array who is a shallow copy of @array
1901 mono_array_clone (MonoArray *array)
1906 MonoClass *klass = array->obj.vtable->klass;
1908 MONO_ARCH_SAVE_REGS;
1910 if (array->bounds == NULL) {
1911 size = mono_array_length (array);
1912 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1913 klass, &size, NULL);
1915 size *= mono_array_element_size (klass);
1916 memcpy (o, array, sizeof (MonoArray) + size);
1921 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1922 size = mono_array_element_size (klass);
1923 for (i = 0; i < klass->rank; ++i) {
1924 sizes [i] = array->bounds [i].length;
1925 size *= array->bounds [i].length;
1926 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1928 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1929 klass, sizes, sizes + klass->rank);
1930 memcpy (o, array, sizeof(MonoArray) + size);
1935 /* helper macros to check for overflow when calculating the size of arrays */
1936 #define MYGUINT32_MAX 4294967295U
1937 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1938 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1939 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1940 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1941 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1944 * mono_array_new_full:
1945 * @domain: domain where the object is created
1946 * @array_class: array class
1947 * @lengths: lengths for each dimension in the array
1948 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1950 * This routine creates a new array objects with the given dimensions,
1951 * lower bounds and type.
1954 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1955 guint32 *lengths, guint32 *lower_bounds)
1957 guint32 byte_len, len;
1960 MonoArrayBounds *bounds;
1964 if (!array_class->inited)
1965 mono_class_init (array_class);
1967 byte_len = mono_array_element_size (array_class);
1970 if (array_class->rank == 1 &&
1971 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1978 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1980 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1982 for (i = 0; i < array_class->rank; ++i)
1983 if ((int) lengths [i] < 0)
1986 for (i = 0; i < array_class->rank; ++i) {
1987 bounds [i].length = lengths [i];
1988 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1989 mono_gc_out_of_memory (MYGUINT32_MAX);
1994 for (i = 0; i < array_class->rank; ++i)
1995 bounds [i].lower_bound = lower_bounds [i];
1998 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1999 mono_gc_out_of_memory (MYGUINT32_MAX);
2001 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2002 mono_gc_out_of_memory (MYGUINT32_MAX);
2003 byte_len += sizeof (MonoArray);
2005 * Following three lines almost taken from mono_object_new ():
2006 * they need to be kept in sync.
2008 vtable = mono_class_vtable (domain, array_class);
2009 #if CREATION_SPEEDUP
2010 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2011 o = mono_object_allocate_spec (byte_len, vtable);
2013 o = mono_object_allocate (byte_len);
2017 o = mono_object_allocate (byte_len);
2021 array = (MonoArray*)o;
2023 array->bounds = bounds;
2024 array->max_length = len;
2026 mono_profiler_allocation (o, array_class);
2033 * @domain: domain where the object is created
2034 * @eclass: element class
2035 * @n: number of array elements
2037 * This routine creates a new szarray with @n elements of type @eclass.
2040 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
2044 MONO_ARCH_SAVE_REGS;
2046 ac = mono_array_class_get (eclass, 1);
2047 g_assert (ac != NULL);
2049 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
2053 * mono_array_new_specific:
2054 * @vtable: a vtable in the appropriate domain for an initialized class
2055 * @n: number of array elements
2057 * This routine is a fast alternative to mono_array_new() for code which
2058 * can be sure about the domain it operates in.
2061 mono_array_new_specific (MonoVTable *vtable, guint32 n)
2065 guint32 byte_len, elem_size;
2067 MONO_ARCH_SAVE_REGS;
2072 elem_size = mono_array_element_size (vtable->klass);
2073 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
2074 mono_gc_out_of_memory (MYGUINT32_MAX);
2075 byte_len = n * elem_size;
2076 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2077 mono_gc_out_of_memory (MYGUINT32_MAX);
2078 byte_len += sizeof (MonoArray);
2079 #if CREATION_SPEEDUP
2080 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2081 o = mono_object_allocate_spec (byte_len, vtable);
2083 /* printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2084 o = mono_object_allocate (byte_len);
2088 o = mono_object_allocate (byte_len);
2092 ao = (MonoArray *)o;
2095 mono_profiler_allocation (o, vtable->klass);
2101 * mono_string_new_utf16:
2102 * @text: a pointer to an utf16 string
2103 * @len: the length of the string
2105 * Returns: A newly created string object which contains @text.
2108 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
2112 s = mono_string_new_size (domain, len);
2113 g_assert (s != NULL);
2115 memcpy (mono_string_chars (s), text, len * 2);
2121 * mono_string_new_size:
2122 * @text: a pointer to an utf16 string
2123 * @len: the length of the string
2125 * Returns: A newly created string object of @len
2128 mono_string_new_size (MonoDomain *domain, gint32 len)
2132 size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2134 /* overflow ? can't fit it, can't allocate it! */
2136 mono_gc_out_of_memory (-1);
2138 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2140 #if CREATION_SPEEDUP
2141 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2142 s = mono_object_allocate_spec (size, vtable);
2144 s = (MonoString*)mono_object_allocate (size);
2145 s->object.vtable = vtable;
2148 s = (MonoString*)mono_object_allocate (size);
2149 s->object.vtable = vtable;
2153 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2159 * mono_string_new_len:
2160 * @text: a pointer to an utf8 string
2161 * @length: number of bytes in @text to consider
2163 * Returns: A newly created string object which contains @text.
2166 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2168 GError *error = NULL;
2169 MonoString *o = NULL;
2171 glong items_written;
2173 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2176 o = mono_string_new_utf16 (domain, ut, items_written);
2178 g_error_free (error);
2187 * @text: a pointer to an utf8 string
2189 * Returns: A newly created string object which contains @text.
2192 mono_string_new (MonoDomain *domain, const char *text)
2194 GError *error = NULL;
2195 MonoString *o = NULL;
2197 glong items_written;
2202 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2205 o = mono_string_new_utf16 (domain, ut, items_written);
2207 g_error_free (error);
2215 * mono_string_new_wrapper:
2216 * @text: pointer to utf8 characters.
2218 * Helper function to create a string object from @text in the current domain.
2221 mono_string_new_wrapper (const char *text)
2223 MonoDomain *domain = mono_domain_get ();
2225 MONO_ARCH_SAVE_REGS;
2228 return mono_string_new (domain, text);
2235 * @class: the class of the value
2236 * @value: a pointer to the unboxed data
2238 * Returns: A newly created object which contains @value.
2241 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2247 g_assert (class->valuetype);
2249 vtable = mono_class_vtable (domain, class);
2250 size = mono_class_instance_size (class);
2251 res = mono_object_allocate (size);
2252 res->vtable = vtable;
2253 mono_profiler_allocation (res, class);
2255 size = size - sizeof (MonoObject);
2257 #if NO_UNALIGNED_ACCESS
2258 memcpy ((char *)res + sizeof (MonoObject), value, size);
2262 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2265 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2268 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2271 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2274 memcpy ((char *)res + sizeof (MonoObject), value, size);
2277 if (class->has_finalize)
2278 mono_object_register_finalizer (res);
2283 mono_object_get_domain (MonoObject *obj)
2285 return mono_object_domain (obj);
2289 mono_object_get_class (MonoObject *obj)
2291 return mono_object_class (obj);
2295 mono_object_unbox (MonoObject *obj)
2297 /* add assert for valuetypes? */
2298 g_assert (obj->vtable->klass->valuetype);
2299 return ((char*)obj) + sizeof (MonoObject);
2303 * mono_object_isinst:
2305 * @klass: a pointer to a class
2307 * Returns: @obj if @obj is derived from @klass
2310 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2313 mono_class_init (klass);
2315 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2316 return mono_object_isinst_mbyref (obj, klass);
2321 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2325 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2334 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2335 if ((klass->interface_id <= vt->max_interface_id) &&
2336 (vt->interface_offsets [klass->interface_id] != 0))
2340 MonoClass *oklass = vt->klass;
2341 if ((oklass == mono_defaults.transparent_proxy_class))
2342 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2344 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2348 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2350 MonoDomain *domain = mono_domain_get ();
2352 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2353 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2354 MonoMethod *im = NULL;
2358 for (i = 0; i < rpklass->method.count; ++i) {
2359 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2360 im = rpklass->methods [i];
2365 im = mono_object_get_virtual_method (rp, im);
2368 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2371 res = mono_runtime_invoke (im, rp, pa, NULL);
2373 if (*(MonoBoolean *) mono_object_unbox(res)) {
2374 /* Update the vtable of the remote type, so it can safely cast to this new type */
2375 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2376 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2385 * mono_object_castclass_mbyref:
2387 * @klass: a pointer to a class
2389 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2392 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2394 if (!obj) return NULL;
2395 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2397 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2399 "InvalidCastException"));
2404 MonoDomain *orig_domain;
2410 str_lookup (MonoDomain *domain, gpointer user_data)
2412 LDStrInfo *info = user_data;
2413 if (info->res || domain == info->orig_domain)
2415 mono_domain_lock (domain);
2416 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2417 mono_domain_unlock (domain);
2421 mono_string_is_interned_lookup (MonoString *str, int insert)
2423 MonoGHashTable *ldstr_table;
2426 char *ins = g_malloc (4 + str->length * 2);
2429 /* Encode the length */
2430 /* Same code as in mono_image_insert_string () */
2432 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2435 * ins is stored in the hash table as a key and needs to have the same
2436 * representation as in the metadata: we swap the character bytes on big
2439 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2442 char *p2 = (char *)mono_string_chars (str);
2443 for (i = 0; i < str->length; ++i) {
2450 memcpy (p, mono_string_chars (str), str->length * 2);
2452 domain = ((MonoObject *)str)->vtable->domain;
2453 ldstr_table = domain->ldstr_table;
2454 mono_domain_lock (domain);
2455 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2456 mono_domain_unlock (domain);
2461 mono_g_hash_table_insert (ldstr_table, ins, str);
2462 mono_domain_unlock (domain);
2465 LDStrInfo ldstr_info;
2466 ldstr_info.orig_domain = domain;
2467 ldstr_info.ins = ins;
2468 ldstr_info.res = NULL;
2470 mono_domain_foreach (str_lookup, &ldstr_info);
2471 if (ldstr_info.res) {
2473 * the string was already interned in some other domain:
2474 * intern it in the current one as well.
2476 mono_g_hash_table_insert (ldstr_table, ins, str);
2477 mono_domain_unlock (domain);
2481 mono_domain_unlock (domain);
2487 mono_string_is_interned (MonoString *o)
2489 return mono_string_is_interned_lookup (o, FALSE);
2493 mono_string_intern (MonoString *str)
2495 return mono_string_is_interned_lookup (str, TRUE);
2500 * @domain: the domain where the string will be used.
2501 * @image: a metadata context
2502 * @idx: index into the user string table.
2504 * Implementation for the ldstr opcode.
2507 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2509 MONO_ARCH_SAVE_REGS;
2512 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2514 return mono_ldstr_metdata_sig (domain, mono_metadata_user_string (image, idx));
2518 * mono_ldstr_metdata_sig
2519 * @domain: the domain for the string
2520 * @sig: the signature of a metadata string
2522 * returns a MonoString for a string stored in the metadata
2525 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig)
2527 const char *str = sig;
2531 mono_domain_lock (domain);
2532 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2533 mono_domain_unlock (domain);
2537 len2 = mono_metadata_decode_blob_size (str, &str);
2540 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2541 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2544 guint16 *p2 = (guint16*)mono_string_chars (o);
2545 for (i = 0; i < len2; ++i) {
2546 *p2 = GUINT16_FROM_LE (*p2);
2551 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2552 mono_domain_unlock (domain);
2558 * mono_string_to_utf8:
2559 * @s: a System.String
2561 * Return the UTF8 representation for @s.
2562 * the resulting buffer nedds to be freed with g_free().
2565 mono_string_to_utf8 (MonoString *s)
2568 GError *error = NULL;
2574 return g_strdup ("");
2576 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2578 g_warning (error->message);
2579 g_error_free (error);
2586 * mono_string_to_utf16:
2589 * Return an null-terminated array of the utf-16 chars
2590 * contained in @s. The result must be freed with g_free().
2591 * This is a temporary helper until our string implementation
2592 * is reworked to always include the null terminating char.
2595 mono_string_to_utf16 (MonoString *s)
2602 as = g_malloc ((s->length * 2) + 2);
2603 as [(s->length * 2)] = '\0';
2604 as [(s->length * 2) + 1] = '\0';
2607 return (gunichar2 *)(as);
2610 memcpy (as, mono_string_chars(s), s->length * 2);
2611 return (gunichar2 *)(as);
2615 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2618 mono_string_from_utf16 (gunichar2 *data)
2620 MonoDomain *domain = mono_domain_get ();
2626 while (data [len]) len++;
2628 return mono_string_new_utf16 (domain, data, len);
2632 default_ex_handler (MonoException *ex)
2634 MonoObject *o = (MonoObject*)ex;
2635 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2639 static MonoExceptionFunc ex_handler = default_ex_handler;
2642 mono_install_handler (MonoExceptionFunc func)
2644 ex_handler = func? func: default_ex_handler;
2648 * mono_raise_exception:
2649 * @ex: exception object
2651 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2654 mono_raise_exception (MonoException *ex)
2657 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2658 * that will cause gcc to omit the function epilog, causing problems when
2659 * the JIT tries to walk the stack, since the return address on the stack
2660 * will point into the next function in the executable, not this one.
2667 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2669 MonoWaitHandle *res;
2671 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2673 res->handle = handle;
2679 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2681 MonoAsyncResult *res;
2683 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2686 res->async_state = state;
2688 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2690 res->sync_completed = FALSE;
2691 res->completed = FALSE;
2697 mono_message_init (MonoDomain *domain,
2698 MonoMethodMessage *this,
2699 MonoReflectionMethod *method,
2700 MonoArray *out_args)
2702 MonoMethodSignature *sig = method->method->signature;
2708 this->method = method;
2710 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2711 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2712 this->async_result = NULL;
2713 this->call_type = CallType_Sync;
2715 names = g_new (char *, sig->param_count);
2716 mono_method_get_param_names (method->method, (const char **) names);
2717 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2719 for (i = 0; i < sig->param_count; i++) {
2720 name = mono_string_new (domain, names [i]);
2721 mono_array_set (this->names, gpointer, i, name);
2725 for (i = 0, j = 0; i < sig->param_count; i++) {
2727 if (sig->params [i]->byref) {
2729 gpointer arg = mono_array_get (out_args, gpointer, j);
2730 mono_array_set (this->args, gpointer, i, arg);
2734 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2739 mono_array_set (this->arg_types, guint8, i, arg_type);
2744 * mono_remoting_invoke:
2745 * @real_proxy: pointer to a RealProxy object
2746 * @msg: The MonoMethodMessage to execute
2747 * @exc: used to store exceptions
2748 * @out_args: used to store output arguments
2750 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2751 * IMessage interface and it is not trivial to extract results from there. So
2752 * we call an helper method PrivateInvoke instead of calling
2753 * RealProxy::Invoke() directly.
2755 * Returns: the result object.
2758 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2759 MonoObject **exc, MonoArray **out_args)
2761 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2764 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2770 klass = mono_defaults.real_proxy_class;
2772 for (i = 0; i < klass->method.count; ++i) {
2773 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2774 klass->methods [i]->signature->param_count == 4) {
2775 im = klass->methods [i];
2781 real_proxy->vtable->domain->private_invoke_method = im;
2784 pa [0] = real_proxy;
2789 return mono_runtime_invoke (im, NULL, pa, exc);
2793 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2794 MonoObject **exc, MonoArray **out_args)
2798 MonoMethodSignature *sig;
2800 int i, j, outarg_count = 0;
2802 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2804 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2805 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2806 target = tp->rp->unwrapped_server;
2808 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2812 domain = mono_domain_get ();
2813 method = msg->method->method;
2814 sig = method->signature;
2816 for (i = 0; i < sig->param_count; i++) {
2817 if (sig->params [i]->byref)
2821 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2824 ret = mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
2826 for (i = 0, j = 0; i < sig->param_count; i++) {
2827 if (sig->params [i]->byref) {
2829 arg = mono_array_get (msg->args, gpointer, i);
2830 mono_array_set (*out_args, gpointer, j, arg);
2839 mono_print_unhandled_exception (MonoObject *exc)
2841 char *message = (char *) "";
2845 gboolean free_message = FALSE;
2848 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2849 klass = exc->vtable->klass;
2851 while (klass && method == NULL) {
2852 for (i = 0; i < klass->method.count; ++i) {
2853 method = klass->methods [i];
2854 if (!strcmp ("ToString", method->name) &&
2855 method->signature->param_count == 0 &&
2856 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2857 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2864 klass = klass->parent;
2869 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2871 message = mono_string_to_utf8 (str);
2872 free_message = TRUE;
2877 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2878 * exc->vtable->klass->name, message);
2880 g_printerr ("\nUnhandled Exception: %s\n", message);
2887 * mono_delegate_ctor:
2888 * @this: pointer to an uninitialized delegate object
2889 * @target: target object
2890 * @addr: pointer to native code
2892 * This is used to initialize a delegate. We also insert the method_info if
2893 * we find the info with mono_jit_info_table_find().
2896 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2898 MonoDomain *domain = mono_domain_get ();
2899 MonoDelegate *delegate = (MonoDelegate *)this;
2900 MonoMethod *method = NULL;
2907 class = this->vtable->klass;
2909 if ((ji = mono_jit_info_table_find (domain, addr))) {
2910 method = ji->method;
2911 delegate->method_info = mono_method_get_object (domain, method, NULL);
2914 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2916 method = mono_marshal_get_remoting_invoke (method);
2917 delegate->method_ptr = mono_compile_method (method);
2918 delegate->target = target;
2920 delegate->method_ptr = addr;
2921 delegate->target = target;
2926 * mono_method_call_message_new:
2928 * Translates arguments pointers into a Message.
2931 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2932 MonoDelegate **cb, MonoObject **state)
2934 MonoDomain *domain = mono_domain_get ();
2935 MonoMethodSignature *sig = method->signature;
2936 MonoMethodMessage *msg;
2939 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2942 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2943 count = sig->param_count - 2;
2945 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2946 count = sig->param_count;
2949 for (i = 0; i < count; i++) {
2954 if (sig->params [i]->byref)
2955 vpos = *((gpointer *)params [i]);
2959 type = sig->params [i]->type;
2960 class = mono_class_from_mono_type (sig->params [i]);
2962 if (class->valuetype)
2963 arg = mono_value_box (domain, class, vpos);
2965 arg = *((MonoObject **)vpos);
2967 mono_array_set (msg->args, gpointer, i, arg);
2970 if (cb != NULL && state != NULL) {
2971 *cb = *((MonoDelegate **)params [i]);
2973 *state = *((MonoObject **)params [i]);
2980 * mono_method_return_message_restore:
2982 * Restore results from message based processing back to arguments pointers
2985 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2987 MonoMethodSignature *sig = method->signature;
2988 int i, j, type, size;
2989 for (i = 0, j = 0; i < sig->param_count; i++) {
2990 MonoType *pt = sig->params [i];
2993 char *arg = mono_array_get (out_args, gpointer, j);
2997 case MONO_TYPE_VOID:
2998 g_assert_not_reached ();
3002 case MONO_TYPE_BOOLEAN:
3005 case MONO_TYPE_CHAR:
3012 case MONO_TYPE_VALUETYPE: {
3013 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
3014 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
3017 case MONO_TYPE_STRING:
3018 case MONO_TYPE_CLASS:
3019 case MONO_TYPE_ARRAY:
3020 case MONO_TYPE_SZARRAY:
3021 case MONO_TYPE_OBJECT:
3022 **((MonoObject ***)params [i]) = (MonoObject *)arg;
3025 g_assert_not_reached ();
3034 * mono_load_remote_field:
3035 * @this: pointer to an object
3036 * @klass: klass of the object containing @field
3037 * @field: the field to load
3038 * @res: a storage to store the result
3040 * This method is called by the runtime on attempts to load fields of
3041 * transparent proxy objects. @this points to such TP, @klass is the class of
3042 * the object containing @field. @res is a storage location which can be
3043 * used to store the result.
3045 * Returns: an address pointing to the value of field.
3048 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
3050 static MonoMethod *getter = NULL;
3051 MonoDomain *domain = mono_domain_get ();
3052 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3053 MonoClass *field_class;
3054 MonoMethodMessage *msg;
3055 MonoArray *out_args;
3059 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3064 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3065 mono_field_get_value (tp->rp->unwrapped_server, field, res);
3072 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3073 MonoMethod *cm = mono_defaults.object_class->methods [i];
3075 if (!strcmp (cm->name, "FieldGetter")) {
3083 field_class = mono_class_from_mono_type (field->type);
3085 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3086 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3087 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3089 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3090 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3092 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3094 if (exc) mono_raise_exception ((MonoException *)exc);
3096 *res = mono_array_get (out_args, MonoObject *, 0);
3098 if (field_class->valuetype) {
3099 return ((char *)*res) + sizeof (MonoObject);
3105 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
3107 static MonoMethod *getter = NULL;
3108 MonoDomain *domain = mono_domain_get ();
3109 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3110 MonoClass *field_class;
3111 MonoMethodMessage *msg;
3112 MonoArray *out_args;
3113 MonoObject *exc, *res;
3115 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3117 field_class = mono_class_from_mono_type (field->type);
3119 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3121 if (field_class->valuetype) {
3122 res = mono_object_new (domain, field_class);
3123 val = ((gchar *) res) + sizeof (MonoObject);
3127 mono_field_get_value (tp->rp->unwrapped_server, field, val);
3134 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3135 MonoMethod *cm = mono_defaults.object_class->methods [i];
3137 if (!strcmp (cm->name, "FieldGetter")) {
3145 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3146 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3147 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3149 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3150 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3152 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3154 if (exc) mono_raise_exception ((MonoException *)exc);
3156 res = mono_array_get (out_args, MonoObject *, 0);
3162 * mono_store_remote_field:
3163 * @this: pointer to an object
3164 * @klass: klass of the object containing @field
3165 * @field: the field to load
3166 * @val: the value/object to store
3168 * This method is called by the runtime on attempts to store fields of
3169 * transparent proxy objects. @this points to such TP, @klass is the class of
3170 * the object containing @field. @val is the new value to store in @field.
3173 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3175 static MonoMethod *setter = NULL;
3176 MonoDomain *domain = mono_domain_get ();
3177 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3178 MonoClass *field_class;
3179 MonoMethodMessage *msg;
3180 MonoArray *out_args;
3184 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3186 field_class = mono_class_from_mono_type (field->type);
3188 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3189 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3190 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3197 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3198 MonoMethod *cm = mono_defaults.object_class->methods [i];
3200 if (!strcmp (cm->name, "FieldSetter")) {
3208 if (field_class->valuetype)
3209 arg = mono_value_box (domain, field_class, val);
3211 arg = *((MonoObject **)val);
3214 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3215 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3217 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3218 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3219 mono_array_set (msg->args, gpointer, 2, arg);
3221 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3223 if (exc) mono_raise_exception ((MonoException *)exc);
3227 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3229 static MonoMethod *setter = NULL;
3230 MonoDomain *domain = mono_domain_get ();
3231 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3232 MonoClass *field_class;
3233 MonoMethodMessage *msg;
3234 MonoArray *out_args;
3237 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3239 field_class = mono_class_from_mono_type (field->type);
3241 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3242 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3243 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3250 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3251 MonoMethod *cm = mono_defaults.object_class->methods [i];
3253 if (!strcmp (cm->name, "FieldSetter")) {
3261 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3262 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3264 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3265 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3266 mono_array_set (msg->args, gpointer, 2, arg);
3268 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3270 if (exc) mono_raise_exception ((MonoException *)exc);