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.h>
20 #include <mono/metadata/appdomain.h>
21 #include <mono/metadata/assembly.h>
22 #include <mono/metadata/threadpool.h>
23 #include "mono/metadata/debug-helpers.h"
29 mono_runtime_object_init (MonoObject *this)
32 MonoMethod *method = NULL;
33 MonoClass *klass = this->vtable->klass;
35 for (i = 0; i < klass->method.count; ++i) {
36 if (!strcmp (".ctor", klass->methods [i]->name) &&
37 klass->methods [i]->signature->param_count == 0) {
38 method = klass->methods [i];
45 mono_runtime_invoke (method, this, NULL, NULL);
50 * @klass: klass that needs to be initialized
52 * This routine calls the class constructor for @class.
55 mono_runtime_class_init (MonoClass *klass)
59 for (i = 0; i < klass->method.count; ++i) {
60 MonoMethod *method = klass->methods [i];
61 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
62 (strcmp (".cctor", method->name) == 0)) {
63 mono_runtime_invoke (method, NULL, NULL, NULL);
68 /* No class constructor found */
72 default_trampoline (MonoMethod *method)
78 default_remoting_trampoline (MonoMethod *method)
80 g_error ("remoting not installed");
84 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
85 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
88 mono_install_trampoline (MonoTrampoline func)
90 arch_create_jit_trampoline = func? func: default_trampoline;
94 mono_install_remoting_trampoline (MonoTrampoline func)
96 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
99 static MonoCompileFunc default_mono_compile_method = NULL;
102 mono_install_compile_method (MonoCompileFunc func)
104 default_mono_compile_method = func;
108 mono_compile_method (MonoMethod *method)
110 if (!default_mono_compile_method) {
111 g_error ("compile method called on uninitialized runtime");
114 return default_mono_compile_method (method);
118 #if 0 && HAVE_BOEHM_GC
120 vtable_finalizer (void *obj, void *data) {
121 g_print ("%s finalized (%p)\n", (char*)data, obj);
127 * @domain: the application domain
128 * @class: the class to initialize
130 * VTables are domain specific because we create domain specific code, and
131 * they contain the domain specific static class data.
134 mono_class_vtable (MonoDomain *domain, MonoClass *class)
138 MonoClassField *field;
140 guint32 cols [MONO_CONSTANT_SIZE];
147 /* can interfaces have static fields? */
148 if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
149 g_assert_not_reached ();
151 mono_domain_lock (domain);
152 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
153 mono_domain_unlock (domain);
158 mono_class_init (class);
160 mono_stats.used_class_count++;
161 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
163 vt = mono_mempool_alloc0 (domain->mp, sizeof (MonoVTable) +
164 class->vtable_size * sizeof (gpointer));
168 if (class->class_size) {
170 vt->data = GC_malloc (class->class_size + 8);
171 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
172 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
173 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
175 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
178 mono_stats.class_static_data_size += class->class_size + 8;
181 for (i = class->field.first; i < class->field.last; ++i) {
182 field = &class->fields [i - class->field.first];
183 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
185 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
186 MonoClass *fklass = mono_class_from_mono_type (field->type);
187 t = (char*)vt->data + field->offset;
188 g_assert (fklass->valuetype);
189 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
192 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
194 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1));
196 g_warning ("constant for field %s not found", field->name);
199 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE);
200 p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]);
201 len = mono_metadata_decode_blob_size (p, &p);
202 t = (char*)vt->data + field->offset;
203 /* should we check that the type matches? */
204 switch (cols [MONO_CONSTANT_TYPE]) {
205 case MONO_TYPE_BOOLEAN:
213 guint16 *val = (guint16*)t;
219 guint32 *val = (guint32*)t;
225 guint64 *val = (guint64*)t;
230 float *val = (float*)t;
235 double *val = (double*)t;
239 case MONO_TYPE_STRING: {
240 /*gpointer *val = (gpointer*)t;
241 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);*/
244 case MONO_TYPE_CLASS:
245 /* nothing to do, we malloc0 the data and the value can be 0 only */
248 g_warning ("type 0x%02x should not be in constant table", cols [MONO_CONSTANT_TYPE]);
252 vt->max_interface_id = class->max_interface_id;
254 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
255 sizeof (gpointer) * (class->max_interface_id + 1));
257 /* initialize interface offsets */
258 for (k = class; k ; k = k->parent) {
259 for (i = 0; i < k->interface_count; i++) {
261 MonoClass *ic = k->interfaces [i];
262 slot = class->interface_offsets [ic->interface_id];
263 vt->interface_offsets [ic->interface_id] = &vt->vtable [slot];
267 /* initialize vtable */
268 for (i = 0; i < class->vtable_size; ++i) {
271 if ((cm = class->vtable [i]))
272 vt->vtable [i] = arch_create_jit_trampoline (cm);
275 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
276 mono_domain_unlock (domain);
278 /* make sure the the parent is initialized */
280 mono_class_vtable (domain, class->parent);
282 mono_runtime_class_init (class);
288 * mono_class_proxy_vtable:
289 * @domain: the application domain
290 * @class: the class to proxy
292 * Creates a vtable for transparent proxies. It is basically
293 * a copy of the real vtable of @class, but all function pointers invoke
294 * the remoting functions, and vtable->klass points to the
295 * transparent proxy class, and not to @class.
298 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
300 MonoVTable *vt, *pvt;
303 if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
306 vt = mono_class_vtable (domain, class);
307 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
309 mono_stats.class_vtable_size += vtsize;
311 pvt = mono_mempool_alloc (domain->mp, vtsize);
312 memcpy (pvt, vt, vtsize);
314 pvt->klass = mono_defaults.transparent_proxy_class;
316 /* initialize vtable */
317 for (i = 0; i < class->vtable_size; ++i) {
320 if ((cm = class->vtable [i]))
321 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
324 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
329 static MonoInvokeFunc default_mono_runtime_invoke = NULL;
332 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
334 if (!default_mono_runtime_invoke) {
335 g_error ("runtime invoke called on uninitialized runtime");
339 return default_mono_runtime_invoke (method, obj, params, exc);
343 mono_get_delegate_invoke (MonoClass *klass)
350 for (i = 0; i < klass->method.count; ++i) {
351 if (klass->methods [i]->name[0] == 'I' &&
352 !strcmp ("Invoke", klass->methods [i]->name)) {
353 im = klass->methods [i];
363 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
367 im = mono_get_delegate_invoke (delegate->vtable->klass);
370 return mono_runtime_invoke (im, delegate, params, exc);
373 static MonoArray* main_args;
376 mono_runtime_get_main_args (void)
382 * Execute a standard Main() method (argc/argv contains the
383 * executable name). This method also sets the command line argument value
384 * needed by System.Environment.
387 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
391 MonoArray *args = NULL;
392 MonoDomain *domain = mono_domain_get ();
394 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
395 for (i = 0; i < argc; ++i) {
396 MonoString *arg = mono_string_new (domain, argv [i]);
397 mono_array_set (main_args, gpointer, i, arg);
401 if (method->signature->param_count) {
402 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
403 for (i = 0; i < argc; ++i) {
404 MonoString *arg = mono_string_new (domain, argv [i]);
405 mono_array_set (args, gpointer, i, arg);
409 mono_assembly_set_main (method->klass->image->assembly);
411 return mono_runtime_exec_main (method, args, exc);
415 * We call this function when we dectect an unhandled exception. It invokes the
416 * UnhandledException event in AppDomain or print a warning to the console
419 mono_unhandled_exception (MonoObject *exc)
421 MonoDomain *domain = mono_domain_get ();
422 MonoClassField *field;
423 MonoObject *delegate;
425 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
426 "UnhandledException");
429 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
432 mono_print_unhandled_exception (exc);
434 MonoObject *e = NULL;
437 /* fixme: pass useful arguments */
440 mono_runtime_delegate_invoke (delegate, pa, &e);
443 g_warning ("exception inside UnhandledException handler!");
448 * Execute a standard Main() method (args doesn't contain the
452 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
459 /* FIXME: check signature of method */
460 if (method->signature->ret->type == MONO_TYPE_I4) {
462 res = mono_runtime_invoke (method, NULL, pa, exc);
464 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
468 mono_runtime_invoke (method, NULL, pa, exc);
479 mono_install_runtime_invoke (MonoInvokeFunc func)
481 default_mono_runtime_invoke = func;
485 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
488 MonoMethodSignature *sig = method->signature;
492 if (NULL != params) {
493 pa = alloca (sizeof (gpointer) * mono_array_length (params));
494 for (i = 0; i < mono_array_length (params); i++) {
495 if (sig->params [i]->byref) {
499 switch (sig->params [i]->type) {
502 case MONO_TYPE_BOOLEAN:
512 case MONO_TYPE_VALUETYPE:
513 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
515 case MONO_TYPE_STRING:
516 case MONO_TYPE_OBJECT:
517 case MONO_TYPE_CLASS:
518 case MONO_TYPE_SZARRAY:
519 pa [i] = (char *)(((gpointer *)params->vector)[i]);
522 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
527 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
528 obj = mono_object_new (mono_domain_get (), method->klass);
529 mono_runtime_invoke (method, obj, pa, exc);
532 return mono_runtime_invoke (method, obj, pa, exc);
536 * mono_object_allocate:
537 * @size: number of bytes to allocate
539 * This is a very simplistic routine until we have our GC-aware
542 * Returns: an allocated object of size @size, or NULL on failure.
545 mono_object_allocate (size_t size)
548 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
549 void *o = GC_malloc (size);
551 void *o = calloc (1, size);
560 * Frees the memory used by the object. Debugging purposes
561 * only, as we will have our GC system.
564 mono_object_free (MonoObject *o)
567 g_error ("mono_object_free called with boehm gc.");
569 MonoClass *c = o->vtable->klass;
571 memset (o, 0, c->instance_size);
578 * @klass: the class of the object that we want to create
580 * Returns: A newly created object whose definition is
581 * looked up using @klass
584 mono_object_new (MonoDomain *domain, MonoClass *klass)
586 return mono_object_new_specific (mono_class_vtable (domain, klass));
590 * mono_object_new_specific:
591 * @vtable: the vtable of the object that we want to create
593 * Returns: A newly created object with class and domain specified
597 mono_object_new_specific (MonoVTable *vtable)
601 mono_stats.new_object_count++;
603 o = mono_object_allocate (vtable->klass->instance_size);
605 if (vtable->klass->has_finalize)
606 mono_object_register_finalizer (o);
612 * mono_object_new_from_token:
613 * @image: Context where the type_token is hosted
614 * @token: a token of the type that we want to create
616 * Returns: A newly created object whose definition is
617 * looked up using @token in the @image image
620 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
624 class = mono_class_get (image, token);
626 return mono_object_new (domain, class);
632 * @obj: the object to clone
634 * Returns: A newly created object who is a shallow copy of @obj
637 mono_object_clone (MonoObject *obj)
642 size = obj->vtable->klass->instance_size;
643 o = mono_object_allocate (size);
645 memcpy (o, obj, size);
647 if (obj->vtable->klass->has_finalize)
648 mono_object_register_finalizer (o);
654 * @array: the array to clone
656 * Returns: A newly created array who is a shallow copy of @array
659 mono_array_clone (MonoArray *array)
664 MonoClass *klass = array->obj.vtable->klass;
666 if (array->bounds == NULL) {
667 size = mono_array_length (array);
668 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
671 size *= mono_array_element_size (klass);
672 memcpy (o, array, sizeof (MonoArray) + size);
677 sizes = alloca (klass->rank * sizeof(guint32) * 2);
678 size = mono_array_element_size (klass);
679 for (i = 0; i < klass->rank; ++i) {
680 sizes [i] = array->bounds [i].length;
681 size *= array->bounds [i].length;
682 sizes [i + klass->rank] = array->bounds [i].lower_bound;
684 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
685 klass, sizes, sizes + klass->rank);
686 memcpy (o, array, sizeof(MonoArray) + size);
692 * mono_array_new_full:
693 * @domain: domain where the object is created
694 * @array_class: array class
695 * @lengths: lengths for each dimension in the array
696 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
698 * This routine creates a new array objects with the given dimensions,
699 * lower bounds and type.
702 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
703 guint32 *lengths, guint32 *lower_bounds)
705 guint32 byte_len, len;
708 MonoArrayBounds *bounds;
711 if (!array_class->inited)
712 mono_class_init (array_class);
714 byte_len = mono_array_element_size (array_class);
717 if (array_class->rank == 1 &&
718 (lower_bounds == NULL || lower_bounds [0] == 0)) {
723 bounds = GC_malloc (sizeof (MonoArrayBounds) * array_class->rank);
725 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
727 for (i = 0; i < array_class->rank; ++i) {
728 bounds [i].length = lengths [i];
733 for (i = 0; i < array_class->rank; ++i)
734 bounds [i].lower_bound = lower_bounds [i];
739 * Following three lines almost taken from mono_object_new ():
740 * they need to be kept in sync.
742 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
745 o->vtable = mono_class_vtable (domain, array_class);
747 array = (MonoArray*)o;
749 array->bounds = bounds;
750 array->max_length = len;
757 * @domain: domain where the object is created
758 * @eclass: element class
759 * @n: number of array elements
761 * This routine creates a new szarray with @n elements of type @eclass.
764 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
768 ac = mono_array_class_get (&eclass->byval_arg, 1);
769 g_assert (ac != NULL);
771 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
775 * mono_array_new_specific:
776 * @vtable: a vtable in the appropriate domain for an initialized class
777 * @n: number of array elements
779 * This routine is a fast alternative to mono_array_new() for code which
780 * can be sure about the domain it operates in.
783 mono_array_new_specific (MonoVTable *vtable, guint32 n)
789 byte_len = n * mono_array_element_size (vtable->klass);
790 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
803 * mono_string_new_utf16:
804 * @text: a pointer to an utf16 string
805 * @len: the length of the string
807 * Returns: A newly created string object which contains @text.
810 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
814 s = mono_string_new_size (domain, len);
815 g_assert (s != NULL);
817 memcpy (mono_string_chars (s), text, len * 2);
823 * mono_string_new_size:
824 * @text: a pointer to an utf16 string
825 * @len: the length of the string
827 * Returns: A newly created string object of @len
830 mono_string_new_size (MonoDomain *domain, gint32 len)
835 * enable to get a good speedup: we still need to figure out
836 * how the sync structure is freed.
839 s = GC_malloc_atomic (sizeof (MonoString) + ((len + 1) * 2));
840 s->object.synchronisation = 0;
841 mono_string_chars (s) [len] = 0;
843 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
848 s->object.vtable = mono_class_vtable (domain, mono_defaults.string_class);
855 * mono_string_new_len:
856 * @text: a pointer to an utf8 string
857 * @length: number of bytes in @text to consider
859 * Returns: A newly created string object which contains @text.
862 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
864 GError *error = NULL;
865 MonoString *o = NULL;
870 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
873 o = mono_string_new_utf16 (domain, ut, items_written);
875 g_error_free (error);
884 * @text: a pointer to an utf8 string
886 * Returns: A newly created string object which contains @text.
889 mono_string_new (MonoDomain *domain, const char *text)
891 GError *error = NULL;
892 MonoString *o = NULL;
899 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
902 o = mono_string_new_utf16 (domain, ut, items_written);
904 g_error_free (error);
912 * mono_string_new_wrapper:
913 * @text: pointer to utf8 characters.
915 * Helper function to create a string object from @text in the current domain.
918 mono_string_new_wrapper (const char *text)
920 MonoDomain *domain = mono_domain_get ();
922 return mono_string_new (domain, text);
927 * @class: the class of the value
928 * @value: a pointer to the unboxed data
930 * Returns: A newly created object which contains @value.
933 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
938 g_assert (class->valuetype);
940 size = mono_class_instance_size (class);
941 res = mono_object_allocate (size);
942 res->vtable = mono_class_vtable (domain, class);
944 size = size - sizeof (MonoObject);
946 #if NO_UNALIGNED_ACCESS
947 memcpy ((char *)res + sizeof (MonoObject), value, size);
951 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
954 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
957 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
960 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
963 memcpy ((char *)res + sizeof (MonoObject), value, size);
966 if (class->has_finalize)
967 mono_object_register_finalizer (res);
972 * mono_object_isinst:
974 * @klass: a pointer to a class
976 * Returns: @obj if @obj is derived from @klass
979 mono_object_isinst (MonoObject *obj, MonoClass *klass)
991 mono_class_init (klass);
993 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
994 if ((klass->interface_id <= oklass->max_interface_id) &&
995 vt->interface_offsets [klass->interface_id])
998 if (oklass == mono_defaults.transparent_proxy_class) {
999 /* fixme: add check for IRemotingTypeInfo */
1000 oklass = ((MonoTransparentProxy *)obj)->klass;
1003 if (oklass->rank == klass->rank &&
1004 (oklass->element_class->baseval - klass->element_class->baseval) <=
1005 klass->element_class->diffval)
1008 } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
1016 mono_string_is_interned_lookup (MonoString *str, int insert)
1018 MonoGHashTable *ldstr_table;
1021 char *ins = g_malloc (4 + str->length * 2);
1025 /* Encode the length */
1027 mono_metadata_encode_value (2 * str->length, p, &p);
1030 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
1031 bloblen = (p - ins) + 2 * str->length;
1033 * ins is stored in the hash table as a key and needs to have the same
1034 * representation as in the metadata: we swap the character bytes on big
1037 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1040 char *p2 = mono_string_chars (str);
1041 for (i = 0; i < str->length; ++i) {
1048 memcpy (p, mono_string_chars (str), str->length * 2);
1050 domain = ((MonoObject *)str)->vtable->domain;
1051 ldstr_table = domain->ldstr_table;
1052 mono_domain_lock (domain);
1053 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1054 mono_domain_unlock (domain);
1059 mono_g_hash_table_insert (ldstr_table, ins, str);
1060 mono_domain_unlock (domain);
1063 mono_domain_unlock (domain);
1069 mono_string_is_interned (MonoString *o)
1071 return mono_string_is_interned_lookup (o, FALSE);
1075 mono_string_intern (MonoString *str)
1077 return mono_string_is_interned_lookup (str, TRUE);
1082 * @domain: the domain where the string will be used.
1083 * @image: a metadata context
1084 * @idx: index into the user string table.
1086 * Implementation for the ldstr opcode.
1089 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
1091 const char *str, *sig;
1095 sig = str = mono_metadata_user_string (image, idx);
1097 mono_domain_lock (domain);
1098 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
1099 mono_domain_unlock (domain);
1103 len2 = mono_metadata_decode_blob_size (str, &str);
1106 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
1107 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1110 guint16 *p2 = (guint16*)mono_string_chars (o);
1111 for (i = 0; i < len2; ++i) {
1112 *p2 = GUINT16_FROM_LE (*p2);
1117 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
1118 mono_domain_unlock (domain);
1124 * mono_string_to_utf8:
1125 * @s: a System.String
1127 * Return the UTF8 representation for @s.
1128 * the resulting buffer nedds to be freed with g_free().
1131 mono_string_to_utf8 (MonoString *s)
1134 GError *error = NULL;
1140 return g_strdup ("");
1142 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
1144 g_warning (error->message);
1150 * mono_string_to_utf16:
1153 * Return an null-terminated array of the utf-16 chars
1154 * contained in @s. The result must be freed with g_free().
1155 * This is a temporary helper until our string implementation
1156 * is reworked to always include the null terminating char.
1159 mono_string_to_utf16 (MonoString *s)
1166 as = g_malloc ((s->length * 2) + 2);
1167 as [(s->length * 2)] = '\0';
1168 as [(s->length * 2) + 1] = '\0';
1171 return (gunichar2 *)(as);
1174 memcpy (as, mono_string_chars(s), s->length * 2);
1175 return (gunichar2 *)(as);
1179 default_ex_handler (MonoException *ex)
1181 MonoObject *o = (MonoObject*)ex;
1182 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
1185 static MonoExceptionFunc ex_handler = default_ex_handler;
1188 mono_install_handler (MonoExceptionFunc func)
1190 ex_handler = func? func: default_ex_handler;
1194 * mono_raise_exception:
1195 * @ex: exception object
1197 * Signal the runtime that the exception @ex has been raised in unmanaged code.
1200 mono_raise_exception (MonoException *ex)
1206 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
1208 MonoWaitHandle *res;
1210 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
1212 res->handle = handle;
1218 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
1220 MonoAsyncResult *res;
1222 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
1225 res->async_state = state;
1226 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
1227 res->sync_completed = FALSE;
1228 res->completed = FALSE;
1234 mono_message_init (MonoDomain *domain,
1235 MonoMethodMessage *this,
1236 MonoReflectionMethod *method,
1237 MonoArray *out_args)
1239 MonoMethodSignature *sig = method->method->signature;
1245 this->method = method;
1247 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
1248 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
1250 names = g_new (char *, sig->param_count);
1251 mono_method_get_param_names (method->method, (const char **) names);
1252 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
1254 for (i = 0; i < sig->param_count; i++) {
1255 name = mono_string_new (domain, names [i]);
1256 mono_array_set (this->names, gpointer, i, name);
1261 for (i = 0, j = 0; i < sig->param_count; i++) {
1263 if (sig->params [i]->byref) {
1265 gpointer arg = mono_array_get (out_args, gpointer, j);
1266 mono_array_set (this->args, gpointer, i, arg);
1270 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
1276 mono_array_set (this->arg_types, guint8, i, arg_type);
1281 * mono_remoting_invoke:
1282 * @real_proxy: pointer to a RealProxy object
1283 * @msg: The MonoMethodMessage to execute
1284 * @exc: used to store exceptions
1285 * @out_args: used to store output arguments
1287 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
1288 * IMessage interface and it is not trivial to extract results from there. So
1289 * we call an helper method PrivateInvoke instead of calling
1290 * RealProxy::Invoke() directly.
1292 * Returns: the result object.
1295 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
1296 MonoObject **exc, MonoArray **out_args)
1298 static MonoMethod *im = NULL;
1301 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
1303 /* FIXME: make this domain dependent */
1308 klass = mono_defaults.real_proxy_class;
1310 for (i = 0; i < klass->method.count; ++i) {
1311 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
1312 klass->methods [i]->signature->param_count == 4) {
1313 im = klass->methods [i];
1321 pa [0] = real_proxy;
1326 return mono_runtime_invoke (im, NULL, pa, exc);
1330 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
1331 MonoObject **exc, MonoArray **out_args)
1333 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1335 return mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)target)->rp,
1336 msg, exc, out_args);
1339 MonoDomain *domain = mono_domain_get ();
1340 MonoMethod *method = msg->method->method;
1341 MonoMethodSignature *sig = method->signature;
1342 int i, j, outarg_count = 0;
1344 for (i = 0; i < sig->param_count; i++) {
1345 if (sig->params [i]->byref)
1349 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
1352 for (i = 0, j = 0; i < sig->param_count; i++) {
1353 if (sig->params [i]->byref) {
1355 arg = mono_array_get (msg->args, gpointer, i);
1356 mono_array_set (*out_args, gpointer, j, arg);
1361 return mono_runtime_invoke_array (method, target, msg->args, exc);
1366 mono_print_unhandled_exception (MonoObject *exc)
1368 char *message = g_strdup ("");
1369 char *trace = g_strdup ("");
1372 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
1373 if ((str = ((MonoException *)exc)->message))
1374 message = mono_string_to_utf8 (str);
1375 if ((str = ((MonoException *)exc)->stack_trace))
1376 trace = mono_string_to_utf8 (str);
1379 g_warning ("unhandled exception %s.%s: \"%s\"", exc->vtable->klass->name_space,
1380 exc->vtable->klass->name, message);
1392 * mono_delegate_ctor:
1393 * @this: pointer to an uninitialized delegate object
1394 * @target: target object
1395 * @addr: pointer to native code
1397 * This is used to initialize a delegate. We also insert the method_info if
1398 * we find the info with mono_jit_info_table_find().
1401 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
1403 MonoDomain *domain = mono_domain_get ();
1404 MonoDelegate *delegate = (MonoDelegate *)this;
1405 MonoMethod *method = NULL;
1412 class = this->vtable->klass;
1414 if ((ji = mono_jit_info_table_find (domain, addr))) {
1415 method = ji->method;
1416 delegate->method_info = mono_method_get_object (domain, method);
1419 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1421 delegate->method_ptr = arch_create_remoting_trampoline (method);
1422 delegate->target = target;
1424 delegate->method_ptr = addr;
1425 delegate->target = target;
1430 * mono_method_call_message_new:
1432 * Translates arguments pointers into a Message.
1435 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
1436 MonoDelegate **cb, MonoObject **state)
1438 MonoDomain *domain = mono_domain_get ();
1439 MonoMethodSignature *sig = method->signature;
1440 MonoMethodMessage *msg;
1443 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1446 mono_message_init (domain, msg, mono_method_get_object (domain, invoke), NULL);
1447 count = sig->param_count - 2;
1449 mono_message_init (domain, msg, mono_method_get_object (domain, method), NULL);
1450 count = sig->param_count;
1453 for (i = 0; i < count; i++) {
1458 if (sig->params [i]->byref)
1459 vpos = *((gpointer *)params [i]);
1463 type = sig->params [i]->type;
1464 class = mono_class_from_mono_type (sig->params [i]);
1466 if (class->valuetype)
1467 arg = mono_value_box (domain, class, vpos);
1469 arg = *((MonoObject **)vpos);
1471 mono_array_set (msg->args, gpointer, i, arg);
1475 *cb = *((MonoDelegate **)params [i]);
1477 *state = *((MonoObject **)params [i]);
1484 * mono_method_return_message_restore:
1486 * Restore results from message based processing back to arguments pointers
1489 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
1491 MonoMethodSignature *sig = method->signature;
1492 int i, j, type, size, align;
1494 for (i = 0, j = 0; i < sig->param_count; i++) {
1495 size = mono_type_stack_size (sig->params [i], &align);
1497 if (sig->params [i]->byref) {
1498 char *arg = mono_array_get (out_args, gpointer, j);
1499 type = sig->params [i]->type;
1502 case MONO_TYPE_VOID:
1503 g_assert_not_reached ();
1507 case MONO_TYPE_BOOLEAN:
1510 case MONO_TYPE_CHAR:
1517 case MONO_TYPE_VALUETYPE: {
1518 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
1521 case MONO_TYPE_STRING:
1522 case MONO_TYPE_CLASS:
1523 case MONO_TYPE_ARRAY:
1524 case MONO_TYPE_SZARRAY:
1525 *((MonoObject **)params [i]) = (MonoObject *)arg;
1528 g_assert_not_reached ();