2 * object.c: Object creation for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
14 #include <mono/metadata/mono-endian.h>
15 #include <mono/metadata/tabledefs.h>
16 #include <mono/metadata/tokentype.h>
17 #include <mono/metadata/loader.h>
18 #include <mono/metadata/object.h>
19 #include <mono/metadata/gc-internal.h>
20 #include <mono/metadata/exception.h>
21 #include <mono/metadata/appdomain.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/threadpool.h>
24 #include <mono/metadata/marshal.h>
25 #include "mono/metadata/debug-helpers.h"
26 #include "mono/metadata/marshal.h"
27 #include <mono/metadata/threads.h>
28 #include <mono/metadata/environment.h>
29 #include "mono/metadata/profiler-private.h"
30 #include <mono/os/gc_wrapper.h>
33 * Enable experimental typed allocation using the GC_gcj_malloc function.
35 #ifdef HAVE_GC_GCJ_MALLOC
36 #define CREATION_SPEEDUP 1
40 mono_runtime_object_init (MonoObject *this)
43 MonoMethod *method = NULL;
44 MonoClass *klass = this->vtable->klass;
46 for (i = 0; i < klass->method.count; ++i) {
47 if (!strcmp (".ctor", klass->methods [i]->name) &&
48 klass->methods [i]->signature->param_count == 0) {
49 method = klass->methods [i];
56 mono_runtime_invoke (method, this, NULL, NULL);
60 * mono_runtime_class_init:
61 * @klass: klass that needs to be initialized
63 * This routine calls the class constructor for @class.
66 mono_runtime_class_init (MonoClass *klass)
69 MonoException *exc = NULL;
70 MonoException *exc_to_throw;
74 for (i = 0; i < klass->method.count; ++i) {
75 method = klass->methods [i];
76 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
77 (strcmp (".cctor", method->name) == 0)) {
78 mono_runtime_invoke (method, NULL, NULL, (MonoObject **) &exc);
86 (klass->image == mono_defaults.corlib &&
87 !strcmp (klass->name_space, "System") &&
88 !strcmp (klass->name, "TypeInitializationException")))
89 return; /* No static constructor found or avoid infinite loop */
91 if (klass->name_space && *klass->name_space)
92 full_name = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
94 full_name = g_strdup (klass->name);
96 exc_to_throw = mono_get_exception_type_initialization (full_name, exc);
99 mono_raise_exception (exc_to_throw);
103 default_trampoline (MonoMethod *method)
109 default_remoting_trampoline (MonoMethod *method)
111 g_error ("remoting not installed");
115 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
116 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
119 mono_install_trampoline (MonoTrampoline func)
121 arch_create_jit_trampoline = func? func: default_trampoline;
125 mono_install_remoting_trampoline (MonoTrampoline func)
127 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
130 static MonoCompileFunc default_mono_compile_method = NULL;
133 mono_install_compile_method (MonoCompileFunc func)
135 default_mono_compile_method = func;
139 mono_compile_method (MonoMethod *method)
141 if (!default_mono_compile_method) {
142 g_error ("compile method called on uninitialized runtime");
145 return default_mono_compile_method (method);
149 #if 0 && HAVE_BOEHM_GC
151 vtable_finalizer (void *obj, void *data) {
152 g_print ("%s finalized (%p)\n", (char*)data, obj);
158 #define GC_NO_DESCRIPTOR ((gpointer)(0 | GC_DS_LENGTH))
161 * The vtable is assumed to be reachable by other roots, since vtables
162 * are currently never freed. That might change in the future, but
163 * for now, this is a correct (and worthwhile) optimization.
166 #define GC_HEADER_BITMAP (1 << (G_STRUCT_OFFSET (MonoObject,synchronisation) / sizeof(gpointer)))
169 mono_class_compute_gc_descriptor (MonoClass *class)
171 MonoClassField *field;
174 static gboolean gcj_inited = FALSE;
179 GC_init_gcj_malloc (5, NULL);
183 mono_class_init (class);
185 if (class->gc_descr_inited)
188 class->gc_descr_inited = TRUE;
189 class->gc_descr = GC_NO_DESCRIPTOR;
191 if (class == mono_defaults.string_class) {
192 bitmap = GC_HEADER_BITMAP;
193 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 2);
195 else if (class->rank) {
196 mono_class_compute_gc_descriptor (class->element_class);
198 if (class->element_class->valuetype && (class->element_class->gc_descr != GC_NO_DESCRIPTOR) && (class->element_class->gc_bitmap == GC_HEADER_BITMAP)) {
199 bitmap = GC_HEADER_BITMAP;
201 bitmap += 1 << (G_STRUCT_OFFSET (MonoArray,bounds) / sizeof(gpointer));
202 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, 3);
206 static int count = 0;
210 /* GC 6.1 has trouble handling 64 bit descriptors... */
211 if ((class->instance_size / sizeof (gpointer)) > 30) {
212 // printf ("TOO LARGE: %s %d.\n", class->name, class->instance_size / sizeof (gpointer));
216 bitmap = GC_HEADER_BITMAP;
223 // printf("KLASS: %s.\n", class->name);
225 for (p = class; p != NULL; p = p->parent) {
226 for (i = 0; i < p->field.count; ++i) {
227 field = &p->fields [i];
228 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
230 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
233 pos = field->offset / sizeof (gpointer);
235 if (field->type->byref)
238 switch (field->type->type) {
239 case MONO_TYPE_BOOLEAN:
251 // printf ("F: %s %s %d %lld %llx.\n", class->name, field->name, field->offset, ((guint64)1) << pos, bitmap);
254 case MONO_TYPE_STRING:
255 case MONO_TYPE_SZARRAY:
256 case MONO_TYPE_CLASS:
257 case MONO_TYPE_OBJECT:
258 case MONO_TYPE_ARRAY:
260 g_assert ((field->offset % sizeof(gpointer)) == 0);
262 bitmap |= ((guint64)1) << pos;
263 // printf ("F: %s %s %d %d %lld %llx.\n", class->name, field->name, field->offset, pos, ((guint64)(1)) << pos, bitmap);
265 case MONO_TYPE_VALUETYPE: {
266 MonoClass *fclass = field->type->data.klass;
267 if (!fclass->enumtype) {
268 mono_class_compute_gc_descriptor (fclass);
269 bitmap |= (fclass->gc_bitmap & ~2) << pos;
279 // printf("CLASS: %s.%s -> %d %llx.\n", class->name_space, class->name, class->instance_size / sizeof (gpointer), bitmap);
280 class->gc_bitmap = bitmap;
281 class->gc_descr = (gpointer)GC_make_descriptor ((GC_bitmap)&bitmap, class->instance_size / sizeof (gpointer));
284 #endif /* CREATION_SPEEDUP */
288 * @domain: the application domain
289 * @class: the class to initialize
291 * VTables are domain specific because we create domain specific code, and
292 * they contain the domain specific static class data.
295 mono_class_vtable (MonoDomain *domain, MonoClass *class)
298 MonoClassField *field;
300 guint32 cols [MONO_CONSTANT_SIZE];
307 vt = class->cached_vtable;
308 if (vt && vt->domain == domain)
311 mono_domain_lock (domain);
312 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
313 mono_domain_unlock (domain);
318 mono_class_init (class);
320 mono_stats.used_class_count++;
321 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
323 vt = mono_mempool_alloc0 (domain->mp, sizeof (MonoVTable) +
324 class->vtable_size * sizeof (gpointer));
329 mono_class_compute_gc_descriptor (class);
330 vt->gc_descr = class->gc_descr;
333 if (class->class_size) {
335 vt->data = GC_MALLOC (class->class_size + 8);
336 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
337 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
338 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
340 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
343 mono_stats.class_static_data_size += class->class_size + 8;
346 for (i = class->field.first; i < class->field.last; ++i) {
347 field = &class->fields [i - class->field.first];
348 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
350 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
351 MonoClass *fklass = mono_class_from_mono_type (field->type);
352 t = (char*)vt->data + field->offset;
353 if (fklass->valuetype) {
354 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
356 /* it's a pointer type: add check */
357 g_assert (fklass->byval_arg.type == MONO_TYPE_PTR);
358 *t = *(char *)field->data;
362 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
364 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1));
366 g_warning ("constant for field %s not found", field->name);
369 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE);
370 p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]);
371 len = mono_metadata_decode_blob_size (p, &p);
372 t = (char*)vt->data + field->offset;
373 /* should we check that the type matches? */
374 switch (cols [MONO_CONSTANT_TYPE]) {
375 case MONO_TYPE_BOOLEAN:
383 guint16 *val = (guint16*)t;
389 guint32 *val = (guint32*)t;
395 guint64 *val = (guint64*)t;
400 float *val = (float*)t;
405 double *val = (double*)t;
409 case MONO_TYPE_STRING: {
410 gpointer *val = (gpointer*)t;
411 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
412 gunichar2 *copy = g_malloc (len);
414 for (j = 0; j < len/2; j++) {
415 copy [j] = read16 (p);
418 *val = mono_string_new_utf16 (domain, copy, len/2);
421 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
425 case MONO_TYPE_CLASS:
426 /* nothing to do, we malloc0 the data and the value can be 0 only */
429 g_warning ("type 0x%02x should not be in constant table", cols [MONO_CONSTANT_TYPE]);
433 vt->max_interface_id = class->max_interface_id;
435 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
436 sizeof (gpointer) * (class->max_interface_id + 1));
438 /* initialize interface offsets */
439 for (i = 0; i <= class->max_interface_id; ++i) {
440 int slot = class->interface_offsets [i];
442 vt->interface_offsets [i] = &(vt->vtable [slot]);
446 * arch_create_jit_trampoline () can recursively call this function again
447 * because it compiles icall methods right away.
449 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
450 if (!class->cached_vtable)
451 class->cached_vtable = vt;
453 /* initialize vtable */
454 for (i = 0; i < class->vtable_size; ++i) {
457 if ((cm = class->vtable [i]))
458 vt->vtable [i] = arch_create_jit_trampoline (cm);
461 mono_domain_unlock (domain);
463 /* make sure the the parent is initialized */
465 mono_class_vtable (domain, class->parent);
467 mono_runtime_class_init (class);
469 if (class->contextbound)
478 * mono_class_proxy_vtable:
479 * @domain: the application domain
480 * @class: the class to proxy
482 * Creates a vtable for transparent proxies. It is basically
483 * a copy of the real vtable of @class, but all function pointers invoke
484 * the remoting functions, and vtable->klass points to the
485 * transparent proxy class, and not to @class.
488 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
490 MonoVTable *vt, *pvt;
491 int i, j, vtsize, interface_vtsize = 0;
492 MonoClass* iclass = NULL;
495 if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
498 if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
501 class = mono_defaults.marshalbyrefobject_class;
503 method_count = iclass->method.count;
504 for (i = 0; i < iclass->interface_count; i++)
505 method_count += iclass->interfaces[i]->method.count;
507 interface_vtsize = method_count * sizeof (gpointer);
510 vt = mono_class_vtable (domain, class);
511 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
513 mono_stats.class_vtable_size += vtsize + interface_vtsize;
515 pvt = mono_mempool_alloc (domain->mp, vtsize + interface_vtsize);
516 memcpy (pvt, vt, vtsize);
518 pvt->klass = mono_defaults.transparent_proxy_class;
520 /* initialize vtable */
521 for (i = 0; i < class->vtable_size; ++i) {
524 if ((cm = class->vtable [i]))
525 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
528 if (class->flags & TYPE_ATTRIBUTE_ABSTRACT)
530 /* create trampolines for abstract methods */
531 for (k = class; k; k = k->parent) {
532 for (i = 0; i < k->method.count; i++) {
533 int slot = k->methods [i]->slot;
534 if (!pvt->vtable [slot])
535 pvt->vtable [slot] = arch_create_remoting_trampoline (k->methods[i]);
545 pvt->max_interface_id = iclass->max_interface_id;
547 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
548 sizeof (gpointer) * (pvt->max_interface_id + 1));
550 /* Create trampolines for the methods of the interfaces */
551 slot = class->vtable_size;
555 pvt->interface_offsets [interf->interface_id] = &pvt->vtable [slot];
557 for (j = 0; j < interf->method.count; ++j) {
558 MonoMethod *cm = interf->methods [j];
559 pvt->vtable [slot + j] = arch_create_remoting_trampoline (cm);
561 slot += interf->method.count;
562 if (++i < iclass->interface_count) interf = iclass->interfaces[i];
571 pvt->interface_offsets = mono_mempool_alloc0 (domain->mp,
572 sizeof (gpointer) * (pvt->max_interface_id + 1));
574 /* initialize interface offsets */
575 for (i = 0; i <= class->max_interface_id; ++i) {
576 int slot = class->interface_offsets [i];
578 pvt->interface_offsets [i] = &(pvt->vtable [slot]);
582 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
588 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
589 * the instance of a callvirt of method.
592 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
598 klass = mono_object_class (obj);
599 if (klass == mono_defaults.transparent_proxy_class) {
600 klass = ((MonoTransparentProxy *)obj)->klass;
606 if (!is_proxy && ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)))
609 vtable = klass->vtable;
611 /* check method->slot is a valid index: perform isinstance? */
612 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
613 res = vtable [klass->interface_offsets [method->klass->interface_id] + method->slot];
615 res = vtable [method->slot];
620 return mono_marshal_get_remoting_invoke (res);
626 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
628 g_error ("runtime invoke called on uninitialized runtime");
632 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
635 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
637 return default_mono_runtime_invoke (method, obj, params, exc);
641 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
644 gpointer *p = (gpointer*)dest;
651 case MONO_TYPE_BOOLEAN:
654 guint8 *p = (guint8*)dest;
655 *p = *(guint8*)value;
660 case MONO_TYPE_CHAR: {
661 guint16 *p = (guint16*)dest;
662 *p = *(guint16*)value;
665 #if SIZEOF_VOID_P == 4
671 gint32 *p = (gint32*)dest;
672 *p = *(gint32*)value;
675 #if SIZEOF_VOID_P == 8
681 gint64 *p = (gint64*)dest;
682 *p = *(gint64*)value;
686 float *p = (float*)dest;
691 double *p = (double*)dest;
692 *p = *(double*)value;
695 case MONO_TYPE_STRING:
696 case MONO_TYPE_SZARRAY:
697 case MONO_TYPE_CLASS:
698 case MONO_TYPE_OBJECT:
699 case MONO_TYPE_ARRAY:
700 case MONO_TYPE_PTR: {
701 gpointer *p = (gpointer*)dest;
702 *p = deref_pointer? *(gpointer*)value: value;
705 case MONO_TYPE_VALUETYPE:
706 if (type->data.klass->enumtype) {
707 t = type->data.klass->enum_basetype->type;
711 size = mono_class_value_size (type->data.klass, NULL);
712 memcpy (dest, value, size);
716 g_warning ("got type %x", type->type);
717 g_assert_not_reached ();
722 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
726 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
728 dest = (char*)obj + field->offset;
729 set_value (field->type, dest, value, FALSE);
733 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
737 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
739 dest = (char*)vt->data + field->offset;
740 set_value (field->type, dest, value, FALSE);
744 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
748 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
750 src = (char*)obj + field->offset;
751 set_value (field->type, value, src, TRUE);
755 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
759 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
761 src = (char*)vt->data + field->offset;
762 set_value (field->type, value, src, TRUE);
766 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
768 default_mono_runtime_invoke (prop->set, obj, params, exc);
772 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
774 return default_mono_runtime_invoke (prop->get, obj, params, exc);
779 mono_get_delegate_invoke (MonoClass *klass)
786 for (i = 0; i < klass->method.count; ++i) {
787 if (klass->methods [i]->name[0] == 'I' &&
788 !strcmp ("Invoke", klass->methods [i]->name)) {
789 im = klass->methods [i];
799 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
803 im = mono_get_delegate_invoke (delegate->vtable->klass);
806 return mono_runtime_invoke (im, delegate, params, exc);
809 static MonoArray* main_args;
812 mono_runtime_get_main_args (void)
818 * Execute a standard Main() method (argc/argv contains the
819 * executable name). This method also sets the command line argument value
820 * needed by System.Environment.
823 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
827 MonoArray *args = NULL;
828 MonoDomain *domain = mono_domain_get ();
830 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
832 if (!g_path_is_absolute (argv [0])) {
833 gchar *basename = g_path_get_basename (argv [0]);
834 gchar *fullpath = g_build_filename (method->klass->image->assembly->basedir,
838 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, fullpath));
842 mono_array_set (main_args, gpointer, 0, mono_string_new (domain, argv [0]));
845 for (i = 1; i < argc; ++i) {
846 MonoString *arg = mono_string_new (domain, argv [i]);
847 mono_array_set (main_args, gpointer, i, arg);
851 if (method->signature->param_count) {
852 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
853 for (i = 0; i < argc; ++i) {
854 MonoString *arg = mono_string_new (domain, argv [i]);
855 mono_array_set (args, gpointer, i, arg);
858 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
861 mono_assembly_set_main (method->klass->image->assembly);
863 return mono_runtime_exec_main (method, args, exc);
866 /* Used in mono_unhandled_exception */
868 create_unhandled_exception_eventargs (MonoObject *exc)
873 MonoBoolean is_terminating = TRUE;
877 klass = mono_class_from_name (mono_defaults.corlib, "System", "UnhandledExceptionEventArgs");
880 mono_class_init (klass);
882 /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */
883 for (i = 0; i < klass->method.count; ++i) {
884 method = klass->methods [i];
885 if (!strcmp (".ctor", method->name) &&
886 method->signature->param_count == 2 &&
887 method->flags & METHOD_ATTRIBUTE_PUBLIC)
895 args [1] = &is_terminating;
897 obj = mono_object_new (mono_domain_get (), klass);
898 mono_runtime_invoke (method, obj, args, NULL);
904 * We call this function when we detect an unhandled exception
905 * in the default domain.
906 * It invokes the * UnhandledException event in AppDomain or prints
907 * a warning to the console
910 mono_unhandled_exception (MonoObject *exc)
912 MonoDomain *domain = mono_domain_get ();
913 MonoClassField *field;
914 MonoObject *delegate;
916 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
917 "UnhandledException");
920 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
921 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
923 if (domain != mono_root_domain || !delegate) {
924 mono_print_unhandled_exception (exc);
926 MonoObject *e = NULL;
929 pa [0] = domain->domain;
930 pa [1] = create_unhandled_exception_eventargs (exc);
931 mono_runtime_delegate_invoke (delegate, pa, &e);
934 gchar *msg = mono_string_to_utf8 (((MonoException *) e)->message);
935 g_warning ("exception inside UnhandledException handler: %s\n", msg);
943 * Launch a new thread to start all setup that requires managed code
946 * main_func is called back from the thread with main_args as the
947 * parameter. The callback function is expected to start Main()
948 * eventually. This function then waits for all managed threads to
952 mono_runtime_exec_managed_code (MonoDomain *domain,
953 MonoMainThreadFunc main_func,
956 mono_thread_create (domain, main_func, main_args);
958 mono_thread_manage ();
962 * Execute a standard Main() method (args doesn't contain the
966 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
976 domain = mono_object_domain (args);
977 if (!domain->entry_assembly) {
978 domain->entry_assembly = method->klass->image->assembly;
979 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
982 /* FIXME: check signature of method */
983 if (method->signature->ret->type == MONO_TYPE_I4) {
985 res = mono_runtime_invoke (method, NULL, pa, exc);
987 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
991 mono_environment_exitcode_set (rval);
993 mono_runtime_invoke (method, NULL, pa, exc);
997 /* If the return type of Main is void, only
998 * set the exitcode if an exception was thrown
999 * (we don't want to blow away an
1000 * explicitly-set exit code)
1003 mono_environment_exitcode_set (rval);
1011 mono_install_runtime_invoke (MonoInvokeFunc func)
1013 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
1017 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
1020 MonoMethodSignature *sig = method->signature;
1021 gpointer *pa = NULL;
1024 if (NULL != params) {
1025 pa = alloca (sizeof (gpointer) * mono_array_length (params));
1026 for (i = 0; i < mono_array_length (params); i++) {
1027 if (sig->params [i]->byref) {
1031 switch (sig->params [i]->type) {
1034 case MONO_TYPE_BOOLEAN:
1037 case MONO_TYPE_CHAR:
1046 case MONO_TYPE_VALUETYPE:
1047 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
1049 case MONO_TYPE_STRING:
1050 case MONO_TYPE_OBJECT:
1051 case MONO_TYPE_CLASS:
1052 case MONO_TYPE_ARRAY:
1053 case MONO_TYPE_SZARRAY:
1054 if (sig->params [i]->byref)
1055 pa [i] = &(((gpointer *)params->vector)[i]);
1057 pa [i] = (char *)(((gpointer *)params->vector)[i]);
1060 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
1065 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
1067 obj = mono_object_new (mono_domain_get (), method->klass);
1068 if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
1069 method = mono_marshal_get_remoting_invoke (method->klass->vtable [method->slot]);
1072 mono_runtime_invoke (method, obj, pa, exc);
1075 return mono_runtime_invoke (method, obj, pa, exc);
1079 * mono_object_allocate:
1080 * @size: number of bytes to allocate
1082 * This is a very simplistic routine until we have our GC-aware
1085 * Returns: an allocated object of size @size, or NULL on failure.
1088 mono_object_allocate (size_t size)
1091 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
1092 void *o = GC_MALLOC (size);
1094 void *o = calloc (1, size);
1096 mono_stats.new_object_count++;
1104 * Frees the memory used by the object. Debugging purposes
1105 * only, as we will have our GC system.
1108 mono_object_free (MonoObject *o)
1111 g_error ("mono_object_free called with boehm gc.");
1113 MonoClass *c = o->vtable->klass;
1115 memset (o, 0, c->instance_size);
1122 * @klass: the class of the object that we want to create
1124 * Returns: A newly created object whose definition is
1125 * looked up using @klass
1128 mono_object_new (MonoDomain *domain, MonoClass *klass)
1130 MONO_ARCH_SAVE_REGS;
1131 return mono_object_new_specific (mono_class_vtable (domain, klass));
1135 * mono_object_new_specific:
1136 * @vtable: the vtable of the object that we want to create
1138 * Returns: A newly created object with class and domain specified
1142 mono_object_new_specific (MonoVTable *vtable)
1146 MONO_ARCH_SAVE_REGS;
1151 MonoMethod *im = vtable->domain->create_proxy_for_type_method;
1154 MonoClass *klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Activation", "ActivationServices");
1158 mono_class_init (klass);
1160 for (i = 0; i < klass->method.count; ++i) {
1161 if (!strcmp ("CreateProxyForType", klass->methods [i]->name) &&
1162 klass->methods [i]->signature->param_count == 1) {
1163 im = klass->methods [i];
1168 vtable->domain->create_proxy_for_type_method = im;
1171 pa [0] = mono_type_get_object (mono_domain_get (), &vtable->klass->byval_arg);
1173 o = mono_runtime_invoke (im, NULL, pa, NULL);
1174 if (o != NULL) return o;
1177 return mono_object_new_alloc_specific (vtable);
1181 mono_object_new_alloc_specific (MonoVTable *vtable)
1185 #if CREATION_SPEEDUP
1186 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1187 o = GC_GCJ_MALLOC (vtable->klass->instance_size, vtable);
1190 // printf("OBJECT: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1191 o = mono_object_allocate (vtable->klass->instance_size);
1195 o = mono_object_allocate (vtable->klass->instance_size);
1198 if (vtable->klass->has_finalize)
1199 mono_object_register_finalizer (o);
1201 mono_profiler_allocation (o, vtable->klass);
1206 * mono_object_new_from_token:
1207 * @image: Context where the type_token is hosted
1208 * @token: a token of the type that we want to create
1210 * Returns: A newly created object whose definition is
1211 * looked up using @token in the @image image
1214 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
1218 class = mono_class_get (image, token);
1220 return mono_object_new (domain, class);
1225 * mono_object_clone:
1226 * @obj: the object to clone
1228 * Returns: A newly created object who is a shallow copy of @obj
1231 mono_object_clone (MonoObject *obj)
1236 size = obj->vtable->klass->instance_size;
1237 o = mono_object_allocate (size);
1238 mono_profiler_allocation (o, obj->vtable->klass);
1240 memcpy (o, obj, size);
1242 if (obj->vtable->klass->has_finalize)
1243 mono_object_register_finalizer (o);
1249 * @array: the array to clone
1251 * Returns: A newly created array who is a shallow copy of @array
1254 mono_array_clone (MonoArray *array)
1259 MonoClass *klass = array->obj.vtable->klass;
1261 MONO_ARCH_SAVE_REGS;
1263 if (array->bounds == NULL) {
1264 size = mono_array_length (array);
1265 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1266 klass, &size, NULL);
1268 size *= mono_array_element_size (klass);
1269 memcpy (o, array, sizeof (MonoArray) + size);
1274 sizes = alloca (klass->rank * sizeof(guint32) * 2);
1275 size = mono_array_element_size (klass);
1276 for (i = 0; i < klass->rank; ++i) {
1277 sizes [i] = array->bounds [i].length;
1278 size *= array->bounds [i].length;
1279 sizes [i + klass->rank] = array->bounds [i].lower_bound;
1281 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
1282 klass, sizes, sizes + klass->rank);
1283 memcpy (o, array, sizeof(MonoArray) + size);
1289 * mono_array_new_full:
1290 * @domain: domain where the object is created
1291 * @array_class: array class
1292 * @lengths: lengths for each dimension in the array
1293 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
1295 * This routine creates a new array objects with the given dimensions,
1296 * lower bounds and type.
1299 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
1300 guint32 *lengths, guint32 *lower_bounds)
1302 guint32 byte_len, len;
1305 MonoArrayBounds *bounds;
1309 if (!array_class->inited)
1310 mono_class_init (array_class);
1312 byte_len = mono_array_element_size (array_class);
1315 if (array_class->rank == 1 &&
1316 (lower_bounds == NULL || lower_bounds [0] == 0)) {
1321 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
1323 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
1325 for (i = 0; i < array_class->rank; ++i) {
1326 bounds [i].length = lengths [i];
1331 for (i = 0; i < array_class->rank; ++i)
1332 bounds [i].lower_bound = lower_bounds [i];
1337 * Following three lines almost taken from mono_object_new ():
1338 * they need to be kept in sync.
1340 vtable = mono_class_vtable (domain, array_class);
1341 #if CREATION_SPEEDUP
1342 if (vtable->gc_descr != GC_NO_DESCRIPTOR)
1343 o = GC_GCJ_MALLOC (sizeof (MonoArray) + byte_len, vtable);
1345 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1351 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1357 array = (MonoArray*)o;
1359 array->bounds = bounds;
1360 array->max_length = len;
1362 mono_profiler_allocation (o, array_class);
1369 * @domain: domain where the object is created
1370 * @eclass: element class
1371 * @n: number of array elements
1373 * This routine creates a new szarray with @n elements of type @eclass.
1376 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
1380 MONO_ARCH_SAVE_REGS;
1382 ac = mono_array_class_get (&eclass->byval_arg, 1);
1383 g_assert (ac != NULL);
1385 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
1389 * mono_array_new_specific:
1390 * @vtable: a vtable in the appropriate domain for an initialized class
1391 * @n: number of array elements
1393 * This routine is a fast alternative to mono_array_new() for code which
1394 * can be sure about the domain it operates in.
1397 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1403 byte_len = n * mono_array_element_size (vtable->klass);
1404 #if CREATION_SPEEDUP
1405 if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
1406 o = GC_GCJ_MALLOC (sizeof (MonoArray) + byte_len, vtable);
1408 // printf("ARRAY: %s.%s.\n", vtable->klass->name_space, vtable->klass->name);
1409 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1413 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1419 ao = (MonoArray *)o;
1422 mono_profiler_allocation (o, vtable->klass);
1428 * mono_string_new_utf16:
1429 * @text: a pointer to an utf16 string
1430 * @len: the length of the string
1432 * Returns: A newly created string object which contains @text.
1435 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1439 s = mono_string_new_size (domain, len);
1440 g_assert (s != NULL);
1442 memcpy (mono_string_chars (s), text, len * 2);
1448 * mono_string_new_size:
1449 * @text: a pointer to an utf16 string
1450 * @len: the length of the string
1452 * Returns: A newly created string object of @len
1455 mono_string_new_size (MonoDomain *domain, gint32 len)
1460 vtable = mono_class_vtable (domain, mono_defaults.string_class);
1462 #if CREATION_SPEEDUP
1463 s = GC_GCJ_MALLOC (sizeof (MonoString) + ((len + 1) * 2), vtable);
1465 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1466 s->object.vtable = vtable;
1472 mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
1478 * mono_string_new_len:
1479 * @text: a pointer to an utf8 string
1480 * @length: number of bytes in @text to consider
1482 * Returns: A newly created string object which contains @text.
1485 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1487 GError *error = NULL;
1488 MonoString *o = NULL;
1490 glong items_written;
1492 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1495 o = mono_string_new_utf16 (domain, ut, items_written);
1497 g_error_free (error);
1506 * @text: a pointer to an utf8 string
1508 * Returns: A newly created string object which contains @text.
1511 mono_string_new (MonoDomain *domain, const char *text)
1513 GError *error = NULL;
1514 MonoString *o = NULL;
1516 glong items_written;
1521 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1524 o = mono_string_new_utf16 (domain, ut, items_written);
1526 g_error_free (error);
1534 * mono_string_new_wrapper:
1535 * @text: pointer to utf8 characters.
1537 * Helper function to create a string object from @text in the current domain.
1540 mono_string_new_wrapper (const char *text)
1542 MonoDomain *domain = mono_domain_get ();
1545 return mono_string_new (domain, text);
1552 * @class: the class of the value
1553 * @value: a pointer to the unboxed data
1555 * Returns: A newly created object which contains @value.
1558 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1564 g_assert (class->valuetype);
1566 vtable = mono_class_vtable (domain, class);
1567 size = mono_class_instance_size (class);
1568 res = mono_object_allocate (size);
1569 res->vtable = vtable;
1570 mono_profiler_allocation (res, class);
1572 size = size - sizeof (MonoObject);
1574 #if NO_UNALIGNED_ACCESS
1575 memcpy ((char *)res + sizeof (MonoObject), value, size);
1579 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
1582 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
1585 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
1588 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
1591 memcpy ((char *)res + sizeof (MonoObject), value, size);
1594 if (class->has_finalize)
1595 mono_object_register_finalizer (res);
1600 * mono_object_isinst:
1602 * @klass: a pointer to a class
1604 * Returns: @obj if @obj is derived from @klass
1607 mono_object_isinst (MonoObject *obj, MonoClass *klass)
1619 mono_class_init (klass);
1621 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1622 if ((klass->interface_id <= vt->max_interface_id) &&
1623 vt->interface_offsets [klass->interface_id])
1626 if (oklass == mono_defaults.transparent_proxy_class) {
1627 /* fixme: add check for IRemotingTypeInfo */
1628 oklass = ((MonoTransparentProxy *)obj)->klass;
1631 if (oklass->rank == klass->rank &&
1632 (oklass->cast_class->baseval - klass->cast_class->baseval) <=
1633 klass->cast_class->diffval)
1636 } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
1644 MonoDomain *orig_domain;
1650 str_lookup (MonoDomain *domain, gpointer user_data)
1652 LDStrInfo *info = user_data;
1653 if (info->res || domain == info->orig_domain)
1655 mono_domain_lock (domain);
1656 info->res = mono_g_hash_table_lookup (domain->ldstr_table, info->ins);
1657 mono_domain_unlock (domain);
1661 mono_string_is_interned_lookup (MonoString *str, int insert)
1663 MonoGHashTable *ldstr_table;
1666 char *ins = g_malloc (4 + str->length * 2);
1670 /* Encode the length */
1672 mono_metadata_encode_value (2 * str->length, p, &p);
1675 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
1676 bloblen = (p - ins) + 2 * str->length;
1678 * ins is stored in the hash table as a key and needs to have the same
1679 * representation as in the metadata: we swap the character bytes on big
1682 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1685 char *p2 = mono_string_chars (str);
1686 for (i = 0; i < str->length; ++i) {
1693 memcpy (p, mono_string_chars (str), str->length * 2);
1695 domain = ((MonoObject *)str)->vtable->domain;
1696 ldstr_table = domain->ldstr_table;
1697 mono_domain_lock (domain);
1698 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1699 mono_domain_unlock (domain);
1704 mono_g_hash_table_insert (ldstr_table, ins, str);
1705 mono_domain_unlock (domain);
1708 LDStrInfo ldstr_info;
1709 ldstr_info.orig_domain = domain;
1710 ldstr_info.ins = ins;
1711 ldstr_info.res = NULL;
1713 mono_domain_foreach (str_lookup, &ldstr_info);
1714 if (ldstr_info.res) {
1716 * the string was already interned in some other domain:
1717 * intern it in the current one as well.
1719 mono_g_hash_table_insert (ldstr_table, ins, str);
1720 mono_domain_unlock (domain);
1724 mono_domain_unlock (domain);
1730 mono_string_is_interned (MonoString *o)
1732 return mono_string_is_interned_lookup (o, FALSE);
1736 mono_string_intern (MonoString *str)
1738 return mono_string_is_interned_lookup (str, TRUE);
1743 * @domain: the domain where the string will be used.
1744 * @image: a metadata context
1745 * @idx: index into the user string table.
1747 * Implementation for the ldstr opcode.
1750 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
1752 const char *str, *sig;
1756 MONO_ARCH_SAVE_REGS;
1758 if (image->assembly->dynamic)
1759 return mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx);
1761 sig = str = mono_metadata_user_string (image, idx);
1763 mono_domain_lock (domain);
1764 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
1765 mono_domain_unlock (domain);
1769 len2 = mono_metadata_decode_blob_size (str, &str);
1772 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
1773 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1776 guint16 *p2 = (guint16*)mono_string_chars (o);
1777 for (i = 0; i < len2; ++i) {
1778 *p2 = GUINT16_FROM_LE (*p2);
1783 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
1784 mono_domain_unlock (domain);
1790 * mono_string_to_utf8:
1791 * @s: a System.String
1793 * Return the UTF8 representation for @s.
1794 * the resulting buffer nedds to be freed with g_free().
1797 mono_string_to_utf8 (MonoString *s)
1800 GError *error = NULL;
1806 return g_strdup ("");
1808 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
1810 g_warning (error->message);
1816 * mono_string_to_utf16:
1819 * Return an null-terminated array of the utf-16 chars
1820 * contained in @s. The result must be freed with g_free().
1821 * This is a temporary helper until our string implementation
1822 * is reworked to always include the null terminating char.
1825 mono_string_to_utf16 (MonoString *s)
1832 as = g_malloc ((s->length * 2) + 2);
1833 as [(s->length * 2)] = '\0';
1834 as [(s->length * 2) + 1] = '\0';
1837 return (gunichar2 *)(as);
1840 memcpy (as, mono_string_chars(s), s->length * 2);
1841 return (gunichar2 *)(as);
1845 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
1848 mono_string_from_utf16 (gunichar2 *data)
1850 MonoDomain *domain = mono_domain_get ();
1856 while (data [len]) len++;
1858 return mono_string_new_utf16 (domain, data, len);
1862 default_ex_handler (MonoException *ex)
1864 MonoObject *o = (MonoObject*)ex;
1865 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
1868 static MonoExceptionFunc ex_handler = default_ex_handler;
1871 mono_install_handler (MonoExceptionFunc func)
1873 ex_handler = func? func: default_ex_handler;
1877 * mono_raise_exception:
1878 * @ex: exception object
1880 * Signal the runtime that the exception @ex has been raised in unmanaged code.
1883 mono_raise_exception (MonoException *ex)
1889 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
1891 MonoWaitHandle *res;
1893 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
1895 res->handle = handle;
1901 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
1903 MonoAsyncResult *res;
1905 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
1908 res->async_state = state;
1909 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
1910 res->sync_completed = FALSE;
1911 res->completed = FALSE;
1917 mono_message_init (MonoDomain *domain,
1918 MonoMethodMessage *this,
1919 MonoReflectionMethod *method,
1920 MonoArray *out_args)
1922 MonoMethodSignature *sig = method->method->signature;
1928 this->method = method;
1930 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
1931 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
1933 names = g_new (char *, sig->param_count);
1934 mono_method_get_param_names (method->method, (const char **) names);
1935 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
1937 for (i = 0; i < sig->param_count; i++) {
1938 name = mono_string_new (domain, names [i]);
1939 mono_array_set (this->names, gpointer, i, name);
1944 for (i = 0, j = 0; i < sig->param_count; i++) {
1946 if (sig->params [i]->byref) {
1948 gpointer arg = mono_array_get (out_args, gpointer, j);
1949 mono_array_set (this->args, gpointer, i, arg);
1953 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
1959 mono_array_set (this->arg_types, guint8, i, arg_type);
1964 * mono_remoting_invoke:
1965 * @real_proxy: pointer to a RealProxy object
1966 * @msg: The MonoMethodMessage to execute
1967 * @exc: used to store exceptions
1968 * @out_args: used to store output arguments
1970 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
1971 * IMessage interface and it is not trivial to extract results from there. So
1972 * we call an helper method PrivateInvoke instead of calling
1973 * RealProxy::Invoke() directly.
1975 * Returns: the result object.
1978 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
1979 MonoObject **exc, MonoArray **out_args)
1981 MonoMethod *im = real_proxy->vtable->domain->private_invoke_method;
1984 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
1990 klass = mono_defaults.real_proxy_class;
1992 for (i = 0; i < klass->method.count; ++i) {
1993 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
1994 klass->methods [i]->signature->param_count == 4) {
1995 im = klass->methods [i];
2001 real_proxy->vtable->domain->private_invoke_method = im;
2004 pa [0] = real_proxy;
2009 return mono_runtime_invoke (im, NULL, pa, exc);
2013 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
2014 MonoObject **exc, MonoArray **out_args)
2018 MonoMethodSignature *sig;
2019 int i, j, outarg_count = 0;
2021 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2023 MonoTransparentProxy* tp = (MonoTransparentProxy *)target;
2024 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2025 target = tp->rp->unwrapped_server;
2027 return mono_remoting_invoke ((MonoObject *)tp->rp, msg, exc, out_args);
2031 domain = mono_domain_get ();
2032 method = msg->method->method;
2033 sig = method->signature;
2035 for (i = 0; i < sig->param_count; i++) {
2036 if (sig->params [i]->byref)
2040 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2043 for (i = 0, j = 0; i < sig->param_count; i++) {
2044 if (sig->params [i]->byref) {
2046 arg = mono_array_get (msg->args, gpointer, i);
2047 mono_array_set (*out_args, gpointer, j, arg);
2052 return mono_runtime_invoke_array (method, target, msg->args, exc);
2056 mono_print_unhandled_exception (MonoObject *exc)
2058 char *message = (char *) "";
2062 gboolean free_message = FALSE;
2065 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
2066 klass = exc->vtable->klass;
2068 while (klass && method == NULL) {
2069 for (i = 0; i < klass->method.count; ++i) {
2070 method = klass->methods [i];
2071 if (!strcmp ("ToString", method->name) &&
2072 method->signature->param_count == 0 &&
2073 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
2074 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
2081 klass = klass->parent;
2086 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
2088 message = mono_string_to_utf8 (str);
2089 free_message = TRUE;
2094 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
2095 * exc->vtable->klass->name, message);
2097 g_printerr ("\nUnhandled Exception: %s\n", message);
2104 * mono_delegate_ctor:
2105 * @this: pointer to an uninitialized delegate object
2106 * @target: target object
2107 * @addr: pointer to native code
2109 * This is used to initialize a delegate. We also insert the method_info if
2110 * we find the info with mono_jit_info_table_find().
2113 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
2115 MonoDomain *domain = mono_domain_get ();
2116 MonoDelegate *delegate = (MonoDelegate *)this;
2117 MonoMethod *method = NULL;
2124 class = this->vtable->klass;
2126 if ((ji = mono_jit_info_table_find (domain, addr))) {
2127 method = ji->method;
2128 delegate->method_info = mono_method_get_object (domain, method, NULL);
2131 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
2133 method = mono_marshal_get_remoting_invoke (method);
2134 delegate->method_ptr = mono_compile_method (method);
2135 delegate->target = target;
2137 delegate->method_ptr = addr;
2138 delegate->target = target;
2143 * mono_method_call_message_new:
2145 * Translates arguments pointers into a Message.
2148 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
2149 MonoDelegate **cb, MonoObject **state)
2151 MonoDomain *domain = mono_domain_get ();
2152 MonoMethodSignature *sig = method->signature;
2153 MonoMethodMessage *msg;
2156 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2159 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
2160 count = sig->param_count - 2;
2162 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
2163 count = sig->param_count;
2166 for (i = 0; i < count; i++) {
2171 if (sig->params [i]->byref)
2172 vpos = *((gpointer *)params [i]);
2176 type = sig->params [i]->type;
2177 class = mono_class_from_mono_type (sig->params [i]);
2179 if (class->valuetype)
2180 arg = mono_value_box (domain, class, vpos);
2182 arg = *((MonoObject **)vpos);
2184 mono_array_set (msg->args, gpointer, i, arg);
2188 *cb = *((MonoDelegate **)params [i]);
2190 *state = *((MonoObject **)params [i]);
2197 * mono_method_return_message_restore:
2199 * Restore results from message based processing back to arguments pointers
2202 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
2204 MonoMethodSignature *sig = method->signature;
2205 int i, j, type, size;
2207 for (i = 0, j = 0; i < sig->param_count; i++) {
2208 MonoType *pt = sig->params [i];
2210 size = mono_type_stack_size (pt, NULL);
2213 char *arg = mono_array_get (out_args, gpointer, j);
2217 case MONO_TYPE_VOID:
2218 g_assert_not_reached ();
2222 case MONO_TYPE_BOOLEAN:
2225 case MONO_TYPE_CHAR:
2232 case MONO_TYPE_VALUETYPE: {
2233 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
2236 case MONO_TYPE_STRING:
2237 case MONO_TYPE_CLASS:
2238 case MONO_TYPE_ARRAY:
2239 case MONO_TYPE_SZARRAY:
2240 **((MonoObject ***)params [i]) = (MonoObject *)arg;
2243 g_assert_not_reached ();
2252 * mono_load_remote_field:
2253 * @this: pointer to an object
2254 * @klass: klass of the object containing @field
2255 * @field: the field to load
2256 * @res: a storage to store the result
2258 * This method is called by the runtime on attempts to load fields of
2259 * transparent proxy objects. @this points to such TP, @klass is the class of
2260 * the object containing @field. @res is a storage location which can be
2261 * used to store the result.
2263 * Returns: an address pointing to the value of field.
2266 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
2268 static MonoMethod *getter = NULL;
2269 MonoDomain *domain = mono_domain_get ();
2270 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2271 MonoClass *field_class;
2272 MonoMethodMessage *msg;
2273 MonoArray *out_args;
2277 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2282 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2283 mono_field_get_value (tp->rp->unwrapped_server, field, res);
2290 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2291 MonoMethod *cm = mono_defaults.object_class->methods [i];
2293 if (!strcmp (cm->name, "FieldGetter")) {
2301 field_class = mono_class_from_mono_type (field->type);
2303 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2304 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2305 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2307 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2308 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2310 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2312 *res = mono_array_get (out_args, MonoObject *, 0);
2314 if (field_class->valuetype) {
2315 return ((char *)*res) + sizeof (MonoObject);
2321 mono_load_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field)
2323 static MonoMethod *getter = NULL;
2324 MonoDomain *domain = mono_domain_get ();
2325 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2326 MonoClass *field_class;
2327 MonoMethodMessage *msg;
2328 MonoArray *out_args;
2329 MonoObject *exc, *res;
2331 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2333 field_class = mono_class_from_mono_type (field->type);
2335 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2337 if (field_class->valuetype) {
2338 res = mono_object_new (domain, field_class);
2339 val = ((gchar *) res) + sizeof (MonoObject);
2343 mono_field_get_value (tp->rp->unwrapped_server, field, val);
2350 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2351 MonoMethod *cm = mono_defaults.object_class->methods [i];
2353 if (!strcmp (cm->name, "FieldGetter")) {
2361 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2362 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2363 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
2365 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2366 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2368 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2370 res = mono_array_get (out_args, MonoObject *, 0);
2376 * mono_store_remote_field:
2377 * @this: pointer to an object
2378 * @klass: klass of the object containing @field
2379 * @field: the field to load
2380 * @val: the value/object to store
2382 * This method is called by the runtime on attempts to store fields of
2383 * transparent proxy objects. @this points to such TP, @klass is the class of
2384 * the object containing @field. @val is the new value to store in @field.
2387 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
2389 static MonoMethod *setter = NULL;
2390 MonoDomain *domain = mono_domain_get ();
2391 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2392 MonoClass *field_class;
2393 MonoMethodMessage *msg;
2394 MonoArray *out_args;
2398 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2400 field_class = mono_class_from_mono_type (field->type);
2402 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2403 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, val);
2404 else mono_field_set_value (tp->rp->unwrapped_server, field, *((MonoObject **)val));
2411 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2412 MonoMethod *cm = mono_defaults.object_class->methods [i];
2414 if (!strcmp (cm->name, "FieldSetter")) {
2422 if (field_class->valuetype)
2423 arg = mono_value_box (domain, field_class, val);
2425 arg = *((MonoObject **)val);
2428 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2429 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2431 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2432 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2433 mono_array_set (msg->args, gpointer, 2, arg);
2435 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);
2439 mono_store_remote_field_new (MonoObject *this, MonoClass *klass, MonoClassField *field, MonoObject *arg)
2441 static MonoMethod *setter = NULL;
2442 MonoDomain *domain = mono_domain_get ();
2443 MonoTransparentProxy *tp = (MonoTransparentProxy *) this;
2444 MonoClass *field_class;
2445 MonoMethodMessage *msg;
2446 MonoArray *out_args;
2449 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
2451 field_class = mono_class_from_mono_type (field->type);
2453 if (tp->klass->contextbound && tp->rp->context == (MonoObject *) mono_context_get ()) {
2454 if (field_class->valuetype) mono_field_set_value (tp->rp->unwrapped_server, field, ((gchar *) arg) + sizeof (MonoObject));
2455 else mono_field_set_value (tp->rp->unwrapped_server, field, &arg);
2462 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
2463 MonoMethod *cm = mono_defaults.object_class->methods [i];
2465 if (!strcmp (cm->name, "FieldSetter")) {
2473 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
2474 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
2476 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
2477 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
2478 mono_array_set (msg->args, gpointer, 2, arg);
2480 mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args);