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>
28 mono_runtime_object_init (MonoObject *this)
31 MonoMethod *method = NULL;
32 MonoClass *klass = this->vtable->klass;
34 for (i = 0; i < klass->method.count; ++i) {
35 if (!strcmp (".ctor", klass->methods [i]->name) &&
36 klass->methods [i]->signature->param_count == 0) {
37 method = klass->methods [i];
44 mono_runtime_invoke (method, this, NULL, NULL);
49 * @klass: klass that needs to be initialized
51 * This routine calls the class constructor for @class.
54 mono_runtime_class_init (MonoClass *klass)
58 for (i = 0; i < klass->method.count; ++i) {
59 MonoMethod *method = klass->methods [i];
60 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
61 (strcmp (".cctor", method->name) == 0)) {
62 mono_runtime_invoke (method, NULL, NULL, NULL);
67 /* No class constructor found */
71 default_trampoline (MonoMethod *method)
77 default_remoting_trampoline (MonoMethod *method)
79 g_error ("remoting not installed");
83 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
84 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
87 mono_install_trampoline (MonoTrampoline func)
89 arch_create_jit_trampoline = func? func: default_trampoline;
93 mono_install_remoting_trampoline (MonoTrampoline func)
95 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
98 #if 0 && HAVE_BOEHM_GC
100 vtable_finalizer (void *obj, void *data) {
101 g_print ("%s finalized (%p)\n", (char*)data, obj);
107 * @domain: the application domain
108 * @class: the class to initialize
110 * VTables are domain specific because we create domain specific code, and
111 * they contain the domain specific static class data.
114 mono_class_vtable (MonoDomain *domain, MonoClass *class)
118 MonoClassField *field;
120 guint32 cols [MONO_CONSTANT_SIZE];
127 /* can interfaces have static fields? */
128 if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
129 g_assert_not_reached ();
131 mono_domain_lock (domain);
132 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
133 mono_domain_unlock (domain);
138 mono_class_init (class);
140 // mono_stats.used_class_count++;
141 // mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
143 vt = mono_mempool_alloc0 (domain->mp, sizeof (MonoVTable) +
144 class->vtable_size * sizeof (gpointer));
148 if (class->class_size) {
150 vt->data = GC_malloc (class->class_size + 8);
151 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
152 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
153 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
155 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
158 // mono_stats.class_static_data_size += class->class_size + 8;
161 for (i = class->field.first; i < class->field.last; ++i) {
162 field = &class->fields [i - class->field.first];
163 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
165 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
167 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1));
169 g_warning ("constant for field %s not found", field->name);
172 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE);
173 p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]);
174 len = mono_metadata_decode_blob_size (p, &p);
175 t = (char*)vt->data + field->offset;
176 /* should we check that the type matches? */
177 switch (cols [MONO_CONSTANT_TYPE]) {
178 case MONO_TYPE_BOOLEAN:
186 guint16 *val = (guint16*)t;
192 guint32 *val = (guint32*)t;
198 guint64 *val = (guint64*)t;
203 float *val = (float*)t;
208 double *val = (double*)t;
212 case MONO_TYPE_STRING: {
213 //gpointer *val = (gpointer*)t;
214 //*val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
217 case MONO_TYPE_CLASS:
218 /* nothing to do, we malloc0 the data and the value can be 0 only */
221 g_warning ("type 0x%02x should not be in constant table", cols [MONO_CONSTANT_TYPE]);
225 vt->max_interface_id = class->max_interface_id;
227 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
228 sizeof (gpointer) * (class->max_interface_id + 1));
230 /* initialize interface offsets */
231 for (k = class; k ; k = k->parent) {
232 for (i = 0; i < k->interface_count; i++) {
234 MonoClass *ic = k->interfaces [i];
235 slot = class->interface_offsets [ic->interface_id];
236 vt->interface_offsets [ic->interface_id] = &vt->vtable [slot];
240 /* initialize vtable */
241 for (i = 0; i < class->vtable_size; ++i) {
244 if ((cm = class->vtable [i]))
245 vt->vtable [i] = arch_create_jit_trampoline (cm);
248 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
249 mono_domain_unlock (domain);
251 /* make sure the the parent is initialized */
253 mono_class_vtable (domain, class->parent);
255 mono_runtime_class_init (class);
261 * mono_class_proxy_vtable:
262 * @domain: the application domain
263 * @class: the class to proxy
265 * Creates a vtable for transparent proxies. It is basically
266 * a copy of the real vtable of @class, but all function pointers invoke
267 * the remoting functions, and vtable->klass points to the
268 * transparent proxy class, and not to @class.
271 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
273 MonoVTable *vt, *pvt;
276 if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
279 vt = mono_class_vtable (domain, class);
280 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
282 // mono_stats.class_vtable_size += vtsize;
284 pvt = mono_mempool_alloc (domain->mp, vtsize);
285 memcpy (pvt, vt, vtsize);
287 pvt->klass = mono_defaults.transparent_proxy_class;
289 /* initialize vtable */
290 for (i = 0; i < class->vtable_size; ++i) {
293 if ((cm = class->vtable [i]))
294 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
297 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
302 static MonoInvokeFunc default_mono_runtime_invoke = NULL;
305 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
307 if (!default_mono_runtime_invoke) {
308 g_error ("runtime invoke called on uninitialized runtime");
311 return default_mono_runtime_invoke (method, obj, params, exc);
315 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
321 klass = ((MonoObject *)delegate)->vtable->klass;
324 for (i = 0; i < klass->method.count; ++i) {
325 if (klass->methods [i]->name[0] == 'I' &&
326 !strcmp ("Invoke", klass->methods [i]->name) &&
327 klass->methods [i]->signature->param_count == 2) {
328 im = klass->methods [i];
334 return mono_runtime_invoke (im, delegate, params, exc);
337 static MonoArray* main_args;
340 mono_runtime_get_main_args (void)
346 * Execute a standard Main() method (argc/argv contains the
347 * executable name). This method also sets the command line argument value
348 * needed by System.Environment.
351 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
355 MonoArray *args = NULL;
356 MonoDomain *domain = mono_domain_get ();
358 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
359 for (i = 0; i < argc; ++i) {
360 MonoString *arg = mono_string_new (domain, argv [i]);
361 mono_array_set (main_args, gpointer, i, arg);
365 if (method->signature->param_count) {
366 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
367 for (i = 0; i < argc; ++i) {
368 MonoString *arg = mono_string_new (domain, argv [i]);
369 mono_array_set (args, gpointer, i, arg);
373 return mono_runtime_exec_main (method, args, exc);
377 * We call this function when we dectect an unhandled exception. It invokes the
378 * UnhandledException event in AppDomain or print a warning to the console
381 mono_unhandled_exception (MonoObject *exc)
383 MonoDomain *domain = mono_domain_get ();
384 MonoClassField *field;
385 MonoObject *delegate;
387 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
388 "UnhandledException");
391 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
394 mono_print_unhandled_exception (exc);
396 MonoObject *e = NULL;
399 /* fixme: pass useful arguments */
402 mono_runtime_delegate_invoke (delegate, pa, &e);
403 /* fixme: what if an exception occured */
405 mono_print_unhandled_exception (exc);
410 * Execute a standard Main() method (args doesn't contain the
414 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
421 /* FIXME: check signature of method */
422 if (method->signature->ret->type == MONO_TYPE_I4) {
424 res = mono_runtime_invoke (method, NULL, pa, exc);
426 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
430 mono_runtime_invoke (method, NULL, pa, exc);
438 mono_unhandled_exception (*exc);
444 mono_install_runtime_invoke (MonoInvokeFunc func)
446 default_mono_runtime_invoke = func;
450 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
453 MonoMethodSignature *sig = method->signature;
457 if (NULL != params) {
458 pa = alloca (sizeof (gpointer) * mono_array_length (params));
459 for (i = 0; i < mono_array_length (params); i++) {
460 if (sig->params [i]->byref) {
464 switch (sig->params [i]->type) {
467 case MONO_TYPE_BOOLEAN:
477 case MONO_TYPE_VALUETYPE:
478 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
480 case MONO_TYPE_STRING:
481 case MONO_TYPE_OBJECT:
482 case MONO_TYPE_CLASS:
483 case MONO_TYPE_SZARRAY:
484 pa [i] = (char *)(((gpointer *)params->vector)[i]);
487 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
492 if (!strcmp (method->name, ".ctor")) {
493 obj = mono_object_new (mono_domain_get (), method->klass);
494 mono_runtime_invoke (method, obj, pa, exc);
497 return mono_runtime_invoke (method, obj, pa, exc);
501 * mono_object_allocate:
502 * @size: number of bytes to allocate
504 * This is a very simplistic routine until we have our GC-aware
507 * Returns: an allocated object of size @size, or NULL on failure.
510 mono_object_allocate (size_t size)
513 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
514 void *o = GC_malloc (size);
516 void *o = calloc (1, size);
525 * Frees the memory used by the object. Debugging purposes
526 * only, as we will have our GC system.
529 mono_object_free (MonoObject *o)
532 g_error ("mono_object_free called with boehm gc.");
534 MonoClass *c = o->vtable->klass;
536 memset (o, 0, c->instance_size);
543 * @klass: the class of the object that we want to create
545 * Returns: A newly created object whose definition is
546 * looked up using @klass
549 mono_object_new (MonoDomain *domain, MonoClass *klass)
551 return mono_object_new_specific (mono_class_vtable (domain, klass));
555 * mono_object_new_specific:
556 * @vtable: the vtable of the object that we want to create
558 * Returns: A newly created object with class and domain specified
562 mono_object_new_specific (MonoVTable *vtable)
566 mono_stats.new_object_count++;
568 o = mono_object_allocate (vtable->klass->instance_size);
570 if (vtable->klass->has_finalize)
571 mono_object_register_finalizer (o);
577 * mono_object_new_from_token:
578 * @image: Context where the type_token is hosted
579 * @token: a token of the type that we want to create
581 * Returns: A newly created object whose definition is
582 * looked up using @token in the @image image
585 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
589 class = mono_class_get (image, token);
591 return mono_object_new (domain, class);
597 * @obj: the object to clone
599 * Returns: A newly created object who is a shallow copy of @obj
602 mono_object_clone (MonoObject *obj)
607 size = obj->vtable->klass->instance_size;
608 o = mono_object_allocate (size);
610 memcpy (o, obj, size);
612 if (obj->vtable->klass->has_finalize)
613 mono_object_register_finalizer (o);
619 * @array: the array to clone
621 * Returns: A newly created array who is a shallow copy of @array
624 mono_array_clone (MonoArray *array)
629 MonoClass *klass = array->obj.vtable->klass;
631 if (array->bounds == NULL) {
632 size = mono_array_length (array);
633 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
636 size *= mono_array_element_size (klass);
637 memcpy (o, array, sizeof (MonoArray) + size);
642 sizes = alloca (klass->rank * sizeof(guint32) * 2);
643 size = mono_array_element_size (klass);
644 for (i = 0; i < klass->rank; ++i) {
645 sizes [i] = array->bounds [i].length;
646 size *= array->bounds [i].length;
647 sizes [i + klass->rank] = array->bounds [i].lower_bound;
649 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
650 klass, sizes, sizes + klass->rank);
651 memcpy (o, array, sizeof(MonoArray) + size);
657 * mono_array_new_full:
658 * @domain: domain where the object is created
659 * @array_class: array class
660 * @lengths: lengths for each dimension in the array
661 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
663 * This routine creates a new array objects with the given dimensions,
664 * lower bounds and type.
667 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
668 guint32 *lengths, guint32 *lower_bounds)
670 guint32 byte_len, len;
673 MonoArrayBounds *bounds;
676 if (!array_class->inited)
677 mono_class_init (array_class);
679 byte_len = mono_array_element_size (array_class);
682 if (array_class->rank == 1 &&
683 (lower_bounds == NULL || lower_bounds [0] == 0)) {
688 bounds = GC_malloc (sizeof (MonoArrayBounds) * array_class->rank);
690 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
692 for (i = 0; i < array_class->rank; ++i) {
693 bounds [i].length = lengths [i];
698 for (i = 0; i < array_class->rank; ++i)
699 bounds [i].lower_bound = lower_bounds [i];
704 * Following three lines almost taken from mono_object_new ():
705 * they need to be kept in sync.
707 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
710 o->vtable = mono_class_vtable (domain, array_class);
712 array = (MonoArray*)o;
714 array->bounds = bounds;
715 array->max_length = len;
722 * @domain: domain where the object is created
723 * @eclass: element class
724 * @n: number of array elements
726 * This routine creates a new szarray with @n elements of type @eclass.
729 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
733 ac = mono_array_class_get (&eclass->byval_arg, 1);
734 g_assert (ac != NULL);
736 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
740 * mono_array_new_specific:
741 * @vtable: a vtable in the appropriate domain for an initialized class
742 * @n: number of array elements
744 * This routine is a fast alternative to mono_array_new() for code which
745 * can be sure about the domain it operates in.
748 mono_array_new_specific (MonoVTable *vtable, guint32 n)
754 byte_len = n * mono_array_element_size (vtable->klass);
755 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
768 * mono_string_new_utf16:
769 * @text: a pointer to an utf16 string
770 * @len: the length of the string
772 * Returns: A newly created string object which contains @text.
775 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
779 s = mono_string_new_size (domain, len);
780 g_assert (s != NULL);
782 memcpy (mono_string_chars (s), text, len * 2);
788 * mono_string_new_size:
789 * @text: a pointer to an utf16 string
790 * @len: the length of the string
792 * Returns: A newly created string object of @len
795 mono_string_new_size (MonoDomain *domain, gint32 len)
800 * enable to get a good speedup: we still need to figure out
801 * how the sync structure is freed.
804 s = GC_malloc_atomic (sizeof (MonoString) + ((len + 1) * 2));
805 s->object.synchronisation = 0;
806 mono_string_chars (s) [len] = 0;
808 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
813 s->object.vtable = mono_class_vtable (domain, mono_defaults.string_class);
820 * mono_string_new_len:
821 * @text: a pointer to an utf8 string
822 * @length: number of bytes in @text to consider
824 * Returns: A newly created string object which contains @text.
827 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
829 GError *error = NULL;
830 MonoString *o = NULL;
835 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
838 o = mono_string_new_utf16 (domain, ut, items_written);
840 g_error_free (error);
849 * @text: a pointer to an utf8 string
851 * Returns: A newly created string object which contains @text.
854 mono_string_new (MonoDomain *domain, const char *text)
856 GError *error = NULL;
857 MonoString *o = NULL;
864 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
867 o = mono_string_new_utf16 (domain, ut, items_written);
869 g_error_free (error);
877 * mono_string_new_wrapper:
878 * @text: pointer to utf8 characters.
880 * Helper function to create a string object from @text in the current domain.
883 mono_string_new_wrapper (const char *text)
885 MonoDomain *domain = mono_domain_get ();
887 return mono_string_new (domain, text);
892 * @class: the class of the value
893 * @value: a pointer to the unboxed data
895 * Returns: A newly created object which contains @value.
898 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
903 g_assert (class->valuetype);
905 size = mono_class_instance_size (class);
906 res = mono_object_allocate (size);
907 res->vtable = mono_class_vtable (domain, class);
909 size = size - sizeof (MonoObject);
911 #if NO_UNALIGNED_ACCESS
912 memcpy ((char *)res + sizeof (MonoObject), value, size);
916 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
919 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
922 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
925 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
928 memcpy ((char *)res + sizeof (MonoObject), value, size);
931 if (class->has_finalize)
932 mono_object_register_finalizer (res);
937 * mono_object_isinst:
939 * @klass: a pointer to a class
941 * Returns: @obj if @obj is derived from @klass
944 mono_object_isinst (MonoObject *obj, MonoClass *klass)
956 mono_class_init (klass);
958 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
959 if ((klass->interface_id <= oklass->max_interface_id) &&
960 vt->interface_offsets [klass->interface_id])
963 if (oklass == mono_defaults.transparent_proxy_class) {
964 /* fixme: add check for IRemotingTypeInfo */
965 oklass = ((MonoTransparentProxy *)obj)->klass;
968 if (oklass->rank == klass->rank &&
969 (oklass->element_class->baseval - klass->element_class->baseval) <=
970 klass->element_class->diffval)
973 } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
981 mono_string_is_interned_lookup (MonoString *str, int insert)
983 MonoGHashTable *ldstr_table;
986 char *ins = g_malloc (4 + str->length * 2);
990 /* Encode the length */
992 mono_metadata_encode_value (2 * str->length, p, &p);
995 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
996 bloblen = (p - ins) + 2 * str->length;
998 * ins is stored in the hash table as a key and needs to have the same
999 * representation as in the metadata: we swap the character bytes on big
1002 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1005 char *p2 = mono_string_chars (str);
1006 for (i = 0; i < str->length; ++i) {
1013 memcpy (p, mono_string_chars (str), str->length * 2);
1015 domain = ((MonoObject *)str)->vtable->domain;
1016 ldstr_table = domain->ldstr_table;
1017 mono_domain_lock (domain);
1018 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1019 mono_domain_unlock (domain);
1024 mono_g_hash_table_insert (ldstr_table, ins, str);
1025 mono_domain_unlock (domain);
1028 mono_domain_unlock (domain);
1034 mono_string_is_interned (MonoString *o)
1036 return mono_string_is_interned_lookup (o, FALSE);
1040 mono_string_intern (MonoString *str)
1042 return mono_string_is_interned_lookup (str, TRUE);
1047 * @domain: the domain where the string will be used.
1048 * @image: a metadata context
1049 * @idx: index into the user string table.
1051 * Implementation for the ldstr opcode.
1054 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
1056 const char *str, *sig;
1060 sig = str = mono_metadata_user_string (image, idx);
1062 mono_domain_lock (domain);
1063 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
1064 mono_domain_unlock (domain);
1068 len2 = mono_metadata_decode_blob_size (str, &str);
1071 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
1072 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1075 guint16 *p2 = (guint16*)mono_string_chars (o);
1076 for (i = 0; i < len2; ++i) {
1077 *p2 = GUINT16_FROM_LE (*p2);
1082 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
1083 mono_domain_unlock (domain);
1089 * mono_string_to_utf8:
1090 * @s: a System.String
1092 * Return the UTF8 representation for @s.
1093 * the resulting buffer nedds to be freed with g_free().
1096 mono_string_to_utf8 (MonoString *s)
1099 GError *error = NULL;
1101 g_assert (s != NULL);
1104 return g_strdup ("");
1106 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
1108 g_warning (error->message);
1114 * mono_string_to_utf16:
1117 * Return an null-terminated array of the utf-16 chars
1118 * contained in @s. The result must be freed with g_free().
1119 * This is a temporary helper until our string implementation
1120 * is reworked to always include the null terminating char.
1123 mono_string_to_utf16 (MonoString *s)
1127 g_assert (s != NULL);
1129 as = g_malloc ((s->length * 2) + 2);
1130 as [(s->length * 2)] = '\0';
1131 as [(s->length * 2) + 1] = '\0';
1134 return (gunichar2 *)(as);
1137 memcpy (as, mono_string_chars(s), s->length * 2);
1139 return (gunichar2 *)(as);
1143 default_ex_handler (MonoException *ex)
1145 MonoObject *o = (MonoObject*)ex;
1146 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
1149 static MonoExceptionFunc ex_handler = default_ex_handler;
1152 mono_install_handler (MonoExceptionFunc func)
1154 ex_handler = func? func: default_ex_handler;
1158 * mono_raise_exception:
1159 * @ex: exception object
1161 * Signal the runtime that the exception @ex has been raised in unmanaged code.
1164 mono_raise_exception (MonoException *ex)
1170 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
1172 MonoWaitHandle *res;
1174 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
1176 res->handle = handle;
1182 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
1184 MonoAsyncResult *res;
1186 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
1189 res->async_state = state;
1190 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
1191 res->sync_completed = FALSE;
1192 res->completed = FALSE;
1198 mono_message_init (MonoDomain *domain,
1199 MonoMethodMessage *this,
1200 MonoReflectionMethod *method,
1201 MonoArray *out_args)
1203 MonoMethodSignature *sig = method->method->signature;
1209 this->method = method;
1211 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
1212 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
1214 names = g_new (char *, sig->param_count);
1215 mono_method_get_param_names (method->method, (const char **) names);
1216 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
1218 for (i = 0; i < sig->param_count; i++) {
1219 name = mono_string_new (domain, names [i]);
1220 mono_array_set (this->names, gpointer, i, name);
1225 for (i = 0, j = 0; i < sig->param_count; i++) {
1227 if (sig->params [i]->byref) {
1229 gpointer arg = mono_array_get (out_args, gpointer, j);
1230 mono_array_set (this->args, gpointer, i, arg);
1234 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
1240 mono_array_set (this->arg_types, guint8, i, arg_type);
1245 * mono_remoting_invoke:
1246 * @real_proxy: pointer to a RealProxy object
1247 * @msg: The MonoMethodMessage to execute
1248 * @exc: used to store exceptions
1249 * @out_args: used to store output arguments
1251 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
1252 * IMessage interface and it is not trivial to extract results from there. So
1253 * we call an helper method PrivateInvoke instead of calling
1254 * RealProxy::Invoke() directly.
1256 * Returns: the result object.
1259 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
1260 MonoObject **exc, MonoArray **out_args)
1262 static MonoMethod *im = NULL;
1265 //static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;
1267 /* fixme: make this domain dependent */
1272 klass = mono_defaults.real_proxy_class;
1274 for (i = 0; i < klass->method.count; ++i) {
1275 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
1276 klass->methods [i]->signature->param_count == 4) {
1277 im = klass->methods [i];
1285 pa [0] = real_proxy;
1290 return mono_runtime_invoke (im, NULL, pa, exc);
1294 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
1295 MonoObject **exc, MonoArray **out_args)
1297 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1299 return mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)target)->rp,
1300 msg, exc, out_args);
1303 MonoDomain *domain = mono_domain_get ();
1304 MonoMethod *method = msg->method->method;
1305 MonoMethodSignature *sig = method->signature;
1306 int i, j, outarg_count = 0;
1308 for (i = 0; i < sig->param_count; i++) {
1309 if (sig->params [i]->byref)
1313 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
1316 for (i = 0, j = 0; i < sig->param_count; i++) {
1317 if (sig->params [i]->byref) {
1319 arg = mono_array_get (msg->args, gpointer, i);
1320 mono_array_set (*out_args, gpointer, j, arg);
1325 return mono_runtime_invoke_array (method, target, msg->args, exc);
1330 mono_print_unhandled_exception (MonoObject *exc)
1332 char *message = g_strdup ("");
1333 char *trace = g_strdup ("");
1336 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
1337 if ((str = ((MonoException *)exc)->message))
1338 message = mono_string_to_utf8 (str);
1339 if ((str = ((MonoException *)exc)->stack_trace))
1340 trace = mono_string_to_utf8 (str);
1343 g_warning ("unhandled exception %s.%s: \"%s\"", exc->vtable->klass->name_space,
1344 exc->vtable->klass->name, message);