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 (mono_field_is_deleted (field))
442 if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)) {
443 gint32 special_static = field_is_special_static (class, field);
444 if (special_static != SPECIAL_STATIC_NONE) {
445 guint32 size, align, offset;
446 size = mono_type_size (field->type, &align);
447 offset = mono_alloc_special_static_data (special_static, size, align);
448 if (!domain->special_static_fields)
449 domain->special_static_fields = g_hash_table_new (NULL, NULL);
450 g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
454 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
455 MonoClass *fklass = mono_class_from_mono_type (field->type);
456 t = (char*)vt->data + field->offset;
457 if (fklass->valuetype) {
458 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
460 /* it's a pointer type: add check */
461 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
462 *t = *(char *)field->data;
466 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
469 if (!field->def_value) {
470 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1), cindex + 1);
473 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
474 field->def_value = g_new0 (MonoConstant, 1);
475 field->def_value->type = constant_cols [MONO_CONSTANT_TYPE];
476 field->def_value->value = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]);
479 p = field->def_value->value;
480 len = mono_metadata_decode_blob_size (p, &p);
481 t = (char*)vt->data + field->offset;
482 /* should we check that the type matches? */
483 switch (field->def_value->type) {
484 case MONO_TYPE_BOOLEAN:
492 guint16 *val = (guint16*)t;
498 guint32 *val = (guint32*)t;
504 guint64 *val = (guint64*)t;
509 float *val = (float*)t;
514 double *val = (double*)t;
518 case MONO_TYPE_STRING: {
519 gpointer *val = (gpointer*)t;
520 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
521 gunichar2 *copy = g_malloc (len);
523 for (j = 0; j < len/2; j++) {
524 copy [j] = read16 (p);
527 *val = mono_string_new_utf16 (domain, copy, len/2);
530 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
534 case MONO_TYPE_CLASS:
535 /* nothing to do, we malloc0 the data and the value can be 0 only */
538 g_warning ("type 0x%02x should not be in constant table", field->def_value->type);
542 vt->max_interface_id = class->max_interface_id;
544 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
545 sizeof (gpointer) * (class->max_interface_id + 1));
547 /* initialize interface offsets */
548 for (i = 0; i <= class->max_interface_id; ++i) {
549 int slot = class->interface_offsets [i];
551 vt->interface_offsets [i] = &(vt->vtable [slot]);
555 * arch_create_jit_trampoline () can recursively call this function again
556 * because it compiles icall methods right away.
558 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
559 if (!class->cached_vtable)
560 class->cached_vtable = vt;
562 /* initialize vtable */
563 for (i = 0; i < class->vtable_size; ++i) {
566 if ((cm = class->vtable [i]))
567 vt->vtable [i] = arch_create_jit_trampoline (cm);
570 mono_domain_unlock (domain);
572 /* make sure the the parent is initialized */
574 mono_class_vtable (domain, class->parent);
576 if (class->contextbound)
585 * mono_class_proxy_vtable:
586 * @domain: the application domain
587 * @class: the class to proxy
589 * Creates a vtable for transparent proxies. It is basically
590 * a copy of the real vtable of @class, but all function pointers invoke
591 * the remoting functions, and vtable->klass points to the
592 * transparent proxy class, and not to @class.
595 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
597 MonoVTable *vt, *pvt;
598 int i, j, vtsize, interface_vtsize = 0;
599 MonoClass* iclass = NULL;
602 mono_domain_lock (domain);
603 pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class);
606 mono_domain_unlock (domain);
610 if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
613 class = mono_defaults.marshalbyrefobject_class;
615 method_count = iclass->method.count;
616 for (i = 0; i < iclass->interface_count; i++)
617 method_count += iclass->interfaces[i]->method.count;
619 interface_vtsize = method_count * sizeof (gpointer);
622 vt = mono_class_vtable (domain, class);
623 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
625 mono_stats.class_vtable_size += vtsize + interface_vtsize;
627 pvt = mono_mempool_alloc (domain->mp, vtsize + interface_vtsize);
628 memcpy (pvt, vt, vtsize);
630 pvt->klass = mono_defaults.transparent_proxy_class;
632 /* initialize vtable */
633 for (i = 0; i < class->vtable_size; ++i) {
636 if ((cm = class->vtable [i]))
637 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
640 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
642 /* create trampolines for abstract methods */
643 for (k = class; k; k = k->parent) {
644 for (i = 0; i < k->method.count; i++) {
645 int slot = k->methods [i]->slot;
646 if (!pvt->vtable [slot])
647 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
657 pvt->max_interface_id = iclass->max_interface_id;
659 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
660 sizeof (gpointer) * (pvt->max_interface_id + 1));
662 /* Create trampolines for the methods of the interfaces */
663 slot = class->vtable_size;
667 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
669 for (j = 0; j < interf->method.count; ++j) {
670 MonoMethod *cm = interf->methods [j];
671 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
673 slot += interf->method.count;
674 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
683 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
684 sizeof (gpointer) * (pvt->max_interface_id + 1));
686 /* initialize interface offsets */
687 for (i = 0; i <= class->max_interface_id; ++i) {
688 int slot = class->interface_offsets [i];
690 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
694 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
696 mono_domain_unlock (domain);
702 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
703 * the instance of a callvirt of method.
706 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
710 MonoMethod *res = NULL;
712 klass = mono_object_class (obj);
713 if (klass == mono_defaults.transparent_proxy_class) {
714 klass = ((MonoTransparentProxy *)obj)->klass;
720 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
723 vtable = klass->vtable;
725 /* check method->slot is a valid index: perform isinstance? */
726 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
728 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
730 res = vtable [method->slot];
734 if (!res) res = method; /* It may be an interface or abstract class method */
735 res = mono_marshal_get_remoting_invoke (res);
744 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
746 g_error ("runtime invoke called on uninitialized runtime");
750 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
753 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
755 return default_mono_runtime_invoke (method, obj, params, exc);
759 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
762 gpointer *p = (gpointer*)dest;
769 case MONO_TYPE_BOOLEAN:
772 guint8 *p = (guint8*)dest;
773 *p = *(guint8*)value;
778 case MONO_TYPE_CHAR: {
779 guint16 *p = (guint16*)dest;
780 *p = *(guint16*)value;
783 #if SIZEOF_VOID_P == 4
789 gint32 *p = (gint32*)dest;
790 *p = *(gint32*)value;
793 #if SIZEOF_VOID_P == 8
799 gint64 *p = (gint64*)dest;
800 *p = *(gint64*)value;
804 float *p = (float*)dest;
809 double *p = (double*)dest;
810 *p = *(double*)value;
813 case MONO_TYPE_STRING:
814 case MONO_TYPE_SZARRAY:
815 case MONO_TYPE_CLASS:
816 case MONO_TYPE_OBJECT:
817 case MONO_TYPE_ARRAY:
818 case MONO_TYPE_PTR: {
819 gpointer *p = (gpointer*)dest;
820 *p = deref_pointer? *(gpointer*)value: value;
823 case MONO_TYPE_VALUETYPE:
824 if (type->data.klass->enumtype) {
825 t = type->data.klass->enum_basetype->type;
829 size = mono_class_value_size (type->data.klass, NULL);
830 memcpy (dest, value, size);
834 g_warning ("got type %x", type->type);
835 g_assert_not_reached ();
840 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
844 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
846 dest = (char*)obj + field->offset;
847 set_value (field->type, dest, value, FALSE);
851 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
855 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
857 dest = (char*)vt->data + field->offset;
858 set_value (field->type, dest, value, FALSE);
862 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
866 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
868 src = (char*)obj + field->offset;
869 set_value (field->type, value, src, TRUE);
873 mono_field_get_value_object (MonoDomain *domain, MonoClassField *field, MonoObject *obj)
877 MonoVTable *vtable = NULL;
879 gboolean is_static = FALSE;
880 gboolean is_ref = FALSE;
882 switch (field->type->type) {
883 case MONO_TYPE_STRING:
884 case MONO_TYPE_OBJECT:
885 case MONO_TYPE_CLASS:
886 case MONO_TYPE_ARRAY:
887 case MONO_TYPE_SZARRAY:
892 case MONO_TYPE_BOOLEAN:
904 case MONO_TYPE_VALUETYPE:
905 is_ref = field->type->byref;
908 g_error ("type 0x%x not handled in "
909 "mono_field_get_value_object", field->type->type);
913 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
915 vtable = mono_class_vtable (domain, field->parent);
916 if (!vtable->initialized)
917 mono_runtime_class_init (vtable);
922 mono_field_static_get_value (vtable, field, &o);
924 mono_field_get_value (obj, field, &o);
929 /* boxed value type */
930 klass = mono_class_from_mono_type (field->type);
931 o = mono_object_new (domain, klass);
932 v = ((gchar *) o) + sizeof (MonoObject);
934 mono_field_static_get_value (vtable, field, v);
936 mono_field_get_value (obj, field, v);
944 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
948 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
950 src = (char*)vt->data + field->offset;
951 set_value (field->type, value, src, TRUE);
955 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
957 default_mono_runtime_invoke (prop->set, obj, params, exc);
961 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
963 return default_mono_runtime_invoke (prop->get, obj, params, exc);
968 mono_get_delegate_invoke (MonoClass *klass)
975 for (i = 0; i < klass->method.count; ++i) {
976 if (klass->methods [i]->name[0] == 'I' &&
977 !strcmp ("Invoke", klass->methods [i]->name)) {
978 im = klass->methods [i];
988 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
992 im = mono_get_delegate_invoke (delegate->vtable->klass);
995 return mono_runtime_invoke (im, delegate, params, exc);
998 static MonoArray* main_args;
1001 mono_runtime_get_main_args (void)
1007 * Execute a standard Main() method (argc/argv contains the
1008 * executable name). This method also sets the command line argument value
1009 * needed by System.Environment.
1012 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
1016 MonoArray *args = NULL;
1017 MonoDomain *domain = mono_domain_get ();
1018 gchar *utf8_fullpath;
1020 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1022 if (!g_path_is_absolute (argv [0])) {
1023 gchar *basename = g_path_get_basename (argv [0]);
1024 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
1028 utf8_fullpath = mono_utf8_from_external (fullpath);
1029 if(utf8_fullpath == NULL) {
1030 /* Printing the arg text will cause glib to
1031 * whinge about "Invalid UTF-8", but at least
1032 * its relevant, and shows the problem text
1035 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", fullpath);
1036 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1043 utf8_fullpath = mono_utf8_from_external (argv[0]);
1044 if(utf8_fullpath == NULL) {
1045 g_print ("\nCannot determine the text encoding for the assembly location: %s\n", argv[0]);
1046 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1051 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, utf8_fullpath));
1052 g_free (utf8_fullpath);
1054 for (i = 1; i < argc; ++i) {
1058 utf8_arg=mono_utf8_from_external (argv[i]);
1059 if(utf8_arg==NULL) {
1060 /* Ditto the comment about Invalid UTF-8 here */
1061 g_print ("\nCannot determine the text encoding for argument %d (%s).\n", i, argv[i]);
1062 g_print ("Please add the correct encoding to MONO_EXTERNAL_ENCODINGS and try again.\n");
1066 arg = mono_string_new (domain, utf8_arg);
1067 mono_array_set (main_args, gpointer, i, arg);
1071 if (method->signature->param_count) {
1072 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
1073 for (i = 0; i < argc; ++i) {
1074 /* The encodings should all work, given that
1075 * we've checked all these args for the
1078 MonoString *arg = mono_string_new (domain, mono_utf8_from_external (argv [i]));
1079 mono_array_set (args, gpointer, i, arg);
1082 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
1085 mono_assembly_set_main (method->klass->image->assembly);
1087 return mono_runtime_exec_main (method, args, exc);
1090 /* Used in mono_unhandled_exception */
1092 create_unhandled_exception_eventargs (MonoObject *exc)
1096 MonoMethod *method = NULL;
1097 MonoBoolean is_terminating = TRUE;
1101 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
1104 mono_class_init (klass);
1106 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
1107 for (i = 0; i < klass->method.count; ++i) {
1108 method = klass->methods [i];
1109 if (!strcmp (".ctor", method->name) &&
1110 method->signature->param_count == 2 &&
1111 method->flags & METHOD_ATTRIBUTE_PUBLIC)
1119 args [1] = &is_terminating;
1121 obj = mono_object_new (mono_domain_get (), klass);
1122 mono_runtime_invoke (method, obj, args, NULL);
1128 * We call this function when we detect an unhandled exception
1129 * in the default domain.
1130 * It invokes the * UnhandledException event in AppDomain or prints
1131 * a warning to the console
1134 mono_unhandled_exception (MonoObject *exc)
1136 MonoDomain *domain = mono_domain_get ();
1137 MonoClassField *field;
1138 MonoObject *delegate;
1140 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
1141 "UnhandledException");
1144 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
1145 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
1147 /* set exitcode only in the main thread? */
1148 mono_environment_exitcode_set (1);
1149 if (domain != mono_root_domain || !delegate) {
1150 mono_print_unhandled_exception (exc);
1152 MonoObject *e = NULL;
1155 pa [0] = domain->domain;
1156 pa [1] = create_unhandled_exception_eventargs (exc);
1157 mono_runtime_delegate_invoke (delegate, pa, &e);
1160 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
1161 g_warning ("exception inside UnhandledException handler: %s\n", msg);
1169 * Launch a new thread to start all setup that requires managed code
1172 * main_func is called back from the thread with main_args as the
1173 * parameter. The callback function is expected to start Main()
1174 * eventually. This function then waits for all managed threads to
1178 mono_runtime_exec_managed_code (MonoDomain *domain,
1179 MonoMainThreadFunc main_func,
1182 mono_thread_create (domain, main_func, main_args);
1184 mono_thread_manage ();
1188 * Execute a standard Main() method (args doesn't contain the
1192 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
1202 domain = mono_object_domain (args);
1203 if (!domain->entry_assembly) {
1204 domain->entry_assembly = method->klass->image->assembly;
1205 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
1208 /* FIXME: check signature of method */
1209 if (method->signature->ret->type == MONO_TYPE_I4) {
1211 res = mono_runtime_invoke (method, NULL, pa, exc);
1213 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
1217 mono_environment_exitcode_set (rval);
1219 mono_runtime_invoke (method, NULL, pa, exc);
1223 /* If the return type of Main is void, only
1224 * set the exitcode if an exception was thrown
1225 * (we don't want to blow away an
1226 * explicitly-set exit code)
1229 mono_environment_exitcode_set (rval);
1237 mono_install_runtime_invoke (MonoInvokeFunc func)
1239 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1243 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1246 MonoMethodSignature *sig = method->signature;
1247 gpointer *pa = NULL;
1250 if (NULL != params) {
1251 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1252 for (i = 0; i < mono_array_length (params); i++) {
1253 if (sig->params [i]->byref) {
1257 switch (sig->params [i]->type) {
1260 case MONO_TYPE_BOOLEAN:
1263 case MONO_TYPE_CHAR:
1272 case MONO_TYPE_VALUETYPE:
1273 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1275 case MONO_TYPE_STRING:
1276 case MONO_TYPE_OBJECT:
1277 case MONO_TYPE_CLASS:
1278 case MONO_TYPE_ARRAY:
1279 case MONO_TYPE_SZARRAY:
1280 if (sig->params [i]->byref)
1281 pa [i] = &(((gpointer *)params->vector)[i]);
1283 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1286 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1291 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1293 obj = mono_object_new (mono_domain_get (), method->klass);
1294 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1295 method = mono_marshal_get_remoting_invoke (method->klass->vtable [method->slot]);
1298 mono_runtime_invoke (method, obj, pa, exc);
1301 return mono_runtime_invoke (method, obj, pa, exc);
1305 out_of_memory (size_t size)
1308 * we could allocate at program startup some memory that we could release
1309 * back to the system at this point if we're really low on memory (ie, size is
1310 * lower than the memory we set apart)
1312 mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
1316 * mono_object_allocate:
1317 * @size: number of bytes to allocate
1319 * This is a very simplistic routine until we have our GC-aware
1322 * Returns: an allocated object of size @size, or NULL on failure.
1324 static inline void *
1325 mono_object_allocate (size_t size)
1328 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1329 void *o = GC_MALLOC (size);
1331 void *o = calloc (1, size);
1333 mono_stats.new_object_count++;
1336 out_of_memory (size);
1340 #if CREATION_SPEEDUP
1341 static inline void *
1342 mono_object_allocate_spec (size_t size, void *gcdescr)
1344 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1345 void *o = GC_GCJ_MALLOC (size, gcdescr);
1346 mono_stats.new_object_count++;
1349 out_of_memory (size);
1357 * Frees the memory used by the object. Debugging purposes
1358 * only, as we will have our GC system.
1361 mono_object_free (MonoObject *o)
1364 g_error ("mono_object_free called with boehm gc.");
1366 MonoClass *c = o->vtable->klass;
1368 memset (o, 0, c->instance_size);
1375 * @klass: the class of the object that we want to create
1377 * Returns: A newly created object whose definition is
1378 * looked up using @klass
1381 mono_object_new (MonoDomain *domain, MonoClass *klass)
1383 MONO_ARCH_SAVE_REGS;
1384 return mono_object_new_specific (mono_class_vtable (domain, klass));
1388 * mono_object_new_specific:
1389 * @vtable: the vtable of the object that we want to create
1391 * Returns: A newly created object with class and domain specified
1395 mono_object_new_specific (MonoVTable *vtable)
1399 MONO_ARCH_SAVE_REGS;
1404 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1407 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1411 mono_class_init (klass);
1413 for (i = 0; i < klass->method.count; ++i) {
1414 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1415 klass->methods [i]->signature->param_count == 1) {
1416 im = klass->methods [i];
1421 vtable->domain->create_proxy_for_type_method = im;
1424 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1426 o = mono_runtime_invoke (im, NULL, pa, NULL);
1427 if (o != NULL) return o;
1430 return mono_object_new_alloc_specific (vtable);
1434 mono_object_new_fast (MonoVTable *vtable)
1437 MONO_ARCH_SAVE_REGS;
1439 #if CREATION_SPEEDUP
1440 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1441 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1443 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1444 o = mono_object_allocate (vtable->klass->instance_size);
1448 o = mono_object_allocate (vtable->klass->instance_size);
1455 mono_object_new_alloc_specific (MonoVTable *vtable)
1459 #if CREATION_SPEEDUP
1460 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1461 o = mono_object_allocate_spec (vtable->klass->instance_size, vtable);
1463 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1464 o = mono_object_allocate (vtable->klass->instance_size);
1468 o = mono_object_allocate (vtable->klass->instance_size);
1471 if (vtable->klass->has_finalize)
1472 mono_object_register_finalizer (o);
1474 mono_profiler_allocation (o, vtable->klass);
1479 * mono_object_new_from_token:
1480 * @image: Context where the type_token is hosted
1481 * @token: a token of the type that we want to create
1483 * Returns: A newly created object whose definition is
1484 * looked up using @token in the @image image
1487 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1491 class = mono_class_get (image, token);
1493 return mono_object_new (domain, class);
1498 * mono_object_clone:
1499 * @obj: the object to clone
1501 * Returns: A newly created object who is a shallow copy of @obj
1504 mono_object_clone (MonoObject *obj)
1509 size = obj->vtable->klass->instance_size;
1510 o = mono_object_allocate (size);
1511 mono_profiler_allocation (o, obj->vtable->klass);
1513 memcpy (o, obj, size);
1515 if (obj->vtable->klass->has_finalize)
1516 mono_object_register_finalizer (o);
1522 * @array: the array to clone
1524 * Returns: A newly created array who is a shallow copy of @array
1527 mono_array_clone (MonoArray *array)
1532 MonoClass *klass = array->obj.vtable->klass;
1534 MONO_ARCH_SAVE_REGS;
1536 if (array->bounds == NULL) {
1537 size = mono_array_length (array);
1538 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1539 klass, &size, NULL);
1541 size *= mono_array_element_size (klass);
1542 memcpy (o, array, sizeof (MonoArray) + size);
1547 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1548 size = mono_array_element_size (klass);
1549 for (i = 0; i < klass->rank; ++i) {
1550 sizes [i] = array->bounds [i].length;
1551 size *= array->bounds [i].length;
1552 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1554 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1555 klass, sizes, sizes + klass->rank);
1556 memcpy (o, array, sizeof(MonoArray) + size);
1561 /* helper macros to check for overflow when calculating the size of arrays */
1562 #define MYGUINT32_MAX 4294967295U
1563 #define CHECK_ADD_OVERFLOW_UN(a,b) \
1564 (guint32)(MYGUINT32_MAX) - (guint32)(b) < (guint32)(a) ? -1 : 0
1565 #define CHECK_MUL_OVERFLOW_UN(a,b) \
1566 ((guint32)(a) == 0) || ((guint32)(b) == 0) ? 0 : \
1567 (guint32)(b) > ((MYGUINT32_MAX) / (guint32)(a))
1570 * mono_array_new_full:
1571 * @domain: domain where the object is created
1572 * @array_class: array class
1573 * @lengths: lengths for each dimension in the array
1574 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1576 * This routine creates a new array objects with the given dimensions,
1577 * lower bounds and type.
1580 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1581 guint32 *lengths, guint32 *lower_bounds)
1583 guint32 byte_len, len;
1586 MonoArrayBounds *bounds;
1590 if (!array_class->inited)
1591 mono_class_init (array_class);
1593 byte_len = mono_array_element_size (array_class);
1596 if (array_class->rank == 1 &&
1597 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1602 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1604 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1606 for (i = 0; i < array_class->rank; ++i) {
1607 bounds [i].length = lengths [i];
1608 if (CHECK_MUL_OVERFLOW_UN (len, lengths [i]))
1609 out_of_memory (MYGUINT32_MAX);
1614 for (i = 0; i < array_class->rank; ++i)
1615 bounds [i].lower_bound = lower_bounds [i];
1618 if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
1619 out_of_memory (MYGUINT32_MAX);
1621 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1622 out_of_memory (MYGUINT32_MAX);
1623 byte_len += sizeof (MonoArray);
1625 * Following three lines almost taken from mono_object_new ():
1626 * they need to be kept in sync.
1628 vtable = mono_class_vtable (domain, array_class);
1629 #if CREATION_SPEEDUP
1630 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1631 o = mono_object_allocate_spec (byte_len, vtable);
1633 o = mono_object_allocate (byte_len);
1637 o = mono_object_allocate (byte_len);
1641 array = (MonoArray*)o;
1643 array->bounds = bounds;
1644 array->max_length = len;
1646 mono_profiler_allocation (o, array_class);
1653 * @domain: domain where the object is created
1654 * @eclass: element class
1655 * @n: number of array elements
1657 * This routine creates a new szarray with @n elements of type @eclass.
1660 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1664 MONO_ARCH_SAVE_REGS;
1666 ac = mono_array_class_get (eclass, 1);
1667 g_assert (ac != NULL);
1669 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1673 * mono_array_new_specific:
1674 * @vtable: a vtable in the appropriate domain for an initialized class
1675 * @n: number of array elements
1677 * This routine is a fast alternative to mono_array_new() for code which
1678 * can be sure about the domain it operates in.
1681 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1685 guint32 byte_len, elem_size;
1687 MONO_ARCH_SAVE_REGS;
1689 elem_size = mono_array_element_size (vtable->klass);
1690 if (CHECK_MUL_OVERFLOW_UN (n, elem_size))
1691 out_of_memory (MYGUINT32_MAX);
1692 byte_len = n * elem_size;
1693 if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray)))
1694 out_of_memory (MYGUINT32_MAX);
1695 byte_len += sizeof (MonoArray);
1696 #if CREATION_SPEEDUP
1697 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1698 o = mono_object_allocate_spec (byte_len, vtable);
1700 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1701 o = mono_object_allocate (byte_len);
1705 o = mono_object_allocate (byte_len);
1709 ao = (MonoArray *)o;
1712 mono_profiler_allocation (o, vtable->klass);
1718 * mono_string_new_utf16:
1719 * @text: a pointer to an utf16 string
1720 * @len: the length of the string
1722 * Returns: A newly created string object which contains @text.
1725 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1729 s = mono_string_new_size (domain, len);
1730 g_assert (s != NULL);
1732 memcpy (mono_string_chars (s), text, len * 2);
1738 * mono_string_new_size:
1739 * @text: a pointer to an utf16 string
1740 * @len: the length of the string
1742 * Returns: A newly created string object of @len
1745 mono_string_new_size (MonoDomain *domain, gint32 len)
1750 vtable = mono_class_vtable (domain, mono_defaults.string_class);
1752 #if CREATION_SPEEDUP
1753 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1754 s = mono_object_allocate_spec (sizeof (MonoString) + ((len + 1) * 2), vtable);
1756 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1757 s->object.vtable = vtable;
1760 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1761 s->object.vtable = vtable;
1765 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
1771 * mono_string_new_len:
1772 * @text: a pointer to an utf8 string
1773 * @length: number of bytes in @text to consider
1775 * Returns: A newly created string object which contains @text.
1778 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1780 GError *error = NULL;
1781 MonoString *o = NULL;
1783 glong items_written;
1785 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1788 o = mono_string_new_utf16 (domain, ut, items_written);
1790 g_error_free (error);
1799 * @text: a pointer to an utf8 string
1801 * Returns: A newly created string object which contains @text.
1804 mono_string_new (MonoDomain *domain, const char *text)
1806 GError *error = NULL;
1807 MonoString *o = NULL;
1809 glong items_written;
1814 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1817 o = mono_string_new_utf16 (domain, ut, items_written);
1819 g_error_free (error);
1827 * mono_string_new_wrapper:
1828 * @text: pointer to utf8 characters.
1830 * Helper function to create a string object from @text in the current domain.
1833 mono_string_new_wrapper (const char *text)
1835 MonoDomain *domain = mono_domain_get ();
1837 MONO_ARCH_SAVE_REGS;
1840 return mono_string_new (domain, text);
1847 * @class: the class of the value
1848 * @value: a pointer to the unboxed data
1850 * Returns: A newly created object which contains @value.
1853 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1859 g_assert (class->valuetype);
1861 vtable = mono_class_vtable (domain, class);
1862 size = mono_class_instance_size (class);
1863 res = mono_object_allocate (size);
1864 res->vtable = vtable;
1865 mono_profiler_allocation (res, class);
1867 size = size - sizeof (MonoObject);
1869 #if NO_UNALIGNED_ACCESS
1870 memcpy ((char *)res + sizeof (MonoObject), value, size);
1874 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
1877 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
1880 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
1883 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
1886 memcpy ((char *)res + sizeof (MonoObject), value, size);
1889 if (class->has_finalize)
1890 mono_object_register_finalizer (res);
1895 mono_object_unbox (MonoObject *obj)
1897 /* add assert for valuetypes? */
1898 return ((char*)obj) + sizeof (MonoObject);
1902 * mono_object_isinst:
1904 * @klass: a pointer to a class
1906 * Returns: @obj if @obj is derived from @klass
1909 mono_object_isinst (MonoObject *obj, MonoClass *klass)
1914 if (klass->marshalbyref)
1915 return mono_object_isinst_mbyref (obj, klass);
1924 mono_class_init (klass);
1926 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1927 if ((klass->interface_id <= vt->max_interface_id) &&
1928 (vt->interface_offsets [klass->interface_id] != 0))
1934 return mono_class_is_assignable_from (klass, oklass) ? obj : NULL;
1938 mono_object_isinst_mbyref (MonoObject *obj, MonoClass *klass)
1949 if (oklass != klass && oklass == mono_defaults.transparent_proxy_class) {
1950 oklass = ((MonoTransparentProxy *)obj)->klass;
1951 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
1954 /* Check for IRemotingTypeInfo */
1955 if (((MonoTransparentProxy *)obj)->custom_type_info) {
1958 MonoObject *rp = (MonoObject *)((MonoTransparentProxy *)obj)->rp;
1959 MonoClass *rpklass = rp->vtable->klass;
1960 MonoMethod *im = NULL;
1964 for (i = 0; i < rpklass->method.count; ++i) {
1965 if (!strcmp ("CanCastTo", rpklass->methods [i]->name) &&
1966 rpklass->methods [i]->signature->param_count == 2) {
1967 im = rpklass->methods [i];
1974 pa [0] = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
1977 res = mono_runtime_invoke (im, rp, pa, NULL);
1978 if (*(MonoBoolean *) mono_object_unbox(res))
1985 if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
1992 * mono_object_castclass_mbyref:
1994 * @klass: a pointer to a class
1996 * Returns: @obj if @obj is derived from @klass, throws an exception otherwise
1999 mono_object_castclass_mbyref (MonoObject *obj, MonoClass *klass)
2001 if (!obj) return NULL;
2002 if (mono_object_isinst_mbyref (obj, klass)) return obj;
2004 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
2006 "InvalidCastException"));
2011 MonoDomain *orig_domain;
2017 str_lookup (MonoDomain *domain, gpointer user_data)
2019 LDStrInfo *info = user_data;
2020 if (info->res || domain == info->orig_domain)
2022 mono_domain_lock (domain);
2023 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
2024 mono_domain_unlock (domain);
2028 mono_string_is_interned_lookup (MonoString *str, int insert)
2030 MonoGHashTable *ldstr_table;
2033 char *ins = g_malloc (4 + str->length * 2);
2037 /* Encode the length */
2039 mono_metadata_encode_value (2 * str->length, p, &p);
2042 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
2043 bloblen = (p - ins) + 2 * str->length;
2045 * ins is stored in the hash table as a key and needs to have the same
2046 * representation as in the metadata: we swap the character bytes on big
2049 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2052 char *p2 = (char *)mono_string_chars (str);
2053 for (i = 0; i < str->length; ++i) {
2060 memcpy (p, mono_string_chars (str), str->length * 2);
2062 domain = ((MonoObject *)str)->vtable->domain;
2063 ldstr_table = domain->ldstr_table;
2064 mono_domain_lock (domain);
2065 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
2066 mono_domain_unlock (domain);
2071 mono_g_hash_table_insert (ldstr_table, ins, str);
2072 mono_domain_unlock (domain);
2075 LDStrInfo ldstr_info;
2076 ldstr_info.orig_domain = domain;
2077 ldstr_info.ins = ins;
2078 ldstr_info.res = NULL;
2080 mono_domain_foreach (str_lookup, &ldstr_info);
2081 if (ldstr_info.res) {
2083 * the string was already interned in some other domain:
2084 * intern it in the current one as well.
2086 mono_g_hash_table_insert (ldstr_table, ins, str);
2087 mono_domain_unlock (domain);
2091 mono_domain_unlock (domain);
2097 mono_string_is_interned (MonoString *o)
2099 return mono_string_is_interned_lookup (o, FALSE);
2103 mono_string_intern (MonoString *str)
2105 return mono_string_is_interned_lookup (str, TRUE);
2110 * @domain: the domain where the string will be used.
2111 * @image: a metadata context
2112 * @idx: index into the user string table.
2114 * Implementation for the ldstr opcode.
2117 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
2119 const char *str, *sig;
2123 MONO_ARCH_SAVE_REGS;
2126 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
2128 sig = str = mono_metadata_user_string (image, idx);
2130 mono_domain_lock (domain);
2131 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
2132 mono_domain_unlock (domain);
2136 len2 = mono_metadata_decode_blob_size (str, &str);
2139 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
2140 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2143 guint16 *p2 = (guint16*)mono_string_chars (o);
2144 for (i = 0; i < len2; ++i) {
2145 *p2 = GUINT16_FROM_LE (*p2);
2150 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
2151 mono_domain_unlock (domain);
2157 * mono_string_to_utf8:
2158 * @s: a System.String
2160 * Return the UTF8 representation for @s.
2161 * the resulting buffer nedds to be freed with g_free().
2164 mono_string_to_utf8 (MonoString *s)
2167 GError *error = NULL;
2173 return g_strdup ("");
2175 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
2177 g_warning (error->message);
2178 g_error_free (error);
2185 * mono_string_to_utf16:
2188 * Return an null-terminated array of the utf-16 chars
2189 * contained in @s. The result must be freed with g_free().
2190 * This is a temporary helper until our string implementation
2191 * is reworked to always include the null terminating char.
2194 mono_string_to_utf16 (MonoString *s)
2201 as = g_malloc ((s->length * 2) + 2);
2202 as [(s->length * 2)] = '\0';
2203 as [(s->length * 2) + 1] = '\0';
2206 return (gunichar2 *)(as);
2209 memcpy (as, mono_string_chars(s), s->length * 2);
2210 return (gunichar2 *)(as);
2214 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
2217 mono_string_from_utf16 (gunichar2 *data)
2219 MonoDomain *domain = mono_domain_get ();
2225 while (data [len]) len++;
2227 return mono_string_new_utf16 (domain, data, len);
2231 default_ex_handler (MonoException *ex)
2233 MonoObject *o = (MonoObject*)ex;
2234 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
2238 static MonoExceptionFunc ex_handler = default_ex_handler;
2241 mono_install_handler (MonoExceptionFunc func)
2243 ex_handler = func? func: default_ex_handler;
2247 * mono_raise_exception:
2248 * @ex: exception object
2250 * Signal the runtime that the exception @ex has been raised in unmanaged code.
2253 mono_raise_exception (MonoException *ex)
2256 * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
2257 * that will cause gcc to omit the function epilog, causing problems when
2258 * the JIT tries to walk the stack, since the return address on the stack
2259 * will point into the next function in the executable, not this one.
2266 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
2268 MonoWaitHandle *res;
2270 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
2272 res->handle = handle;
2278 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
2280 MonoAsyncResult *res;
2282 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
2285 res->async_state = state;
2286 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
2287 res->sync_completed = FALSE;
2288 res->completed = FALSE;
2294 mono_message_init (MonoDomain *domain,
2295 MonoMethodMessage *this,
2296 MonoReflectionMethod *method,
2297 MonoArray *out_args)
2299 MonoMethodSignature *sig = method->method->signature;
2305 this->method = method;
2307 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
2308 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
2309 this->async_result = NULL;
2310 this->call_type = CallType_Sync;
2312 names = g_new (char *, sig->param_count);
2313 mono_method_get_param_names (method->method, (const char **) names);
2314 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
2316 for (i = 0; i < sig->param_count; i++) {
2317 name = mono_string_new (domain, names [i]);
2318 mono_array_set (this->names, gpointer, i, name);
2322 for (i = 0, j = 0; i < sig->param_count; i++) {
2324 if (sig->params [i]->byref) {
2326 gpointer arg = mono_array_get (out_args, gpointer, j);
2327 mono_array_set (this->args, gpointer, i, arg);
2331 if (!(sig->params [i]->attrs & PARAM_ATTRIBUTE_OUT))
2336 mono_array_set (this->arg_types, guint8, i, arg_type);
2341 * mono_remoting_invoke:
2342 * @real_proxy: pointer to a RealProxy object
2343 * @msg: The MonoMethodMessage to execute
2344 * @exc: used to store exceptions
2345 * @out_args: used to store output arguments
2347 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
2348 * IMessage interface and it is not trivial to extract results from there. So
2349 * we call an helper method PrivateInvoke instead of calling
2350 * RealProxy::Invoke() directly.
2352 * Returns: the result object.
2355 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
2356 MonoObject **exc, MonoArray **out_args)
2358 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
2361 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
2367 klass = mono_defaults.real_proxy_class;
2369 for (i = 0; i < klass->method.count; ++i) {
2370 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
2371 klass->methods [i]->signature->param_count == 4) {
2372 im = klass->methods [i];
2378 real_proxy->vtable->domain->private_invoke_method = im;
2381 pa [0] = real_proxy;
2386 return mono_runtime_invoke (im, NULL, pa, exc);
2390 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2391 MonoObject **exc, MonoArray **out_args)
2395 MonoMethodSignature *sig;
2396 int i, j, outarg_count = 0;
2398 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2400 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2401 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2402 target = tp->rp->unwrapped_server;
2404 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2408 domain = mono_domain_get ();
2409 method = msg->method->method;
2410 sig = method->signature;
2412 for (i = 0; i < sig->param_count; i++) {
2413 if (sig->params [i]->byref)
2417 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2420 for (i = 0, j = 0; i < sig->param_count; i++) {
2421 if (sig->params [i]->byref) {
2423 arg = mono_array_get (msg->args, gpointer, i);
2424 mono_array_set (*out_args, gpointer, j, arg);
2429 return mono_runtime_invoke_array (method, target, msg->args, exc);
2433 mono_print_unhandled_exception (MonoObject *exc)
2435 char *message = (char *) "";
2439 gboolean free_message = FALSE;
2442 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2443 klass = exc->vtable->klass;
2445 while (klass && method == NULL) {
2446 for (i = 0; i < klass->method.count; ++i) {
2447 method = klass->methods [i];
2448 if (!strcmp ("ToString", method->name) &&
2449 method->signature->param_count == 0 &&
2450 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2451 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2458 klass = klass->parent;
2463 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2465 message = mono_string_to_utf8 (str);
2466 free_message = TRUE;
2471 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2472 * exc->vtable->klass->name, message);
2474 g_printerr ("\nUnhandled Exception: %s\n", message);
2481 * mono_delegate_ctor:
2482 * @this: pointer to an uninitialized delegate object
2483 * @target: target object
2484 * @addr: pointer to native code
2486 * This is used to initialize a delegate. We also insert the method_info if
2487 * we find the info with mono_jit_info_table_find().
2490 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2492 MonoDomain *domain = mono_domain_get ();
2493 MonoDelegate *delegate = (MonoDelegate *)this;
2494 MonoMethod *method = NULL;
2501 class = this->vtable->klass;
2503 if ((ji = mono_jit_info_table_find (domain, addr))) {
2504 method = ji->method;
2505 delegate->method_info = mono_method_get_object (domain, method, NULL);
2508 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2510 method = mono_marshal_get_remoting_invoke (method);
2511 delegate->method_ptr = mono_compile_method (method);
2512 delegate->target = target;
2514 delegate->method_ptr = addr;
2515 delegate->target = target;
2520 * mono_method_call_message_new:
2522 * Translates arguments pointers into a Message.
2525 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2526 MonoDelegate **cb, MonoObject **state)
2528 MonoDomain *domain = mono_domain_get ();
2529 MonoMethodSignature *sig = method->signature;
2530 MonoMethodMessage *msg;
2533 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2536 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2537 count = sig->param_count - 2;
2539 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2540 count = sig->param_count;
2543 for (i = 0; i < count; i++) {
2548 if (sig->params [i]->byref)
2549 vpos = *((gpointer *)params [i]);
2553 type = sig->params [i]->type;
2554 class = mono_class_from_mono_type (sig->params [i]);
2556 if (class->valuetype)
2557 arg = mono_value_box (domain, class, vpos);
2559 arg = *((MonoObject **)vpos);
2561 mono_array_set (msg->args, gpointer, i, arg);
2564 if (cb != NULL && state != NULL) {
2565 *cb = *((MonoDelegate **)params [i]);
2567 *state = *((MonoObject **)params [i]);
2574 * mono_method_return_message_restore:
2576 * Restore results from message based processing back to arguments pointers
2579 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2581 MonoMethodSignature *sig = method->signature;
2582 int i, j, type, size;
2583 for (i = 0, j = 0; i < sig->param_count; i++) {
2584 MonoType *pt = sig->params [i];
2587 char *arg = mono_array_get (out_args, gpointer, j);
2591 case MONO_TYPE_VOID:
2592 g_assert_not_reached ();
2596 case MONO_TYPE_BOOLEAN:
2599 case MONO_TYPE_CHAR:
2606 case MONO_TYPE_VALUETYPE: {
2607 size = mono_class_value_size (((MonoObject*)arg)->vtable->klass, NULL);
2608 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2611 case MONO_TYPE_STRING:
2612 case MONO_TYPE_CLASS:
2613 case MONO_TYPE_ARRAY:
2614 case MONO_TYPE_SZARRAY:
2615 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2618 g_assert_not_reached ();
2627 * mono_load_remote_field:
2628 * @this: pointer to an object
2629 * @klass: klass of the object containing @field
2630 * @field: the field to load
2631 * @res: a storage to store the result
2633 * This method is called by the runtime on attempts to load fields of
2634 * transparent proxy objects. @this points to such TP, @klass is the class of
2635 * the object containing @field. @res is a storage location which can be
2636 * used to store the result.
2638 * Returns: an address pointing to the value of field.
2641 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2643 static MonoMethod *getter = NULL;
2644 MonoDomain *domain = mono_domain_get ();
2645 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2646 MonoClass *field_class;
2647 MonoMethodMessage *msg;
2648 MonoArray *out_args;
2652 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2657 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2658 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2665 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2666 MonoMethod *cm = mono_defaults.object_class->methods [i];
2668 if (!strcmp (cm->name, "FieldGetter")) {
2676 field_class = mono_class_from_mono_type (field->type);
2678 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2679 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2680 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2682 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2683 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2685 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2687 if (exc) mono_raise_exception ((MonoException *)exc);
2689 *res = mono_array_get (out_args, MonoObject *, 0);
2691 if (field_class->valuetype) {
2692 return ((char *)*res) + sizeof (MonoObject);
2698 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2700 static MonoMethod *getter = NULL;
2701 MonoDomain *domain = mono_domain_get ();
2702 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2703 MonoClass *field_class;
2704 MonoMethodMessage *msg;
2705 MonoArray *out_args;
2706 MonoObject *exc, *res;
2708 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2710 field_class = mono_class_from_mono_type (field->type);
2712 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2714 if (field_class->valuetype) {
2715 res = mono_object_new (domain, field_class);
2716 val = ((gchar *) res) + sizeof (MonoObject);
2720 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2727 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2728 MonoMethod *cm = mono_defaults.object_class->methods [i];
2730 if (!strcmp (cm->name, "FieldGetter")) {
2738 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2739 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2740 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2742 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2743 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2745 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2747 if (exc) mono_raise_exception ((MonoException *)exc);
2749 res = mono_array_get (out_args, MonoObject *, 0);
2755 * mono_store_remote_field:
2756 * @this: pointer to an object
2757 * @klass: klass of the object containing @field
2758 * @field: the field to load
2759 * @val: the value/object to store
2761 * This method is called by the runtime on attempts to store fields of
2762 * transparent proxy objects. @this points to such TP, @klass is the class of
2763 * the object containing @field. @val is the new value to store in @field.
2766 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
2768 static MonoMethod *setter = NULL;
2769 MonoDomain *domain = mono_domain_get ();
2770 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2771 MonoClass *field_class;
2772 MonoMethodMessage *msg;
2773 MonoArray *out_args;
2777 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2779 field_class = mono_class_from_mono_type (field->type);
2781 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2782 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
2783 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
2790 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2791 MonoMethod *cm = mono_defaults.object_class->methods [i];
2793 if (!strcmp (cm->name, "FieldSetter")) {
2801 if (field_class->valuetype)
2802 arg = mono_value_box (domain, field_class, val);
2804 arg = *((MonoObject **)val);
2807 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2808 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2810 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2811 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2812 mono_array_set (msg->args, gpointer, 2, arg);
2814 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2816 if (exc) mono_raise_exception ((MonoException *)exc);
2820 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
2822 static MonoMethod *setter = NULL;
2823 MonoDomain *domain = mono_domain_get ();
2824 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2825 MonoClass *field_class;
2826 MonoMethodMessage *msg;
2827 MonoArray *out_args;
2830 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2832 field_class = mono_class_from_mono_type (field->type);
2834 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2835 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
2836 else mono_field_set_value (tp->rp->unwrapped_server, field, arg);
2843 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2844 MonoMethod *cm = mono_defaults.object_class->methods [i];
2846 if (!strcmp (cm->name, "FieldSetter")) {
2854 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2855 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2857 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2858 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2859 mono_array_set (msg->args, gpointer, 2, arg);
2861 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2863 if (exc) mono_raise_exception ((MonoException *)exc);