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 experimental typed allocation using the GC_gcj_malloc function.
40 #ifdef HAVE_GC_GCJ_MALLOC
41 #define CREATION_SPEEDUP 1
45 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value);
48 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig);
51 mono_runtime_object_init (MonoObject *this)
54 MonoMethod *method = NULL;
55 MonoClass *klass = this->vtable->klass;
57 for (i = 0; i < klass->method.count; ++i) {
58 if (!strcmp (".ctor", klass->methods [i]->name) &&
59 klass->methods [i]->signature->param_count == 0) {
60 method = klass->methods [i];
67 if (method->klass->valuetype)
68 this = mono_object_unbox (this);
69 mono_runtime_invoke (method, this, NULL, NULL);
72 /* The pseudo algorithm for type initialization from the spec
73 Note it doesn't say anything about domains - only threads.
75 2. If the type is initialized you are done.
76 2.1. If the type is not yet initialized, try to take an
78 2.2. If successful, record this thread as responsible for
79 initializing the type and proceed to step 2.3.
80 2.2.1. If not, see whether this thread or any thread
81 waiting for this thread to complete already holds the lock.
82 2.2.2. If so, return since blocking would create a deadlock. This thread
83 will now see an incompletely initialized state for the type,
84 but no deadlock will arise.
85 2.2.3 If not, block until the type is initialized then return.
86 2.3 Initialize the parent type and then all interfaces implemented
88 2.4 Execute the type initialization code for this type.
89 2.5 Mark the type as initialized, release the initialization lock,
90 awaken any threads waiting for this type to be initialized,
97 guint32 initializing_tid;
98 guint32 waiting_count;
99 CRITICAL_SECTION initialization_section;
100 } TypeInitializationLock;
102 /* for locking access to type_initialization_hash and blocked_thread_hash */
103 static CRITICAL_SECTION type_initialization_section;
105 /* from vtable to lock */
106 static GHashTable *type_initialization_hash;
108 /* from thread id to thread id being waited on */
109 static GHashTable *blocked_thread_hash;
112 static MonoThread *main_thread;
115 mono_type_initialization_init (void)
117 InitializeCriticalSection (&type_initialization_section);
118 type_initialization_hash = g_hash_table_new (NULL, NULL);
119 blocked_thread_hash = g_hash_table_new (NULL, NULL);
123 * mono_runtime_class_init:
124 * @vtable: vtable that needs to be initialized
126 * This routine calls the class constructor for @vtable.
129 mono_runtime_class_init (MonoVTable *vtable)
133 MonoException *exc_to_throw;
134 MonoMethod *method = NULL;
141 if (vtable->initialized)
146 klass = vtable->klass;
148 for (i = 0; i < klass->method.count; ++i) {
149 method = klass->methods [i];
150 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
151 (strcmp (".cctor", method->name) == 0)) {
158 MonoDomain *domain = vtable->domain;
159 TypeInitializationLock *lock;
160 guint32 tid = GetCurrentThreadId();
161 int do_initialization = 0;
162 MonoDomain *last_domain = NULL;
164 EnterCriticalSection (&type_initialization_section);
165 /* double check... */
166 if (vtable->initialized) {
167 LeaveCriticalSection (&type_initialization_section);
170 lock = g_hash_table_lookup (type_initialization_hash, vtable);
172 /* This thread will get to do the initialization */
173 if (mono_domain_get () != domain) {
174 /* Transfer into the target domain */
175 last_domain = mono_domain_get ();
176 if (!mono_domain_set (domain, FALSE)) {
177 vtable->initialized = 1;
178 LeaveCriticalSection (&type_initialization_section);
179 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
182 lock = g_malloc (sizeof(TypeInitializationLock));
183 InitializeCriticalSection (&lock->initialization_section);
184 lock->initializing_tid = tid;
185 lock->waiting_count = 1;
186 /* grab the vtable lock while this thread still owns type_initialization_section */
187 EnterCriticalSection (&lock->initialization_section);
188 g_hash_table_insert (type_initialization_hash, vtable, lock);
189 do_initialization = 1;
193 if (lock->initializing_tid == tid) {
194 LeaveCriticalSection (&type_initialization_section);
197 /* see if the thread doing the initialization is already blocked on this thread */
198 blocked = GUINT_TO_POINTER (lock->initializing_tid);
199 while ((blocked = g_hash_table_lookup (blocked_thread_hash, blocked))) {
200 if (blocked == GUINT_TO_POINTER (tid)) {
201 LeaveCriticalSection (&type_initialization_section);
205 ++lock->waiting_count;
206 /* record the fact that we are waiting on the initializing thread */
207 g_hash_table_insert (blocked_thread_hash, GUINT_TO_POINTER (tid), GUINT_TO_POINTER (lock->initializing_tid));
209 LeaveCriticalSection (&type_initialization_section);
211 if (do_initialization) {
212 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
214 mono_domain_set (last_domain, TRUE);
215 LeaveCriticalSection (&lock->initialization_section);
217 /* this just blocks until the initializing thread is done */
218 EnterCriticalSection (&lock->initialization_section);
219 LeaveCriticalSection (&lock->initialization_section);
222 EnterCriticalSection (&type_initialization_section);
223 if (lock->initializing_tid != tid)
224 g_hash_table_remove (blocked_thread_hash, GUINT_TO_POINTER (tid));
225 --lock->waiting_count;
226 if (lock->waiting_count == 0) {
227 DeleteCriticalSection (&lock->initialization_section);
228 g_hash_table_remove (type_initialization_hash, vtable);
231 vtable->initialized = 1;
232 /* FIXME: if the cctor fails, the type must be marked as unusable */
233 LeaveCriticalSection (&type_initialization_section);
235 vtable->initialized = 1;
240 (klass->image == mono_defaults.corlib &&
241 !strcmp (klass->name_space, "System") &&
242 !strcmp (klass->name, "TypeInitializationException")))
243 return; /* No static constructor found or avoid infinite loop */
245 if (klass->name_space && *klass->name_space)
246 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
248 full_name = g_strdup (klass->name);
250 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
253 mono_raise_exception (exc_to_throw);
257 default_trampoline (MonoMethod *method)
263 default_remoting_trampoline (MonoMethod *method)
265 g_error ("remoting not installed");
269 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
270 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
273 mono_install_trampoline (MonoTrampoline func)
275 arch_create_jit_trampoline = func? func: default_trampoline;
279 mono_install_remoting_trampoline (MonoTrampoline func)
281 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
284 static MonoCompileFunc default_mono_compile_method = NULL;
287 mono_install_compile_method (MonoCompileFunc func)
289 default_mono_compile_method = func;
293 mono_compile_method (MonoMethod *method)
295 if (!default_mono_compile_method) {
296 g_error ("compile method called on uninitialized runtime");
299 return default_mono_compile_method (method);
303 #if 0 && HAVE_BOEHM_GC
305 vtable_finalizer (void *obj, void *data) {
306 g_print ("%s finalized (%p)\n", (char*)data, obj);
312 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
315 * The vtables in the root appdomain are assumed to be reachable by other
316 * roots, and we don't use typed allocation in the other domains.
319 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
322 mono_class_compute_gc_descriptor (MonoClass *class)
324 MonoClassField *field;
328 static gboolean gcj_inited = FALSE;
333 GC_init_gcj_malloc (5, NULL);
337 mono_class_init (class);
339 if (class->gc_descr_inited)
342 class->gc_descr_inited = TRUE;
343 class->gc_descr = GC_NO_DESCRIPTOR;
345 if (class == mono_defaults.string_class) {
346 bitmap = GC_HEADER_BITMAP;
347 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
349 else if (class->rank) {
350 mono_class_compute_gc_descriptor (class->element_class);
352 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
353 bitmap = GC_HEADER_BITMAP;
355 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
356 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
360 static int count = 0;
364 /* GC 6.1 has trouble handling 64 bit descriptors... */
365 if ((class->instance_size / sizeof (gpointer)) > 30) {
366 /* printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer)); */
370 bitmap = GC_HEADER_BITMAP;
374 /* if (count > 442) */
377 /* printf("KLASS: %s.\n", class->name); */
379 for (p = class; p != NULL; p = p->parent) {
380 for (i = 0; i < p->field.count; ++i) {
381 field = &p->fields [i];
382 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
384 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
387 pos = field->offset / sizeof (gpointer);
389 if (field->type->byref)
392 switch (field->type->type) {
393 case MONO_TYPE_BOOLEAN:
405 /* printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap); */
408 case MONO_TYPE_STRING:
409 case MONO_TYPE_SZARRAY:
410 case MONO_TYPE_CLASS:
411 case MONO_TYPE_OBJECT:
412 case MONO_TYPE_ARRAY:
414 g_assert ((field->offset % sizeof(gpointer)) == 0);
416 bitmap |= ((guint64)1) << pos;
417 /* printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap); */
419 case MONO_TYPE_VALUETYPE: {
420 MonoClass *fclass = field->type->data.klass;
421 if (!fclass->enumtype) {
422 mono_class_compute_gc_descriptor (fclass);
423 bitmap |= (fclass->gc_bitmap >> (sizeof (MonoObject) / sizeof (gpointer))) << pos;
433 /* printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap); */
434 class->gc_bitmap = bitmap;
435 /* Convert to the format expected by GC_make_descriptor */
436 bm [0] = (guint32)bitmap;
437 bm [1] = (guint32)(bitmap >> 32);
438 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bm, class->instance_size / sizeof (gpointer));
441 #endif /* CREATION_SPEEDUP */
444 * field_is_special_static:
446 * Returns SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
447 * SPECIAL_STATIC_NONE otherwise.
450 field_is_special_static (MonoClass *fklass, MonoClassField *field)
452 MonoCustomAttrInfo *ainfo;
454 ainfo = mono_custom_attrs_from_field (fklass, field);
457 for (i = 0; i < ainfo->num_attrs; ++i) {
458 MonoClass *klass = ainfo->attrs [i].ctor->klass;
459 if (klass->image == mono_defaults.corlib) {
460 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
461 mono_custom_attrs_free (ainfo);
462 return SPECIAL_STATIC_THREAD;
464 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
465 mono_custom_attrs_free (ainfo);
466 return SPECIAL_STATIC_CONTEXT;
470 mono_custom_attrs_free (ainfo);
471 return SPECIAL_STATIC_NONE;
476 * @domain: the application domain
477 * @class: the class to initialize
479 * VTables are domain specific because we create domain specific code, and
480 * they contain the domain specific static class data.
483 mono_class_vtable (MonoDomain *domain, MonoClass *class)
485 MonoVTable *vt = NULL;
486 MonoClassField *field;
491 guint32 constant_cols [MONO_CONSTANT_SIZE];
495 vt = class->cached_vtable;
496 if (vt && vt->domain == domain)
499 mono_domain_lock (domain);
500 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
501 mono_domain_unlock (domain);
506 mono_class_init (class);
508 mono_stats.used_class_count++;
509 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
511 vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
513 vt = mono_mempool_alloc0 (domain->mp, vtable_size);
519 mono_class_compute_gc_descriptor (class);
520 if (domain != mono_get_root_domain ())
522 * We can't use typed allocation in the non-root domains, since the
523 * collector needs the GC descriptor stored in the vtable even after
524 * the mempool containing the vtable is destroyed when the domain is
525 * unloaded. An alternative might be to allocate vtables in the GC
526 * heap, but this does not seem to work (it leads to crashes inside
527 * libgc). If that approach is tried, two gc descriptors need to be
528 * allocated for each class: one for the root domain, and one for all
529 * other domains. The second descriptor should contain a bit for the
530 * vtable field in MonoObject, since we can no longer assume the
531 * vtable is reachable by other roots after the appdomain is unloaded.
533 vt->gc_descr = GC_NO_DESCRIPTOR;
535 vt->gc_descr = class->gc_descr;
538 if (class->class_size) {
540 vt->data = GC_MALLOC (class->class_size + 8);
541 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
542 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
543 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
545 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
548 mono_stats.class_static_data_size += class->class_size + 8;
552 for (i = class->field.first; i < class->field.last; ++i) {
553 field = &class->fields [i - class->field.first];
554 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
556 if (mono_field_is_deleted (field))
558 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
559 gint32 special_static = field_is_special_static (class, field);
560 if (special_static != SPECIAL_STATIC_NONE) {
561 guint32 size, align, offset;
562 size = mono_type_size (field->type, &align);
563 offset = mono_alloc_special_static_data (special_static, size, align);
564 if (!domain->special_static_fields)
565 domain->special_static_fields = g_hash_table_new (NULL, NULL);
566 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
570 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
571 MonoClass *fklass = mono_class_from_mono_type (field->type);
572 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT));
573 t = (char*)vt->data + field->offset;
574 if (fklass->valuetype) {
575 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
577 /* it's a pointer type: add check */
578 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
579 *t = *(char *)field->data;
583 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
588 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1), cindex + 1);
590 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
592 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
593 field->def_type = constant_cols [MONO_CONSTANT_TYPE];
594 field->data = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
597 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL))
598 get_default_field_value (domain, field, (char*)vt->data + field->offset);
601 vt->max_interface_id = class->max_interface_id;
603 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
604 sizeof (gpointer) * (class->max_interface_id + 1));
606 /* initialize interface offsets */
607 for (i = 0; i <= class->max_interface_id; ++i) {
608 int slot = class->interface_offsets [i];
610 vt->interface_offsets [i] = &(vt->vtable [slot]);
614 * arch_create_jit_trampoline () can recursively call this function again
615 * because it compiles icall methods right away.
617 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
618 if (!class->cached_vtable)
619 class->cached_vtable = vt;
621 /* initialize vtable */
622 for (i = 0; i < class->vtable_size; ++i) {
625 if ((cm = class->vtable [i]))
626 vt->vtable [i] = arch_create_jit_trampoline (cm);
629 mono_domain_unlock (domain);
631 /* make sure the the parent is initialized */
633 mono_class_vtable (domain, class->parent);
635 vt->type = mono_type_get_object (domain, &class->byval_arg);
636 if (class->contextbound)
645 * mono_class_proxy_vtable:
646 * @domain: the application domain
647 * @remove_class: the remote class
649 * Creates a vtable for transparent proxies. It is basically
650 * a copy of the real vtable of the class wrapped in @remote_class,
651 * but all function pointers invoke the remoting functions, and
652 * vtable->klass points to the transparent proxy class, and not to @class.
655 mono_class_proxy_vtable (MonoDomain *domain, MonoRemoteClass *remote_class)
657 MonoVTable *vt, *pvt;
658 int i, j, vtsize, max_interface_id, extra_interface_vtsize = 0;
660 MonoClass *class = remote_class->proxy_class;
662 vt = mono_class_vtable (domain, class);
663 max_interface_id = vt->max_interface_id;
665 /* Calculate vtable space for extra interfaces */
666 for (j = 0; j < remote_class->interface_count; j++) {
667 MonoClass* iclass = remote_class->interfaces[j];
668 int method_count = iclass->method.count;
670 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
671 continue; /* interface implemented by the class */
673 for (i = 0; i < iclass->interface_count; i++)
674 method_count += iclass->interfaces[i]->method.count;
676 extra_interface_vtsize += method_count * sizeof (gpointer);
677 if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
680 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
682 mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
684 pvt = mono_mempool_alloc (domain->mp, vtsize + extra_interface_vtsize);
685 memcpy (pvt, vt, vtsize);
687 pvt->klass = mono_defaults.transparent_proxy_class;
689 /* initialize vtable */
690 for (i = 0; i < class->vtable_size; ++i) {
693 if ((cm = class->vtable [i]))
694 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
697 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
699 /* create trampolines for abstract methods */
700 for (k = class; k; k = k->parent) {
701 for (i = 0; i < k->method.count; i++) {
702 int slot = k->methods [i]->slot;
703 if (!pvt->vtable [slot])
704 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
709 pvt->max_interface_id = max_interface_id;
710 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
711 sizeof (gpointer) * (max_interface_id + 1));
713 /* initialize interface offsets */
714 for (i = 0; i <= class->max_interface_id; ++i) {
715 int slot = class->interface_offsets [i];
717 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
720 if (remote_class->interface_count > 0)
722 int slot = class->vtable_size;
727 /* Create trampolines for the methods of the interfaces */
728 for (n = 0; n < remote_class->interface_count; n++)
730 iclass = remote_class->interfaces[n];
731 if (iclass->interface_id <= class->max_interface_id && class->interface_offsets[iclass->interface_id] != 0)
732 continue; /* interface implemented by the class */
737 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
739 for (j = 0; j < interf->method.count; ++j) {
740 MonoMethod *cm = interf->methods [j];
741 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
743 slot += interf->method.count;
744 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
756 * @domain: the application domain
757 * @class_name: name of the remote class
759 * Creates and initializes a MonoRemoteClass object for a remote type.
763 mono_remote_class (MonoDomain *domain, MonoString *class_name, MonoClass *proxy_class)
767 mono_domain_lock (domain);
768 rc = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class_name);
771 mono_domain_unlock (domain);
775 rc = mono_mempool_alloc (domain->mp, sizeof(MonoRemoteClass));
777 rc->interface_count = 0;
778 rc->interfaces = NULL;
779 rc->proxy_class = mono_defaults.marshalbyrefobject_class;
780 rc->proxy_class_name = mono_string_to_utf8 (class_name);
782 mono_g_hash_table_insert (domain->proxy_vtable_hash, class_name, rc);
783 mono_upgrade_remote_class (domain, rc, proxy_class);
785 if (rc->vtable == NULL)
786 rc->vtable = mono_class_proxy_vtable (domain, rc);
788 mono_domain_unlock (domain);
794 extend_interface_array (MonoDomain *domain, MonoRemoteClass *remote_class, int amount)
796 /* Extends the array of interfaces. Memory is extended using blocks of 5 pointers */
798 int current_size = ((remote_class->interface_count / 5) + 1) * 5;
799 remote_class->interface_count += amount;
801 if (remote_class->interface_count > current_size || remote_class->interfaces == NULL)
803 int new_size = ((remote_class->interface_count / 5) + 1) * 5;
804 MonoClass **new_array = mono_mempool_alloc (domain->mp, new_size * sizeof (MonoClass*));
806 if (remote_class->interfaces != NULL)
807 memcpy (new_array, remote_class->interfaces, current_size * sizeof (MonoClass*));
809 remote_class->interfaces = new_array;
815 * mono_upgrade_remote_class:
816 * @domain: the application domain
817 * @remote_class: the remote class
818 * @klass: class to which the remote class can be casted.
820 * Updates the vtable of the remote class by adding the necessary method slots
821 * and interface offsets so it can be safely casted to klass. klass can be a
822 * class or an interface.
824 void mono_upgrade_remote_class (MonoDomain *domain, MonoRemoteClass *remote_class, MonoClass *klass)
826 gboolean redo_vtable;
828 mono_domain_lock (domain);
830 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
833 for (i = 0; i < remote_class->interface_count; i++)
834 if (remote_class->interfaces[i] == klass) redo_vtable = FALSE;
837 extend_interface_array (domain, remote_class, 1);
838 remote_class->interfaces [remote_class->interface_count-1] = klass;
842 redo_vtable = (remote_class->proxy_class != klass);
843 remote_class->proxy_class = klass;
847 remote_class->vtable = mono_class_proxy_vtable (domain, remote_class);
850 printf ("remote class upgrade - class:%s num-interfaces:%d\n", remote_class->proxy_class_name, remote_class->interface_count);
852 for (n=0; n<remote_class->interface_count; n++)
853 printf (" I:%s\n", remote_class->interfaces[n]->name);
856 mono_domain_unlock (domain);
860 * mono_object_get_virtual_method:
862 * Retrieve the MonoMethod that would be called on obj if obj is passed as
863 * the instance of a callvirt of method.
866 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
870 MonoMethod *res = NULL;
872 klass = mono_object_class (obj);
873 if (klass == mono_defaults.transparent_proxy_class) {
874 klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
880 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
883 vtable = klass->vtable;
885 /* check method->slot is a valid index: perform isinstance? */
886 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
888 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
890 if (method->slot != -1)
891 res = vtable [method->slot];
895 if (!res) res = method; /* It may be an interface or abstract class method */
896 res = mono_marshal_get_remoting_invoke (res);
905 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
907 g_error ("runtime invoke called on uninitialized runtime");
911 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
914 * mono_runtime_invoke:
916 * Invokes the method represented by `method' on the object `obj'.
918 * obj is the 'this' pointer, it should be NULL for static
919 * methods, a MonoObject* for object instances and a pointer to
920 * the value type for value types.
922 * The params array contains the arguments to the method with the
923 * same convention: MonoObject* pointers for object instances and
924 * pointers to the value type otherwise.
926 * From unmanaged code you'll usually use the
927 * mono_runtime_invoke() variant.
929 * Note that this function doesn't handle virtual methods for
930 * you, it will exec the exact method you pass: we still need to
931 * expose a function to lookup the derived class implementation
932 * of a virtual method (there are examples of this in the code,
935 * You can pass NULL as the exc argument if you don't want to
936 * catch exceptions, otherwise, *exc will be set to the exception
937 * thrown, if any. if an exception is thrown, you can't use the
938 * MonoObject* result from the function.
940 * If the method returns a value type, it is boxed in an object
944 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
946 return default_mono_runtime_invoke (method, obj, params, exc);
950 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
953 gpointer *p = (gpointer*)dest;
960 case MONO_TYPE_BOOLEAN:
963 guint8 *p = (guint8*)dest;
964 *p = *(guint8*)value;
969 case MONO_TYPE_CHAR: {
970 guint16 *p = (guint16*)dest;
971 *p = *(guint16*)value;
974 #if SIZEOF_VOID_P == 4
980 gint32 *p = (gint32*)dest;
981 *p = *(gint32*)value;
984 #if SIZEOF_VOID_P == 8
990 gint64 *p = (gint64*)dest;
991 *p = *(gint64*)value;
995 float *p = (float*)dest;
1000 double *p = (double*)dest;
1001 *p = *(double*)value;
1004 case MONO_TYPE_STRING:
1005 case MONO_TYPE_SZARRAY:
1006 case MONO_TYPE_CLASS:
1007 case MONO_TYPE_OBJECT:
1008 case MONO_TYPE_ARRAY:
1009 case MONO_TYPE_PTR: {
1010 gpointer *p = (gpointer*)dest;
1011 *p = deref_pointer? *(gpointer*)value: value;
1014 case MONO_TYPE_VALUETYPE:
1015 if (type->data.klass->enumtype) {
1016 t = type->data.klass->enum_basetype->type;
1020 size = mono_class_value_size (type->data.klass, NULL);
1021 memcpy (dest, value, size);
1025 g_warning ("got type %x", type->type);
1026 g_assert_not_reached ();
1031 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
1035 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1037 dest = (char*)obj + field->offset;
1038 set_value (field->type, dest, value, FALSE);
1042 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
1046 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1047 /* you cant set a constant! */
1048 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL));
1050 dest = (char*)vt->data + field->offset;
1051 set_value (field->type, dest, value, FALSE);
1055 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
1059 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
1061 src = (char*)obj + field->offset;
1062 set_value (field->type, value, src, TRUE);
1066 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
1070 MonoVTable *vtable = NULL;
1072 gboolean is_static = FALSE;
1073 gboolean is_ref = FALSE;
1075 switch (field->type->type) {
1076 case MONO_TYPE_STRING:
1077 case MONO_TYPE_OBJECT:
1078 case MONO_TYPE_CLASS:
1079 case MONO_TYPE_ARRAY:
1080 case MONO_TYPE_SZARRAY:
1085 case MONO_TYPE_BOOLEAN:
1088 case MONO_TYPE_CHAR:
1097 case MONO_TYPE_VALUETYPE:
1098 is_ref = field->type->byref;
1101 g_error ("type 0x%x not handled in "
1102 "mono_field_get_value_object", field->type->type);
1106 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1108 vtable = mono_class_vtable (domain, field->parent);
1109 if (!vtable->initialized)
1110 mono_runtime_class_init (vtable);
1115 mono_field_static_get_value (vtable, field, &o);
1117 mono_field_get_value (obj, field, &o);
1122 /* boxed value type */
1123 klass = mono_class_from_mono_type (field->type);
1124 o = mono_object_new (domain, klass);
1125 v = ((gchar *) o) + sizeof (MonoObject);
1127 mono_field_static_get_value (vtable, field, v);
1129 mono_field_get_value (obj, field, v);
1136 get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value)
1138 const char *p = field->data;
1139 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
1141 mono_metadata_decode_blob_size (p, &p);
1143 switch (field->def_type) {
1144 case MONO_TYPE_BOOLEAN:
1147 *(guint8 *) value = *p;
1149 case MONO_TYPE_CHAR:
1152 *(guint16*) value = read16 (p);
1156 *(guint32*) value = read32 (p);
1160 *(guint64*) value = read64 (p);
1163 readr4 (p, (float*) value);
1166 readr8 (p, (double*) value);
1168 case MONO_TYPE_STRING:
1169 *(gpointer*) value = mono_ldstr_metdata_sig (domain, field->data);
1171 case MONO_TYPE_CLASS:
1172 *(gpointer*) value = NULL;
1175 g_warning ("type 0x%02x should not be in constant table", field->def_type);
1180 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
1184 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
1186 if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
1187 get_default_field_value (vt->domain, field, value);
1191 src = (char*)vt->data + field->offset;
1192 set_value (field->type, value, src, TRUE);
1196 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1198 default_mono_runtime_invoke (prop->set, obj, params, exc);
1202 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
1204 return default_mono_runtime_invoke (prop->get, obj, params, exc);
1209 mono_get_delegate_invoke (MonoClass *klass)
1216 for (i = 0; i < klass->method.count; ++i) {
1217 if (klass->methods [i]->name[0] == 'I' &&
1218 !strcmp ("Invoke", klass->methods [i]->name)) {
1219 im = klass->methods [i];
1229 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
1233 im = mono_get_delegate_invoke (delegate->vtable->klass);
1236 return mono_runtime_invoke (im, delegate, params, exc);
1239 static MonoArray* main_args;
1242 mono_runtime_get_main_args (void)
1248 fire_process_exit_event (void)
1250 MonoClassField *field;
1251 MonoDomain *domain = mono_domain_get ();
1253 MonoObject *delegate, *exc;
1255 field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
1258 if (domain != mono_get_root_domain ())
1261 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1262 if (delegate == NULL)
1267 mono_runtime_delegate_invoke (delegate, pa, &exc);
1271 * Execute a standard Main() method (argc/argv contains the
1272 * executable name). This method also sets the command line argument value
1273 * needed by System.Environment.
1276 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1280 MonoArray *args = NULL;
1281 MonoDomain *domain = mono_domain_get ();
1282 gchar *utf8_fullpath;
1285 main_thread = mono_thread_current ();
1287 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1289 if (!g_path_is_absolute (argv [0])) {
1290 gchar *basename = g_path_get_basename (argv [0]);
1291 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1295 utf8_fullpath = mono_utf8_from_external (fullpath);
1296 if(utf8_fullpath == NULL) {
1297 /* Printing the arg text will cause glib to
1298 * whinge about "Invalid UTF-8", but at least
1299 * its relevant, and shows the problem text
1302 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1303 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1310 utf8_fullpath = mono_utf8_from_external (argv[0]);
1311 if(utf8_fullpath == NULL) {
1312 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1313 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1318 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1319 g_free (utf8_fullpath);
1321 for (i = 1; i < argc; ++i) {
1325 utf8_arg=mono_utf8_from_external (argv[i]);
1326 if(utf8_arg==NULL) {
1327 /* Ditto the comment about Invalid UTF-8 here */
1328 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1329 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1333 arg = mono_string_new (domain, utf8_arg);
1334 mono_array_set (main_args, gpointer, i, arg);
1338 if (method->signature->param_count) {
1339 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1340 for (i = 0; i < argc; ++i) {
1341 /* The encodings should all work, given that
1342 * we've checked all these args for the
1345 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1346 mono_array_set (args, gpointer, i, arg);
1349 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1352 mono_assembly_set_main (method->klass->image->assembly);
1354 result = mono_runtime_exec_main (method, args, exc);
1355 fire_process_exit_event ();
1359 /* Used in mono_unhandled_exception */
1361 create_unhandled_exception_eventargs (MonoObject *exc)
1365 MonoMethod *method = NULL;
1366 MonoBoolean is_terminating = TRUE;
1370 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1373 mono_class_init (klass);
1375 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1376 for (i = 0; i < klass->method.count; ++i) {
1377 method = klass->methods [i];
1378 if (!strcmp (".ctor", method->name) &&
1379 method->signature->param_count == 2 &&
1380 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1388 args [1] = &is_terminating;
1390 obj = mono_object_new (mono_domain_get (), klass);
1391 mono_runtime_invoke (method, obj, args, NULL);
1397 * We call this function when we detect an unhandled exception
1398 * in the default domain.
1399 * It invokes the * UnhandledException event in AppDomain or prints
1400 * a warning to the console
1403 mono_unhandled_exception (MonoObject *exc)
1405 MonoDomain *domain = mono_domain_get ();
1406 MonoClassField *field;
1407 MonoObject *delegate;
1409 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1410 "UnhandledException");
1413 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1414 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1416 /* set exitcode only in the main thread */
1417 if (mono_thread_current () == main_thread)
1418 mono_environment_exitcode_set (1);
1419 if (domain != mono_get_root_domain () || !delegate) {
1420 mono_print_unhandled_exception (exc);
1422 MonoObject *e = NULL;
1425 pa [0] = domain->domain;
1426 pa [1] = create_unhandled_exception_eventargs (exc);
1427 mono_runtime_delegate_invoke (delegate, pa, &e);
1430 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1431 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1439 * Launch a new thread to start all setup that requires managed code
1442 * main_func is called back from the thread with main_args as the
1443 * parameter. The callback function is expected to start Main()
1444 * eventually. This function then waits for all managed threads to
1448 mono_runtime_exec_managed_code (MonoDomain *domain,
1449 MonoMainThreadFunc main_func,
1452 mono_thread_create (domain, main_func, main_args);
1454 mono_thread_manage ();
1458 * Execute a standard Main() method (args doesn't contain the
1462 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1472 domain = mono_object_domain (args);
1473 if (!domain->entry_assembly) {
1475 gchar *config_suffix;
1476 MonoAssembly *assembly;
1478 assembly = method->klass->image->assembly;
1479 domain->entry_assembly = assembly;
1480 domain->setup->application_base = mono_string_new (domain, assembly->basedir);
1482 config_suffix = g_strconcat (assembly->aname.name, ".exe.config", NULL);
1483 str = g_build_filename (assembly->basedir, config_suffix, NULL);
1484 g_free (config_suffix);
1485 domain->setup->configuration_file = mono_string_new (domain, str);
1489 /* FIXME: check signature of method */
1490 if (method->signature->ret->type == MONO_TYPE_I4) {
1492 res = mono_runtime_invoke (method, NULL, pa, exc);
1494 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1498 mono_environment_exitcode_set (rval);
1500 mono_runtime_invoke (method, NULL, pa, exc);
1504 /* If the return type of Main is void, only
1505 * set the exitcode if an exception was thrown
1506 * (we don't want to blow away an
1507 * explicitly-set exit code)
1510 mono_environment_exitcode_set (rval);
1518 mono_install_runtime_invoke (MonoInvokeFunc func)
1520 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1524 * mono_runtime_invoke:
1526 * Invokes the method represented by `method' on the object `obj'.
1528 * obj is the 'this' pointer, it should be NULL for static
1529 * methods, a MonoObject* for object instances and a pointer to
1530 * the value type for value types.
1532 * The params array contains the arguments to the method with the
1533 * same convention: MonoObject* pointers for object instances and
1534 * pointers to the value type otherwise. The _invoke_array
1535 * variant takes a C# object[] as the params argument (MonoArray
1536 * *params): in this case the value types are boxed inside the
1537 * respective reference representation.
1539 * From unmanaged code you'll usually use the
1540 * mono_runtime_invoke() variant.
1542 * Note that this function doesn't handle virtual methods for
1543 * you, it will exec the exact method you pass: we still need to
1544 * expose a function to lookup the derived class implementation
1545 * of a virtual method (there are examples of this in the code,
1548 * You can pass NULL as the exc argument if you don't want to
1549 * catch exceptions, otherwise, *exc will be set to the exception
1550 * thrown, if any. if an exception is thrown, you can't use the
1551 * MonoObject* result from the function.
1553 * If the method returns a value type, it is boxed in an object
1557 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1560 MonoMethodSignature *sig = method->signature;
1561 gpointer *pa = NULL;
1564 if (NULL != params) {
1565 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1566 for (i = 0; i < mono_array_length (params); i++) {
1567 if (sig->params [i]->byref) {
1571 switch (sig->params [i]->type) {
1574 case MONO_TYPE_BOOLEAN:
1577 case MONO_TYPE_CHAR:
1586 case MONO_TYPE_VALUETYPE:
1587 /* MS seems to create the objects if a null is passed in */
1588 if (! ((gpointer *)params->vector)[i])
1589 ((gpointer*)params->vector)[i] = mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]));
1590 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1592 case MONO_TYPE_STRING:
1593 case MONO_TYPE_OBJECT:
1594 case MONO_TYPE_CLASS:
1595 case MONO_TYPE_ARRAY:
1596 case MONO_TYPE_SZARRAY:
1597 if (sig->params [i]->byref)
1598 pa [i] = &(((gpointer *)params->vector)[i]);
1600 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1603 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1608 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1611 obj = mono_object_new (mono_domain_get (), method->klass);
1612 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1613 method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
1615 if (method->klass->valuetype)
1616 o = mono_object_unbox (obj);
1620 mono_runtime_invoke (method, o, pa, exc);
1623 /* obj must be already unboxed if needed */
1624 return mono_runtime_invoke (method, obj, pa, exc);
1629 out_of_memory (size_t size)
1632 * we could allocate at program startup some memory that we could release
1633 * back to the system at this point if we're really low on memory (ie, size is
1634 * lower than the memory we set apart)
1636 mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
1640 * mono_object_allocate:
1641 * @size: number of bytes to allocate
1643 * This is a very simplistic routine until we have our GC-aware
1646 * Returns: an allocated object of size @size, or NULL on failure.
1648 static inline void *
1649 mono_object_allocate (size_t size)
1652 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1653 void *o = GC_MALLOC (size);
1655 void *o = calloc (1, size);
1657 mono_stats.new_object_count++;
1660 out_of_memory (size);
1664 #if CREATION_SPEEDUP
1665 static inline void *
1666 mono_object_allocate_spec (size_t size, void *gcdescr)
1668 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1669 void *o = GC_GCJ_MALLOC (size, gcdescr);
1670 mono_stats.new_object_count++;
1673 out_of_memory (size);
1680 * @klass: the class of the object that we want to create
1682 * Returns a newly created object whose definition is
1683 * looked up using @klass. This will not invoke any constructors,
1684 * so the consumer of this routine has to invoke any constructors on
1685 * its own to initialize the object.
1688 mono_object_new (MonoDomain *domain, MonoClass *klass)
1690 MONO_ARCH_SAVE_REGS;
1691 return mono_object_new_specific (mono_class_vtable (domain, klass));
1695 * mono_object_new_specific:
1696 * @vtable: the vtable of the object that we want to create
1698 * Returns: A newly created object with class and domain specified
1702 mono_object_new_specific (MonoVTable *vtable)
1706 MONO_ARCH_SAVE_REGS;
1711 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1714 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1718 mono_class_init (klass);
1720 for (i = 0; i < klass->method.count; ++i) {
1721 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1722 klass->methods [i]->signature->param_count == 1) {
1723 im = klass->methods [i];
1728 vtable->domain->create_proxy_for_type_method = im;
1731 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1733 o = mono_runtime_invoke (im, NULL, pa, NULL);
1734 if (o != NULL) return o;
1737 return mono_object_new_alloc_specific (vtable);
1741 mono_object_new_fast (MonoVTable *vtable)
1744 MONO_ARCH_SAVE_REGS;
1746 #if CREATION_SPEEDUP
1747 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1748 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1750 /* printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
1751 o = mono_object_allocate (vtable->klass->instance_size);
1755 o = mono_object_allocate (vtable->klass->instance_size);
1762 mono_object_new_alloc_specific (MonoVTable *vtable)
1766 #if CREATION_SPEEDUP
1767 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1768 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1770 /* printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
1771 o = mono_object_allocate (vtable->klass->instance_size);
1775 o = mono_object_allocate (vtable->klass->instance_size);
1778 if (vtable->klass->has_finalize)
1779 mono_object_register_finalizer (o);
1781 mono_profiler_allocation (o, vtable->klass);
1786 * mono_object_new_from_token:
1787 * @image: Context where the type_token is hosted
1788 * @token: a token of the type that we want to create
1790 * Returns: A newly created object whose definition is
1791 * looked up using @token in the @image image
1794 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1798 class = mono_class_get (image, token);
1800 return mono_object_new (domain, class);
1805 * mono_object_clone:
1806 * @obj: the object to clone
1808 * Returns: A newly created object who is a shallow copy of @obj
1811 mono_object_clone (MonoObject *obj)
1816 size = obj->vtable->klass->instance_size;
1817 o = mono_object_allocate (size);
1818 mono_profiler_allocation (o, obj->vtable->klass);
1820 memcpy (o, obj, size);
1822 if (obj->vtable->klass->has_finalize)
1823 mono_object_register_finalizer (o);
1829 * @array: the array to clone
1831 * Returns: A newly created array who is a shallow copy of @array
1834 mono_array_clone (MonoArray *array)
1839 MonoClass *klass = array->obj.vtable->klass;
1841 MONO_ARCH_SAVE_REGS;
1843 if (array->bounds == NULL) {
1844 size = mono_array_length (array);
1845 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1846 klass, &size, NULL);
1848 size *= mono_array_element_size (klass);
1849 memcpy (o, array, sizeof (MonoArray) + size);
1854 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1855 size = mono_array_element_size (klass);
1856 for (i = 0; i < klass->rank; ++i) {
1857 sizes [i] = array->bounds [i].length;
1858 size *= array->bounds [i].length;
1859 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1861 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1862 klass, sizes, sizes + klass->rank);
1863 memcpy (o, array, sizeof(MonoArray) + size);
1868 /* helper macros to check for overflow when calculating the size of arrays */
1869 #define MYGUINT32_MAX 4294967295U
1870 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1871 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1872 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1873 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1874 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1877 * mono_array_new_full:
1878 * @domain: domain where the object is created
1879 * @array_class: array class
1880 * @lengths: lengths for each dimension in the array
1881 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1883 * This routine creates a new array objects with the given dimensions,
1884 * lower bounds and type.
1887 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1888 guint32 *lengths, guint32 *lower_bounds)
1890 guint32 byte_len, len;
1893 MonoArrayBounds *bounds;
1897 if (!array_class->inited)
1898 mono_class_init (array_class);
1900 byte_len = mono_array_element_size (array_class);
1903 if (array_class->rank == 1 &&
1904 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1909 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1911 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1913 for (i = 0; i < array_class->rank; ++i) {
1914 bounds [i].length = lengths [i];
1915 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1916 out_of_memory (MYGUINT32_MAX);
1921 for (i = 0; i < array_class->rank; ++i)
1922 bounds [i].lower_bound = lower_bounds [i];
1925 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1926 out_of_memory (MYGUINT32_MAX);
1928 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1929 out_of_memory (MYGUINT32_MAX);
1930 byte_len += sizeof (MonoArray);
1932 * Following three lines almost taken from mono_object_new ():
1933 * they need to be kept in sync.
1935 vtable = mono_class_vtable (domain, array_class);
1936 #if CREATION_SPEEDUP
1937 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1938 o = mono_object_allocate_spec (byte_len, vtable);
1940 o = mono_object_allocate (byte_len);
1944 o = mono_object_allocate (byte_len);
1948 array = (MonoArray*)o;
1950 array->bounds = bounds;
1951 array->max_length = len;
1953 mono_profiler_allocation (o, array_class);
1960 * @domain: domain where the object is created
1961 * @eclass: element class
1962 * @n: number of array elements
1964 * This routine creates a new szarray with @n elements of type @eclass.
1967 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1971 MONO_ARCH_SAVE_REGS;
1973 ac = mono_array_class_get (eclass, 1);
1974 g_assert (ac != NULL);
1976 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1980 * mono_array_new_specific:
1981 * @vtable: a vtable in the appropriate domain for an initialized class
1982 * @n: number of array elements
1984 * This routine is a fast alternative to mono_array_new() for code which
1985 * can be sure about the domain it operates in.
1988 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1992 guint32 byte_len, elem_size;
1994 MONO_ARCH_SAVE_REGS;
1996 elem_size = mono_array_element_size (vtable->klass);
1997 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1998 out_of_memory (MYGUINT32_MAX);
1999 byte_len = n * elem_size;
2000 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
2001 out_of_memory (MYGUINT32_MAX);
2002 byte_len += sizeof (MonoArray);
2003 #if CREATION_SPEEDUP
2004 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
2005 o = mono_object_allocate_spec (byte_len, vtable);
2007 /* printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name); */
2008 o = mono_object_allocate (byte_len);
2012 o = mono_object_allocate (byte_len);
2016 ao = (MonoArray *)o;
2019 mono_profiler_allocation (o, vtable->klass);
2025 * mono_string_new_utf16:
2026 * @text: a pointer to an utf16 string
2027 * @len: the length of the string
2029 * Returns: A newly created string object which contains @text.
2032 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
2036 s = mono_string_new_size (domain, len);
2037 g_assert (s != NULL);
2039 memcpy (mono_string_chars (s), text, len * 2);
2045 * mono_string_new_size:
2046 * @text: a pointer to an utf16 string
2047 * @len: the length of the string
2049 * Returns: A newly created string object of @len
2052 mono_string_new_size (MonoDomain *domain, gint32 len)
2056 size_t size = (sizeof (MonoString) + ((len + 1) * 2));
2058 /* overflow ? can't fit it, can't allocate it! */
2062 vtable = mono_class_vtable (domain, mono_defaults.string_class);
2064 #if CREATION_SPEEDUP
2065 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
2066 s = mono_object_allocate_spec (size, vtable);
2068 s = (MonoString*)mono_object_allocate (size);
2069 s->object.vtable = vtable;
2072 s = (MonoString*)mono_object_allocate (size);
2073 s->object.vtable = vtable;
2077 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
2083 * mono_string_new_len:
2084 * @text: a pointer to an utf8 string
2085 * @length: number of bytes in @text to consider
2087 * Returns: A newly created string object which contains @text.
2090 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
2092 GError *error = NULL;
2093 MonoString *o = NULL;
2095 glong items_written;
2097 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
2100 o = mono_string_new_utf16 (domain, ut, items_written);
2102 g_error_free (error);
2111 * @text: a pointer to an utf8 string
2113 * Returns: A newly created string object which contains @text.
2116 mono_string_new (MonoDomain *domain, const char *text)
2118 GError *error = NULL;
2119 MonoString *o = NULL;
2121 glong items_written;
2126 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
2129 o = mono_string_new_utf16 (domain, ut, items_written);
2131 g_error_free (error);
2139 * mono_string_new_wrapper:
2140 * @text: pointer to utf8 characters.
2142 * Helper function to create a string object from @text in the current domain.
2145 mono_string_new_wrapper (const char *text)
2147 MonoDomain *domain = mono_domain_get ();
2149 MONO_ARCH_SAVE_REGS;
2152 return mono_string_new (domain, text);
2159 * @class: the class of the value
2160 * @value: a pointer to the unboxed data
2162 * Returns: A newly created object which contains @value.
2165 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
2171 g_assert (class->valuetype);
2173 vtable = mono_class_vtable (domain, class);
2174 size = mono_class_instance_size (class);
2175 res = mono_object_allocate (size);
2176 res->vtable = vtable;
2177 mono_profiler_allocation (res, class);
2179 size = size - sizeof (MonoObject);
2181 #if NO_UNALIGNED_ACCESS
2182 memcpy ((char *)res + sizeof (MonoObject), value, size);
2186 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
2189 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
2192 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
2195 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
2198 memcpy ((char *)res + sizeof (MonoObject), value, size);
2201 if (class->has_finalize)
2202 mono_object_register_finalizer (res);
2207 mono_object_get_domain (MonoObject *obj)
2209 return mono_object_domain (obj);
2213 mono_object_get_class (MonoObject *obj)
2215 return mono_object_class (obj);
2219 mono_object_unbox (MonoObject *obj)
2221 /* add assert for valuetypes? */
2222 g_assert (obj->vtable->klass->valuetype);
2223 return ((char*)obj) + sizeof (MonoObject);
2227 * mono_object_isinst:
2229 * @klass: a pointer to a class
2231 * Returns: @obj if @obj is derived from @klass
2234 mono_object_isinst (MonoObject *obj, MonoClass *klass)
2237 mono_class_init (klass);
2239 if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2240 return mono_object_isinst_mbyref (obj, klass);
2245 return mono_class_is_assignable_from (klass, obj->vtable->klass) ? obj : NULL;
2249 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
2258 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2259 if ((klass->interface_id <= vt->max_interface_id) &&
2260 (vt->interface_offsets [klass->interface_id] != 0))
2264 MonoClass *oklass = vt->klass;
2265 if ((oklass == mono_defaults.transparent_proxy_class))
2266 oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
2268 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
2272 if (vt->klass == mono_defaults.transparent_proxy_class && ((MonoTransparentProxy *)obj)->custom_type_info)
2274 MonoDomain *domain = mono_domain_get ();
2276 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
2277 MonoClass *rpklass = mono_defaults.iremotingtypeinfo_class;
2278 MonoMethod *im = NULL;
2282 for (i = 0; i < rpklass->method.count; ++i) {
2283 if (!strcmp ("CanCastTo", rpklass->methods [i]->name)) {
2284 im = rpklass->methods [i];
2289 im = mono_object_get_virtual_method (rp, im);
2292 pa [0] = mono_type_get_object (domain, &klass->byval_arg);
2295 res = mono_runtime_invoke (im, rp, pa, NULL);
2297 if (*(MonoBoolean *) mono_object_unbox(res)) {
2298 /* Update the vtable of the remote type, so it can safely cast to this new type */
2299 mono_upgrade_remote_class (domain, ((MonoTransparentProxy *)obj)->remote_class, klass);
2300 obj->vtable = ((MonoTransparentProxy *)obj)->remote_class->vtable;
2309 * mono_object_castclass_mbyref:
2311 * @klass: a pointer to a class
2313 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
2316 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2318 if (!obj) return NULL;
2319 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2321 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2323 "InvalidCastException"));
2328 MonoDomain *orig_domain;
2334 str_lookup (MonoDomain *domain, gpointer user_data)
2336 LDStrInfo *info = user_data;
2337 if (info->res || domain == info->orig_domain)
2339 mono_domain_lock (domain);
2340 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2341 mono_domain_unlock (domain);
2345 mono_string_is_interned_lookup (MonoString *str, int insert)
2347 MonoGHashTable *ldstr_table;
2350 char *ins = g_malloc (4 + str->length * 2);
2353 /* Encode the length */
2354 /* Same code as in mono_image_insert_string () */
2356 mono_metadata_encode_value (1 | (2 * str->length), p, &p);
2359 * ins is stored in the hash table as a key and needs to have the same
2360 * representation as in the metadata: we swap the character bytes on big
2363 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2366 char *p2 = (char *)mono_string_chars (str);
2367 for (i = 0; i < str->length; ++i) {
2374 memcpy (p, mono_string_chars (str), str->length * 2);
2376 domain = ((MonoObject *)str)->vtable->domain;
2377 ldstr_table = domain->ldstr_table;
2378 mono_domain_lock (domain);
2379 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2380 mono_domain_unlock (domain);
2385 mono_g_hash_table_insert (ldstr_table, ins, str);
2386 mono_domain_unlock (domain);
2389 LDStrInfo ldstr_info;
2390 ldstr_info.orig_domain = domain;
2391 ldstr_info.ins = ins;
2392 ldstr_info.res = NULL;
2394 mono_domain_foreach (str_lookup, &ldstr_info);
2395 if (ldstr_info.res) {
2397 * the string was already interned in some other domain:
2398 * intern it in the current one as well.
2400 mono_g_hash_table_insert (ldstr_table, ins, str);
2401 mono_domain_unlock (domain);
2405 mono_domain_unlock (domain);
2411 mono_string_is_interned (MonoString *o)
2413 return mono_string_is_interned_lookup (o, FALSE);
2417 mono_string_intern (MonoString *str)
2419 return mono_string_is_interned_lookup (str, TRUE);
2424 * @domain: the domain where the string will be used.
2425 * @image: a metadata context
2426 * @idx: index into the user string table.
2428 * Implementation for the ldstr opcode.
2431 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2433 MONO_ARCH_SAVE_REGS;
2436 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2438 return mono_ldstr_metdata_sig (domain, mono_metadata_user_string (image, idx));
2442 * mono_ldstr_metdata_sig
2443 * @domain: the domain for the string
2444 * @sig: the signature of a metadata string
2446 * returns a MonoString for a string stored in the metadata
2449 mono_ldstr_metdata_sig (MonoDomain *domain, const char* sig)
2451 const char *str = sig;
2455 mono_domain_lock (domain);
2456 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2457 mono_domain_unlock (domain);
2461 len2 = mono_metadata_decode_blob_size (str, &str);
2464 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2465 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2468 guint16 *p2 = (guint16*)mono_string_chars (o);
2469 for (i = 0; i < len2; ++i) {
2470 *p2 = GUINT16_FROM_LE (*p2);
2475 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2476 mono_domain_unlock (domain);
2482 * mono_string_to_utf8:
2483 * @s: a System.String
2485 * Return the UTF8 representation for @s.
2486 * the resulting buffer nedds to be freed with g_free().
2489 mono_string_to_utf8 (MonoString *s)
2492 GError *error = NULL;
2498 return g_strdup ("");
2500 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2502 g_warning (error->message);
2503 g_error_free (error);
2510 * mono_string_to_utf16:
2513 * Return an null-terminated array of the utf-16 chars
2514 * contained in @s. The result must be freed with g_free().
2515 * This is a temporary helper until our string implementation
2516 * is reworked to always include the null terminating char.
2519 mono_string_to_utf16 (MonoString *s)
2526 as = g_malloc ((s->length * 2) + 2);
2527 as [(s->length * 2)] = '\0';
2528 as [(s->length * 2) + 1] = '\0';
2531 return (gunichar2 *)(as);
2534 memcpy (as, mono_string_chars(s), s->length * 2);
2535 return (gunichar2 *)(as);
2539 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2542 mono_string_from_utf16 (gunichar2 *data)
2544 MonoDomain *domain = mono_domain_get ();
2550 while (data [len]) len++;
2552 return mono_string_new_utf16 (domain, data, len);
2556 default_ex_handler (MonoException *ex)
2558 MonoObject *o = (MonoObject*)ex;
2559 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2563 static MonoExceptionFunc ex_handler = default_ex_handler;
2566 mono_install_handler (MonoExceptionFunc func)
2568 ex_handler = func? func: default_ex_handler;
2572 * mono_raise_exception:
2573 * @ex: exception object
2575 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2578 mono_raise_exception (MonoException *ex)
2581 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2582 * that will cause gcc to omit the function epilog, causing problems when
2583 * the JIT tries to walk the stack, since the return address on the stack
2584 * will point into the next function in the executable, not this one.
2591 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2593 MonoWaitHandle *res;
2595 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2597 res->handle = handle;
2603 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2605 MonoAsyncResult *res;
2607 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2610 res->async_state = state;
2612 res->handle = (MonoObject *) mono_wait_handle_new (domain, handle);
2614 res->sync_completed = FALSE;
2615 res->completed = FALSE;
2621 mono_message_init (MonoDomain *domain,
2622 MonoMethodMessage *this,
2623 MonoReflectionMethod *method,
2624 MonoArray *out_args)
2626 MonoMethodSignature *sig = method->method->signature;
2632 this->method = method;
2634 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2635 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2636 this->async_result = NULL;
2637 this->call_type = CallType_Sync;
2639 names = g_new (char *, sig->param_count);
2640 mono_method_get_param_names (method->method, (const char **) names);
2641 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2643 for (i = 0; i < sig->param_count; i++) {
2644 name = mono_string_new (domain, names [i]);
2645 mono_array_set (this->names, gpointer, i, name);
2649 for (i = 0, j = 0; i < sig->param_count; i++) {
2651 if (sig->params [i]->byref) {
2653 gpointer arg = mono_array_get (out_args, gpointer, j);
2654 mono_array_set (this->args, gpointer, i, arg);
2658 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2663 mono_array_set (this->arg_types, guint8, i, arg_type);
2668 * mono_remoting_invoke:
2669 * @real_proxy: pointer to a RealProxy object
2670 * @msg: The MonoMethodMessage to execute
2671 * @exc: used to store exceptions
2672 * @out_args: used to store output arguments
2674 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2675 * IMessage interface and it is not trivial to extract results from there. So
2676 * we call an helper method PrivateInvoke instead of calling
2677 * RealProxy::Invoke() directly.
2679 * Returns: the result object.
2682 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2683 MonoObject **exc, MonoArray **out_args)
2685 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2688 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2694 klass = mono_defaults.real_proxy_class;
2696 for (i = 0; i < klass->method.count; ++i) {
2697 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2698 klass->methods [i]->signature->param_count == 4) {
2699 im = klass->methods [i];
2705 real_proxy->vtable->domain->private_invoke_method = im;
2708 pa [0] = real_proxy;
2713 return mono_runtime_invoke (im, NULL, pa, exc);
2717 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2718 MonoObject **exc, MonoArray **out_args)
2722 MonoMethodSignature *sig;
2723 int i, j, outarg_count = 0;
2725 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2727 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2728 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2729 target = tp->rp->unwrapped_server;
2731 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2735 domain = mono_domain_get ();
2736 method = msg->method->method;
2737 sig = method->signature;
2739 for (i = 0; i < sig->param_count; i++) {
2740 if (sig->params [i]->byref)
2744 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2747 for (i = 0, j = 0; i < sig->param_count; i++) {
2748 if (sig->params [i]->byref) {
2750 arg = mono_array_get (msg->args, gpointer, i);
2751 mono_array_set (*out_args, gpointer, j, arg);
2756 return mono_runtime_invoke_array (method, method->klass->valuetype? mono_object_unbox (target): target, msg->args, exc);
2760 mono_print_unhandled_exception (MonoObject *exc)
2762 char *message = (char *) "";
2766 gboolean free_message = FALSE;
2769 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2770 klass = exc->vtable->klass;
2772 while (klass && method == NULL) {
2773 for (i = 0; i < klass->method.count; ++i) {
2774 method = klass->methods [i];
2775 if (!strcmp ("ToString", method->name) &&
2776 method->signature->param_count == 0 &&
2777 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2778 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2785 klass = klass->parent;
2790 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2792 message = mono_string_to_utf8 (str);
2793 free_message = TRUE;
2798 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2799 * exc->vtable->klass->name, message);
2801 g_printerr ("\nUnhandled Exception: %s\n", message);
2808 * mono_delegate_ctor:
2809 * @this: pointer to an uninitialized delegate object
2810 * @target: target object
2811 * @addr: pointer to native code
2813 * This is used to initialize a delegate. We also insert the method_info if
2814 * we find the info with mono_jit_info_table_find().
2817 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2819 MonoDomain *domain = mono_domain_get ();
2820 MonoDelegate *delegate = (MonoDelegate *)this;
2821 MonoMethod *method = NULL;
2828 class = this->vtable->klass;
2830 if ((ji = mono_jit_info_table_find (domain, addr))) {
2831 method = ji->method;
2832 delegate->method_info = mono_method_get_object (domain, method, NULL);
2835 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2837 method = mono_marshal_get_remoting_invoke (method);
2838 delegate->method_ptr = mono_compile_method (method);
2839 delegate->target = target;
2841 delegate->method_ptr = addr;
2842 delegate->target = target;
2847 * mono_method_call_message_new:
2849 * Translates arguments pointers into a Message.
2852 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2853 MonoDelegate **cb, MonoObject **state)
2855 MonoDomain *domain = mono_domain_get ();
2856 MonoMethodSignature *sig = method->signature;
2857 MonoMethodMessage *msg;
2860 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2863 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2864 count = sig->param_count - 2;
2866 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2867 count = sig->param_count;
2870 for (i = 0; i < count; i++) {
2875 if (sig->params [i]->byref)
2876 vpos = *((gpointer *)params [i]);
2880 type = sig->params [i]->type;
2881 class = mono_class_from_mono_type (sig->params [i]);
2883 if (class->valuetype)
2884 arg = mono_value_box (domain, class, vpos);
2886 arg = *((MonoObject **)vpos);
2888 mono_array_set (msg->args, gpointer, i, arg);
2891 if (cb != NULL && state != NULL) {
2892 *cb = *((MonoDelegate **)params [i]);
2894 *state = *((MonoObject **)params [i]);
2901 * mono_method_return_message_restore:
2903 * Restore results from message based processing back to arguments pointers
2906 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2908 MonoMethodSignature *sig = method->signature;
2909 int i, j, type, size;
2910 for (i = 0, j = 0; i < sig->param_count; i++) {
2911 MonoType *pt = sig->params [i];
2914 char *arg = mono_array_get (out_args, gpointer, j);
2918 case MONO_TYPE_VOID:
2919 g_assert_not_reached ();
2923 case MONO_TYPE_BOOLEAN:
2926 case MONO_TYPE_CHAR:
2933 case MONO_TYPE_VALUETYPE: {
2934 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2935 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2938 case MONO_TYPE_STRING:
2939 case MONO_TYPE_CLASS:
2940 case MONO_TYPE_ARRAY:
2941 case MONO_TYPE_SZARRAY:
2942 case MONO_TYPE_OBJECT:
2943 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2946 g_assert_not_reached ();
2955 * mono_load_remote_field:
2956 * @this: pointer to an object
2957 * @klass: klass of the object containing @field
2958 * @field: the field to load
2959 * @res: a storage to store the result
2961 * This method is called by the runtime on attempts to load fields of
2962 * transparent proxy objects. @this points to such TP, @klass is the class of
2963 * the object containing @field. @res is a storage location which can be
2964 * used to store the result.
2966 * Returns: an address pointing to the value of field.
2969 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2971 static MonoMethod *getter = NULL;
2972 MonoDomain *domain = mono_domain_get ();
2973 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2974 MonoClass *field_class;
2975 MonoMethodMessage *msg;
2976 MonoArray *out_args;
2980 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2985 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2986 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2993 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2994 MonoMethod *cm = mono_defaults.object_class->methods [i];
2996 if (!strcmp (cm->name, "FieldGetter")) {
3004 field_class = mono_class_from_mono_type (field->type);
3006 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3007 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3008 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3010 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3011 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3013 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3015 if (exc) mono_raise_exception ((MonoException *)exc);
3017 *res = mono_array_get (out_args, MonoObject *, 0);
3019 if (field_class->valuetype) {
3020 return ((char *)*res) + sizeof (MonoObject);
3026 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
3028 static MonoMethod *getter = NULL;
3029 MonoDomain *domain = mono_domain_get ();
3030 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3031 MonoClass *field_class;
3032 MonoMethodMessage *msg;
3033 MonoArray *out_args;
3034 MonoObject *exc, *res;
3036 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3038 field_class = mono_class_from_mono_type (field->type);
3040 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3042 if (field_class->valuetype) {
3043 res = mono_object_new (domain, field_class);
3044 val = ((gchar *) res) + sizeof (MonoObject);
3048 mono_field_get_value (tp->rp->unwrapped_server, field, val);
3055 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3056 MonoMethod *cm = mono_defaults.object_class->methods [i];
3058 if (!strcmp (cm->name, "FieldGetter")) {
3066 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3067 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3068 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
3070 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3071 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3073 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3075 if (exc) mono_raise_exception ((MonoException *)exc);
3077 res = mono_array_get (out_args, MonoObject *, 0);
3083 * mono_store_remote_field:
3084 * @this: pointer to an object
3085 * @klass: klass of the object containing @field
3086 * @field: the field to load
3087 * @val: the value/object to store
3089 * This method is called by the runtime on attempts to store fields of
3090 * transparent proxy objects. @this points to such TP, @klass is the class of
3091 * the object containing @field. @val is the new value to store in @field.
3094 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
3096 static MonoMethod *setter = NULL;
3097 MonoDomain *domain = mono_domain_get ();
3098 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3099 MonoClass *field_class;
3100 MonoMethodMessage *msg;
3101 MonoArray *out_args;
3105 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3107 field_class = mono_class_from_mono_type (field->type);
3109 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3110 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
3111 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
3118 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3119 MonoMethod *cm = mono_defaults.object_class->methods [i];
3121 if (!strcmp (cm->name, "FieldSetter")) {
3129 if (field_class->valuetype)
3130 arg = mono_value_box (domain, field_class, val);
3132 arg = *((MonoObject **)val);
3135 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3136 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3138 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3139 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3140 mono_array_set (msg->args, gpointer, 2, arg);
3142 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3144 if (exc) mono_raise_exception ((MonoException *)exc);
3148 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
3150 static MonoMethod *setter = NULL;
3151 MonoDomain *domain = mono_domain_get ();
3152 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
3153 MonoClass *field_class;
3154 MonoMethodMessage *msg;
3155 MonoArray *out_args;
3158 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
3160 field_class = mono_class_from_mono_type (field->type);
3162 if (tp->remote_class->proxy_class->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
3163 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
3164 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
3171 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
3172 MonoMethod *cm = mono_defaults.object_class->methods [i];
3174 if (!strcmp (cm->name, "FieldSetter")) {
3182 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
3183 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
3185 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
3186 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
3187 mono_array_set (msg->args, gpointer, 2, arg);
3189 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
3191 if (exc) mono_raise_exception ((MonoException *)exc);