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;
375 guint32 constant_cols [MONO_CONSTANT_SIZE];
379 vt = class->cached_vtable;
380 if (vt && vt->domain == domain)
383 mono_domain_lock (domain);
384 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
385 mono_domain_unlock (domain);
390 mono_class_init (class);
392 mono_stats.used_class_count++;
393 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
395 vtable_size = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
397 vt = mono_mempool_alloc0 (domain->mp, vtable_size);
403 mono_class_compute_gc_descriptor (class);
404 if (domain != mono_root_domain)
406 * We can't use typed allocation in the non-root domains, since the
407 * collector needs the GC descriptor stored in the vtable even after
408 * the mempool containing the vtable is destroyed when the domain is
409 * unloaded. An alternative might be to allocate vtables in the GC
410 * heap, but this does not seem to work (it leads to crashes inside
411 * libgc). If that approach is tried, two gc descriptors need to be
412 * allocated for each class: one for the root domain, and one for all
413 * other domains. The second descriptor should contain a bit for the
414 * vtable field in MonoObject, since we can no longer assume the
415 * vtable is reachable by other roots after the appdomain is unloaded.
417 vt->gc_descr = GC_NO_DESCRIPTOR;
419 vt->gc_descr = class->gc_descr;
422 if (class->class_size) {
424 vt->data = GC_MALLOC (class->class_size + 8);
425 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
426 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
427 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
429 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
432 mono_stats.class_static_data_size += class->class_size + 8;
436 for (i = class->field.first; i < class->field.last; ++i) {
437 field = &class->fields [i - class->field.first];
438 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
440 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
441 gint32 special_static = field_is_special_static (class, field);
442 if (special_static != SPECIAL_STATIC_NONE) {
443 guint32 size, align, offset;
444 size = mono_type_size (field->type, &align);
445 offset = mono_alloc_special_static_data (special_static, size, align);
446 if (!domain->special_static_fields)
447 domain->special_static_fields = g_hash_table_new (NULL, NULL);
448 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
452 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
453 MonoClass *fklass = mono_class_from_mono_type (field->type);
454 t = (char*)vt->data + field->offset;
455 if (fklass->valuetype) {
456 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
458 /* it's a pointer type: add check */
459 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
460 *t = *(char *)field->data;
464 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
467 if (!field->def_value) {
468 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1), cindex + 1);
471 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
472 field->def_value = g_new0 (MonoConstant, 1);
473 field->def_value->type = constant_cols [MONO_CONSTANT_TYPE];
474 field->def_value->value = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
477 p = field->def_value->value;
478 len = mono_metadata_decode_blob_size (p, &p);
479 t = (char*)vt->data + field->offset;
480 /* should we check that the type matches? */
481 switch (field->def_value->type) {
482 case MONO_TYPE_BOOLEAN:
490 guint16 *val = (guint16*)t;
496 guint32 *val = (guint32*)t;
502 guint64 *val = (guint64*)t;
507 float *val = (float*)t;
512 double *val = (double*)t;
516 case MONO_TYPE_STRING: {
517 gpointer *val = (gpointer*)t;
518 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
519 gunichar2 *copy = g_malloc (len);
521 for (j = 0; j < len/2; j++) {
522 copy [j] = read16 (p);
525 *val = mono_string_new_utf16 (domain, copy, len/2);
528 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
532 case MONO_TYPE_CLASS:
533 /* nothing to do, we malloc0 the data and the value can be 0 only */
536 g_warning ("type 0x%02x should not be in constant table", field->def_value->type);
540 vt->max_interface_id = class->max_interface_id;
542 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
543 sizeof (gpointer) * (class->max_interface_id + 1));
545 /* initialize interface offsets */
546 for (i = 0; i <= class->max_interface_id; ++i) {
547 int slot = class->interface_offsets [i];
549 vt->interface_offsets [i] = &(vt->vtable [slot]);
553 * arch_create_jit_trampoline () can recursively call this function again
554 * because it compiles icall methods right away.
556 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
557 if (!class->cached_vtable)
558 class->cached_vtable = vt;
560 /* initialize vtable */
561 for (i = 0; i < class->vtable_size; ++i) {
564 if ((cm = class->vtable [i]))
565 vt->vtable [i] = arch_create_jit_trampoline (cm);
568 mono_domain_unlock (domain);
570 /* make sure the the parent is initialized */
572 mono_class_vtable (domain, class->parent);
574 if (class->contextbound)
583 * mono_class_proxy_vtable:
584 * @domain: the application domain
585 * @class: the class to proxy
587 * Creates a vtable for transparent proxies. It is basically
588 * a copy of the real vtable of @class, but all function pointers invoke
589 * the remoting functions, and vtable->klass points to the
590 * transparent proxy class, and not to @class.
593 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
595 MonoVTable *vt, *pvt;
596 int i, j, vtsize, interface_vtsize = 0;
597 MonoClass* iclass = NULL;
600 mono_domain_lock (domain);
601 pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class);
604 mono_domain_unlock (domain);
608 if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
611 class = mono_defaults.marshalbyrefobject_class;
613 method_count = iclass->method.count;
614 for (i = 0; i < iclass->interface_count; i++)
615 method_count += iclass->interfaces[i]->method.count;
617 interface_vtsize = method_count * sizeof (gpointer);
620 vt = mono_class_vtable (domain, class);
621 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
623 mono_stats.class_vtable_size += vtsize + interface_vtsize;
625 pvt = mono_mempool_alloc (domain->mp, vtsize + interface_vtsize);
626 memcpy (pvt, vt, vtsize);
628 pvt->klass = mono_defaults.transparent_proxy_class;
630 /* initialize vtable */
631 for (i = 0; i < class->vtable_size; ++i) {
634 if ((cm = class->vtable [i]))
635 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
638 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
640 /* create trampolines for abstract methods */
641 for (k = class; k; k = k->parent) {
642 for (i = 0; i < k->method.count; i++) {
643 int slot = k->methods [i]->slot;
644 if (!pvt->vtable [slot])
645 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
655 pvt->max_interface_id = iclass->max_interface_id;
657 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
658 sizeof (gpointer) * (pvt->max_interface_id + 1));
660 /* Create trampolines for the methods of the interfaces */
661 slot = class->vtable_size;
665 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
667 for (j = 0; j < interf->method.count; ++j) {
668 MonoMethod *cm = interf->methods [j];
669 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
671 slot += interf->method.count;
672 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
681 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
682 sizeof (gpointer) * (pvt->max_interface_id + 1));
684 /* initialize interface offsets */
685 for (i = 0; i <= class->max_interface_id; ++i) {
686 int slot = class->interface_offsets [i];
688 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
692 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
694 mono_domain_unlock (domain);
700 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
701 * the instance of a callvirt of method.
704 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
708 MonoMethod *res = NULL;
710 klass = mono_object_class (obj);
711 if (klass == mono_defaults.transparent_proxy_class) {
712 klass = ((MonoTransparentProxy *)obj)->klass;
718 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
721 vtable = klass->vtable;
723 /* check method->slot is a valid index: perform isinstance? */
724 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
726 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
728 res = vtable [method->slot];
732 if (!res) res = method; /* It may be an interface or abstract class method */
733 res = mono_marshal_get_remoting_invoke (res);
742 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
744 g_error ("runtime invoke called on uninitialized runtime");
748 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
751 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
753 return default_mono_runtime_invoke (method, obj, params, exc);
757 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
760 gpointer *p = (gpointer*)dest;
767 case MONO_TYPE_BOOLEAN:
770 guint8 *p = (guint8*)dest;
771 *p = *(guint8*)value;
776 case MONO_TYPE_CHAR: {
777 guint16 *p = (guint16*)dest;
778 *p = *(guint16*)value;
781 #if SIZEOF_VOID_P == 4
787 gint32 *p = (gint32*)dest;
788 *p = *(gint32*)value;
791 #if SIZEOF_VOID_P == 8
797 gint64 *p = (gint64*)dest;
798 *p = *(gint64*)value;
802 float *p = (float*)dest;
807 double *p = (double*)dest;
808 *p = *(double*)value;
811 case MONO_TYPE_STRING:
812 case MONO_TYPE_SZARRAY:
813 case MONO_TYPE_CLASS:
814 case MONO_TYPE_OBJECT:
815 case MONO_TYPE_ARRAY:
816 case MONO_TYPE_PTR: {
817 gpointer *p = (gpointer*)dest;
818 *p = deref_pointer? *(gpointer*)value: value;
821 case MONO_TYPE_VALUETYPE:
822 if (type->data.klass->enumtype) {
823 t = type->data.klass->enum_basetype->type;
827 size = mono_class_value_size (type->data.klass, NULL);
828 memcpy (dest, value, size);
832 g_warning ("got type %x", type->type);
833 g_assert_not_reached ();
838 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
842 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
844 dest = (char*)obj + field->offset;
845 set_value (field->type, dest, value, FALSE);
849 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
853 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
855 dest = (char*)vt->data + field->offset;
856 set_value (field->type, dest, value, FALSE);
860 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
864 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
866 src = (char*)obj + field->offset;
867 set_value (field->type, value, src, TRUE);
871 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
877 gboolean is_static = FALSE;
878 gboolean is_ref = FALSE;
880 switch (field->type->type) {
881 case MONO_TYPE_STRING:
882 case MONO_TYPE_OBJECT:
883 case MONO_TYPE_CLASS:
884 case MONO_TYPE_ARRAY:
885 case MONO_TYPE_SZARRAY:
890 case MONO_TYPE_BOOLEAN:
902 case MONO_TYPE_VALUETYPE:
903 is_ref = field->type->byref;
906 g_error ("type 0x%x not handled in "
907 "mono_field_get_value_object", field->type->type);
911 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
913 vtable = mono_class_vtable (domain, field->parent);
914 if (!vtable->initialized)
915 mono_runtime_class_init (vtable);
920 mono_field_static_get_value (vtable, field, &o);
922 mono_field_get_value (obj, field, &o);
927 /* boxed value type */
928 klass = mono_class_from_mono_type (field->type);
929 o = mono_object_new (domain, klass);
930 v = ((gchar *) o) + sizeof (MonoObject);
932 mono_field_static_get_value (vtable, field, v);
934 mono_field_get_value (obj, field, v);
942 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
946 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
948 src = (char*)vt->data + field->offset;
949 set_value (field->type, value, src, TRUE);
953 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
955 default_mono_runtime_invoke (prop->set, obj, params, exc);
959 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
961 return default_mono_runtime_invoke (prop->get, obj, params, exc);
966 mono_get_delegate_invoke (MonoClass *klass)
973 for (i = 0; i < klass->method.count; ++i) {
974 if (klass->methods [i]->name[0] == 'I' &&
975 !strcmp ("Invoke", klass->methods [i]->name)) {
976 im = klass->methods [i];
986 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
990 im = mono_get_delegate_invoke (delegate->vtable->klass);
993 return mono_runtime_invoke (im, delegate, params, exc);
996 static MonoArray* main_args;
999 mono_runtime_get_main_args (void)
1005 * Execute a standard Main() method (argc/argv contains the
1006 * executable name). This method also sets the command line argument value
1007 * needed by System.Environment.
1010 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1014 MonoArray *args = NULL;
1015 MonoDomain *domain = mono_domain_get ();
1016 gchar *utf8_fullpath;
1018 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1020 if (!g_path_is_absolute (argv [0])) {
1021 gchar *basename = g_path_get_basename (argv [0]);
1022 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1026 utf8_fullpath = mono_utf8_from_external (fullpath);
1027 if(utf8_fullpath == NULL) {
1028 /* Printing the arg text will cause glib to
1029 * whinge about "Invalid UTF-8", but at least
1030 * its relevant, and shows the problem text
1033 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1034 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1041 utf8_fullpath = mono_utf8_from_external (argv[0]);
1042 if(utf8_fullpath == NULL) {
1043 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1044 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1049 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1050 g_free (utf8_fullpath);
1052 for (i = 1; i < argc; ++i) {
1056 utf8_arg=mono_utf8_from_external (argv[i]);
1057 if(utf8_arg==NULL) {
1058 /* Ditto the comment about Invalid UTF-8 here */
1059 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1060 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1064 arg = mono_string_new (domain, utf8_arg);
1065 mono_array_set (main_args, gpointer, i, arg);
1069 if (method->signature->param_count) {
1070 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1071 for (i = 0; i < argc; ++i) {
1072 /* The encodings should all work, given that
1073 * we've checked all these args for the
1076 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1077 mono_array_set (args, gpointer, i, arg);
1080 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1083 mono_assembly_set_main (method->klass->image->assembly);
1085 return mono_runtime_exec_main (method, args, exc);
1088 /* Used in mono_unhandled_exception */
1090 create_unhandled_exception_eventargs (MonoObject *exc)
1095 MonoBoolean is_terminating = TRUE;
1099 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1102 mono_class_init (klass);
1104 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1105 for (i = 0; i < klass->method.count; ++i) {
1106 method = klass->methods [i];
1107 if (!strcmp (".ctor", method->name) &&
1108 method->signature->param_count == 2 &&
1109 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1117 args [1] = &is_terminating;
1119 obj = mono_object_new (mono_domain_get (), klass);
1120 mono_runtime_invoke (method, obj, args, NULL);
1126 * We call this function when we detect an unhandled exception
1127 * in the default domain.
1128 * It invokes the * UnhandledException event in AppDomain or prints
1129 * a warning to the console
1132 mono_unhandled_exception (MonoObject *exc)
1134 MonoDomain *domain = mono_domain_get ();
1135 MonoClassField *field;
1136 MonoObject *delegate;
1138 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1139 "UnhandledException");
1142 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1143 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1145 /* set exitcode only in the main thread? */
1146 mono_environment_exitcode_set (1);
1147 if (domain != mono_root_domain || !delegate) {
1148 mono_print_unhandled_exception (exc);
1150 MonoObject *e = NULL;
1153 pa [0] = domain->domain;
1154 pa [1] = create_unhandled_exception_eventargs (exc);
1155 mono_runtime_delegate_invoke (delegate, pa, &e);
1158 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1159 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1167 * Launch a new thread to start all setup that requires managed code
1170 * main_func is called back from the thread with main_args as the
1171 * parameter. The callback function is expected to start Main()
1172 * eventually. This function then waits for all managed threads to
1176 mono_runtime_exec_managed_code (MonoDomain *domain,
1177 MonoMainThreadFunc main_func,
1180 mono_thread_create (domain, main_func, main_args);
1182 mono_thread_manage ();
1186 * Execute a standard Main() method (args doesn't contain the
1190 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1200 domain = mono_object_domain (args);
1201 if (!domain->entry_assembly) {
1202 domain->entry_assembly = method->klass->image->assembly;
1203 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
1206 /* FIXME: check signature of method */
1207 if (method->signature->ret->type == MONO_TYPE_I4) {
1209 res = mono_runtime_invoke (method, NULL, pa, exc);
1211 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1215 mono_environment_exitcode_set (rval);
1217 mono_runtime_invoke (method, NULL, pa, exc);
1221 /* If the return type of Main is void, only
1222 * set the exitcode if an exception was thrown
1223 * (we don't want to blow away an
1224 * explicitly-set exit code)
1227 mono_environment_exitcode_set (rval);
1235 mono_install_runtime_invoke (MonoInvokeFunc func)
1237 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1241 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1244 MonoMethodSignature *sig = method->signature;
1245 gpointer *pa = NULL;
1248 if (NULL != params) {
1249 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1250 for (i = 0; i < mono_array_length (params); i++) {
1251 if (sig->params [i]->byref) {
1255 switch (sig->params [i]->type) {
1258 case MONO_TYPE_BOOLEAN:
1261 case MONO_TYPE_CHAR:
1270 case MONO_TYPE_VALUETYPE:
1271 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1273 case MONO_TYPE_STRING:
1274 case MONO_TYPE_OBJECT:
1275 case MONO_TYPE_CLASS:
1276 case MONO_TYPE_ARRAY:
1277 case MONO_TYPE_SZARRAY:
1278 if (sig->params [i]->byref)
1279 pa [i] = &(((gpointer *)params->vector)[i]);
1281 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1284 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1289 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1291 obj = mono_object_new (mono_domain_get (), method->klass);
1292 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1293 method = mono_marshal_get_remoting_invoke (method->klass->vtable [method->slot]);
1296 mono_runtime_invoke (method, obj, pa, exc);
1299 return mono_runtime_invoke (method, obj, pa, exc);
1303 out_of_memory (size_t size)
1306 * we could allocate at program startup some memory that we could release
1307 * back to the system at this point if we're really low on memory (ie, size is
1308 * lower than the memory we set apart)
1310 mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
1314 * mono_object_allocate:
1315 * @size: number of bytes to allocate
1317 * This is a very simplistic routine until we have our GC-aware
1320 * Returns: an allocated object of size @size, or NULL on failure.
1322 static inline void *
1323 mono_object_allocate (size_t size)
1326 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1327 void *o = GC_MALLOC (size);
1329 void *o = calloc (1, size);
1331 mono_stats.new_object_count++;
1334 out_of_memory (size);
1338 #if CREATION_SPEEDUP
1339 static inline void *
1340 mono_object_allocate_spec (size_t size, void *gcdescr)
1342 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1343 void *o = GC_GCJ_MALLOC (size, gcdescr);
1344 mono_stats.new_object_count++;
1347 out_of_memory (size);
1355 * Frees the memory used by the object. Debugging purposes
1356 * only, as we will have our GC system.
1359 mono_object_free (MonoObject *o)
1362 g_error ("mono_object_free called with boehm gc.");
1364 MonoClass *c = o->vtable->klass;
1366 memset (o, 0, c->instance_size);
1373 * @klass: the class of the object that we want to create
1375 * Returns: A newly created object whose definition is
1376 * looked up using @klass
1379 mono_object_new (MonoDomain *domain, MonoClass *klass)
1381 MONO_ARCH_SAVE_REGS;
1382 return mono_object_new_specific (mono_class_vtable (domain, klass));
1386 * mono_object_new_specific:
1387 * @vtable: the vtable of the object that we want to create
1389 * Returns: A newly created object with class and domain specified
1393 mono_object_new_specific (MonoVTable *vtable)
1397 MONO_ARCH_SAVE_REGS;
1402 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1405 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1409 mono_class_init (klass);
1411 for (i = 0; i < klass->method.count; ++i) {
1412 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1413 klass->methods [i]->signature->param_count == 1) {
1414 im = klass->methods [i];
1419 vtable->domain->create_proxy_for_type_method = im;
1422 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1424 o = mono_runtime_invoke (im, NULL, pa, NULL);
1425 if (o != NULL) return o;
1428 return mono_object_new_alloc_specific (vtable);
1432 mono_object_new_fast (MonoVTable *vtable)
1435 MONO_ARCH_SAVE_REGS;
1437 #if CREATION_SPEEDUP
1438 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1439 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1441 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1442 o = mono_object_allocate (vtable->klass->instance_size);
1446 o = mono_object_allocate (vtable->klass->instance_size);
1453 mono_object_new_alloc_specific (MonoVTable *vtable)
1457 #if CREATION_SPEEDUP
1458 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1459 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1461 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1462 o = mono_object_allocate (vtable->klass->instance_size);
1466 o = mono_object_allocate (vtable->klass->instance_size);
1469 if (vtable->klass->has_finalize)
1470 mono_object_register_finalizer (o);
1472 mono_profiler_allocation (o, vtable->klass);
1477 * mono_object_new_from_token:
1478 * @image: Context where the type_token is hosted
1479 * @token: a token of the type that we want to create
1481 * Returns: A newly created object whose definition is
1482 * looked up using @token in the @image image
1485 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1489 class = mono_class_get (image, token);
1491 return mono_object_new (domain, class);
1496 * mono_object_clone:
1497 * @obj: the object to clone
1499 * Returns: A newly created object who is a shallow copy of @obj
1502 mono_object_clone (MonoObject *obj)
1507 size = obj->vtable->klass->instance_size;
1508 o = mono_object_allocate (size);
1509 mono_profiler_allocation (o, obj->vtable->klass);
1511 memcpy (o, obj, size);
1513 if (obj->vtable->klass->has_finalize)
1514 mono_object_register_finalizer (o);
1520 * @array: the array to clone
1522 * Returns: A newly created array who is a shallow copy of @array
1525 mono_array_clone (MonoArray *array)
1530 MonoClass *klass = array->obj.vtable->klass;
1532 MONO_ARCH_SAVE_REGS;
1534 if (array->bounds == NULL) {
1535 size = mono_array_length (array);
1536 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1537 klass, &size, NULL);
1539 size *= mono_array_element_size (klass);
1540 memcpy (o, array, sizeof (MonoArray) + size);
1545 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1546 size = mono_array_element_size (klass);
1547 for (i = 0; i < klass->rank; ++i) {
1548 sizes [i] = array->bounds [i].length;
1549 size *= array->bounds [i].length;
1550 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1552 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1553 klass, sizes, sizes + klass->rank);
1554 memcpy (o, array, sizeof(MonoArray) + size);
1559 /* helper macros to check for overflow when calculating the size of arrays */
1560 #define MYGUINT32_MAX 4294967295U
1561 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1562 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1563 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1564 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1565 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1568 * mono_array_new_full:
1569 * @domain: domain where the object is created
1570 * @array_class: array class
1571 * @lengths: lengths for each dimension in the array
1572 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1574 * This routine creates a new array objects with the given dimensions,
1575 * lower bounds and type.
1578 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1579 guint32 *lengths, guint32 *lower_bounds)
1581 guint32 byte_len, len;
1584 MonoArrayBounds *bounds;
1588 if (!array_class->inited)
1589 mono_class_init (array_class);
1591 byte_len = mono_array_element_size (array_class);
1594 if (array_class->rank == 1 &&
1595 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1600 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1602 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1604 for (i = 0; i < array_class->rank; ++i) {
1605 bounds [i].length = lengths [i];
1606 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1607 out_of_memory (MYGUINT32_MAX);
1612 for (i = 0; i < array_class->rank; ++i)
1613 bounds [i].lower_bound = lower_bounds [i];
1616 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1617 out_of_memory (MYGUINT32_MAX);
1619 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1620 out_of_memory (MYGUINT32_MAX);
1621 byte_len += sizeof (MonoArray);
1623 * Following three lines almost taken from mono_object_new ():
1624 * they need to be kept in sync.
1626 vtable = mono_class_vtable (domain, array_class);
1627 #if CREATION_SPEEDUP
1628 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1629 o = mono_object_allocate_spec (byte_len, vtable);
1631 o = mono_object_allocate (byte_len);
1635 o = mono_object_allocate (byte_len);
1639 array = (MonoArray*)o;
1641 array->bounds = bounds;
1642 array->max_length = len;
1644 mono_profiler_allocation (o, array_class);
1651 * @domain: domain where the object is created
1652 * @eclass: element class
1653 * @n: number of array elements
1655 * This routine creates a new szarray with @n elements of type @eclass.
1658 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1662 MONO_ARCH_SAVE_REGS;
1664 ac = mono_array_class_get (eclass, 1);
1665 g_assert (ac != NULL);
1667 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1671 * mono_array_new_specific:
1672 * @vtable: a vtable in the appropriate domain for an initialized class
1673 * @n: number of array elements
1675 * This routine is a fast alternative to mono_array_new() for code which
1676 * can be sure about the domain it operates in.
1679 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1683 guint32 byte_len, elem_size;
1685 MONO_ARCH_SAVE_REGS;
1687 elem_size = mono_array_element_size (vtable->klass);
1688 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1689 out_of_memory (MYGUINT32_MAX);
1690 byte_len = n * elem_size;
1691 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1692 out_of_memory (MYGUINT32_MAX);
1693 byte_len += sizeof (MonoArray);
1694 #if CREATION_SPEEDUP
1695 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1696 o = mono_object_allocate_spec (byte_len, vtable);
1698 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1699 o = mono_object_allocate (byte_len);
1703 o = mono_object_allocate (byte_len);
1707 ao = (MonoArray *)o;
1710 mono_profiler_allocation (o, vtable->klass);
1716 * mono_string_new_utf16:
1717 * @text: a pointer to an utf16 string
1718 * @len: the length of the string
1720 * Returns: A newly created string object which contains @text.
1723 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1727 s = mono_string_new_size (domain, len);
1728 g_assert (s != NULL);
1730 memcpy (mono_string_chars (s), text, len * 2);
1736 * mono_string_new_size:
1737 * @text: a pointer to an utf16 string
1738 * @len: the length of the string
1740 * Returns: A newly created string object of @len
1743 mono_string_new_size (MonoDomain *domain, gint32 len)
1748 vtable = mono_class_vtable (domain, mono_defaults.string_class);
1750 #if CREATION_SPEEDUP
1751 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1752 s = mono_object_allocate_spec (sizeof (MonoString) + ((len + 1) * 2), vtable);
1754 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1755 s->object.vtable = vtable;
1758 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1759 s->object.vtable = vtable;
1763 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
1769 * mono_string_new_len:
1770 * @text: a pointer to an utf8 string
1771 * @length: number of bytes in @text to consider
1773 * Returns: A newly created string object which contains @text.
1776 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1778 GError *error = NULL;
1779 MonoString *o = NULL;
1781 glong items_written;
1783 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1786 o = mono_string_new_utf16 (domain, ut, items_written);
1788 g_error_free (error);
1797 * @text: a pointer to an utf8 string
1799 * Returns: A newly created string object which contains @text.
1802 mono_string_new (MonoDomain *domain, const char *text)
1804 GError *error = NULL;
1805 MonoString *o = NULL;
1807 glong items_written;
1812 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1815 o = mono_string_new_utf16 (domain, ut, items_written);
1817 g_error_free (error);
1825 * mono_string_new_wrapper:
1826 * @text: pointer to utf8 characters.
1828 * Helper function to create a string object from @text in the current domain.
1831 mono_string_new_wrapper (const char *text)
1833 MonoDomain *domain = mono_domain_get ();
1835 MONO_ARCH_SAVE_REGS;
1838 return mono_string_new (domain, text);
1845 * @class: the class of the value
1846 * @value: a pointer to the unboxed data
1848 * Returns: A newly created object which contains @value.
1851 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1857 g_assert (class->valuetype);
1859 vtable = mono_class_vtable (domain, class);
1860 size = mono_class_instance_size (class);
1861 res = mono_object_allocate (size);
1862 res->vtable = vtable;
1863 mono_profiler_allocation (res, class);
1865 size = size - sizeof (MonoObject);
1867 #if NO_UNALIGNED_ACCESS
1868 memcpy ((char *)res + sizeof (MonoObject), value, size);
1872 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
1875 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
1878 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
1881 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
1884 memcpy ((char *)res + sizeof (MonoObject), value, size);
1887 if (class->has_finalize)
1888 mono_object_register_finalizer (res);
1893 mono_object_unbox (MonoObject *obj)
1895 /* add assert for valuetypes? */
1896 return ((char*)obj) + sizeof (MonoObject);
1900 * mono_object_isinst:
1902 * @klass: a pointer to a class
1904 * Returns: @obj if @obj is derived from @klass
1907 mono_object_isinst (MonoObject *obj, MonoClass *klass)
1919 mono_class_init (klass);
1921 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1922 if ((klass->interface_id <= vt->max_interface_id) &&
1923 (vt->interface_offsets [klass->interface_id] != 0))
1929 if (oklass != klass && oklass == mono_defaults.transparent_proxy_class) {
1930 /* fixme: add check for IRemotingTypeInfo */
1931 if (klass->marshalbyref)
1932 oklass = ((MonoTransparentProxy *)obj)->klass;
1935 return mono_class_is_assignable_from (klass, oklass) ? obj : NULL;
1939 MonoDomain *orig_domain;
1945 str_lookup (MonoDomain *domain, gpointer user_data)
1947 LDStrInfo *info = user_data;
1948 if (info->res || domain == info->orig_domain)
1950 mono_domain_lock (domain);
1951 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
1952 mono_domain_unlock (domain);
1956 mono_string_is_interned_lookup (MonoString *str, int insert)
1958 MonoGHashTable *ldstr_table;
1961 char *ins = g_malloc (4 + str->length * 2);
1965 /* Encode the length */
1967 mono_metadata_encode_value (2 * str->length, p, &p);
1970 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
1971 bloblen = (p - ins) + 2 * str->length;
1973 * ins is stored in the hash table as a key and needs to have the same
1974 * representation as in the metadata: we swap the character bytes on big
1977 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1980 char *p2 = (char *)mono_string_chars (str);
1981 for (i = 0; i < str->length; ++i) {
1988 memcpy (p, mono_string_chars (str), str->length * 2);
1990 domain = ((MonoObject *)str)->vtable->domain;
1991 ldstr_table = domain->ldstr_table;
1992 mono_domain_lock (domain);
1993 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1994 mono_domain_unlock (domain);
1999 mono_g_hash_table_insert (ldstr_table, ins, str);
2000 mono_domain_unlock (domain);
2003 LDStrInfo ldstr_info;
2004 ldstr_info.orig_domain = domain;
2005 ldstr_info.ins = ins;
2006 ldstr_info.res = NULL;
2008 mono_domain_foreach (str_lookup, &ldstr_info);
2009 if (ldstr_info.res) {
2011 * the string was already interned in some other domain:
2012 * intern it in the current one as well.
2014 mono_g_hash_table_insert (ldstr_table, ins, str);
2015 mono_domain_unlock (domain);
2019 mono_domain_unlock (domain);
2025 mono_string_is_interned (MonoString *o)
2027 return mono_string_is_interned_lookup (o, FALSE);
2031 mono_string_intern (MonoString *str)
2033 return mono_string_is_interned_lookup (str, TRUE);
2038 * @domain: the domain where the string will be used.
2039 * @image: a metadata context
2040 * @idx: index into the user string table.
2042 * Implementation for the ldstr opcode.
2045 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2047 const char *str, *sig;
2051 MONO_ARCH_SAVE_REGS;
2053 if (image->assembly->dynamic)
2054 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2056 sig = str = mono_metadata_user_string (image, idx);
2058 mono_domain_lock (domain);
2059 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2060 mono_domain_unlock (domain);
2064 len2 = mono_metadata_decode_blob_size (str, &str);
2067 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2068 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2071 guint16 *p2 = (guint16*)mono_string_chars (o);
2072 for (i = 0; i < len2; ++i) {
2073 *p2 = GUINT16_FROM_LE (*p2);
2078 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2079 mono_domain_unlock (domain);
2085 * mono_string_to_utf8:
2086 * @s: a System.String
2088 * Return the UTF8 representation for @s.
2089 * the resulting buffer nedds to be freed with g_free().
2092 mono_string_to_utf8 (MonoString *s)
2095 GError *error = NULL;
2101 return g_strdup ("");
2103 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2105 g_warning (error->message);
2106 g_error_free (error);
2113 * mono_string_to_utf16:
2116 * Return an null-terminated array of the utf-16 chars
2117 * contained in @s. The result must be freed with g_free().
2118 * This is a temporary helper until our string implementation
2119 * is reworked to always include the null terminating char.
2122 mono_string_to_utf16 (MonoString *s)
2129 as = g_malloc ((s->length * 2) + 2);
2130 as [(s->length * 2)] = '\0';
2131 as [(s->length * 2) + 1] = '\0';
2134 return (gunichar2 *)(as);
2137 memcpy (as, mono_string_chars(s), s->length * 2);
2138 return (gunichar2 *)(as);
2142 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2145 mono_string_from_utf16 (gunichar2 *data)
2147 MonoDomain *domain = mono_domain_get ();
2153 while (data [len]) len++;
2155 return mono_string_new_utf16 (domain, data, len);
2159 default_ex_handler (MonoException *ex)
2161 MonoObject *o = (MonoObject*)ex;
2162 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2166 static MonoExceptionFunc ex_handler = default_ex_handler;
2169 mono_install_handler (MonoExceptionFunc func)
2171 ex_handler = func? func: default_ex_handler;
2175 * mono_raise_exception:
2176 * @ex: exception object
2178 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2181 mono_raise_exception (MonoException *ex)
2184 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2185 * that will cause gcc to omit the function epilog, causing problems when
2186 * the JIT tries to walk the stack, since the return address on the stack
2187 * will point into the next function in the executable, not this one.
2194 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2196 MonoWaitHandle *res;
2198 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2200 res->handle = handle;
2206 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2208 MonoAsyncResult *res;
2210 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2213 res->async_state = state;
2214 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
2215 res->sync_completed = FALSE;
2216 res->completed = FALSE;
2222 mono_message_init (MonoDomain *domain,
2223 MonoMethodMessage *this,
2224 MonoReflectionMethod *method,
2225 MonoArray *out_args)
2227 MonoMethodSignature *sig = method->method->signature;
2233 this->method = method;
2235 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2236 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2237 this->async_result = NULL;
2238 this->call_type = CallType_Sync;
2240 names = g_new (char *, sig->param_count);
2241 mono_method_get_param_names (method->method, (const char **) names);
2242 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2244 for (i = 0; i < sig->param_count; i++) {
2245 name = mono_string_new (domain, names [i]);
2246 mono_array_set (this->names, gpointer, i, name);
2250 for (i = 0, j = 0; i < sig->param_count; i++) {
2252 if (sig->params [i]->byref) {
2254 gpointer arg = mono_array_get (out_args, gpointer, j);
2255 mono_array_set (this->args, gpointer, i, arg);
2259 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2264 mono_array_set (this->arg_types, guint8, i, arg_type);
2269 * mono_remoting_invoke:
2270 * @real_proxy: pointer to a RealProxy object
2271 * @msg: The MonoMethodMessage to execute
2272 * @exc: used to store exceptions
2273 * @out_args: used to store output arguments
2275 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2276 * IMessage interface and it is not trivial to extract results from there. So
2277 * we call an helper method PrivateInvoke instead of calling
2278 * RealProxy::Invoke() directly.
2280 * Returns: the result object.
2283 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2284 MonoObject **exc, MonoArray **out_args)
2286 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2289 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2295 klass = mono_defaults.real_proxy_class;
2297 for (i = 0; i < klass->method.count; ++i) {
2298 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2299 klass->methods [i]->signature->param_count == 4) {
2300 im = klass->methods [i];
2306 real_proxy->vtable->domain->private_invoke_method = im;
2309 pa [0] = real_proxy;
2314 return mono_runtime_invoke (im, NULL, pa, exc);
2318 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2319 MonoObject **exc, MonoArray **out_args)
2323 MonoMethodSignature *sig;
2324 int i, j, outarg_count = 0;
2326 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2328 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2329 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2330 target = tp->rp->unwrapped_server;
2332 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2336 domain = mono_domain_get ();
2337 method = msg->method->method;
2338 sig = method->signature;
2340 for (i = 0; i < sig->param_count; i++) {
2341 if (sig->params [i]->byref)
2345 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2348 for (i = 0, j = 0; i < sig->param_count; i++) {
2349 if (sig->params [i]->byref) {
2351 arg = mono_array_get (msg->args, gpointer, i);
2352 mono_array_set (*out_args, gpointer, j, arg);
2357 return mono_runtime_invoke_array (method, target, msg->args, exc);
2361 mono_print_unhandled_exception (MonoObject *exc)
2363 char *message = (char *) "";
2367 gboolean free_message = FALSE;
2370 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2371 klass = exc->vtable->klass;
2373 while (klass && method == NULL) {
2374 for (i = 0; i < klass->method.count; ++i) {
2375 method = klass->methods [i];
2376 if (!strcmp ("ToString", method->name) &&
2377 method->signature->param_count == 0 &&
2378 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2379 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2386 klass = klass->parent;
2391 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2393 message = mono_string_to_utf8 (str);
2394 free_message = TRUE;
2399 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2400 * exc->vtable->klass->name, message);
2402 g_printerr ("\nUnhandled Exception: %s\n", message);
2409 * mono_delegate_ctor:
2410 * @this: pointer to an uninitialized delegate object
2411 * @target: target object
2412 * @addr: pointer to native code
2414 * This is used to initialize a delegate. We also insert the method_info if
2415 * we find the info with mono_jit_info_table_find().
2418 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2420 MonoDomain *domain = mono_domain_get ();
2421 MonoDelegate *delegate = (MonoDelegate *)this;
2422 MonoMethod *method = NULL;
2429 class = this->vtable->klass;
2431 if ((ji = mono_jit_info_table_find (domain, addr))) {
2432 method = ji->method;
2433 delegate->method_info = mono_method_get_object (domain, method, NULL);
2436 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2438 method = mono_marshal_get_remoting_invoke (method);
2439 delegate->method_ptr = mono_compile_method (method);
2440 delegate->target = target;
2442 delegate->method_ptr = addr;
2443 delegate->target = target;
2448 * mono_method_call_message_new:
2450 * Translates arguments pointers into a Message.
2453 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2454 MonoDelegate **cb, MonoObject **state)
2456 MonoDomain *domain = mono_domain_get ();
2457 MonoMethodSignature *sig = method->signature;
2458 MonoMethodMessage *msg;
2461 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2464 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2465 count = sig->param_count - 2;
2467 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2468 count = sig->param_count;
2471 for (i = 0; i < count; i++) {
2476 if (sig->params [i]->byref)
2477 vpos = *((gpointer *)params [i]);
2481 type = sig->params [i]->type;
2482 class = mono_class_from_mono_type (sig->params [i]);
2484 if (class->valuetype)
2485 arg = mono_value_box (domain, class, vpos);
2487 arg = *((MonoObject **)vpos);
2489 mono_array_set (msg->args, gpointer, i, arg);
2492 if (cb != NULL && state != NULL) {
2493 *cb = *((MonoDelegate **)params [i]);
2495 *state = *((MonoObject **)params [i]);
2502 * mono_method_return_message_restore:
2504 * Restore results from message based processing back to arguments pointers
2507 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2509 MonoMethodSignature *sig = method->signature;
2510 int i, j, type, size;
2511 for (i = 0, j = 0; i < sig->param_count; i++) {
2512 MonoType *pt = sig->params [i];
2515 char *arg = mono_array_get (out_args, gpointer, j);
2519 case MONO_TYPE_VOID:
2520 g_assert_not_reached ();
2524 case MONO_TYPE_BOOLEAN:
2527 case MONO_TYPE_CHAR:
2534 case MONO_TYPE_VALUETYPE: {
2535 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2536 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2539 case MONO_TYPE_STRING:
2540 case MONO_TYPE_CLASS:
2541 case MONO_TYPE_ARRAY:
2542 case MONO_TYPE_SZARRAY:
2543 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2546 g_assert_not_reached ();
2555 * mono_load_remote_field:
2556 * @this: pointer to an object
2557 * @klass: klass of the object containing @field
2558 * @field: the field to load
2559 * @res: a storage to store the result
2561 * This method is called by the runtime on attempts to load fields of
2562 * transparent proxy objects. @this points to such TP, @klass is the class of
2563 * the object containing @field. @res is a storage location which can be
2564 * used to store the result.
2566 * Returns: an address pointing to the value of field.
2569 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2571 static MonoMethod *getter = NULL;
2572 MonoDomain *domain = mono_domain_get ();
2573 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2574 MonoClass *field_class;
2575 MonoMethodMessage *msg;
2576 MonoArray *out_args;
2580 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2585 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2586 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2593 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2594 MonoMethod *cm = mono_defaults.object_class->methods [i];
2596 if (!strcmp (cm->name, "FieldGetter")) {
2604 field_class = mono_class_from_mono_type (field->type);
2606 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2607 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2608 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2610 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2611 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2613 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2615 if (exc) mono_raise_exception ((MonoException *)exc);
2617 *res = mono_array_get (out_args, MonoObject *, 0);
2619 if (field_class->valuetype) {
2620 return ((char *)*res) + sizeof (MonoObject);
2626 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2628 static MonoMethod *getter = NULL;
2629 MonoDomain *domain = mono_domain_get ();
2630 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2631 MonoClass *field_class;
2632 MonoMethodMessage *msg;
2633 MonoArray *out_args;
2634 MonoObject *exc, *res;
2636 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2638 field_class = mono_class_from_mono_type (field->type);
2640 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2642 if (field_class->valuetype) {
2643 res = mono_object_new (domain, field_class);
2644 val = ((gchar *) res) + sizeof (MonoObject);
2648 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2655 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2656 MonoMethod *cm = mono_defaults.object_class->methods [i];
2658 if (!strcmp (cm->name, "FieldGetter")) {
2666 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2667 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2668 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2670 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2671 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2673 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2675 if (exc) mono_raise_exception ((MonoException *)exc);
2677 res = mono_array_get (out_args, MonoObject *, 0);
2683 * mono_store_remote_field:
2684 * @this: pointer to an object
2685 * @klass: klass of the object containing @field
2686 * @field: the field to load
2687 * @val: the value/object to store
2689 * This method is called by the runtime on attempts to store fields of
2690 * transparent proxy objects. @this points to such TP, @klass is the class of
2691 * the object containing @field. @val is the new value to store in @field.
2694 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
2696 static MonoMethod *setter = NULL;
2697 MonoDomain *domain = mono_domain_get ();
2698 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2699 MonoClass *field_class;
2700 MonoMethodMessage *msg;
2701 MonoArray *out_args;
2705 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2707 field_class = mono_class_from_mono_type (field->type);
2709 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2710 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
2711 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
2718 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2719 MonoMethod *cm = mono_defaults.object_class->methods [i];
2721 if (!strcmp (cm->name, "FieldSetter")) {
2729 if (field_class->valuetype)
2730 arg = mono_value_box (domain, field_class, val);
2732 arg = *((MonoObject **)val);
2735 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2736 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2738 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2739 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2740 mono_array_set (msg->args, gpointer, 2, arg);
2742 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2744 if (exc) mono_raise_exception ((MonoException *)exc);
2748 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
2750 static MonoMethod *setter = NULL;
2751 MonoDomain *domain = mono_domain_get ();
2752 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2753 MonoClass *field_class;
2754 MonoMethodMessage *msg;
2755 MonoArray *out_args;
2758 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2760 field_class = mono_class_from_mono_type (field->type);
2762 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2763 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
2764 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
2771 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2772 MonoMethod *cm = mono_defaults.object_class->methods [i];
2774 if (!strcmp (cm->name, "FieldSetter")) {
2782 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2783 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2785 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2786 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2787 mono_array_set (msg->args, gpointer, 2, arg);
2789 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2791 if (exc) mono_raise_exception ((MonoException *)exc);