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>
33 * Enable experimental typed allocation using the GC_gcj_malloc function.
35 #ifdef HAVE_GC_GCJ_MALLOC
36 #define CREATION_SPEEDUP 1
40 mono_runtime_object_init (MonoObject *this)
43 MonoMethod *method = NULL;
44 MonoClass *klass = this->vtable->klass;
46 for (i = 0; i < klass->method.count; ++i) {
47 if (!strcmp (".ctor", klass->methods [i]->name) &&
48 klass->methods [i]->signature->param_count == 0) {
49 method = klass->methods [i];
56 mono_runtime_invoke (method, this, NULL, NULL);
60 * mono_runtime_class_init:
61 * @vtable: vtable that needs to be initialized
63 * This routine calls the class constructor for @vtable.
66 mono_runtime_class_init (MonoVTable *vtable)
70 MonoException *exc_to_throw;
78 if (vtable->initialized || vtable->initializing)
83 klass = vtable->klass;
85 for (i = 0; i < klass->method.count; ++i) {
86 method = klass->methods [i];
87 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
88 (strcmp (".cctor", method->name) == 0)) {
95 mono_domain_lock (vtable->domain);
97 if (vtable->initialized || vtable->initializing)
99 vtable->initializing = 1;
100 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
101 vtable->initialized = 1;
102 vtable->initializing = 0;
103 /* FIXME: if the cctor fails, the type must be marked as unusable */
104 mono_domain_unlock (vtable->domain);
106 vtable->initialized = 1;
111 (klass->image == mono_defaults.corlib &&
112 !strcmp (klass->name_space, "System") &&
113 !strcmp (klass->name, "TypeInitializationException")))
114 return; /* No static constructor found or avoid infinite loop */
116 if (klass->name_space && *klass->name_space)
117 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
119 full_name = g_strdup (klass->name);
121 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
124 mono_raise_exception (exc_to_throw);
128 default_trampoline (MonoMethod *method)
134 default_remoting_trampoline (MonoMethod *method)
136 g_error ("remoting not installed");
140 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
141 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
144 mono_install_trampoline (MonoTrampoline func)
146 arch_create_jit_trampoline = func? func: default_trampoline;
150 mono_install_remoting_trampoline (MonoTrampoline func)
152 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
155 static MonoCompileFunc default_mono_compile_method = NULL;
158 mono_install_compile_method (MonoCompileFunc func)
160 default_mono_compile_method = func;
164 mono_compile_method (MonoMethod *method)
166 if (!default_mono_compile_method) {
167 g_error ("compile method called on uninitialized runtime");
170 return default_mono_compile_method (method);
174 #if 0 && HAVE_BOEHM_GC
176 vtable_finalizer (void *obj, void *data) {
177 g_print ("%s finalized (%p)\n", (char*)data, obj);
183 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
186 * The vtable is assumed to be reachable by other roots, since vtables
187 * are currently never freed. That might change in the future, but
188 * for now, this is a correct (and worthwhile) optimization.
191 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
194 mono_class_compute_gc_descriptor (MonoClass *class)
196 MonoClassField *field;
199 static gboolean gcj_inited = FALSE;
204 GC_init_gcj_malloc (5, NULL);
208 mono_class_init (class);
210 if (class->gc_descr_inited)
213 class->gc_descr_inited = TRUE;
214 class->gc_descr = GC_NO_DESCRIPTOR;
216 if (class == mono_defaults.string_class) {
217 bitmap = GC_HEADER_BITMAP;
218 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
220 else if (class->rank) {
221 mono_class_compute_gc_descriptor (class->element_class);
223 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
224 bitmap = GC_HEADER_BITMAP;
226 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
227 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
231 static int count = 0;
235 /* GC 6.1 has trouble handling 64 bit descriptors... */
236 if ((class->instance_size / sizeof (gpointer)) > 30) {
237 // printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer));
241 bitmap = GC_HEADER_BITMAP;
248 // printf("KLASS: %s.\n", class->name);
250 for (p = class; p != NULL; p = p->parent) {
251 for (i = 0; i < p->field.count; ++i) {
252 field = &p->fields [i];
253 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
255 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
258 pos = field->offset / sizeof (gpointer);
260 if (field->type->byref)
263 switch (field->type->type) {
264 case MONO_TYPE_BOOLEAN:
276 // printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap);
279 case MONO_TYPE_STRING:
280 case MONO_TYPE_SZARRAY:
281 case MONO_TYPE_CLASS:
282 case MONO_TYPE_OBJECT:
283 case MONO_TYPE_ARRAY:
285 g_assert ((field->offset % sizeof(gpointer)) == 0);
287 bitmap |= ((guint64)1) << pos;
288 // printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap);
290 case MONO_TYPE_VALUETYPE: {
291 MonoClass *fclass = field->type->data.klass;
292 if (!fclass->enumtype) {
293 mono_class_compute_gc_descriptor (fclass);
294 bitmap |= (fclass->gc_bitmap & ~2) << pos;
304 // printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap);
305 class->gc_bitmap = bitmap;
306 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, class->instance_size / sizeof (gpointer));
309 #endif /* CREATION_SPEEDUP */
312 field_is_thread_static (MonoClass *fklass, MonoClassField *field)
314 MonoCustomAttrInfo *ainfo;
316 ainfo = mono_custom_attrs_from_field (fklass, field);
319 for (i = 0; i < ainfo->num_attrs; ++i) {
320 MonoClass *klass = ainfo->attrs [i].ctor->klass;
321 if (strcmp (klass->name, "ThreadStaticAttribute") == 0 && klass->image == mono_defaults.corlib) {
322 mono_custom_attrs_free (ainfo);
326 mono_custom_attrs_free (ainfo);
332 * @domain: the application domain
333 * @class: the class to initialize
335 * VTables are domain specific because we create domain specific code, and
336 * they contain the domain specific static class data.
339 mono_class_vtable (MonoDomain *domain, MonoClass *class)
342 MonoClassField *field;
349 vt = class->cached_vtable;
350 if (vt && vt->domain == domain)
353 mono_domain_lock (domain);
354 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
355 mono_domain_unlock (domain);
360 mono_class_init (class);
362 mono_stats.used_class_count++;
363 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
365 vt = mono_mempool_alloc0 (domain->mp, sizeof (MonoVTable) +
366 class->vtable_size * sizeof (gpointer));
371 mono_class_compute_gc_descriptor (class);
372 vt->gc_descr = class->gc_descr;
375 if (class->class_size) {
377 vt->data = GC_MALLOC (class->class_size + 8);
378 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
379 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
380 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
382 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
385 mono_stats.class_static_data_size += class->class_size + 8;
388 for (i = class->field.first; i < class->field.last; ++i) {
389 field = &class->fields [i - class->field.first];
390 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
392 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
393 if (field_is_thread_static (class, field)) {
394 guint32 size, align, offset;
395 size = mono_type_size (field->type, &align);
396 offset = mono_threads_alloc_static_data (size, align);
397 if (!domain->thread_static_fields)
398 domain->thread_static_fields = g_hash_table_new (NULL, NULL);
399 g_hash_table_insert (domain->thread_static_fields, field, GUINT_TO_POINTER (offset));
403 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
404 MonoClass *fklass = mono_class_from_mono_type (field->type);
405 t = (char*)vt->data + field->offset;
406 if (fklass->valuetype) {
407 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
409 /* it's a pointer type: add check */
410 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
411 *t = *(char *)field->data;
415 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
417 p = field->def_value->value;
418 len = mono_metadata_decode_blob_size (p, &p);
419 t = (char*)vt->data + field->offset;
420 /* should we check that the type matches? */
421 switch (field->def_value->type) {
422 case MONO_TYPE_BOOLEAN:
430 guint16 *val = (guint16*)t;
436 guint32 *val = (guint32*)t;
442 guint64 *val = (guint64*)t;
447 float *val = (float*)t;
452 double *val = (double*)t;
456 case MONO_TYPE_STRING: {
457 gpointer *val = (gpointer*)t;
458 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
459 gunichar2 *copy = g_malloc (len);
461 for (j = 0; j < len/2; j++) {
462 copy [j] = read16 (p);
465 *val = mono_string_new_utf16 (domain, copy, len/2);
468 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
472 case MONO_TYPE_CLASS:
473 /* nothing to do, we malloc0 the data and the value can be 0 only */
476 g_warning ("type 0x%02x should not be in constant table", field->def_value->type);
480 vt->max_interface_id = class->max_interface_id;
482 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
483 sizeof (gpointer) * (class->max_interface_id + 1));
485 /* initialize interface offsets */
486 for (i = 0; i <= class->max_interface_id; ++i) {
487 int slot = class->interface_offsets [i];
489 vt->interface_offsets [i] = &(vt->vtable [slot]);
493 * arch_create_jit_trampoline () can recursively call this function again
494 * because it compiles icall methods right away.
496 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
497 if (!class->cached_vtable)
498 class->cached_vtable = vt;
500 /* initialize vtable */
501 for (i = 0; i < class->vtable_size; ++i) {
504 if ((cm = class->vtable [i]))
505 vt->vtable [i] = arch_create_jit_trampoline (cm);
508 mono_domain_unlock (domain);
510 /* make sure the the parent is initialized */
512 mono_class_vtable (domain, class->parent);
514 if (class->contextbound)
523 * mono_class_proxy_vtable:
524 * @domain: the application domain
525 * @class: the class to proxy
527 * Creates a vtable for transparent proxies. It is basically
528 * a copy of the real vtable of @class, but all function pointers invoke
529 * the remoting functions, and vtable->klass points to the
530 * transparent proxy class, and not to @class.
533 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
535 MonoVTable *vt, *pvt;
536 int i, j, vtsize, interface_vtsize = 0;
537 MonoClass* iclass = NULL;
540 if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
543 if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
546 class = mono_defaults.marshalbyrefobject_class;
548 method_count = iclass->method.count;
549 for (i = 0; i < iclass->interface_count; i++)
550 method_count += iclass->interfaces[i]->method.count;
552 interface_vtsize = method_count * sizeof (gpointer);
555 vt = mono_class_vtable (domain, class);
556 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
558 mono_stats.class_vtable_size += vtsize + interface_vtsize;
560 pvt = mono_mempool_alloc (domain->mp, vtsize + interface_vtsize);
561 memcpy (pvt, vt, vtsize);
563 pvt->klass = mono_defaults.transparent_proxy_class;
565 /* initialize vtable */
566 for (i = 0; i < class->vtable_size; ++i) {
569 if ((cm = class->vtable [i]))
570 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
573 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
575 /* create trampolines for abstract methods */
576 for (k = class; k; k = k->parent) {
577 for (i = 0; i < k->method.count; i++) {
578 int slot = k->methods [i]->slot;
579 if (!pvt->vtable [slot])
580 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
590 pvt->max_interface_id = iclass->max_interface_id;
592 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
593 sizeof (gpointer) * (pvt->max_interface_id + 1));
595 /* Create trampolines for the methods of the interfaces */
596 slot = class->vtable_size;
600 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
602 for (j = 0; j < interf->method.count; ++j) {
603 MonoMethod *cm = interf->methods [j];
604 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
606 slot += interf->method.count;
607 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
616 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
617 sizeof (gpointer) * (pvt->max_interface_id + 1));
619 /* initialize interface offsets */
620 for (i = 0; i <= class->max_interface_id; ++i) {
621 int slot = class->interface_offsets [i];
623 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
627 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
633 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
634 * the instance of a callvirt of method.
637 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
643 klass = mono_object_class (obj);
644 if (klass == mono_defaults.transparent_proxy_class) {
645 klass = ((MonoTransparentProxy *)obj)->klass;
651 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
654 vtable = klass->vtable;
656 /* check method->slot is a valid index: perform isinstance? */
657 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
658 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
660 res = vtable [method->slot];
665 return mono_marshal_get_remoting_invoke (res);
671 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
673 g_error ("runtime invoke called on uninitialized runtime");
677 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
680 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
682 return default_mono_runtime_invoke (method, obj, params, exc);
686 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
689 gpointer *p = (gpointer*)dest;
696 case MONO_TYPE_BOOLEAN:
699 guint8 *p = (guint8*)dest;
700 *p = *(guint8*)value;
705 case MONO_TYPE_CHAR: {
706 guint16 *p = (guint16*)dest;
707 *p = *(guint16*)value;
710 #if SIZEOF_VOID_P == 4
716 gint32 *p = (gint32*)dest;
717 *p = *(gint32*)value;
720 #if SIZEOF_VOID_P == 8
726 gint64 *p = (gint64*)dest;
727 *p = *(gint64*)value;
731 float *p = (float*)dest;
736 double *p = (double*)dest;
737 *p = *(double*)value;
740 case MONO_TYPE_STRING:
741 case MONO_TYPE_SZARRAY:
742 case MONO_TYPE_CLASS:
743 case MONO_TYPE_OBJECT:
744 case MONO_TYPE_ARRAY:
745 case MONO_TYPE_PTR: {
746 gpointer *p = (gpointer*)dest;
747 *p = deref_pointer? *(gpointer*)value: value;
750 case MONO_TYPE_VALUETYPE:
751 if (type->data.klass->enumtype) {
752 t = type->data.klass->enum_basetype->type;
756 size = mono_class_value_size (type->data.klass, NULL);
757 memcpy (dest, value, size);
761 g_warning ("got type %x", type->type);
762 g_assert_not_reached ();
767 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
771 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
773 dest = (char*)obj + field->offset;
774 set_value (field->type, dest, value, FALSE);
778 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
782 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
784 dest = (char*)vt->data + field->offset;
785 set_value (field->type, dest, value, FALSE);
789 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
793 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
795 src = (char*)obj + field->offset;
796 set_value (field->type, value, src, TRUE);
800 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
804 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
806 src = (char*)vt->data + field->offset;
807 set_value (field->type, value, src, TRUE);
811 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
813 default_mono_runtime_invoke (prop->set, obj, params, exc);
817 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
819 return default_mono_runtime_invoke (prop->get, obj, params, exc);
824 mono_get_delegate_invoke (MonoClass *klass)
831 for (i = 0; i < klass->method.count; ++i) {
832 if (klass->methods [i]->name[0] == 'I' &&
833 !strcmp ("Invoke", klass->methods [i]->name)) {
834 im = klass->methods [i];
844 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
848 im = mono_get_delegate_invoke (delegate->vtable->klass);
851 return mono_runtime_invoke (im, delegate, params, exc);
854 static MonoArray* main_args;
857 mono_runtime_get_main_args (void)
863 * Execute a standard Main() method (argc/argv contains the
864 * executable name). This method also sets the command line argument value
865 * needed by System.Environment.
868 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
872 MonoArray *args = NULL;
873 MonoDomain *domain = mono_domain_get ();
875 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
877 if (!g_path_is_absolute (argv [0])) {
878 gchar *basename = g_path_get_basename (argv [0]);
879 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
883 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, fullpath));
887 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, argv [0]));
890 for (i = 1; i < argc; ++i) {
891 MonoString *arg = mono_string_new (domain, argv [i]);
892 mono_array_set (main_args, gpointer, i, arg);
896 if (method->signature->param_count) {
897 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
898 for (i = 0; i < argc; ++i) {
899 MonoString *arg = mono_string_new (domain, argv [i]);
900 mono_array_set (args, gpointer, i, arg);
903 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
906 mono_assembly_set_main (method->klass->image->assembly);
908 return mono_runtime_exec_main (method, args, exc);
911 /* Used in mono_unhandled_exception */
913 create_unhandled_exception_eventargs (MonoObject *exc)
918 MonoBoolean is_terminating = TRUE;
922 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
925 mono_class_init (klass);
927 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
928 for (i = 0; i < klass->method.count; ++i) {
929 method = klass->methods [i];
930 if (!strcmp (".ctor", method->name) &&
931 method->signature->param_count == 2 &&
932 method->flags & METHOD_ATTRIBUTE_PUBLIC)
940 args [1] = &is_terminating;
942 obj = mono_object_new (mono_domain_get (), klass);
943 mono_runtime_invoke (method, obj, args, NULL);
949 * We call this function when we detect an unhandled exception
950 * in the default domain.
951 * It invokes the * UnhandledException event in AppDomain or prints
952 * a warning to the console
955 mono_unhandled_exception (MonoObject *exc)
957 MonoDomain *domain = mono_domain_get ();
958 MonoClassField *field;
959 MonoObject *delegate;
961 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
962 "UnhandledException");
965 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
966 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
968 /* set exitcode only in the main thread? */
969 mono_environment_exitcode_set (1);
970 if (domain != mono_root_domain || !delegate) {
971 mono_print_unhandled_exception (exc);
973 MonoObject *e = NULL;
976 pa [0] = domain->domain;
977 pa [1] = create_unhandled_exception_eventargs (exc);
978 mono_runtime_delegate_invoke (delegate, pa, &e);
981 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
982 g_warning ("exception inside UnhandledException handler: %s\n", msg);
990 * Launch a new thread to start all setup that requires managed code
993 * main_func is called back from the thread with main_args as the
994 * parameter. The callback function is expected to start Main()
995 * eventually. This function then waits for all managed threads to
999 mono_runtime_exec_managed_code (MonoDomain *domain,
1000 MonoMainThreadFunc main_func,
1003 mono_thread_create (domain, main_func, main_args);
1005 mono_thread_manage ();
1009 * Execute a standard Main() method (args doesn't contain the
1013 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1023 domain = mono_object_domain (args);
1024 if (!domain->entry_assembly) {
1025 domain->entry_assembly = method->klass->image->assembly;
1026 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
1029 /* FIXME: check signature of method */
1030 if (method->signature->ret->type == MONO_TYPE_I4) {
1032 res = mono_runtime_invoke (method, NULL, pa, exc);
1034 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1038 mono_environment_exitcode_set (rval);
1040 mono_runtime_invoke (method, NULL, pa, exc);
1044 /* If the return type of Main is void, only
1045 * set the exitcode if an exception was thrown
1046 * (we don't want to blow away an
1047 * explicitly-set exit code)
1050 mono_environment_exitcode_set (rval);
1058 mono_install_runtime_invoke (MonoInvokeFunc func)
1060 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1064 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1067 MonoMethodSignature *sig = method->signature;
1068 gpointer *pa = NULL;
1071 if (NULL != params) {
1072 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1073 for (i = 0; i < mono_array_length (params); i++) {
1074 if (sig->params [i]->byref) {
1078 switch (sig->params [i]->type) {
1081 case MONO_TYPE_BOOLEAN:
1084 case MONO_TYPE_CHAR:
1093 case MONO_TYPE_VALUETYPE:
1094 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1096 case MONO_TYPE_STRING:
1097 case MONO_TYPE_OBJECT:
1098 case MONO_TYPE_CLASS:
1099 case MONO_TYPE_ARRAY:
1100 case MONO_TYPE_SZARRAY:
1101 if (sig->params [i]->byref)
1102 pa [i] = &(((gpointer *)params->vector)[i]);
1104 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1107 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1112 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1114 obj = mono_object_new (mono_domain_get (), method->klass);
1115 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1116 method = mono_marshal_get_remoting_invoke (method->klass->vtable [method->slot]);
1119 mono_runtime_invoke (method, obj, pa, exc);
1122 return mono_runtime_invoke (method, obj, pa, exc);
1125 G_GNUC_NORETURN static void
1126 out_of_memory (size_t size)
1129 * we could allocate at program startup some memory that we could release
1130 * back to the system at this point if we're really low on memory (ie, size is
1131 * lower than the memory we set apart)
1133 MonoException * ex = mono_exception_from_name (mono_defaults.corlib, "System", "OutOfMemoryException");
1134 mono_raise_exception (ex);
1138 * mono_object_allocate:
1139 * @size: number of bytes to allocate
1141 * This is a very simplistic routine until we have our GC-aware
1144 * Returns: an allocated object of size @size, or NULL on failure.
1147 mono_object_allocate (size_t size)
1150 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1151 void *o = GC_MALLOC (size);
1153 void *o = calloc (1, size);
1155 mono_stats.new_object_count++;
1158 out_of_memory (size);
1162 #if CREATION_SPEEDUP
1164 mono_object_allocate_spec (size_t size, void *gcdescr)
1166 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1167 void *o = GC_GCJ_MALLOC (size, gcdescr);
1168 mono_stats.new_object_count++;
1171 out_of_memory (size);
1179 * Frees the memory used by the object. Debugging purposes
1180 * only, as we will have our GC system.
1183 mono_object_free (MonoObject *o)
1186 g_error ("mono_object_free called with boehm gc.");
1188 MonoClass *c = o->vtable->klass;
1190 memset (o, 0, c->instance_size);
1197 * @klass: the class of the object that we want to create
1199 * Returns: A newly created object whose definition is
1200 * looked up using @klass
1203 mono_object_new (MonoDomain *domain, MonoClass *klass)
1205 MONO_ARCH_SAVE_REGS;
1206 return mono_object_new_specific (mono_class_vtable (domain, klass));
1210 * mono_object_new_specific:
1211 * @vtable: the vtable of the object that we want to create
1213 * Returns: A newly created object with class and domain specified
1217 mono_object_new_specific (MonoVTable *vtable)
1221 MONO_ARCH_SAVE_REGS;
1226 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1229 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1233 mono_class_init (klass);
1235 for (i = 0; i < klass->method.count; ++i) {
1236 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1237 klass->methods [i]->signature->param_count == 1) {
1238 im = klass->methods [i];
1243 vtable->domain->create_proxy_for_type_method = im;
1246 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1248 o = mono_runtime_invoke (im, NULL, pa, NULL);
1249 if (o != NULL) return o;
1252 return mono_object_new_alloc_specific (vtable);
1256 mono_object_new_alloc_specific (MonoVTable *vtable)
1260 #if CREATION_SPEEDUP
1261 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1262 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1264 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1265 o = mono_object_allocate (vtable->klass->instance_size);
1269 o = mono_object_allocate (vtable->klass->instance_size);
1272 if (vtable->klass->has_finalize)
1273 mono_object_register_finalizer (o);
1275 mono_profiler_allocation (o, vtable->klass);
1280 * mono_object_new_from_token:
1281 * @image: Context where the type_token is hosted
1282 * @token: a token of the type that we want to create
1284 * Returns: A newly created object whose definition is
1285 * looked up using @token in the @image image
1288 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1292 class = mono_class_get (image, token);
1294 return mono_object_new (domain, class);
1299 * mono_object_clone:
1300 * @obj: the object to clone
1302 * Returns: A newly created object who is a shallow copy of @obj
1305 mono_object_clone (MonoObject *obj)
1310 size = obj->vtable->klass->instance_size;
1311 o = mono_object_allocate (size);
1312 mono_profiler_allocation (o, obj->vtable->klass);
1314 memcpy (o, obj, size);
1316 if (obj->vtable->klass->has_finalize)
1317 mono_object_register_finalizer (o);
1323 * @array: the array to clone
1325 * Returns: A newly created array who is a shallow copy of @array
1328 mono_array_clone (MonoArray *array)
1333 MonoClass *klass = array->obj.vtable->klass;
1335 MONO_ARCH_SAVE_REGS;
1337 if (array->bounds == NULL) {
1338 size = mono_array_length (array);
1339 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1340 klass, &size, NULL);
1342 size *= mono_array_element_size (klass);
1343 memcpy (o, array, sizeof (MonoArray) + size);
1348 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1349 size = mono_array_element_size (klass);
1350 for (i = 0; i < klass->rank; ++i) {
1351 sizes [i] = array->bounds [i].length;
1352 size *= array->bounds [i].length;
1353 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1355 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1356 klass, sizes, sizes + klass->rank);
1357 memcpy (o, array, sizeof(MonoArray) + size);
1362 /* helper macros to check for overflow when calculating the size of arrays */
1363 #define MYGUINT32_MAX 4294967295U
1364 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1365 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1366 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1367 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1368 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1371 * mono_array_new_full:
1372 * @domain: domain where the object is created
1373 * @array_class: array class
1374 * @lengths: lengths for each dimension in the array
1375 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1377 * This routine creates a new array objects with the given dimensions,
1378 * lower bounds and type.
1381 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1382 guint32 *lengths, guint32 *lower_bounds)
1384 guint32 byte_len, len;
1387 MonoArrayBounds *bounds;
1391 if (!array_class->inited)
1392 mono_class_init (array_class);
1394 byte_len = mono_array_element_size (array_class);
1397 if (array_class->rank == 1 &&
1398 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1403 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1405 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1407 for (i = 0; i < array_class->rank; ++i) {
1408 bounds [i].length = lengths [i];
1409 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1410 out_of_memory (MYGUINT32_MAX);
1415 for (i = 0; i < array_class->rank; ++i)
1416 bounds [i].lower_bound = lower_bounds [i];
1419 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1420 out_of_memory (MYGUINT32_MAX);
1422 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1423 out_of_memory (MYGUINT32_MAX);
1424 byte_len += sizeof (MonoArray);
1426 * Following three lines almost taken from mono_object_new ():
1427 * they need to be kept in sync.
1429 vtable = mono_class_vtable (domain, array_class);
1430 #if CREATION_SPEEDUP
1431 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1432 o = mono_object_allocate_spec (byte_len, vtable);
1434 o = mono_object_allocate (byte_len);
1438 o = mono_object_allocate (byte_len);
1442 array = (MonoArray*)o;
1444 array->bounds = bounds;
1445 array->max_length = len;
1447 mono_profiler_allocation (o, array_class);
1454 * @domain: domain where the object is created
1455 * @eclass: element class
1456 * @n: number of array elements
1458 * This routine creates a new szarray with @n elements of type @eclass.
1461 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1465 MONO_ARCH_SAVE_REGS;
1467 ac = mono_array_class_get (&eclass->byval_arg, 1);
1468 g_assert (ac != NULL);
1470 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1474 * mono_array_new_specific:
1475 * @vtable: a vtable in the appropriate domain for an initialized class
1476 * @n: number of array elements
1478 * This routine is a fast alternative to mono_array_new() for code which
1479 * can be sure about the domain it operates in.
1482 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1486 guint32 byte_len, elem_size;
1488 MONO_ARCH_SAVE_REGS;
1490 elem_size = mono_array_element_size (vtable->klass);
1491 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1492 out_of_memory (MYGUINT32_MAX);
1493 byte_len = n * elem_size;
1494 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1495 out_of_memory (MYGUINT32_MAX);
1496 byte_len += sizeof (MonoArray);
1497 #if CREATION_SPEEDUP
1498 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1499 o = mono_object_allocate_spec (byte_len, vtable);
1501 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1502 o = mono_object_allocate (byte_len);
1506 o = mono_object_allocate (byte_len);
1510 ao = (MonoArray *)o;
1513 mono_profiler_allocation (o, vtable->klass);
1519 * mono_string_new_utf16:
1520 * @text: a pointer to an utf16 string
1521 * @len: the length of the string
1523 * Returns: A newly created string object which contains @text.
1526 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1530 s = mono_string_new_size (domain, len);
1531 g_assert (s != NULL);
1533 memcpy (mono_string_chars (s), text, len * 2);
1539 * mono_string_new_size:
1540 * @text: a pointer to an utf16 string
1541 * @len: the length of the string
1543 * Returns: A newly created string object of @len
1546 mono_string_new_size (MonoDomain *domain, gint32 len)
1551 vtable = mono_class_vtable (domain, mono_defaults.string_class);
1553 #if CREATION_SPEEDUP
1554 s = mono_object_allocate_spec (sizeof (MonoString) + ((len + 1) * 2), vtable);
1556 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1557 s->object.vtable = vtable;
1561 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
1567 * mono_string_new_len:
1568 * @text: a pointer to an utf8 string
1569 * @length: number of bytes in @text to consider
1571 * Returns: A newly created string object which contains @text.
1574 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1576 GError *error = NULL;
1577 MonoString *o = NULL;
1579 glong items_written;
1581 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1584 o = mono_string_new_utf16 (domain, ut, items_written);
1586 g_error_free (error);
1595 * @text: a pointer to an utf8 string
1597 * Returns: A newly created string object which contains @text.
1600 mono_string_new (MonoDomain *domain, const char *text)
1602 GError *error = NULL;
1603 MonoString *o = NULL;
1605 glong items_written;
1610 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1613 o = mono_string_new_utf16 (domain, ut, items_written);
1615 g_error_free (error);
1623 * mono_string_new_wrapper:
1624 * @text: pointer to utf8 characters.
1626 * Helper function to create a string object from @text in the current domain.
1629 mono_string_new_wrapper (const char *text)
1631 MonoDomain *domain = mono_domain_get ();
1633 MONO_ARCH_SAVE_REGS;
1636 return mono_string_new (domain, text);
1643 * @class: the class of the value
1644 * @value: a pointer to the unboxed data
1646 * Returns: A newly created object which contains @value.
1649 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1655 g_assert (class->valuetype);
1657 vtable = mono_class_vtable (domain, class);
1658 size = mono_class_instance_size (class);
1659 res = mono_object_allocate (size);
1660 res->vtable = vtable;
1661 mono_profiler_allocation (res, class);
1663 size = size - sizeof (MonoObject);
1665 #if NO_UNALIGNED_ACCESS
1666 memcpy ((char *)res + sizeof (MonoObject), value, size);
1670 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
1673 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
1676 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
1679 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
1682 memcpy ((char *)res + sizeof (MonoObject), value, size);
1685 if (class->has_finalize)
1686 mono_object_register_finalizer (res);
1691 mono_object_unbox (MonoObject *obj)
1693 /* add assert for valuetypes? */
1694 return ((char*)obj) + sizeof (MonoObject);
1698 * mono_object_isinst:
1700 * @klass: a pointer to a class
1702 * Returns: @obj if @obj is derived from @klass
1705 mono_object_isinst (MonoObject *obj, MonoClass *klass)
1717 mono_class_init (klass);
1719 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1720 if ((klass->interface_id <= vt->max_interface_id) &&
1721 vt->interface_offsets [klass->interface_id])
1724 if (oklass == mono_defaults.transparent_proxy_class) {
1725 /* fixme: add check for IRemotingTypeInfo */
1726 oklass = ((MonoTransparentProxy *)obj)->klass;
1729 if (oklass->rank == klass->rank && mono_class_has_parent (oklass->cast_class, klass->cast_class))
1732 } else if (mono_class_has_parent (oklass, klass))
1740 MonoDomain *orig_domain;
1746 str_lookup (MonoDomain *domain, gpointer user_data)
1748 LDStrInfo *info = user_data;
1749 if (info->res || domain == info->orig_domain)
1751 mono_domain_lock (domain);
1752 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
1753 mono_domain_unlock (domain);
1757 mono_string_is_interned_lookup (MonoString *str, int insert)
1759 MonoGHashTable *ldstr_table;
1762 char *ins = g_malloc (4 + str->length * 2);
1766 /* Encode the length */
1768 mono_metadata_encode_value (2 * str->length, p, &p);
1771 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
1772 bloblen = (p - ins) + 2 * str->length;
1774 * ins is stored in the hash table as a key and needs to have the same
1775 * representation as in the metadata: we swap the character bytes on big
1778 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1781 char *p2 = mono_string_chars (str);
1782 for (i = 0; i < str->length; ++i) {
1789 memcpy (p, mono_string_chars (str), str->length * 2);
1791 domain = ((MonoObject *)str)->vtable->domain;
1792 ldstr_table = domain->ldstr_table;
1793 mono_domain_lock (domain);
1794 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1795 mono_domain_unlock (domain);
1800 mono_g_hash_table_insert (ldstr_table, ins, str);
1801 mono_domain_unlock (domain);
1804 LDStrInfo ldstr_info;
1805 ldstr_info.orig_domain = domain;
1806 ldstr_info.ins = ins;
1807 ldstr_info.res = NULL;
1809 mono_domain_foreach (str_lookup, &ldstr_info);
1810 if (ldstr_info.res) {
1812 * the string was already interned in some other domain:
1813 * intern it in the current one as well.
1815 mono_g_hash_table_insert (ldstr_table, ins, str);
1816 mono_domain_unlock (domain);
1820 mono_domain_unlock (domain);
1826 mono_string_is_interned (MonoString *o)
1828 return mono_string_is_interned_lookup (o, FALSE);
1832 mono_string_intern (MonoString *str)
1834 return mono_string_is_interned_lookup (str, TRUE);
1839 * @domain: the domain where the string will be used.
1840 * @image: a metadata context
1841 * @idx: index into the user string table.
1843 * Implementation for the ldstr opcode.
1846 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
1848 const char *str, *sig;
1852 MONO_ARCH_SAVE_REGS;
1854 if (image->assembly->dynamic)
1855 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
1857 sig = str = mono_metadata_user_string (image, idx);
1859 mono_domain_lock (domain);
1860 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
1861 mono_domain_unlock (domain);
1865 len2 = mono_metadata_decode_blob_size (str, &str);
1868 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
1869 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1872 guint16 *p2 = (guint16*)mono_string_chars (o);
1873 for (i = 0; i < len2; ++i) {
1874 *p2 = GUINT16_FROM_LE (*p2);
1879 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
1880 mono_domain_unlock (domain);
1886 * mono_string_to_utf8:
1887 * @s: a System.String
1889 * Return the UTF8 representation for @s.
1890 * the resulting buffer nedds to be freed with g_free().
1893 mono_string_to_utf8 (MonoString *s)
1896 GError *error = NULL;
1902 return g_strdup ("");
1904 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
1906 g_warning (error->message);
1907 g_error_free (error);
1914 * mono_string_to_utf16:
1917 * Return an null-terminated array of the utf-16 chars
1918 * contained in @s. The result must be freed with g_free().
1919 * This is a temporary helper until our string implementation
1920 * is reworked to always include the null terminating char.
1923 mono_string_to_utf16 (MonoString *s)
1930 as = g_malloc ((s->length * 2) + 2);
1931 as [(s->length * 2)] = '\0';
1932 as [(s->length * 2) + 1] = '\0';
1935 return (gunichar2 *)(as);
1938 memcpy (as, mono_string_chars(s), s->length * 2);
1939 return (gunichar2 *)(as);
1943 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
1946 mono_string_from_utf16 (gunichar2 *data)
1948 MonoDomain *domain = mono_domain_get ();
1954 while (data [len]) len++;
1956 return mono_string_new_utf16 (domain, data, len);
1959 G_GNUC_NORETURN static void
1960 default_ex_handler (MonoException *ex)
1962 MonoObject *o = (MonoObject*)ex;
1963 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
1967 static G_GNUC_NORETURN MonoExceptionFunc ex_handler = default_ex_handler;
1970 mono_install_handler (MonoExceptionFunc func)
1972 ex_handler = func? func: default_ex_handler;
1976 * mono_raise_exception:
1977 * @ex: exception object
1979 * Signal the runtime that the exception @ex has been raised in unmanaged code.
1981 G_GNUC_NORETURN void
1982 mono_raise_exception (MonoException *ex)
1988 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
1990 MonoWaitHandle *res;
1992 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
1994 res->handle = handle;
2000 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2002 MonoAsyncResult *res;
2004 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2007 res->async_state = state;
2008 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
2009 res->sync_completed = FALSE;
2010 res->completed = FALSE;
2016 mono_message_init (MonoDomain *domain,
2017 MonoMethodMessage *this,
2018 MonoReflectionMethod *method,
2019 MonoArray *out_args)
2021 MonoMethodSignature *sig = method->method->signature;
2027 this->method = method;
2029 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2030 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2032 names = g_new (char *, sig->param_count);
2033 mono_method_get_param_names (method->method, (const char **) names);
2034 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2036 for (i = 0; i < sig->param_count; i++) {
2037 name = mono_string_new (domain, names [i]);
2038 mono_array_set (this->names, gpointer, i, name);
2043 for (i = 0, j = 0; i < sig->param_count; i++) {
2045 if (sig->params [i]->byref) {
2047 gpointer arg = mono_array_get (out_args, gpointer, j);
2048 mono_array_set (this->args, gpointer, i, arg);
2052 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
2058 mono_array_set (this->arg_types, guint8, i, arg_type);
2063 * mono_remoting_invoke:
2064 * @real_proxy: pointer to a RealProxy object
2065 * @msg: The MonoMethodMessage to execute
2066 * @exc: used to store exceptions
2067 * @out_args: used to store output arguments
2069 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2070 * IMessage interface and it is not trivial to extract results from there. So
2071 * we call an helper method PrivateInvoke instead of calling
2072 * RealProxy::Invoke() directly.
2074 * Returns: the result object.
2077 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2078 MonoObject **exc, MonoArray **out_args)
2080 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2083 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2089 klass = mono_defaults.real_proxy_class;
2091 for (i = 0; i < klass->method.count; ++i) {
2092 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2093 klass->methods [i]->signature->param_count == 4) {
2094 im = klass->methods [i];
2100 real_proxy->vtable->domain->private_invoke_method = im;
2103 pa [0] = real_proxy;
2108 return mono_runtime_invoke (im, NULL, pa, exc);
2112 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2113 MonoObject **exc, MonoArray **out_args)
2117 MonoMethodSignature *sig;
2118 int i, j, outarg_count = 0;
2120 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2122 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2123 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2124 target = tp->rp->unwrapped_server;
2126 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2130 domain = mono_domain_get ();
2131 method = msg->method->method;
2132 sig = method->signature;
2134 for (i = 0; i < sig->param_count; i++) {
2135 if (sig->params [i]->byref)
2139 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2142 for (i = 0, j = 0; i < sig->param_count; i++) {
2143 if (sig->params [i]->byref) {
2145 arg = mono_array_get (msg->args, gpointer, i);
2146 mono_array_set (*out_args, gpointer, j, arg);
2151 return mono_runtime_invoke_array (method, target, msg->args, exc);
2155 mono_print_unhandled_exception (MonoObject *exc)
2157 char *message = (char *) "";
2161 gboolean free_message = FALSE;
2164 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2165 klass = exc->vtable->klass;
2167 while (klass && method == NULL) {
2168 for (i = 0; i < klass->method.count; ++i) {
2169 method = klass->methods [i];
2170 if (!strcmp ("ToString", method->name) &&
2171 method->signature->param_count == 0 &&
2172 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2173 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2180 klass = klass->parent;
2185 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2187 message = mono_string_to_utf8 (str);
2188 free_message = TRUE;
2193 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2194 * exc->vtable->klass->name, message);
2196 g_printerr ("\nUnhandled Exception: %s\n", message);
2203 * mono_delegate_ctor:
2204 * @this: pointer to an uninitialized delegate object
2205 * @target: target object
2206 * @addr: pointer to native code
2208 * This is used to initialize a delegate. We also insert the method_info if
2209 * we find the info with mono_jit_info_table_find().
2212 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2214 MonoDomain *domain = mono_domain_get ();
2215 MonoDelegate *delegate = (MonoDelegate *)this;
2216 MonoMethod *method = NULL;
2223 class = this->vtable->klass;
2225 if ((ji = mono_jit_info_table_find (domain, addr))) {
2226 method = ji->method;
2227 delegate->method_info = mono_method_get_object (domain, method, NULL);
2230 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2232 method = mono_marshal_get_remoting_invoke (method);
2233 delegate->method_ptr = mono_compile_method (method);
2234 delegate->target = target;
2236 delegate->method_ptr = addr;
2237 delegate->target = target;
2242 * mono_method_call_message_new:
2244 * Translates arguments pointers into a Message.
2247 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2248 MonoDelegate **cb, MonoObject **state)
2250 MonoDomain *domain = mono_domain_get ();
2251 MonoMethodSignature *sig = method->signature;
2252 MonoMethodMessage *msg;
2255 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2258 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2259 count = sig->param_count - 2;
2261 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2262 count = sig->param_count;
2265 for (i = 0; i < count; i++) {
2270 if (sig->params [i]->byref)
2271 vpos = *((gpointer *)params [i]);
2275 type = sig->params [i]->type;
2276 class = mono_class_from_mono_type (sig->params [i]);
2278 if (class->valuetype)
2279 arg = mono_value_box (domain, class, vpos);
2281 arg = *((MonoObject **)vpos);
2283 mono_array_set (msg->args, gpointer, i, arg);
2287 *cb = *((MonoDelegate **)params [i]);
2289 *state = *((MonoObject **)params [i]);
2296 * mono_method_return_message_restore:
2298 * Restore results from message based processing back to arguments pointers
2301 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2303 MonoMethodSignature *sig = method->signature;
2304 int i, j, type, size;
2306 for (i = 0, j = 0; i < sig->param_count; i++) {
2307 MonoType *pt = sig->params [i];
2309 size = mono_type_stack_size (pt, NULL);
2312 char *arg = mono_array_get (out_args, gpointer, j);
2316 case MONO_TYPE_VOID:
2317 g_assert_not_reached ();
2321 case MONO_TYPE_BOOLEAN:
2324 case MONO_TYPE_CHAR:
2331 case MONO_TYPE_VALUETYPE: {
2332 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2335 case MONO_TYPE_STRING:
2336 case MONO_TYPE_CLASS:
2337 case MONO_TYPE_ARRAY:
2338 case MONO_TYPE_SZARRAY:
2339 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2342 g_assert_not_reached ();
2351 * mono_load_remote_field:
2352 * @this: pointer to an object
2353 * @klass: klass of the object containing @field
2354 * @field: the field to load
2355 * @res: a storage to store the result
2357 * This method is called by the runtime on attempts to load fields of
2358 * transparent proxy objects. @this points to such TP, @klass is the class of
2359 * the object containing @field. @res is a storage location which can be
2360 * used to store the result.
2362 * Returns: an address pointing to the value of field.
2365 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2367 static MonoMethod *getter = NULL;
2368 MonoDomain *domain = mono_domain_get ();
2369 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2370 MonoClass *field_class;
2371 MonoMethodMessage *msg;
2372 MonoArray *out_args;
2376 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2381 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2382 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2389 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2390 MonoMethod *cm = mono_defaults.object_class->methods [i];
2392 if (!strcmp (cm->name, "FieldGetter")) {
2400 field_class = mono_class_from_mono_type (field->type);
2402 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2403 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2404 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2406 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2407 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2409 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2411 *res = mono_array_get (out_args, MonoObject *, 0);
2413 if (field_class->valuetype) {
2414 return ((char *)*res) + sizeof (MonoObject);
2420 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2422 static MonoMethod *getter = NULL;
2423 MonoDomain *domain = mono_domain_get ();
2424 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2425 MonoClass *field_class;
2426 MonoMethodMessage *msg;
2427 MonoArray *out_args;
2428 MonoObject *exc, *res;
2430 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2432 field_class = mono_class_from_mono_type (field->type);
2434 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2436 if (field_class->valuetype) {
2437 res = mono_object_new (domain, field_class);
2438 val = ((gchar *) res) + sizeof (MonoObject);
2442 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2449 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2450 MonoMethod *cm = mono_defaults.object_class->methods [i];
2452 if (!strcmp (cm->name, "FieldGetter")) {
2460 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2461 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2462 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2464 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2465 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2467 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2469 res = mono_array_get (out_args, MonoObject *, 0);
2475 * mono_store_remote_field:
2476 * @this: pointer to an object
2477 * @klass: klass of the object containing @field
2478 * @field: the field to load
2479 * @val: the value/object to store
2481 * This method is called by the runtime on attempts to store fields of
2482 * transparent proxy objects. @this points to such TP, @klass is the class of
2483 * the object containing @field. @val is the new value to store in @field.
2486 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
2488 static MonoMethod *setter = NULL;
2489 MonoDomain *domain = mono_domain_get ();
2490 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2491 MonoClass *field_class;
2492 MonoMethodMessage *msg;
2493 MonoArray *out_args;
2497 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2499 field_class = mono_class_from_mono_type (field->type);
2501 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2502 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
2503 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
2510 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2511 MonoMethod *cm = mono_defaults.object_class->methods [i];
2513 if (!strcmp (cm->name, "FieldSetter")) {
2521 if (field_class->valuetype)
2522 arg = mono_value_box (domain, field_class, val);
2524 arg = *((MonoObject **)val);
2527 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2528 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2530 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2531 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2532 mono_array_set (msg->args, gpointer, 2, arg);
2534 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2538 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
2540 static MonoMethod *setter = NULL;
2541 MonoDomain *domain = mono_domain_get ();
2542 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2543 MonoClass *field_class;
2544 MonoMethodMessage *msg;
2545 MonoArray *out_args;
2548 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2550 field_class = mono_class_from_mono_type (field->type);
2552 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2553 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
2554 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
2561 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2562 MonoMethod *cm = mono_defaults.object_class->methods [i];
2564 if (!strcmp (cm->name, "FieldSetter")) {
2572 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2573 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2575 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2576 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2577 mono_array_set (msg->args, gpointer, 2, arg);
2579 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);