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>
31 #include <mono/utils/strenc.h>
34 * Enable experimental typed allocation using the GC_gcj_malloc function.
36 #ifdef HAVE_GC_GCJ_MALLOC
37 #define CREATION_SPEEDUP 1
41 mono_runtime_object_init (MonoObject *this)
44 MonoMethod *method = NULL;
45 MonoClass *klass = this->vtable->klass;
47 for (i = 0; i < klass->method.count; ++i) {
48 if (!strcmp (".ctor", klass->methods [i]->name) &&
49 klass->methods [i]->signature->param_count == 0) {
50 method = klass->methods [i];
57 mono_runtime_invoke (method, this, NULL, NULL);
61 * mono_runtime_class_init:
62 * @vtable: vtable that needs to be initialized
64 * This routine calls the class constructor for @vtable.
67 mono_runtime_class_init (MonoVTable *vtable)
71 MonoException *exc_to_throw;
72 MonoMethod *method = NULL;
76 MonoDomain *last_domain = NULL;
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 mono_domain_lock (vtable->domain);
99 if (vtable->initialized || vtable->initializing) {
100 mono_domain_unlock (vtable->domain);
103 vtable->initializing = 1;
104 if (mono_domain_get () != vtable->domain) {
105 /* Transfer into the target domain */
106 last_domain = mono_domain_get ();
107 if (!mono_domain_set (vtable->domain, FALSE)) {
108 vtable->initialized = 1;
109 vtable->initializing = 0;
110 mono_domain_unlock (vtable->domain);
111 mono_raise_exception (mono_get_exception_appdomain_unloaded ());
114 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
116 mono_domain_set (last_domain, TRUE);
117 vtable->initialized = 1;
118 vtable->initializing = 0;
119 /* FIXME: if the cctor fails, the type must be marked as unusable */
120 mono_domain_unlock (vtable->domain);
122 vtable->initialized = 1;
127 (klass->image == mono_defaults.corlib &&
128 !strcmp (klass->name_space, "System") &&
129 !strcmp (klass->name, "TypeInitializationException")))
130 return; /* No static constructor found or avoid infinite loop */
132 if (klass->name_space && *klass->name_space)
133 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
135 full_name = g_strdup (klass->name);
137 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
140 mono_raise_exception (exc_to_throw);
144 default_trampoline (MonoMethod *method)
150 default_remoting_trampoline (MonoMethod *method)
152 g_error ("remoting not installed");
156 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
157 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
160 mono_install_trampoline (MonoTrampoline func)
162 arch_create_jit_trampoline = func? func: default_trampoline;
166 mono_install_remoting_trampoline (MonoTrampoline func)
168 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
171 static MonoCompileFunc default_mono_compile_method = NULL;
174 mono_install_compile_method (MonoCompileFunc func)
176 default_mono_compile_method = func;
180 mono_compile_method (MonoMethod *method)
182 if (!default_mono_compile_method) {
183 g_error ("compile method called on uninitialized runtime");
186 return default_mono_compile_method (method);
190 #if 0 && HAVE_BOEHM_GC
192 vtable_finalizer (void *obj, void *data) {
193 g_print ("%s finalized (%p)\n", (char*)data, obj);
199 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
202 * The vtables in the root appdomain are assumed to be reachable by other
203 * roots, and we don't use typed allocation in the other domains.
206 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
209 mono_class_compute_gc_descriptor (MonoClass *class)
211 MonoClassField *field;
214 static gboolean gcj_inited = FALSE;
219 GC_init_gcj_malloc (5, NULL);
223 mono_class_init (class);
225 if (class->gc_descr_inited)
228 class->gc_descr_inited = TRUE;
229 class->gc_descr = GC_NO_DESCRIPTOR;
231 if (class == mono_defaults.string_class) {
232 bitmap = GC_HEADER_BITMAP;
233 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
235 else if (class->rank) {
236 mono_class_compute_gc_descriptor (class->element_class);
238 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
239 bitmap = GC_HEADER_BITMAP;
241 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
242 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
246 static int count = 0;
250 /* GC 6.1 has trouble handling 64 bit descriptors... */
251 if ((class->instance_size / sizeof (gpointer)) > 30) {
252 // printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer));
256 bitmap = GC_HEADER_BITMAP;
263 // printf("KLASS: %s.\n", class->name);
265 for (p = class; p != NULL; p = p->parent) {
266 for (i = 0; i < p->field.count; ++i) {
267 field = &p->fields [i];
268 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
270 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
273 pos = field->offset / sizeof (gpointer);
275 if (field->type->byref)
278 switch (field->type->type) {
279 case MONO_TYPE_BOOLEAN:
291 // printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap);
294 case MONO_TYPE_STRING:
295 case MONO_TYPE_SZARRAY:
296 case MONO_TYPE_CLASS:
297 case MONO_TYPE_OBJECT:
298 case MONO_TYPE_ARRAY:
300 g_assert ((field->offset % sizeof(gpointer)) == 0);
302 bitmap |= ((guint64)1) << pos;
303 // printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap);
305 case MONO_TYPE_VALUETYPE: {
306 MonoClass *fclass = field->type->data.klass;
307 if (!fclass->enumtype) {
308 mono_class_compute_gc_descriptor (fclass);
309 bitmap |= (fclass->gc_bitmap & ~2) << pos;
319 // printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap);
320 class->gc_bitmap = bitmap;
321 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, class->instance_size / sizeof (gpointer));
324 #endif /* CREATION_SPEEDUP */
327 * field_is_special_static:
329 * Returns SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
330 * SPECIAL_STATIC_NONE otherwise.
333 field_is_special_static (MonoClass *fklass, MonoClassField *field)
335 MonoCustomAttrInfo *ainfo;
337 ainfo = mono_custom_attrs_from_field (fklass, field);
340 for (i = 0; i < ainfo->num_attrs; ++i) {
341 MonoClass *klass = ainfo->attrs [i].ctor->klass;
342 if (klass->image == mono_defaults.corlib) {
343 if (strcmp (klass->name, "ThreadStaticAttribute") == 0) {
344 mono_custom_attrs_free (ainfo);
345 return SPECIAL_STATIC_THREAD;
347 else if (strcmp (klass->name, "ContextStaticAttribute") == 0) {
348 mono_custom_attrs_free (ainfo);
349 return SPECIAL_STATIC_CONTEXT;
353 mono_custom_attrs_free (ainfo);
354 return SPECIAL_STATIC_NONE;
359 * @domain: the application domain
360 * @class: the class to initialize
362 * VTables are domain specific because we create domain specific code, and
363 * they contain the domain specific static class data.
366 mono_class_vtable (MonoDomain *domain, MonoClass *class)
368 MonoVTable *vt = NULL;
369 MonoClassField *field;
377 vt = class->cached_vtable;
378 if (vt && vt->domain == domain)
381 mono_domain_lock (domain);
382 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
383 mono_domain_unlock (domain);
388 mono_class_init (class);
390 mono_stats.used_class_count++;
391 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
393 vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
395 vt = mono_mempool_alloc0 (domain->mp, vtable_size);
401 mono_class_compute_gc_descriptor (class);
402 if (domain != mono_root_domain)
404 * We can't use typed allocation in the non-root domains, since the
405 * collector needs the GC descriptor stored in the vtable even after
406 * the mempool containing the vtable is destroyed when the domain is
407 * unloaded. An alternative might be to allocate vtables in the GC
408 * heap, but this does not seem to work (it leads to crashes inside
409 * libgc). If that approach is tried, two gc descriptors need to be
410 * allocated for each class: one for the root domain, and one for all
411 * other domains. The second descriptor should contain a bit for the
412 * vtable field in MonoObject, since we can no longer assume the
413 * vtable is reachable by other roots after the appdomain is unloaded.
415 vt->gc_descr = GC_NO_DESCRIPTOR;
417 vt->gc_descr = class->gc_descr;
420 if (class->class_size) {
422 vt->data = GC_MALLOC (class->class_size + 8);
423 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
424 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
425 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
427 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
430 mono_stats.class_static_data_size += class->class_size + 8;
433 for (i = class->field.first; i < class->field.last; ++i) {
434 field = &class->fields [i - class->field.first];
435 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
437 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
438 gint32 special_static = field_is_special_static (class, field);
439 if (special_static != SPECIAL_STATIC_NONE) {
440 guint32 size, align, offset;
441 size = mono_type_size (field->type, &align);
442 offset = mono_alloc_special_static_data (special_static, size, align);
443 if (!domain->special_static_fields)
444 domain->special_static_fields = g_hash_table_new (NULL, NULL);
445 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
449 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
450 MonoClass *fklass = mono_class_from_mono_type (field->type);
451 t = (char*)vt->data + field->offset;
452 if (fklass->valuetype) {
453 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
455 /* it's a pointer type: add check */
456 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
457 *t = *(char *)field->data;
461 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
463 p = field->def_value->value;
464 len = mono_metadata_decode_blob_size (p, &p);
465 t = (char*)vt->data + field->offset;
466 /* should we check that the type matches? */
467 switch (field->def_value->type) {
468 case MONO_TYPE_BOOLEAN:
476 guint16 *val = (guint16*)t;
482 guint32 *val = (guint32*)t;
488 guint64 *val = (guint64*)t;
493 float *val = (float*)t;
498 double *val = (double*)t;
502 case MONO_TYPE_STRING: {
503 gpointer *val = (gpointer*)t;
504 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
505 gunichar2 *copy = g_malloc (len);
507 for (j = 0; j < len/2; j++) {
508 copy [j] = read16 (p);
511 *val = mono_string_new_utf16 (domain, copy, len/2);
514 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
518 case MONO_TYPE_CLASS:
519 /* nothing to do, we malloc0 the data and the value can be 0 only */
522 g_warning ("type 0x%02x should not be in constant table", field->def_value->type);
526 vt->max_interface_id = class->max_interface_id;
528 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
529 sizeof (gpointer) * (class->max_interface_id + 1));
531 /* initialize interface offsets */
532 for (i = 0; i <= class->max_interface_id; ++i) {
533 int slot = class->interface_offsets [i];
535 vt->interface_offsets [i] = &(vt->vtable [slot]);
539 * arch_create_jit_trampoline () can recursively call this function again
540 * because it compiles icall methods right away.
542 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
543 if (!class->cached_vtable)
544 class->cached_vtable = vt;
546 /* initialize vtable */
547 for (i = 0; i < class->vtable_size; ++i) {
550 if ((cm = class->vtable [i]))
551 vt->vtable [i] = arch_create_jit_trampoline (cm);
554 mono_domain_unlock (domain);
556 /* make sure the the parent is initialized */
558 mono_class_vtable (domain, class->parent);
560 if (class->contextbound)
569 * mono_class_proxy_vtable:
570 * @domain: the application domain
571 * @class: the class to proxy
573 * Creates a vtable for transparent proxies. It is basically
574 * a copy of the real vtable of @class, but all function pointers invoke
575 * the remoting functions, and vtable->klass points to the
576 * transparent proxy class, and not to @class.
579 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
581 MonoVTable *vt, *pvt;
582 int i, j, vtsize, interface_vtsize = 0;
583 MonoClass* iclass = NULL;
586 mono_domain_lock (domain);
587 pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class);
590 mono_domain_unlock (domain);
594 if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
597 class = mono_defaults.marshalbyrefobject_class;
599 method_count = iclass->method.count;
600 for (i = 0; i < iclass->interface_count; i++)
601 method_count += iclass->interfaces[i]->method.count;
603 interface_vtsize = method_count * sizeof (gpointer);
606 vt = mono_class_vtable (domain, class);
607 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
609 mono_stats.class_vtable_size += vtsize + interface_vtsize;
611 pvt = mono_mempool_alloc (domain->mp, vtsize + interface_vtsize);
612 memcpy (pvt, vt, vtsize);
614 pvt->klass = mono_defaults.transparent_proxy_class;
616 /* initialize vtable */
617 for (i = 0; i < class->vtable_size; ++i) {
620 if ((cm = class->vtable [i]))
621 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
624 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
626 /* create trampolines for abstract methods */
627 for (k = class; k; k = k->parent) {
628 for (i = 0; i < k->method.count; i++) {
629 int slot = k->methods [i]->slot;
630 if (!pvt->vtable [slot])
631 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
641 pvt->max_interface_id = iclass->max_interface_id;
643 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
644 sizeof (gpointer) * (pvt->max_interface_id + 1));
646 /* Create trampolines for the methods of the interfaces */
647 slot = class->vtable_size;
651 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
653 for (j = 0; j < interf->method.count; ++j) {
654 MonoMethod *cm = interf->methods [j];
655 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
657 slot += interf->method.count;
658 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
667 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
668 sizeof (gpointer) * (pvt->max_interface_id + 1));
670 /* initialize interface offsets */
671 for (i = 0; i <= class->max_interface_id; ++i) {
672 int slot = class->interface_offsets [i];
674 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
678 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
680 mono_domain_unlock (domain);
686 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
687 * the instance of a callvirt of method.
690 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
694 MonoMethod *res = NULL;
696 klass = mono_object_class (obj);
697 if (klass == mono_defaults.transparent_proxy_class) {
698 klass = ((MonoTransparentProxy *)obj)->klass;
704 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
707 vtable = klass->vtable;
709 /* check method->slot is a valid index: perform isinstance? */
710 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
712 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
714 res = vtable [method->slot];
718 if (!res) res = method; /* It may be an interface or abstract class method */
719 res = mono_marshal_get_remoting_invoke (res);
728 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
730 g_error ("runtime invoke called on uninitialized runtime");
734 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
737 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
739 return default_mono_runtime_invoke (method, obj, params, exc);
743 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
746 gpointer *p = (gpointer*)dest;
753 case MONO_TYPE_BOOLEAN:
756 guint8 *p = (guint8*)dest;
757 *p = *(guint8*)value;
762 case MONO_TYPE_CHAR: {
763 guint16 *p = (guint16*)dest;
764 *p = *(guint16*)value;
767 #if SIZEOF_VOID_P == 4
773 gint32 *p = (gint32*)dest;
774 *p = *(gint32*)value;
777 #if SIZEOF_VOID_P == 8
783 gint64 *p = (gint64*)dest;
784 *p = *(gint64*)value;
788 float *p = (float*)dest;
793 double *p = (double*)dest;
794 *p = *(double*)value;
797 case MONO_TYPE_STRING:
798 case MONO_TYPE_SZARRAY:
799 case MONO_TYPE_CLASS:
800 case MONO_TYPE_OBJECT:
801 case MONO_TYPE_ARRAY:
802 case MONO_TYPE_PTR: {
803 gpointer *p = (gpointer*)dest;
804 *p = deref_pointer? *(gpointer*)value: value;
807 case MONO_TYPE_VALUETYPE:
808 if (type->data.klass->enumtype) {
809 t = type->data.klass->enum_basetype->type;
813 size = mono_class_value_size (type->data.klass, NULL);
814 memcpy (dest, value, size);
818 g_warning ("got type %x", type->type);
819 g_assert_not_reached ();
824 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
828 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
830 dest = (char*)obj + field->offset;
831 set_value (field->type, dest, value, FALSE);
835 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
839 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
841 dest = (char*)vt->data + field->offset;
842 set_value (field->type, dest, value, FALSE);
846 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
850 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
852 src = (char*)obj + field->offset;
853 set_value (field->type, value, src, TRUE);
857 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
863 gboolean is_static = FALSE;
864 gboolean is_ref = FALSE;
866 switch (field->type->type) {
867 case MONO_TYPE_STRING:
868 case MONO_TYPE_OBJECT:
869 case MONO_TYPE_CLASS:
870 case MONO_TYPE_ARRAY:
871 case MONO_TYPE_SZARRAY:
876 case MONO_TYPE_BOOLEAN:
888 case MONO_TYPE_VALUETYPE:
889 is_ref = field->type->byref;
892 g_error ("type 0x%x not handled in "
893 "mono_field_get_value_object", field->type->type);
897 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
899 vtable = mono_class_vtable (domain, field->parent);
900 if (!vtable->initialized)
901 mono_runtime_class_init (vtable);
906 mono_field_static_get_value (vtable, field, &o);
908 mono_field_get_value (obj, field, &o);
913 /* boxed value type */
914 klass = mono_class_from_mono_type (field->type);
915 o = mono_object_new (domain, klass);
916 v = ((gchar *) o) + sizeof (MonoObject);
918 mono_field_static_get_value (vtable, field, v);
920 mono_field_get_value (obj, field, v);
928 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
932 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
934 src = (char*)vt->data + field->offset;
935 set_value (field->type, value, src, TRUE);
939 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
941 default_mono_runtime_invoke (prop->set, obj, params, exc);
945 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
947 return default_mono_runtime_invoke (prop->get, obj, params, exc);
952 mono_get_delegate_invoke (MonoClass *klass)
959 for (i = 0; i < klass->method.count; ++i) {
960 if (klass->methods [i]->name[0] == 'I' &&
961 !strcmp ("Invoke", klass->methods [i]->name)) {
962 im = klass->methods [i];
972 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
976 im = mono_get_delegate_invoke (delegate->vtable->klass);
979 return mono_runtime_invoke (im, delegate, params, exc);
982 static MonoArray* main_args;
985 mono_runtime_get_main_args (void)
991 * Execute a standard Main() method (argc/argv contains the
992 * executable name). This method also sets the command line argument value
993 * needed by System.Environment.
996 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1000 MonoArray *args = NULL;
1001 MonoDomain *domain = mono_domain_get ();
1002 gchar *utf8_fullpath;
1004 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1006 if (!g_path_is_absolute (argv [0])) {
1007 gchar *basename = g_path_get_basename (argv [0]);
1008 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1012 utf8_fullpath = mono_utf8_from_external (fullpath);
1013 if(utf8_fullpath == NULL) {
1014 /* Printing the arg text will cause glib to
1015 * whinge about "Invalid UTF-8", but at least
1016 * its relevant, and shows the problem text
1019 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1020 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1027 utf8_fullpath = mono_utf8_from_external (argv[0]);
1028 if(utf8_fullpath == NULL) {
1029 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1030 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1035 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1036 g_free (utf8_fullpath);
1038 for (i = 1; i < argc; ++i) {
1042 utf8_arg=mono_utf8_from_external (argv[i]);
1043 if(utf8_arg==NULL) {
1044 /* Ditto the comment about Invalid UTF-8 here */
1045 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1046 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1050 arg = mono_string_new (domain, utf8_arg);
1051 mono_array_set (main_args, gpointer, i, arg);
1055 if (method->signature->param_count) {
1056 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1057 for (i = 0; i < argc; ++i) {
1058 /* The encodings should all work, given that
1059 * we've checked all these args for the
1062 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1063 mono_array_set (args, gpointer, i, arg);
1066 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1069 mono_assembly_set_main (method->klass->image->assembly);
1071 return mono_runtime_exec_main (method, args, exc);
1074 /* Used in mono_unhandled_exception */
1076 create_unhandled_exception_eventargs (MonoObject *exc)
1081 MonoBoolean is_terminating = TRUE;
1085 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1088 mono_class_init (klass);
1090 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1091 for (i = 0; i < klass->method.count; ++i) {
1092 method = klass->methods [i];
1093 if (!strcmp (".ctor", method->name) &&
1094 method->signature->param_count == 2 &&
1095 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1103 args [1] = &is_terminating;
1105 obj = mono_object_new (mono_domain_get (), klass);
1106 mono_runtime_invoke (method, obj, args, NULL);
1112 * We call this function when we detect an unhandled exception
1113 * in the default domain.
1114 * It invokes the * UnhandledException event in AppDomain or prints
1115 * a warning to the console
1118 mono_unhandled_exception (MonoObject *exc)
1120 MonoDomain *domain = mono_domain_get ();
1121 MonoClassField *field;
1122 MonoObject *delegate;
1124 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1125 "UnhandledException");
1128 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1129 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1131 /* set exitcode only in the main thread? */
1132 mono_environment_exitcode_set (1);
1133 if (domain != mono_root_domain || !delegate) {
1134 mono_print_unhandled_exception (exc);
1136 MonoObject *e = NULL;
1139 pa [0] = domain->domain;
1140 pa [1] = create_unhandled_exception_eventargs (exc);
1141 mono_runtime_delegate_invoke (delegate, pa, &e);
1144 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1145 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1153 * Launch a new thread to start all setup that requires managed code
1156 * main_func is called back from the thread with main_args as the
1157 * parameter. The callback function is expected to start Main()
1158 * eventually. This function then waits for all managed threads to
1162 mono_runtime_exec_managed_code (MonoDomain *domain,
1163 MonoMainThreadFunc main_func,
1166 mono_thread_create (domain, main_func, main_args);
1168 mono_thread_manage ();
1172 * Execute a standard Main() method (args doesn't contain the
1176 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1186 domain = mono_object_domain (args);
1187 if (!domain->entry_assembly) {
1188 domain->entry_assembly = method->klass->image->assembly;
1189 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
1192 /* FIXME: check signature of method */
1193 if (method->signature->ret->type == MONO_TYPE_I4) {
1195 res = mono_runtime_invoke (method, NULL, pa, exc);
1197 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1201 mono_environment_exitcode_set (rval);
1203 mono_runtime_invoke (method, NULL, pa, exc);
1207 /* If the return type of Main is void, only
1208 * set the exitcode if an exception was thrown
1209 * (we don't want to blow away an
1210 * explicitly-set exit code)
1213 mono_environment_exitcode_set (rval);
1221 mono_install_runtime_invoke (MonoInvokeFunc func)
1223 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1227 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1230 MonoMethodSignature *sig = method->signature;
1231 gpointer *pa = NULL;
1234 if (NULL != params) {
1235 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1236 for (i = 0; i < mono_array_length (params); i++) {
1237 if (sig->params [i]->byref) {
1241 switch (sig->params [i]->type) {
1244 case MONO_TYPE_BOOLEAN:
1247 case MONO_TYPE_CHAR:
1256 case MONO_TYPE_VALUETYPE:
1257 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1259 case MONO_TYPE_STRING:
1260 case MONO_TYPE_OBJECT:
1261 case MONO_TYPE_CLASS:
1262 case MONO_TYPE_ARRAY:
1263 case MONO_TYPE_SZARRAY:
1264 if (sig->params [i]->byref)
1265 pa [i] = &(((gpointer *)params->vector)[i]);
1267 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1270 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1275 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1277 obj = mono_object_new (mono_domain_get (), method->klass);
1278 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1279 method = mono_marshal_get_remoting_invoke (method->klass->vtable [method->slot]);
1282 mono_runtime_invoke (method, obj, pa, exc);
1285 return mono_runtime_invoke (method, obj, pa, exc);
1289 out_of_memory (size_t size)
1292 * we could allocate at program startup some memory that we could release
1293 * back to the system at this point if we're really low on memory (ie, size is
1294 * lower than the memory we set apart)
1296 mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
1300 * mono_object_allocate:
1301 * @size: number of bytes to allocate
1303 * This is a very simplistic routine until we have our GC-aware
1306 * Returns: an allocated object of size @size, or NULL on failure.
1309 mono_object_allocate (size_t size)
1312 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1313 void *o = GC_MALLOC (size);
1315 void *o = calloc (1, size);
1317 mono_stats.new_object_count++;
1320 out_of_memory (size);
1324 #if CREATION_SPEEDUP
1326 mono_object_allocate_spec (size_t size, void *gcdescr)
1328 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1329 void *o = GC_GCJ_MALLOC (size, gcdescr);
1330 mono_stats.new_object_count++;
1333 out_of_memory (size);
1341 * Frees the memory used by the object. Debugging purposes
1342 * only, as we will have our GC system.
1345 mono_object_free (MonoObject *o)
1348 g_error ("mono_object_free called with boehm gc.");
1350 MonoClass *c = o->vtable->klass;
1352 memset (o, 0, c->instance_size);
1359 * @klass: the class of the object that we want to create
1361 * Returns: A newly created object whose definition is
1362 * looked up using @klass
1365 mono_object_new (MonoDomain *domain, MonoClass *klass)
1367 MONO_ARCH_SAVE_REGS;
1368 return mono_object_new_specific (mono_class_vtable (domain, klass));
1372 * mono_object_new_specific:
1373 * @vtable: the vtable of the object that we want to create
1375 * Returns: A newly created object with class and domain specified
1379 mono_object_new_specific (MonoVTable *vtable)
1383 MONO_ARCH_SAVE_REGS;
1388 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1391 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1395 mono_class_init (klass);
1397 for (i = 0; i < klass->method.count; ++i) {
1398 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1399 klass->methods [i]->signature->param_count == 1) {
1400 im = klass->methods [i];
1405 vtable->domain->create_proxy_for_type_method = im;
1408 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1410 o = mono_runtime_invoke (im, NULL, pa, NULL);
1411 if (o != NULL) return o;
1414 return mono_object_new_alloc_specific (vtable);
1418 mono_object_new_fast (MonoVTable *vtable)
1421 MONO_ARCH_SAVE_REGS;
1423 #if CREATION_SPEEDUP
1424 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1425 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1427 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1428 o = mono_object_allocate (vtable->klass->instance_size);
1432 o = mono_object_allocate (vtable->klass->instance_size);
1439 mono_object_new_alloc_specific (MonoVTable *vtable)
1443 #if CREATION_SPEEDUP
1444 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1445 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1447 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1448 o = mono_object_allocate (vtable->klass->instance_size);
1452 o = mono_object_allocate (vtable->klass->instance_size);
1455 if (vtable->klass->has_finalize)
1456 mono_object_register_finalizer (o);
1458 mono_profiler_allocation (o, vtable->klass);
1463 * mono_object_new_from_token:
1464 * @image: Context where the type_token is hosted
1465 * @token: a token of the type that we want to create
1467 * Returns: A newly created object whose definition is
1468 * looked up using @token in the @image image
1471 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1475 class = mono_class_get (image, token);
1477 return mono_object_new (domain, class);
1482 * mono_object_clone:
1483 * @obj: the object to clone
1485 * Returns: A newly created object who is a shallow copy of @obj
1488 mono_object_clone (MonoObject *obj)
1493 size = obj->vtable->klass->instance_size;
1494 o = mono_object_allocate (size);
1495 mono_profiler_allocation (o, obj->vtable->klass);
1497 memcpy (o, obj, size);
1499 if (obj->vtable->klass->has_finalize)
1500 mono_object_register_finalizer (o);
1506 * @array: the array to clone
1508 * Returns: A newly created array who is a shallow copy of @array
1511 mono_array_clone (MonoArray *array)
1516 MonoClass *klass = array->obj.vtable->klass;
1518 MONO_ARCH_SAVE_REGS;
1520 if (array->bounds == NULL) {
1521 size = mono_array_length (array);
1522 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1523 klass, &size, NULL);
1525 size *= mono_array_element_size (klass);
1526 memcpy (o, array, sizeof (MonoArray) + size);
1531 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1532 size = mono_array_element_size (klass);
1533 for (i = 0; i < klass->rank; ++i) {
1534 sizes [i] = array->bounds [i].length;
1535 size *= array->bounds [i].length;
1536 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1538 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1539 klass, sizes, sizes + klass->rank);
1540 memcpy (o, array, sizeof(MonoArray) + size);
1545 /* helper macros to check for overflow when calculating the size of arrays */
1546 #define MYGUINT32_MAX 4294967295U
1547 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1548 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1549 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1550 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1551 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1554 * mono_array_new_full:
1555 * @domain: domain where the object is created
1556 * @array_class: array class
1557 * @lengths: lengths for each dimension in the array
1558 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1560 * This routine creates a new array objects with the given dimensions,
1561 * lower bounds and type.
1564 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1565 guint32 *lengths, guint32 *lower_bounds)
1567 guint32 byte_len, len;
1570 MonoArrayBounds *bounds;
1574 if (!array_class->inited)
1575 mono_class_init (array_class);
1577 byte_len = mono_array_element_size (array_class);
1580 if (array_class->rank == 1 &&
1581 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1586 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1588 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1590 for (i = 0; i < array_class->rank; ++i) {
1591 bounds [i].length = lengths [i];
1592 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1593 out_of_memory (MYGUINT32_MAX);
1598 for (i = 0; i < array_class->rank; ++i)
1599 bounds [i].lower_bound = lower_bounds [i];
1602 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1603 out_of_memory (MYGUINT32_MAX);
1605 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1606 out_of_memory (MYGUINT32_MAX);
1607 byte_len += sizeof (MonoArray);
1609 * Following three lines almost taken from mono_object_new ():
1610 * they need to be kept in sync.
1612 vtable = mono_class_vtable (domain, array_class);
1613 #if CREATION_SPEEDUP
1614 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1615 o = mono_object_allocate_spec (byte_len, vtable);
1617 o = mono_object_allocate (byte_len);
1621 o = mono_object_allocate (byte_len);
1625 array = (MonoArray*)o;
1627 array->bounds = bounds;
1628 array->max_length = len;
1630 mono_profiler_allocation (o, array_class);
1637 * @domain: domain where the object is created
1638 * @eclass: element class
1639 * @n: number of array elements
1641 * This routine creates a new szarray with @n elements of type @eclass.
1644 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1648 MONO_ARCH_SAVE_REGS;
1650 ac = mono_array_class_get (eclass, 1);
1651 g_assert (ac != NULL);
1653 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1657 * mono_array_new_specific:
1658 * @vtable: a vtable in the appropriate domain for an initialized class
1659 * @n: number of array elements
1661 * This routine is a fast alternative to mono_array_new() for code which
1662 * can be sure about the domain it operates in.
1665 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1669 guint32 byte_len, elem_size;
1671 MONO_ARCH_SAVE_REGS;
1673 elem_size = mono_array_element_size (vtable->klass);
1674 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1675 out_of_memory (MYGUINT32_MAX);
1676 byte_len = n * elem_size;
1677 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1678 out_of_memory (MYGUINT32_MAX);
1679 byte_len += sizeof (MonoArray);
1680 #if CREATION_SPEEDUP
1681 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1682 o = mono_object_allocate_spec (byte_len, vtable);
1684 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1685 o = mono_object_allocate (byte_len);
1689 o = mono_object_allocate (byte_len);
1693 ao = (MonoArray *)o;
1696 mono_profiler_allocation (o, vtable->klass);
1702 * mono_string_new_utf16:
1703 * @text: a pointer to an utf16 string
1704 * @len: the length of the string
1706 * Returns: A newly created string object which contains @text.
1709 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1713 s = mono_string_new_size (domain, len);
1714 g_assert (s != NULL);
1716 memcpy (mono_string_chars (s), text, len * 2);
1722 * mono_string_new_size:
1723 * @text: a pointer to an utf16 string
1724 * @len: the length of the string
1726 * Returns: A newly created string object of @len
1729 mono_string_new_size (MonoDomain *domain, gint32 len)
1734 vtable = mono_class_vtable (domain, mono_defaults.string_class);
1736 #if CREATION_SPEEDUP
1737 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1738 s = mono_object_allocate_spec (sizeof (MonoString) + ((len + 1) * 2), vtable);
1740 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1741 s->object.vtable = vtable;
1744 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1745 s->object.vtable = vtable;
1749 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
1755 * mono_string_new_len:
1756 * @text: a pointer to an utf8 string
1757 * @length: number of bytes in @text to consider
1759 * Returns: A newly created string object which contains @text.
1762 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1764 GError *error = NULL;
1765 MonoString *o = NULL;
1767 glong items_written;
1769 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1772 o = mono_string_new_utf16 (domain, ut, items_written);
1774 g_error_free (error);
1783 * @text: a pointer to an utf8 string
1785 * Returns: A newly created string object which contains @text.
1788 mono_string_new (MonoDomain *domain, const char *text)
1790 GError *error = NULL;
1791 MonoString *o = NULL;
1793 glong items_written;
1798 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1801 o = mono_string_new_utf16 (domain, ut, items_written);
1803 g_error_free (error);
1811 * mono_string_new_wrapper:
1812 * @text: pointer to utf8 characters.
1814 * Helper function to create a string object from @text in the current domain.
1817 mono_string_new_wrapper (const char *text)
1819 MonoDomain *domain = mono_domain_get ();
1821 MONO_ARCH_SAVE_REGS;
1824 return mono_string_new (domain, text);
1831 * @class: the class of the value
1832 * @value: a pointer to the unboxed data
1834 * Returns: A newly created object which contains @value.
1837 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1843 g_assert (class->valuetype);
1845 vtable = mono_class_vtable (domain, class);
1846 size = mono_class_instance_size (class);
1847 res = mono_object_allocate (size);
1848 res->vtable = vtable;
1849 mono_profiler_allocation (res, class);
1851 size = size - sizeof (MonoObject);
1853 #if NO_UNALIGNED_ACCESS
1854 memcpy ((char *)res + sizeof (MonoObject), value, size);
1858 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
1861 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
1864 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
1867 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
1870 memcpy ((char *)res + sizeof (MonoObject), value, size);
1873 if (class->has_finalize)
1874 mono_object_register_finalizer (res);
1879 mono_object_unbox (MonoObject *obj)
1881 /* add assert for valuetypes? */
1882 return ((char*)obj) + sizeof (MonoObject);
1886 * mono_object_isinst:
1888 * @klass: a pointer to a class
1890 * Returns: @obj if @obj is derived from @klass
1893 mono_object_isinst (MonoObject *obj, MonoClass *klass)
1905 mono_class_init (klass);
1907 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1908 if ((klass->interface_id <= vt->max_interface_id) &&
1909 (vt->interface_offsets [klass->interface_id] != 0))
1915 if (oklass != klass && oklass == mono_defaults.transparent_proxy_class) {
1916 /* fixme: add check for IRemotingTypeInfo */
1917 if (klass->marshalbyref)
1918 oklass = ((MonoTransparentProxy *)obj)->klass;
1921 return mono_class_is_assignable_from (klass, oklass) ? obj : NULL;
1925 MonoDomain *orig_domain;
1931 str_lookup (MonoDomain *domain, gpointer user_data)
1933 LDStrInfo *info = user_data;
1934 if (info->res || domain == info->orig_domain)
1936 mono_domain_lock (domain);
1937 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
1938 mono_domain_unlock (domain);
1942 mono_string_is_interned_lookup (MonoString *str, int insert)
1944 MonoGHashTable *ldstr_table;
1947 char *ins = g_malloc (4 + str->length * 2);
1951 /* Encode the length */
1953 mono_metadata_encode_value (2 * str->length, p, &p);
1956 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
1957 bloblen = (p - ins) + 2 * str->length;
1959 * ins is stored in the hash table as a key and needs to have the same
1960 * representation as in the metadata: we swap the character bytes on big
1963 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1966 char *p2 = (char *)mono_string_chars (str);
1967 for (i = 0; i < str->length; ++i) {
1974 memcpy (p, mono_string_chars (str), str->length * 2);
1976 domain = ((MonoObject *)str)->vtable->domain;
1977 ldstr_table = domain->ldstr_table;
1978 mono_domain_lock (domain);
1979 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1980 mono_domain_unlock (domain);
1985 mono_g_hash_table_insert (ldstr_table, ins, str);
1986 mono_domain_unlock (domain);
1989 LDStrInfo ldstr_info;
1990 ldstr_info.orig_domain = domain;
1991 ldstr_info.ins = ins;
1992 ldstr_info.res = NULL;
1994 mono_domain_foreach (str_lookup, &ldstr_info);
1995 if (ldstr_info.res) {
1997 * the string was already interned in some other domain:
1998 * intern it in the current one as well.
2000 mono_g_hash_table_insert (ldstr_table, ins, str);
2001 mono_domain_unlock (domain);
2005 mono_domain_unlock (domain);
2011 mono_string_is_interned (MonoString *o)
2013 return mono_string_is_interned_lookup (o, FALSE);
2017 mono_string_intern (MonoString *str)
2019 return mono_string_is_interned_lookup (str, TRUE);
2024 * @domain: the domain where the string will be used.
2025 * @image: a metadata context
2026 * @idx: index into the user string table.
2028 * Implementation for the ldstr opcode.
2031 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2033 const char *str, *sig;
2037 MONO_ARCH_SAVE_REGS;
2039 if (image->assembly->dynamic)
2040 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2042 sig = str = mono_metadata_user_string (image, idx);
2044 mono_domain_lock (domain);
2045 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2046 mono_domain_unlock (domain);
2050 len2 = mono_metadata_decode_blob_size (str, &str);
2053 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2054 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2057 guint16 *p2 = (guint16*)mono_string_chars (o);
2058 for (i = 0; i < len2; ++i) {
2059 *p2 = GUINT16_FROM_LE (*p2);
2064 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2065 mono_domain_unlock (domain);
2071 * mono_string_to_utf8:
2072 * @s: a System.String
2074 * Return the UTF8 representation for @s.
2075 * the resulting buffer nedds to be freed with g_free().
2078 mono_string_to_utf8 (MonoString *s)
2081 GError *error = NULL;
2087 return g_strdup ("");
2089 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2091 g_warning (error->message);
2092 g_error_free (error);
2099 * mono_string_to_utf16:
2102 * Return an null-terminated array of the utf-16 chars
2103 * contained in @s. The result must be freed with g_free().
2104 * This is a temporary helper until our string implementation
2105 * is reworked to always include the null terminating char.
2108 mono_string_to_utf16 (MonoString *s)
2115 as = g_malloc ((s->length * 2) + 2);
2116 as [(s->length * 2)] = '\0';
2117 as [(s->length * 2) + 1] = '\0';
2120 return (gunichar2 *)(as);
2123 memcpy (as, mono_string_chars(s), s->length * 2);
2124 return (gunichar2 *)(as);
2128 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2131 mono_string_from_utf16 (gunichar2 *data)
2133 MonoDomain *domain = mono_domain_get ();
2139 while (data [len]) len++;
2141 return mono_string_new_utf16 (domain, data, len);
2145 default_ex_handler (MonoException *ex)
2147 MonoObject *o = (MonoObject*)ex;
2148 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2152 static MonoExceptionFunc ex_handler = default_ex_handler;
2155 mono_install_handler (MonoExceptionFunc func)
2157 ex_handler = func? func: default_ex_handler;
2161 * mono_raise_exception:
2162 * @ex: exception object
2164 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2167 mono_raise_exception (MonoException *ex)
2170 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2171 * that will cause gcc to omit the function epilog, causing problems when
2172 * the JIT tries to walk the stack, since the return address on the stack
2173 * will point into the next function in the executable, not this one.
2180 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2182 MonoWaitHandle *res;
2184 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2186 res->handle = handle;
2192 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2194 MonoAsyncResult *res;
2196 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2199 res->async_state = state;
2200 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
2201 res->sync_completed = FALSE;
2202 res->completed = FALSE;
2208 mono_message_init (MonoDomain *domain,
2209 MonoMethodMessage *this,
2210 MonoReflectionMethod *method,
2211 MonoArray *out_args)
2213 MonoMethodSignature *sig = method->method->signature;
2219 this->method = method;
2221 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2222 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2223 this->async_result = NULL;
2224 this->call_type = CallType_Sync;
2226 names = g_new (char *, sig->param_count);
2227 mono_method_get_param_names (method->method, (const char **) names);
2228 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2230 for (i = 0; i < sig->param_count; i++) {
2231 name = mono_string_new (domain, names [i]);
2232 mono_array_set (this->names, gpointer, i, name);
2236 for (i = 0, j = 0; i < sig->param_count; i++) {
2238 if (sig->params [i]->byref) {
2240 gpointer arg = mono_array_get (out_args, gpointer, j);
2241 mono_array_set (this->args, gpointer, i, arg);
2245 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2250 mono_array_set (this->arg_types, guint8, i, arg_type);
2255 * mono_remoting_invoke:
2256 * @real_proxy: pointer to a RealProxy object
2257 * @msg: The MonoMethodMessage to execute
2258 * @exc: used to store exceptions
2259 * @out_args: used to store output arguments
2261 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2262 * IMessage interface and it is not trivial to extract results from there. So
2263 * we call an helper method PrivateInvoke instead of calling
2264 * RealProxy::Invoke() directly.
2266 * Returns: the result object.
2269 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2270 MonoObject **exc, MonoArray **out_args)
2272 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2275 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2281 klass = mono_defaults.real_proxy_class;
2283 for (i = 0; i < klass->method.count; ++i) {
2284 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2285 klass->methods [i]->signature->param_count == 4) {
2286 im = klass->methods [i];
2292 real_proxy->vtable->domain->private_invoke_method = im;
2295 pa [0] = real_proxy;
2300 return mono_runtime_invoke (im, NULL, pa, exc);
2304 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2305 MonoObject **exc, MonoArray **out_args)
2309 MonoMethodSignature *sig;
2310 int i, j, outarg_count = 0;
2312 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2314 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2315 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2316 target = tp->rp->unwrapped_server;
2318 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2322 domain = mono_domain_get ();
2323 method = msg->method->method;
2324 sig = method->signature;
2326 for (i = 0; i < sig->param_count; i++) {
2327 if (sig->params [i]->byref)
2331 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2334 for (i = 0, j = 0; i < sig->param_count; i++) {
2335 if (sig->params [i]->byref) {
2337 arg = mono_array_get (msg->args, gpointer, i);
2338 mono_array_set (*out_args, gpointer, j, arg);
2343 return mono_runtime_invoke_array (method, target, msg->args, exc);
2347 mono_print_unhandled_exception (MonoObject *exc)
2349 char *message = (char *) "";
2353 gboolean free_message = FALSE;
2356 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2357 klass = exc->vtable->klass;
2359 while (klass && method == NULL) {
2360 for (i = 0; i < klass->method.count; ++i) {
2361 method = klass->methods [i];
2362 if (!strcmp ("ToString", method->name) &&
2363 method->signature->param_count == 0 &&
2364 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2365 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2372 klass = klass->parent;
2377 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2379 message = mono_string_to_utf8 (str);
2380 free_message = TRUE;
2385 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2386 * exc->vtable->klass->name, message);
2388 g_printerr ("\nUnhandled Exception: %s\n", message);
2395 * mono_delegate_ctor:
2396 * @this: pointer to an uninitialized delegate object
2397 * @target: target object
2398 * @addr: pointer to native code
2400 * This is used to initialize a delegate. We also insert the method_info if
2401 * we find the info with mono_jit_info_table_find().
2404 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2406 MonoDomain *domain = mono_domain_get ();
2407 MonoDelegate *delegate = (MonoDelegate *)this;
2408 MonoMethod *method = NULL;
2415 class = this->vtable->klass;
2417 if ((ji = mono_jit_info_table_find (domain, addr))) {
2418 method = ji->method;
2419 delegate->method_info = mono_method_get_object (domain, method, NULL);
2422 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2424 method = mono_marshal_get_remoting_invoke (method);
2425 delegate->method_ptr = mono_compile_method (method);
2426 delegate->target = target;
2428 delegate->method_ptr = addr;
2429 delegate->target = target;
2434 * mono_method_call_message_new:
2436 * Translates arguments pointers into a Message.
2439 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2440 MonoDelegate **cb, MonoObject **state)
2442 MonoDomain *domain = mono_domain_get ();
2443 MonoMethodSignature *sig = method->signature;
2444 MonoMethodMessage *msg;
2447 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2450 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2451 count = sig->param_count - 2;
2453 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2454 count = sig->param_count;
2457 for (i = 0; i < count; i++) {
2462 if (sig->params [i]->byref)
2463 vpos = *((gpointer *)params [i]);
2467 type = sig->params [i]->type;
2468 class = mono_class_from_mono_type (sig->params [i]);
2470 if (class->valuetype)
2471 arg = mono_value_box (domain, class, vpos);
2473 arg = *((MonoObject **)vpos);
2475 mono_array_set (msg->args, gpointer, i, arg);
2478 if (cb != NULL && state != NULL) {
2479 *cb = *((MonoDelegate **)params [i]);
2481 *state = *((MonoObject **)params [i]);
2488 * mono_method_return_message_restore:
2490 * Restore results from message based processing back to arguments pointers
2493 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2495 MonoMethodSignature *sig = method->signature;
2496 int i, j, type, size;
2497 for (i = 0, j = 0; i < sig->param_count; i++) {
2498 MonoType *pt = sig->params [i];
2501 char *arg = mono_array_get (out_args, gpointer, j);
2505 case MONO_TYPE_VOID:
2506 g_assert_not_reached ();
2510 case MONO_TYPE_BOOLEAN:
2513 case MONO_TYPE_CHAR:
2520 case MONO_TYPE_VALUETYPE: {
2521 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2522 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2525 case MONO_TYPE_STRING:
2526 case MONO_TYPE_CLASS:
2527 case MONO_TYPE_ARRAY:
2528 case MONO_TYPE_SZARRAY:
2529 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2532 g_assert_not_reached ();
2541 * mono_load_remote_field:
2542 * @this: pointer to an object
2543 * @klass: klass of the object containing @field
2544 * @field: the field to load
2545 * @res: a storage to store the result
2547 * This method is called by the runtime on attempts to load fields of
2548 * transparent proxy objects. @this points to such TP, @klass is the class of
2549 * the object containing @field. @res is a storage location which can be
2550 * used to store the result.
2552 * Returns: an address pointing to the value of field.
2555 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2557 static MonoMethod *getter = NULL;
2558 MonoDomain *domain = mono_domain_get ();
2559 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2560 MonoClass *field_class;
2561 MonoMethodMessage *msg;
2562 MonoArray *out_args;
2566 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2571 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2572 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2579 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2580 MonoMethod *cm = mono_defaults.object_class->methods [i];
2582 if (!strcmp (cm->name, "FieldGetter")) {
2590 field_class = mono_class_from_mono_type (field->type);
2592 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2593 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2594 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2596 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2597 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2599 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2601 if (exc) mono_raise_exception ((MonoException *)exc);
2603 *res = mono_array_get (out_args, MonoObject *, 0);
2605 if (field_class->valuetype) {
2606 return ((char *)*res) + sizeof (MonoObject);
2612 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2614 static MonoMethod *getter = NULL;
2615 MonoDomain *domain = mono_domain_get ();
2616 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2617 MonoClass *field_class;
2618 MonoMethodMessage *msg;
2619 MonoArray *out_args;
2620 MonoObject *exc, *res;
2622 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2624 field_class = mono_class_from_mono_type (field->type);
2626 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2628 if (field_class->valuetype) {
2629 res = mono_object_new (domain, field_class);
2630 val = ((gchar *) res) + sizeof (MonoObject);
2634 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2641 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2642 MonoMethod *cm = mono_defaults.object_class->methods [i];
2644 if (!strcmp (cm->name, "FieldGetter")) {
2652 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2653 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2654 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2656 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2657 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2659 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2661 if (exc) mono_raise_exception ((MonoException *)exc);
2663 res = mono_array_get (out_args, MonoObject *, 0);
2669 * mono_store_remote_field:
2670 * @this: pointer to an object
2671 * @klass: klass of the object containing @field
2672 * @field: the field to load
2673 * @val: the value/object to store
2675 * This method is called by the runtime on attempts to store fields of
2676 * transparent proxy objects. @this points to such TP, @klass is the class of
2677 * the object containing @field. @val is the new value to store in @field.
2680 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
2682 static MonoMethod *setter = NULL;
2683 MonoDomain *domain = mono_domain_get ();
2684 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2685 MonoClass *field_class;
2686 MonoMethodMessage *msg;
2687 MonoArray *out_args;
2691 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2693 field_class = mono_class_from_mono_type (field->type);
2695 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2696 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
2697 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
2704 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2705 MonoMethod *cm = mono_defaults.object_class->methods [i];
2707 if (!strcmp (cm->name, "FieldSetter")) {
2715 if (field_class->valuetype)
2716 arg = mono_value_box (domain, field_class, val);
2718 arg = *((MonoObject **)val);
2721 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2722 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2724 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2725 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2726 mono_array_set (msg->args, gpointer, 2, arg);
2728 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2730 if (exc) mono_raise_exception ((MonoException *)exc);
2734 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
2736 static MonoMethod *setter = NULL;
2737 MonoDomain *domain = mono_domain_get ();
2738 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2739 MonoClass *field_class;
2740 MonoMethodMessage *msg;
2741 MonoArray *out_args;
2744 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2746 field_class = mono_class_from_mono_type (field->type);
2748 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2749 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
2750 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
2757 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2758 MonoMethod *cm = mono_defaults.object_class->methods [i];
2760 if (!strcmp (cm->name, "FieldSetter")) {
2768 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2769 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2771 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2772 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2773 mono_array_set (msg->args, gpointer, 2, arg);
2775 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2777 if (exc) mono_raise_exception ((MonoException *)exc);