2 * object.c: Object creation for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
14 #include <mono/metadata/mono-endian.h>
15 #include <mono/metadata/tabledefs.h>
16 #include <mono/metadata/tokentype.h>
17 #include <mono/metadata/loader.h>
18 #include <mono/metadata/object.h>
19 #include <mono/metadata/gc-internal.h>
20 #include <mono/metadata/exception.h>
21 #include <mono/metadata/appdomain.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/threadpool.h>
24 #include <mono/metadata/marshal.h>
25 #include "mono/metadata/debug-helpers.h"
26 #include "mono/metadata/marshal.h"
27 #include <mono/metadata/threads.h>
28 #include <mono/metadata/environment.h>
29 #include "mono/metadata/profiler-private.h"
30 #include <mono/os/gc_wrapper.h>
32 CRITICAL_SECTION *metadata_section = NULL;
35 * Enable experimental typed allocation using the GC_gcj_malloc function.
37 #ifdef HAVE_GC_GCJ_MALLOC
38 #define CREATION_SPEEDUP 1
42 mono_runtime_object_init (MonoObject *this)
45 MonoMethod *method = NULL;
46 MonoClass *klass = this->vtable->klass;
48 for (i = 0; i < klass->method.count; ++i) {
49 if (!strcmp (".ctor", klass->methods [i]->name) &&
50 klass->methods [i]->signature->param_count == 0) {
51 method = klass->methods [i];
58 mono_runtime_invoke (method, this, NULL, NULL);
62 * mono_runtime_class_init:
63 * @vtable: vtable that needs to be initialized
65 * This routine calls the class constructor for @vtable.
68 mono_runtime_class_init (MonoVTable *vtable)
72 MonoException *exc_to_throw;
80 if (vtable->initialized || vtable->initializing)
85 klass = vtable->klass;
87 for (i = 0; i < klass->method.count; ++i) {
88 method = klass->methods [i];
89 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
90 (strcmp (".cctor", method->name) == 0)) {
97 EnterCriticalSection (metadata_section);
98 mono_domain_lock (vtable->domain);
100 if (vtable->initialized || vtable->initializing) {
101 mono_domain_unlock (vtable->domain);
102 LeaveCriticalSection (metadata_section);
105 vtable->initializing = 1;
106 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
107 vtable->initialized = 1;
108 vtable->initializing = 0;
109 /* FIXME: if the cctor fails, the type must be marked as unusable */
110 mono_domain_unlock (vtable->domain);
111 LeaveCriticalSection (metadata_section);
113 vtable->initialized = 1;
118 (klass->image == mono_defaults.corlib &&
119 !strcmp (klass->name_space, "System") &&
120 !strcmp (klass->name, "TypeInitializationException")))
121 return; /* No static constructor found or avoid infinite loop */
123 if (klass->name_space && *klass->name_space)
124 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
126 full_name = g_strdup (klass->name);
128 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
131 mono_raise_exception (exc_to_throw);
135 default_trampoline (MonoMethod *method)
141 default_remoting_trampoline (MonoMethod *method)
143 g_error ("remoting not installed");
147 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
148 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
151 mono_install_trampoline (MonoTrampoline func)
153 arch_create_jit_trampoline = func? func: default_trampoline;
157 mono_install_remoting_trampoline (MonoTrampoline func)
159 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
162 static MonoCompileFunc default_mono_compile_method = NULL;
165 mono_install_compile_method (MonoCompileFunc func)
167 default_mono_compile_method = func;
171 mono_compile_method (MonoMethod *method)
173 if (!default_mono_compile_method) {
174 g_error ("compile method called on uninitialized runtime");
177 return default_mono_compile_method (method);
181 #if 0 && HAVE_BOEHM_GC
183 vtable_finalizer (void *obj, void *data) {
184 g_print ("%s finalized (%p)\n", (char*)data, obj);
190 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
193 * The vtable is assumed to be reachable by other roots, since vtables
194 * are currently never freed. That might change in the future, but
195 * for now, this is a correct (and worthwhile) optimization.
198 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
201 mono_class_compute_gc_descriptor (MonoClass *class)
203 MonoClassField *field;
206 static gboolean gcj_inited = FALSE;
211 GC_init_gcj_malloc (5, NULL);
215 mono_class_init (class);
217 if (class->gc_descr_inited)
220 class->gc_descr_inited = TRUE;
221 class->gc_descr = GC_NO_DESCRIPTOR;
223 if (class == mono_defaults.string_class) {
224 bitmap = GC_HEADER_BITMAP;
225 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
227 else if (class->rank) {
228 mono_class_compute_gc_descriptor (class->element_class);
230 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
231 bitmap = GC_HEADER_BITMAP;
233 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
234 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
238 static int count = 0;
242 /* GC 6.1 has trouble handling 64 bit descriptors... */
243 if ((class->instance_size / sizeof (gpointer)) > 30) {
244 // printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer));
248 bitmap = GC_HEADER_BITMAP;
255 // printf("KLASS: %s.\n", class->name);
257 for (p = class; p != NULL; p = p->parent) {
258 for (i = 0; i < p->field.count; ++i) {
259 field = &p->fields [i];
260 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
262 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
265 pos = field->offset / sizeof (gpointer);
267 if (field->type->byref)
270 switch (field->type->type) {
271 case MONO_TYPE_BOOLEAN:
283 // printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap);
286 case MONO_TYPE_STRING:
287 case MONO_TYPE_SZARRAY:
288 case MONO_TYPE_CLASS:
289 case MONO_TYPE_OBJECT:
290 case MONO_TYPE_ARRAY:
292 g_assert ((field->offset % sizeof(gpointer)) == 0);
294 bitmap |= ((guint64)1) << pos;
295 // printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap);
297 case MONO_TYPE_VALUETYPE: {
298 MonoClass *fclass = field->type->data.klass;
299 if (!fclass->enumtype) {
300 mono_class_compute_gc_descriptor (fclass);
301 bitmap |= (fclass->gc_bitmap & ~2) << pos;
311 // printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap);
312 class->gc_bitmap = bitmap;
313 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, class->instance_size / sizeof (gpointer));
316 #endif /* CREATION_SPEEDUP */
319 field_is_thread_static (MonoClass *fklass, MonoClassField *field)
321 MonoCustomAttrInfo *ainfo;
323 ainfo = mono_custom_attrs_from_field (fklass, field);
326 for (i = 0; i < ainfo->num_attrs; ++i) {
327 MonoClass *klass = ainfo->attrs [i].ctor->klass;
328 if (strcmp (klass->name, "ThreadStaticAttribute") == 0 && klass->image == mono_defaults.corlib) {
329 mono_custom_attrs_free (ainfo);
333 mono_custom_attrs_free (ainfo);
339 * @domain: the application domain
340 * @class: the class to initialize
342 * VTables are domain specific because we create domain specific code, and
343 * they contain the domain specific static class data.
346 mono_class_vtable (MonoDomain *domain, MonoClass *class)
349 MonoClassField *field;
356 vt = class->cached_vtable;
357 if (vt && vt->domain == domain)
360 mono_domain_lock (domain);
361 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
362 mono_domain_unlock (domain);
367 mono_class_init (class);
369 mono_stats.used_class_count++;
370 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
372 vt = mono_mempool_alloc0 (domain->mp, sizeof (MonoVTable) +
373 class->vtable_size * sizeof (gpointer));
378 mono_class_compute_gc_descriptor (class);
379 vt->gc_descr = class->gc_descr;
382 if (class->class_size) {
384 vt->data = GC_MALLOC (class->class_size + 8);
385 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
386 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
387 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
389 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
392 mono_stats.class_static_data_size += class->class_size + 8;
395 for (i = class->field.first; i < class->field.last; ++i) {
396 field = &class->fields [i - class->field.first];
397 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
399 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
400 if (field_is_thread_static (class, field)) {
401 guint32 size, align, offset;
402 size = mono_type_size (field->type, &align);
403 offset = mono_threads_alloc_static_data (size, align);
404 if (!domain->thread_static_fields)
405 domain->thread_static_fields = g_hash_table_new (NULL, NULL);
406 g_hash_table_insert (domain->thread_static_fields, field, GUINT_TO_POINTER (offset));
410 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
411 MonoClass *fklass = mono_class_from_mono_type (field->type);
412 t = (char*)vt->data + field->offset;
413 if (fklass->valuetype) {
414 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
416 /* it's a pointer type: add check */
417 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
418 *t = *(char *)field->data;
422 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
424 p = field->def_value->value;
425 len = mono_metadata_decode_blob_size (p, &p);
426 t = (char*)vt->data + field->offset;
427 /* should we check that the type matches? */
428 switch (field->def_value->type) {
429 case MONO_TYPE_BOOLEAN:
437 guint16 *val = (guint16*)t;
443 guint32 *val = (guint32*)t;
449 guint64 *val = (guint64*)t;
454 float *val = (float*)t;
459 double *val = (double*)t;
463 case MONO_TYPE_STRING: {
464 gpointer *val = (gpointer*)t;
465 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
466 gunichar2 *copy = g_malloc (len);
468 for (j = 0; j < len/2; j++) {
469 copy [j] = read16 (p);
472 *val = mono_string_new_utf16 (domain, copy, len/2);
475 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
479 case MONO_TYPE_CLASS:
480 /* nothing to do, we malloc0 the data and the value can be 0 only */
483 g_warning ("type 0x%02x should not be in constant table", field->def_value->type);
487 vt->max_interface_id = class->max_interface_id;
489 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
490 sizeof (gpointer) * (class->max_interface_id + 1));
492 /* initialize interface offsets */
493 for (i = 0; i <= class->max_interface_id; ++i) {
494 int slot = class->interface_offsets [i];
496 vt->interface_offsets [i] = &(vt->vtable [slot]);
500 * arch_create_jit_trampoline () can recursively call this function again
501 * because it compiles icall methods right away.
503 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
504 if (!class->cached_vtable)
505 class->cached_vtable = vt;
507 /* initialize vtable */
508 for (i = 0; i < class->vtable_size; ++i) {
511 if ((cm = class->vtable [i]))
512 vt->vtable [i] = arch_create_jit_trampoline (cm);
515 mono_domain_unlock (domain);
517 /* make sure the the parent is initialized */
519 mono_class_vtable (domain, class->parent);
521 if (class->contextbound)
530 * mono_class_proxy_vtable:
531 * @domain: the application domain
532 * @class: the class to proxy
534 * Creates a vtable for transparent proxies. It is basically
535 * a copy of the real vtable of @class, but all function pointers invoke
536 * the remoting functions, and vtable->klass points to the
537 * transparent proxy class, and not to @class.
540 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
542 MonoVTable *vt, *pvt;
543 int i, j, vtsize, interface_vtsize = 0;
544 MonoClass* iclass = NULL;
547 if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
550 if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
553 class = mono_defaults.marshalbyrefobject_class;
555 method_count = iclass->method.count;
556 for (i = 0; i < iclass->interface_count; i++)
557 method_count += iclass->interfaces[i]->method.count;
559 interface_vtsize = method_count * sizeof (gpointer);
562 vt = mono_class_vtable (domain, class);
563 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
565 mono_stats.class_vtable_size += vtsize + interface_vtsize;
567 pvt = mono_mempool_alloc (domain->mp, vtsize + interface_vtsize);
568 memcpy (pvt, vt, vtsize);
570 pvt->klass = mono_defaults.transparent_proxy_class;
572 /* initialize vtable */
573 for (i = 0; i < class->vtable_size; ++i) {
576 if ((cm = class->vtable [i]))
577 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
580 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
582 /* create trampolines for abstract methods */
583 for (k = class; k; k = k->parent) {
584 for (i = 0; i < k->method.count; i++) {
585 int slot = k->methods [i]->slot;
586 if (!pvt->vtable [slot])
587 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
597 pvt->max_interface_id = iclass->max_interface_id;
599 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
600 sizeof (gpointer) * (pvt->max_interface_id + 1));
602 /* Create trampolines for the methods of the interfaces */
603 slot = class->vtable_size;
607 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
609 for (j = 0; j < interf->method.count; ++j) {
610 MonoMethod *cm = interf->methods [j];
611 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
613 slot += interf->method.count;
614 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
623 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
624 sizeof (gpointer) * (pvt->max_interface_id + 1));
626 /* initialize interface offsets */
627 for (i = 0; i <= class->max_interface_id; ++i) {
628 int slot = class->interface_offsets [i];
630 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
634 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
640 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
641 * the instance of a callvirt of method.
644 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
650 klass = mono_object_class (obj);
651 if (klass == mono_defaults.transparent_proxy_class) {
652 klass = ((MonoTransparentProxy *)obj)->klass;
658 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
661 vtable = klass->vtable;
663 /* check method->slot is a valid index: perform isinstance? */
664 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
665 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
667 res = vtable [method->slot];
672 return mono_marshal_get_remoting_invoke (res);
678 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
680 g_error ("runtime invoke called on uninitialized runtime");
684 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
687 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
689 return default_mono_runtime_invoke (method, obj, params, exc);
693 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
696 gpointer *p = (gpointer*)dest;
703 case MONO_TYPE_BOOLEAN:
706 guint8 *p = (guint8*)dest;
707 *p = *(guint8*)value;
712 case MONO_TYPE_CHAR: {
713 guint16 *p = (guint16*)dest;
714 *p = *(guint16*)value;
717 #if SIZEOF_VOID_P == 4
723 gint32 *p = (gint32*)dest;
724 *p = *(gint32*)value;
727 #if SIZEOF_VOID_P == 8
733 gint64 *p = (gint64*)dest;
734 *p = *(gint64*)value;
738 float *p = (float*)dest;
743 double *p = (double*)dest;
744 *p = *(double*)value;
747 case MONO_TYPE_STRING:
748 case MONO_TYPE_SZARRAY:
749 case MONO_TYPE_CLASS:
750 case MONO_TYPE_OBJECT:
751 case MONO_TYPE_ARRAY:
752 case MONO_TYPE_PTR: {
753 gpointer *p = (gpointer*)dest;
754 *p = deref_pointer? *(gpointer*)value: value;
757 case MONO_TYPE_VALUETYPE:
758 if (type->data.klass->enumtype) {
759 t = type->data.klass->enum_basetype->type;
763 size = mono_class_value_size (type->data.klass, NULL);
764 memcpy (dest, value, size);
768 g_warning ("got type %x", type->type);
769 g_assert_not_reached ();
774 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
778 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
780 dest = (char*)obj + field->offset;
781 set_value (field->type, dest, value, FALSE);
785 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
789 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
791 dest = (char*)vt->data + field->offset;
792 set_value (field->type, dest, value, FALSE);
796 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
800 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
802 src = (char*)obj + field->offset;
803 set_value (field->type, value, src, TRUE);
807 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
811 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
813 src = (char*)vt->data + field->offset;
814 set_value (field->type, value, src, TRUE);
818 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
820 default_mono_runtime_invoke (prop->set, obj, params, exc);
824 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
826 return default_mono_runtime_invoke (prop->get, obj, params, exc);
831 mono_get_delegate_invoke (MonoClass *klass)
838 for (i = 0; i < klass->method.count; ++i) {
839 if (klass->methods [i]->name[0] == 'I' &&
840 !strcmp ("Invoke", klass->methods [i]->name)) {
841 im = klass->methods [i];
851 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
855 im = mono_get_delegate_invoke (delegate->vtable->klass);
858 return mono_runtime_invoke (im, delegate, params, exc);
861 static MonoArray* main_args;
864 mono_runtime_get_main_args (void)
870 * Execute a standard Main() method (argc/argv contains the
871 * executable name). This method also sets the command line argument value
872 * needed by System.Environment.
875 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
879 MonoArray *args = NULL;
880 MonoDomain *domain = mono_domain_get ();
882 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
884 if (!g_path_is_absolute (argv [0])) {
885 gchar *basename = g_path_get_basename (argv [0]);
886 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
890 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, fullpath));
894 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, argv [0]));
897 for (i = 1; i < argc; ++i) {
898 MonoString *arg = mono_string_new (domain, argv [i]);
899 mono_array_set (main_args, gpointer, i, arg);
903 if (method->signature->param_count) {
904 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
905 for (i = 0; i < argc; ++i) {
906 MonoString *arg = mono_string_new (domain, argv [i]);
907 mono_array_set (args, gpointer, i, arg);
910 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
913 mono_assembly_set_main (method->klass->image->assembly);
915 return mono_runtime_exec_main (method, args, exc);
918 /* Used in mono_unhandled_exception */
920 create_unhandled_exception_eventargs (MonoObject *exc)
925 MonoBoolean is_terminating = TRUE;
929 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
932 mono_class_init (klass);
934 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
935 for (i = 0; i < klass->method.count; ++i) {
936 method = klass->methods [i];
937 if (!strcmp (".ctor", method->name) &&
938 method->signature->param_count == 2 &&
939 method->flags & METHOD_ATTRIBUTE_PUBLIC)
947 args [1] = &is_terminating;
949 obj = mono_object_new (mono_domain_get (), klass);
950 mono_runtime_invoke (method, obj, args, NULL);
956 * We call this function when we detect an unhandled exception
957 * in the default domain.
958 * It invokes the * UnhandledException event in AppDomain or prints
959 * a warning to the console
962 mono_unhandled_exception (MonoObject *exc)
964 MonoDomain *domain = mono_domain_get ();
965 MonoClassField *field;
966 MonoObject *delegate;
968 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
969 "UnhandledException");
972 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
973 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
975 /* set exitcode only in the main thread? */
976 mono_environment_exitcode_set (1);
977 if (domain != mono_root_domain || !delegate) {
978 mono_print_unhandled_exception (exc);
980 MonoObject *e = NULL;
983 pa [0] = domain->domain;
984 pa [1] = create_unhandled_exception_eventargs (exc);
985 mono_runtime_delegate_invoke (delegate, pa, &e);
988 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
989 g_warning ("exception inside UnhandledException handler: %s\n", msg);
997 * Launch a new thread to start all setup that requires managed code
1000 * main_func is called back from the thread with main_args as the
1001 * parameter. The callback function is expected to start Main()
1002 * eventually. This function then waits for all managed threads to
1006 mono_runtime_exec_managed_code (MonoDomain *domain,
1007 MonoMainThreadFunc main_func,
1010 mono_thread_create (domain, main_func, main_args);
1012 mono_thread_manage ();
1016 * Execute a standard Main() method (args doesn't contain the
1020 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1030 domain = mono_object_domain (args);
1031 if (!domain->entry_assembly) {
1032 domain->entry_assembly = method->klass->image->assembly;
1033 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
1036 /* FIXME: check signature of method */
1037 if (method->signature->ret->type == MONO_TYPE_I4) {
1039 res = mono_runtime_invoke (method, NULL, pa, exc);
1041 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1045 mono_environment_exitcode_set (rval);
1047 mono_runtime_invoke (method, NULL, pa, exc);
1051 /* If the return type of Main is void, only
1052 * set the exitcode if an exception was thrown
1053 * (we don't want to blow away an
1054 * explicitly-set exit code)
1057 mono_environment_exitcode_set (rval);
1065 mono_install_runtime_invoke (MonoInvokeFunc func)
1067 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1071 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1074 MonoMethodSignature *sig = method->signature;
1075 gpointer *pa = NULL;
1078 if (NULL != params) {
1079 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1080 for (i = 0; i < mono_array_length (params); i++) {
1081 if (sig->params [i]->byref) {
1085 switch (sig->params [i]->type) {
1088 case MONO_TYPE_BOOLEAN:
1091 case MONO_TYPE_CHAR:
1100 case MONO_TYPE_VALUETYPE:
1101 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1103 case MONO_TYPE_STRING:
1104 case MONO_TYPE_OBJECT:
1105 case MONO_TYPE_CLASS:
1106 case MONO_TYPE_ARRAY:
1107 case MONO_TYPE_SZARRAY:
1108 if (sig->params [i]->byref)
1109 pa [i] = &(((gpointer *)params->vector)[i]);
1111 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1114 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1119 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1121 obj = mono_object_new (mono_domain_get (), method->klass);
1122 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1123 method = mono_marshal_get_remoting_invoke (method->klass->vtable [method->slot]);
1126 mono_runtime_invoke (method, obj, pa, exc);
1129 return mono_runtime_invoke (method, obj, pa, exc);
1132 G_GNUC_NORETURN static void
1133 out_of_memory (size_t size)
1136 * we could allocate at program startup some memory that we could release
1137 * back to the system at this point if we're really low on memory (ie, size is
1138 * lower than the memory we set apart)
1140 MonoException * ex = mono_exception_from_name (mono_defaults.corlib, "System", "OutOfMemoryException");
1141 mono_raise_exception (ex);
1145 * mono_object_allocate:
1146 * @size: number of bytes to allocate
1148 * This is a very simplistic routine until we have our GC-aware
1151 * Returns: an allocated object of size @size, or NULL on failure.
1154 mono_object_allocate (size_t size)
1157 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1158 void *o = GC_MALLOC (size);
1160 void *o = calloc (1, size);
1162 mono_stats.new_object_count++;
1165 out_of_memory (size);
1169 #if CREATION_SPEEDUP
1171 mono_object_allocate_spec (size_t size, void *gcdescr)
1173 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1174 void *o = GC_GCJ_MALLOC (size, gcdescr);
1175 mono_stats.new_object_count++;
1178 out_of_memory (size);
1186 * Frees the memory used by the object. Debugging purposes
1187 * only, as we will have our GC system.
1190 mono_object_free (MonoObject *o)
1193 g_error ("mono_object_free called with boehm gc.");
1195 MonoClass *c = o->vtable->klass;
1197 memset (o, 0, c->instance_size);
1204 * @klass: the class of the object that we want to create
1206 * Returns: A newly created object whose definition is
1207 * looked up using @klass
1210 mono_object_new (MonoDomain *domain, MonoClass *klass)
1212 MONO_ARCH_SAVE_REGS;
1213 return mono_object_new_specific (mono_class_vtable (domain, klass));
1217 * mono_object_new_specific:
1218 * @vtable: the vtable of the object that we want to create
1220 * Returns: A newly created object with class and domain specified
1224 mono_object_new_specific (MonoVTable *vtable)
1228 MONO_ARCH_SAVE_REGS;
1233 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1236 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1240 mono_class_init (klass);
1242 for (i = 0; i < klass->method.count; ++i) {
1243 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1244 klass->methods [i]->signature->param_count == 1) {
1245 im = klass->methods [i];
1250 vtable->domain->create_proxy_for_type_method = im;
1253 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1255 o = mono_runtime_invoke (im, NULL, pa, NULL);
1256 if (o != NULL) return o;
1259 return mono_object_new_alloc_specific (vtable);
1263 mono_object_new_fast (MonoVTable *vtable)
1266 MONO_ARCH_SAVE_REGS;
1268 #if CREATION_SPEEDUP
1269 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1270 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1272 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1273 o = mono_object_allocate (vtable->klass->instance_size);
1277 o = mono_object_allocate (vtable->klass->instance_size);
1284 mono_object_new_alloc_specific (MonoVTable *vtable)
1288 #if CREATION_SPEEDUP
1289 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1290 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1292 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1293 o = mono_object_allocate (vtable->klass->instance_size);
1297 o = mono_object_allocate (vtable->klass->instance_size);
1300 if (vtable->klass->has_finalize)
1301 mono_object_register_finalizer (o);
1303 mono_profiler_allocation (o, vtable->klass);
1308 * mono_object_new_from_token:
1309 * @image: Context where the type_token is hosted
1310 * @token: a token of the type that we want to create
1312 * Returns: A newly created object whose definition is
1313 * looked up using @token in the @image image
1316 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1320 class = mono_class_get (image, token);
1322 return mono_object_new (domain, class);
1327 * mono_object_clone:
1328 * @obj: the object to clone
1330 * Returns: A newly created object who is a shallow copy of @obj
1333 mono_object_clone (MonoObject *obj)
1338 size = obj->vtable->klass->instance_size;
1339 o = mono_object_allocate (size);
1340 mono_profiler_allocation (o, obj->vtable->klass);
1342 memcpy (o, obj, size);
1344 if (obj->vtable->klass->has_finalize)
1345 mono_object_register_finalizer (o);
1351 * @array: the array to clone
1353 * Returns: A newly created array who is a shallow copy of @array
1356 mono_array_clone (MonoArray *array)
1361 MonoClass *klass = array->obj.vtable->klass;
1363 MONO_ARCH_SAVE_REGS;
1365 if (array->bounds == NULL) {
1366 size = mono_array_length (array);
1367 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1368 klass, &size, NULL);
1370 size *= mono_array_element_size (klass);
1371 memcpy (o, array, sizeof (MonoArray) + size);
1376 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1377 size = mono_array_element_size (klass);
1378 for (i = 0; i < klass->rank; ++i) {
1379 sizes [i] = array->bounds [i].length;
1380 size *= array->bounds [i].length;
1381 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1383 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1384 klass, sizes, sizes + klass->rank);
1385 memcpy (o, array, sizeof(MonoArray) + size);
1390 /* helper macros to check for overflow when calculating the size of arrays */
1391 #define MYGUINT32_MAX 4294967295U
1392 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1393 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1394 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1395 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1396 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1399 * mono_array_new_full:
1400 * @domain: domain where the object is created
1401 * @array_class: array class
1402 * @lengths: lengths for each dimension in the array
1403 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1405 * This routine creates a new array objects with the given dimensions,
1406 * lower bounds and type.
1409 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1410 guint32 *lengths, guint32 *lower_bounds)
1412 guint32 byte_len, len;
1415 MonoArrayBounds *bounds;
1419 if (!array_class->inited)
1420 mono_class_init (array_class);
1422 byte_len = mono_array_element_size (array_class);
1425 if (array_class->rank == 1 &&
1426 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1431 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1433 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1435 for (i = 0; i < array_class->rank; ++i) {
1436 bounds [i].length = lengths [i];
1437 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1438 out_of_memory (MYGUINT32_MAX);
1443 for (i = 0; i < array_class->rank; ++i)
1444 bounds [i].lower_bound = lower_bounds [i];
1447 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1448 out_of_memory (MYGUINT32_MAX);
1450 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1451 out_of_memory (MYGUINT32_MAX);
1452 byte_len += sizeof (MonoArray);
1454 * Following three lines almost taken from mono_object_new ():
1455 * they need to be kept in sync.
1457 vtable = mono_class_vtable (domain, array_class);
1458 #if CREATION_SPEEDUP
1459 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1460 o = mono_object_allocate_spec (byte_len, vtable);
1462 o = mono_object_allocate (byte_len);
1466 o = mono_object_allocate (byte_len);
1470 array = (MonoArray*)o;
1472 array->bounds = bounds;
1473 array->max_length = len;
1475 mono_profiler_allocation (o, array_class);
1482 * @domain: domain where the object is created
1483 * @eclass: element class
1484 * @n: number of array elements
1486 * This routine creates a new szarray with @n elements of type @eclass.
1489 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1493 MONO_ARCH_SAVE_REGS;
1495 ac = mono_array_class_get (eclass, 1);
1496 g_assert (ac != NULL);
1498 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1502 * mono_array_new_specific:
1503 * @vtable: a vtable in the appropriate domain for an initialized class
1504 * @n: number of array elements
1506 * This routine is a fast alternative to mono_array_new() for code which
1507 * can be sure about the domain it operates in.
1510 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1514 guint32 byte_len, elem_size;
1516 MONO_ARCH_SAVE_REGS;
1518 elem_size = mono_array_element_size (vtable->klass);
1519 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1520 out_of_memory (MYGUINT32_MAX);
1521 byte_len = n * elem_size;
1522 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1523 out_of_memory (MYGUINT32_MAX);
1524 byte_len += sizeof (MonoArray);
1525 #if CREATION_SPEEDUP
1526 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1527 o = mono_object_allocate_spec (byte_len, vtable);
1529 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1530 o = mono_object_allocate (byte_len);
1534 o = mono_object_allocate (byte_len);
1538 ao = (MonoArray *)o;
1541 mono_profiler_allocation (o, vtable->klass);
1547 * mono_string_new_utf16:
1548 * @text: a pointer to an utf16 string
1549 * @len: the length of the string
1551 * Returns: A newly created string object which contains @text.
1554 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1558 s = mono_string_new_size (domain, len);
1559 g_assert (s != NULL);
1561 memcpy (mono_string_chars (s), text, len * 2);
1567 * mono_string_new_size:
1568 * @text: a pointer to an utf16 string
1569 * @len: the length of the string
1571 * Returns: A newly created string object of @len
1574 mono_string_new_size (MonoDomain *domain, gint32 len)
1579 vtable = mono_class_vtable (domain, mono_defaults.string_class);
1581 #if CREATION_SPEEDUP
1582 s = mono_object_allocate_spec (sizeof (MonoString) + ((len + 1) * 2), vtable);
1584 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1585 s->object.vtable = vtable;
1589 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
1595 * mono_string_new_len:
1596 * @text: a pointer to an utf8 string
1597 * @length: number of bytes in @text to consider
1599 * Returns: A newly created string object which contains @text.
1602 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1604 GError *error = NULL;
1605 MonoString *o = NULL;
1607 glong items_written;
1609 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1612 o = mono_string_new_utf16 (domain, ut, items_written);
1614 g_error_free (error);
1623 * @text: a pointer to an utf8 string
1625 * Returns: A newly created string object which contains @text.
1628 mono_string_new (MonoDomain *domain, const char *text)
1630 GError *error = NULL;
1631 MonoString *o = NULL;
1633 glong items_written;
1638 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1641 o = mono_string_new_utf16 (domain, ut, items_written);
1643 g_error_free (error);
1651 * mono_string_new_wrapper:
1652 * @text: pointer to utf8 characters.
1654 * Helper function to create a string object from @text in the current domain.
1657 mono_string_new_wrapper (const char *text)
1659 MonoDomain *domain = mono_domain_get ();
1661 MONO_ARCH_SAVE_REGS;
1664 return mono_string_new (domain, text);
1671 * @class: the class of the value
1672 * @value: a pointer to the unboxed data
1674 * Returns: A newly created object which contains @value.
1677 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1683 g_assert (class->valuetype);
1685 vtable = mono_class_vtable (domain, class);
1686 size = mono_class_instance_size (class);
1687 res = mono_object_allocate (size);
1688 res->vtable = vtable;
1689 mono_profiler_allocation (res, class);
1691 size = size - sizeof (MonoObject);
1693 #if NO_UNALIGNED_ACCESS
1694 memcpy ((char *)res + sizeof (MonoObject), value, size);
1698 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
1701 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
1704 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
1707 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
1710 memcpy ((char *)res + sizeof (MonoObject), value, size);
1713 if (class->has_finalize)
1714 mono_object_register_finalizer (res);
1719 mono_object_unbox (MonoObject *obj)
1721 /* add assert for valuetypes? */
1722 return ((char*)obj) + sizeof (MonoObject);
1726 * mono_object_isinst:
1728 * @klass: a pointer to a class
1730 * Returns: @obj if @obj is derived from @klass
1733 mono_object_isinst (MonoObject *obj, MonoClass *klass)
1745 mono_class_init (klass);
1747 if (oklass == mono_defaults.transparent_proxy_class) {
1748 /* fixme: add check for IRemotingTypeInfo */
1749 MonoRealProxy *rp = ((MonoTransparentProxy *)obj)->rp;
1751 type = rp->class_to_proxy->type;
1752 oklass = mono_class_from_mono_type (type);
1755 return mono_class_is_assignable_from (klass, oklass) ? obj : NULL;
1759 MonoDomain *orig_domain;
1765 str_lookup (MonoDomain *domain, gpointer user_data)
1767 LDStrInfo *info = user_data;
1768 if (info->res || domain == info->orig_domain)
1770 mono_domain_lock (domain);
1771 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
1772 mono_domain_unlock (domain);
1776 mono_string_is_interned_lookup (MonoString *str, int insert)
1778 MonoGHashTable *ldstr_table;
1781 char *ins = g_malloc (4 + str->length * 2);
1785 /* Encode the length */
1787 mono_metadata_encode_value (2 * str->length, p, &p);
1790 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
1791 bloblen = (p - ins) + 2 * str->length;
1793 * ins is stored in the hash table as a key and needs to have the same
1794 * representation as in the metadata: we swap the character bytes on big
1797 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1800 char *p2 = mono_string_chars (str);
1801 for (i = 0; i < str->length; ++i) {
1808 memcpy (p, mono_string_chars (str), str->length * 2);
1810 domain = ((MonoObject *)str)->vtable->domain;
1811 ldstr_table = domain->ldstr_table;
1812 mono_domain_lock (domain);
1813 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1814 mono_domain_unlock (domain);
1819 mono_g_hash_table_insert (ldstr_table, ins, str);
1820 mono_domain_unlock (domain);
1823 LDStrInfo ldstr_info;
1824 ldstr_info.orig_domain = domain;
1825 ldstr_info.ins = ins;
1826 ldstr_info.res = NULL;
1828 mono_domain_foreach (str_lookup, &ldstr_info);
1829 if (ldstr_info.res) {
1831 * the string was already interned in some other domain:
1832 * intern it in the current one as well.
1834 mono_g_hash_table_insert (ldstr_table, ins, str);
1835 mono_domain_unlock (domain);
1839 mono_domain_unlock (domain);
1845 mono_string_is_interned (MonoString *o)
1847 return mono_string_is_interned_lookup (o, FALSE);
1851 mono_string_intern (MonoString *str)
1853 return mono_string_is_interned_lookup (str, TRUE);
1858 * @domain: the domain where the string will be used.
1859 * @image: a metadata context
1860 * @idx: index into the user string table.
1862 * Implementation for the ldstr opcode.
1865 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
1867 const char *str, *sig;
1871 MONO_ARCH_SAVE_REGS;
1873 if (image->assembly->dynamic)
1874 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
1876 sig = str = mono_metadata_user_string (image, idx);
1878 mono_domain_lock (domain);
1879 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
1880 mono_domain_unlock (domain);
1884 len2 = mono_metadata_decode_blob_size (str, &str);
1887 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
1888 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1891 guint16 *p2 = (guint16*)mono_string_chars (o);
1892 for (i = 0; i < len2; ++i) {
1893 *p2 = GUINT16_FROM_LE (*p2);
1898 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
1899 mono_domain_unlock (domain);
1905 * mono_string_to_utf8:
1906 * @s: a System.String
1908 * Return the UTF8 representation for @s.
1909 * the resulting buffer nedds to be freed with g_free().
1912 mono_string_to_utf8 (MonoString *s)
1915 GError *error = NULL;
1921 return g_strdup ("");
1923 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
1925 g_warning (error->message);
1926 g_error_free (error);
1933 * mono_string_to_utf16:
1936 * Return an null-terminated array of the utf-16 chars
1937 * contained in @s. The result must be freed with g_free().
1938 * This is a temporary helper until our string implementation
1939 * is reworked to always include the null terminating char.
1942 mono_string_to_utf16 (MonoString *s)
1949 as = g_malloc ((s->length * 2) + 2);
1950 as [(s->length * 2)] = '\0';
1951 as [(s->length * 2) + 1] = '\0';
1954 return (gunichar2 *)(as);
1957 memcpy (as, mono_string_chars(s), s->length * 2);
1958 return (gunichar2 *)(as);
1962 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
1965 mono_string_from_utf16 (gunichar2 *data)
1967 MonoDomain *domain = mono_domain_get ();
1973 while (data [len]) len++;
1975 return mono_string_new_utf16 (domain, data, len);
1978 G_GNUC_NORETURN static void
1979 default_ex_handler (MonoException *ex)
1981 MonoObject *o = (MonoObject*)ex;
1982 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
1986 static G_GNUC_NORETURN MonoExceptionFunc ex_handler = default_ex_handler;
1989 mono_install_handler (MonoExceptionFunc func)
1991 ex_handler = func? func: default_ex_handler;
1995 * mono_raise_exception:
1996 * @ex: exception object
1998 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2000 G_GNUC_NORETURN void
2001 mono_raise_exception (MonoException *ex)
2007 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2009 MonoWaitHandle *res;
2011 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2013 res->handle = handle;
2019 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2021 MonoAsyncResult *res;
2023 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2026 res->async_state = state;
2027 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
2028 res->sync_completed = FALSE;
2029 res->completed = FALSE;
2035 mono_message_init (MonoDomain *domain,
2036 MonoMethodMessage *this,
2037 MonoReflectionMethod *method,
2038 MonoArray *out_args)
2040 MonoMethodSignature *sig = method->method->signature;
2046 this->method = method;
2048 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2049 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2051 names = g_new (char *, sig->param_count);
2052 mono_method_get_param_names (method->method, (const char **) names);
2053 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2055 for (i = 0; i < sig->param_count; i++) {
2056 name = mono_string_new (domain, names [i]);
2057 mono_array_set (this->names, gpointer, i, name);
2062 for (i = 0, j = 0; i < sig->param_count; i++) {
2064 if (sig->params [i]->byref) {
2066 gpointer arg = mono_array_get (out_args, gpointer, j);
2067 mono_array_set (this->args, gpointer, i, arg);
2071 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
2077 mono_array_set (this->arg_types, guint8, i, arg_type);
2082 * mono_remoting_invoke:
2083 * @real_proxy: pointer to a RealProxy object
2084 * @msg: The MonoMethodMessage to execute
2085 * @exc: used to store exceptions
2086 * @out_args: used to store output arguments
2088 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2089 * IMessage interface and it is not trivial to extract results from there. So
2090 * we call an helper method PrivateInvoke instead of calling
2091 * RealProxy::Invoke() directly.
2093 * Returns: the result object.
2096 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2097 MonoObject **exc, MonoArray **out_args)
2099 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2102 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2108 klass = mono_defaults.real_proxy_class;
2110 for (i = 0; i < klass->method.count; ++i) {
2111 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2112 klass->methods [i]->signature->param_count == 4) {
2113 im = klass->methods [i];
2119 real_proxy->vtable->domain->private_invoke_method = im;
2122 pa [0] = real_proxy;
2127 return mono_runtime_invoke (im, NULL, pa, exc);
2131 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2132 MonoObject **exc, MonoArray **out_args)
2136 MonoMethodSignature *sig;
2137 int i, j, outarg_count = 0;
2139 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2141 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2142 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2143 target = tp->rp->unwrapped_server;
2145 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2149 domain = mono_domain_get ();
2150 method = msg->method->method;
2151 sig = method->signature;
2153 for (i = 0; i < sig->param_count; i++) {
2154 if (sig->params [i]->byref)
2158 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2161 for (i = 0, j = 0; i < sig->param_count; i++) {
2162 if (sig->params [i]->byref) {
2164 arg = mono_array_get (msg->args, gpointer, i);
2165 mono_array_set (*out_args, gpointer, j, arg);
2170 return mono_runtime_invoke_array (method, target, msg->args, exc);
2174 mono_print_unhandled_exception (MonoObject *exc)
2176 char *message = (char *) "";
2180 gboolean free_message = FALSE;
2183 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2184 klass = exc->vtable->klass;
2186 while (klass && method == NULL) {
2187 for (i = 0; i < klass->method.count; ++i) {
2188 method = klass->methods [i];
2189 if (!strcmp ("ToString", method->name) &&
2190 method->signature->param_count == 0 &&
2191 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2192 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2199 klass = klass->parent;
2204 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2206 message = mono_string_to_utf8 (str);
2207 free_message = TRUE;
2212 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2213 * exc->vtable->klass->name, message);
2215 g_printerr ("\nUnhandled Exception: %s\n", message);
2222 * mono_delegate_ctor:
2223 * @this: pointer to an uninitialized delegate object
2224 * @target: target object
2225 * @addr: pointer to native code
2227 * This is used to initialize a delegate. We also insert the method_info if
2228 * we find the info with mono_jit_info_table_find().
2231 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2233 MonoDomain *domain = mono_domain_get ();
2234 MonoDelegate *delegate = (MonoDelegate *)this;
2235 MonoMethod *method = NULL;
2242 class = this->vtable->klass;
2244 if ((ji = mono_jit_info_table_find (domain, addr))) {
2245 method = ji->method;
2246 delegate->method_info = mono_method_get_object (domain, method, NULL);
2249 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2251 method = mono_marshal_get_remoting_invoke (method);
2252 delegate->method_ptr = mono_compile_method (method);
2253 delegate->target = target;
2255 delegate->method_ptr = addr;
2256 delegate->target = target;
2261 * mono_method_call_message_new:
2263 * Translates arguments pointers into a Message.
2266 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2267 MonoDelegate **cb, MonoObject **state)
2269 MonoDomain *domain = mono_domain_get ();
2270 MonoMethodSignature *sig = method->signature;
2271 MonoMethodMessage *msg;
2274 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2277 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2278 count = sig->param_count - 2;
2280 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2281 count = sig->param_count;
2284 for (i = 0; i < count; i++) {
2289 if (sig->params [i]->byref)
2290 vpos = *((gpointer *)params [i]);
2294 type = sig->params [i]->type;
2295 class = mono_class_from_mono_type (sig->params [i]);
2297 if (class->valuetype)
2298 arg = mono_value_box (domain, class, vpos);
2300 arg = *((MonoObject **)vpos);
2302 mono_array_set (msg->args, gpointer, i, arg);
2306 *cb = *((MonoDelegate **)params [i]);
2308 *state = *((MonoObject **)params [i]);
2315 * mono_method_return_message_restore:
2317 * Restore results from message based processing back to arguments pointers
2320 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2322 MonoMethodSignature *sig = method->signature;
2323 int i, j, type, size;
2325 for (i = 0, j = 0; i < sig->param_count; i++) {
2326 MonoType *pt = sig->params [i];
2328 size = mono_type_stack_size (pt, NULL);
2331 char *arg = mono_array_get (out_args, gpointer, j);
2335 case MONO_TYPE_VOID:
2336 g_assert_not_reached ();
2340 case MONO_TYPE_BOOLEAN:
2343 case MONO_TYPE_CHAR:
2350 case MONO_TYPE_VALUETYPE: {
2351 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2354 case MONO_TYPE_STRING:
2355 case MONO_TYPE_CLASS:
2356 case MONO_TYPE_ARRAY:
2357 case MONO_TYPE_SZARRAY:
2358 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2361 g_assert_not_reached ();
2370 * mono_load_remote_field:
2371 * @this: pointer to an object
2372 * @klass: klass of the object containing @field
2373 * @field: the field to load
2374 * @res: a storage to store the result
2376 * This method is called by the runtime on attempts to load fields of
2377 * transparent proxy objects. @this points to such TP, @klass is the class of
2378 * the object containing @field. @res is a storage location which can be
2379 * used to store the result.
2381 * Returns: an address pointing to the value of field.
2384 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2386 static MonoMethod *getter = NULL;
2387 MonoDomain *domain = mono_domain_get ();
2388 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2389 MonoClass *field_class;
2390 MonoMethodMessage *msg;
2391 MonoArray *out_args;
2395 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2400 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2401 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2408 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2409 MonoMethod *cm = mono_defaults.object_class->methods [i];
2411 if (!strcmp (cm->name, "FieldGetter")) {
2419 field_class = mono_class_from_mono_type (field->type);
2421 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2422 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2423 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2425 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2426 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2428 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2430 *res = mono_array_get (out_args, MonoObject *, 0);
2432 if (field_class->valuetype) {
2433 return ((char *)*res) + sizeof (MonoObject);
2439 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2441 static MonoMethod *getter = NULL;
2442 MonoDomain *domain = mono_domain_get ();
2443 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2444 MonoClass *field_class;
2445 MonoMethodMessage *msg;
2446 MonoArray *out_args;
2447 MonoObject *exc, *res;
2449 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2451 field_class = mono_class_from_mono_type (field->type);
2453 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2455 if (field_class->valuetype) {
2456 res = mono_object_new (domain, field_class);
2457 val = ((gchar *) res) + sizeof (MonoObject);
2461 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2468 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2469 MonoMethod *cm = mono_defaults.object_class->methods [i];
2471 if (!strcmp (cm->name, "FieldGetter")) {
2479 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2480 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2481 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2483 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2484 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2486 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2488 res = mono_array_get (out_args, MonoObject *, 0);
2494 * mono_store_remote_field:
2495 * @this: pointer to an object
2496 * @klass: klass of the object containing @field
2497 * @field: the field to load
2498 * @val: the value/object to store
2500 * This method is called by the runtime on attempts to store fields of
2501 * transparent proxy objects. @this points to such TP, @klass is the class of
2502 * the object containing @field. @val is the new value to store in @field.
2505 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
2507 static MonoMethod *setter = NULL;
2508 MonoDomain *domain = mono_domain_get ();
2509 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2510 MonoClass *field_class;
2511 MonoMethodMessage *msg;
2512 MonoArray *out_args;
2516 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2518 field_class = mono_class_from_mono_type (field->type);
2520 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2521 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
2522 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
2529 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2530 MonoMethod *cm = mono_defaults.object_class->methods [i];
2532 if (!strcmp (cm->name, "FieldSetter")) {
2540 if (field_class->valuetype)
2541 arg = mono_value_box (domain, field_class, val);
2543 arg = *((MonoObject **)val);
2546 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2547 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2549 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2550 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2551 mono_array_set (msg->args, gpointer, 2, arg);
2553 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2557 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
2559 static MonoMethod *setter = NULL;
2560 MonoDomain *domain = mono_domain_get ();
2561 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2562 MonoClass *field_class;
2563 MonoMethodMessage *msg;
2564 MonoArray *out_args;
2567 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2569 field_class = mono_class_from_mono_type (field->type);
2571 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2572 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
2573 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
2580 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2581 MonoMethod *cm = mono_defaults.object_class->methods [i];
2583 if (!strcmp (cm->name, "FieldSetter")) {
2591 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2592 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2594 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2595 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2596 mono_array_set (msg->args, gpointer, 2, arg);
2598 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);