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/os/gc_wrapper.h>
30 * enable to get a good speedup: we still need to figure out
31 * how the sync structure is freed.
33 #define CREATION_SPEEDUP 0
36 mono_runtime_object_init (MonoObject *this)
39 MonoMethod *method = NULL;
40 MonoClass *klass = this->vtable->klass;
42 for (i = 0; i < klass->method.count; ++i) {
43 if (!strcmp (".ctor", klass->methods [i]->name) &&
44 klass->methods [i]->signature->param_count == 0) {
45 method = klass->methods [i];
52 mono_runtime_invoke (method, this, NULL, NULL);
57 * @klass: klass that needs to be initialized
59 * This routine calls the class constructor for @class.
62 mono_runtime_class_init (MonoClass *klass)
66 for (i = 0; i < klass->method.count; ++i) {
67 MonoMethod *method = klass->methods [i];
68 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
69 (strcmp (".cctor", method->name) == 0)) {
70 mono_runtime_invoke (method, NULL, NULL, NULL);
75 /* No class constructor found */
79 default_trampoline (MonoMethod *method)
85 default_remoting_trampoline (MonoMethod *method)
87 g_error ("remoting not installed");
91 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
92 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
95 mono_install_trampoline (MonoTrampoline func)
97 arch_create_jit_trampoline = func? func: default_trampoline;
101 mono_install_remoting_trampoline (MonoTrampoline func)
103 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
106 static MonoCompileFunc default_mono_compile_method = NULL;
109 mono_install_compile_method (MonoCompileFunc func)
111 default_mono_compile_method = func;
115 mono_compile_method (MonoMethod *method)
117 if (!default_mono_compile_method) {
118 g_error ("compile method called on uninitialized runtime");
121 return default_mono_compile_method (method);
125 #if 0 && HAVE_BOEHM_GC
127 vtable_finalizer (void *obj, void *data) {
128 g_print ("%s finalized (%p)\n", (char*)data, obj);
134 * @domain: the application domain
135 * @class: the class to initialize
137 * VTables are domain specific because we create domain specific code, and
138 * they contain the domain specific static class data.
141 mono_class_vtable (MonoDomain *domain, MonoClass *class)
145 MonoClassField *field;
147 guint32 cols [MONO_CONSTANT_SIZE];
154 vt = class->cached_vtable;
155 if (vt && vt->domain == domain)
158 mono_domain_lock (domain);
159 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
160 mono_domain_unlock (domain);
165 mono_class_init (class);
167 mono_stats.used_class_count++;
168 mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
170 vt = mono_mempool_alloc0 (domain->mp, sizeof (MonoVTable) +
171 class->vtable_size * sizeof (gpointer));
175 if (class->class_size) {
177 vt->data = GC_MALLOC (class->class_size + 8);
178 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
179 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
180 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
182 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
185 mono_stats.class_static_data_size += class->class_size + 8;
188 for (i = class->field.first; i < class->field.last; ++i) {
189 field = &class->fields [i - class->field.first];
190 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
192 if ((field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
193 MonoClass *fklass = mono_class_from_mono_type (field->type);
194 t = (char*)vt->data + field->offset;
195 g_assert (fklass->valuetype);
196 memcpy (t, field->data, mono_class_value_size (fklass, NULL));
199 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
201 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1));
203 g_warning ("constant for field %s not found", field->name);
206 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE);
207 p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]);
208 len = mono_metadata_decode_blob_size (p, &p);
209 t = (char*)vt->data + field->offset;
210 /* should we check that the type matches? */
211 switch (cols [MONO_CONSTANT_TYPE]) {
212 case MONO_TYPE_BOOLEAN:
220 guint16 *val = (guint16*)t;
226 guint32 *val = (guint32*)t;
232 guint64 *val = (guint64*)t;
237 float *val = (float*)t;
242 double *val = (double*)t;
246 case MONO_TYPE_STRING: {
247 gpointer *val = (gpointer*)t;
248 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
249 gunichar2 *copy = g_malloc (len);
251 for (j = 0; j < len/2; j++) {
252 copy [j] = read16 (p);
255 *val = mono_string_new_utf16 (domain, copy, len/2);
258 *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
262 case MONO_TYPE_CLASS:
263 /* nothing to do, we malloc0 the data and the value can be 0 only */
266 g_warning ("type 0x%02x should not be in constant table", cols [MONO_CONSTANT_TYPE]);
270 vt->max_interface_id = class->max_interface_id;
272 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
273 sizeof (gpointer) * (class->max_interface_id + 1));
275 /* initialize interface offsets */
276 for (k = class; k ; k = k->parent) {
277 for (i = 0; i < k->interface_count; i++) {
279 MonoClass *ic = k->interfaces [i];
280 slot = class->interface_offsets [ic->interface_id];
281 vt->interface_offsets [ic->interface_id] = &vt->vtable [slot];
285 /* initialize vtable */
286 for (i = 0; i < class->vtable_size; ++i) {
289 if ((cm = class->vtable [i]))
290 vt->vtable [i] = arch_create_jit_trampoline (cm);
293 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
294 if (!class->cached_vtable)
295 class->cached_vtable = vt;
297 mono_domain_unlock (domain);
299 /* make sure the the parent is initialized */
301 mono_class_vtable (domain, class->parent);
303 mono_runtime_class_init (class);
309 * mono_class_proxy_vtable:
310 * @domain: the application domain
311 * @class: the class to proxy
313 * Creates a vtable for transparent proxies. It is basically
314 * a copy of the real vtable of @class, but all function pointers invoke
315 * the remoting functions, and vtable->klass points to the
316 * transparent proxy class, and not to @class.
319 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
321 MonoVTable *vt, *pvt;
324 if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
327 vt = mono_class_vtable (domain, class);
328 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
330 mono_stats.class_vtable_size += vtsize;
332 pvt = mono_mempool_alloc (domain->mp, vtsize);
333 memcpy (pvt, vt, vtsize);
335 pvt->klass = mono_defaults.transparent_proxy_class;
337 /* initialize vtable */
338 for (i = 0; i < class->vtable_size; ++i) {
341 if ((cm = class->vtable [i]))
342 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
345 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
351 * Retrieve the MonoMethod that would to be called on obj if obj is passed as
352 * the instance of a callvirt of method.
355 mono_object_get_virtual_method (MonoObject *obj, MonoMethod *method) {
361 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL))
364 klass = mono_object_class (obj);
365 if (klass == mono_defaults.transparent_proxy_class) {
366 klass = ((MonoTransparentProxy *)obj)->klass;
371 vtable = klass->vtable;
373 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
374 res = vtable [method->klass->interface_id + method->slot];
376 res = vtable [method->slot];
381 return mono_marshal_get_remoting_invoke (res);
387 dummy_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
389 g_error ("runtime invoke called on uninitialized runtime");
393 static MonoInvokeFunc default_mono_runtime_invoke = dummy_mono_runtime_invoke;
396 mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
398 return default_mono_runtime_invoke (method, obj, params, exc);
402 set_value (MonoType *type, void *dest, void *value, int deref_pointer) {
405 gpointer *p = (gpointer*)dest;
412 case MONO_TYPE_BOOLEAN:
415 guint8 *p = (guint8*)dest;
416 *p = *(guint8*)value;
421 case MONO_TYPE_CHAR: {
422 guint16 *p = (guint16*)dest;
423 *p = *(guint16*)value;
426 #if SIZEOF_VOID_P == 4
432 gint32 *p = (gint32*)dest;
433 *p = *(gint32*)value;
436 #if SIZEOF_VOID_P == 8
442 gint64 *p = (gint64*)dest;
443 *p = *(gint64*)value;
447 float *p = (float*)dest;
452 double *p = (double*)dest;
453 *p = *(double*)value;
456 case MONO_TYPE_STRING:
457 case MONO_TYPE_SZARRAY:
458 case MONO_TYPE_CLASS:
459 case MONO_TYPE_OBJECT:
460 case MONO_TYPE_ARRAY:
461 case MONO_TYPE_PTR: {
462 gpointer *p = (gpointer*)dest;
463 *p = deref_pointer? *(gpointer*)value: value;
466 case MONO_TYPE_VALUETYPE:
467 if (type->data.klass->enumtype) {
468 t = type->data.klass->enum_basetype->type;
472 size = mono_class_value_size (type->data.klass, NULL);
473 memcpy (dest, value, size);
477 g_warning ("got type %x", type->type);
478 g_assert_not_reached ();
483 mono_field_set_value (MonoObject *obj, MonoClassField *field, void *value)
487 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
489 dest = (char*)obj + field->offset;
490 set_value (field->type, dest, value, FALSE);
494 mono_field_static_set_value (MonoVTable *vt, MonoClassField *field, void *value)
498 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
500 dest = (char*)vt->data + field->offset;
501 set_value (field->type, dest, value, FALSE);
505 mono_field_get_value (MonoObject *obj, MonoClassField *field, void *value)
509 g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
511 src = (char*)obj + field->offset;
512 set_value (field->type, value, src, TRUE);
516 mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
520 g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
522 src = (char*)vt->data + field->offset;
523 set_value (field->type, value, src, TRUE);
527 mono_property_set_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
529 default_mono_runtime_invoke (prop->set, obj, params, exc);
533 mono_property_get_value (MonoProperty *prop, void *obj, void **params, MonoObject **exc)
535 return default_mono_runtime_invoke (prop->get, obj, params, exc);
540 mono_get_delegate_invoke (MonoClass *klass)
547 for (i = 0; i < klass->method.count; ++i) {
548 if (klass->methods [i]->name[0] == 'I' &&
549 !strcmp ("Invoke", klass->methods [i]->name)) {
550 im = klass->methods [i];
560 mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
564 im = mono_get_delegate_invoke (delegate->vtable->klass);
567 return mono_runtime_invoke (im, delegate, params, exc);
570 static MonoArray* main_args;
573 mono_runtime_get_main_args (void)
578 MonoMethod *mono_start_method = NULL;
581 * Execute a standard Main() method (argc/argv contains the
582 * executable name). This method also sets the command line argument value
583 * needed by System.Environment.
586 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
590 MonoArray *args = NULL;
591 MonoDomain *domain = mono_domain_get ();
593 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
594 for (i = 0; i < argc; ++i) {
595 MonoString *arg = mono_string_new (domain, argv [i]);
596 mono_array_set (main_args, gpointer, i, arg);
600 if (method->signature->param_count) {
601 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
602 for (i = 0; i < argc; ++i) {
603 MonoString *arg = mono_string_new (domain, argv [i]);
604 mono_array_set (args, gpointer, i, arg);
607 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, 0);
610 mono_assembly_set_main (method->klass->image->assembly);
612 mono_start_method = mono_marshal_get_runtime_invoke (method);
614 return mono_runtime_exec_main (method, args, exc);
618 * We call this function when we dectect an unhandled exception. It invokes the
619 * UnhandledException event in AppDomain or print a warning to the console
622 mono_unhandled_exception (MonoObject *exc)
624 MonoDomain *domain = mono_domain_get ();
625 MonoClassField *field;
626 MonoObject *delegate;
628 field=mono_class_get_field_from_name(mono_defaults.appdomain_class,
629 "UnhandledException");
632 if (exc->vtable->klass != mono_defaults.threadabortexception_class) {
633 delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
636 mono_print_unhandled_exception (exc);
638 MonoObject *e = NULL;
641 /* fixme: pass useful arguments */
644 mono_runtime_delegate_invoke (delegate, pa, &e);
647 g_warning ("exception inside UnhandledException handler!");
653 * Execute a standard Main() method (args doesn't contain the
657 mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
667 domain = mono_object_domain (args);
668 if (!domain->entry_assembly) {
669 domain->entry_assembly = method->klass->image->assembly;
670 ves_icall_System_AppDomainSetup_InitAppDomainSetup (domain->setup);
673 /* FIXME: check signature of method */
674 if (method->signature->ret->type == MONO_TYPE_I4) {
676 res = mono_runtime_invoke (method, NULL, pa, exc);
678 rval = *(guint32 *)((char *)res + sizeof (MonoObject));
682 mono_runtime_invoke (method, NULL, pa, exc);
693 mono_install_runtime_invoke (MonoInvokeFunc func)
695 default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke;
699 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params,
702 MonoMethodSignature *sig = method->signature;
706 if (NULL != params) {
707 pa = alloca (sizeof (gpointer) * mono_array_length (params));
708 for (i = 0; i < mono_array_length (params); i++) {
709 if (sig->params [i]->byref) {
713 switch (sig->params [i]->type) {
716 case MONO_TYPE_BOOLEAN:
728 case MONO_TYPE_VALUETYPE:
729 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
731 case MONO_TYPE_STRING:
732 case MONO_TYPE_OBJECT:
733 case MONO_TYPE_CLASS:
734 case MONO_TYPE_ARRAY:
735 case MONO_TYPE_SZARRAY:
736 pa [i] = (char *)(((gpointer *)params->vector)[i]);
739 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
744 if (!strcmp (method->name, ".ctor") && method->klass != mono_defaults.string_class) {
746 obj = mono_object_new (mono_domain_get (), method->klass);
747 mono_runtime_invoke (method, obj, pa, exc);
750 return mono_runtime_invoke (method, obj, pa, exc);
754 * mono_object_allocate:
755 * @size: number of bytes to allocate
757 * This is a very simplistic routine until we have our GC-aware
760 * Returns: an allocated object of size @size, or NULL on failure.
763 mono_object_allocate (size_t size)
766 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
767 void *o = GC_MALLOC (size);
769 void *o = calloc (1, size);
772 mono_stats.new_object_count++;
780 * Frees the memory used by the object. Debugging purposes
781 * only, as we will have our GC system.
784 mono_object_free (MonoObject *o)
787 g_error ("mono_object_free called with boehm gc.");
789 MonoClass *c = o->vtable->klass;
791 memset (o, 0, c->instance_size);
798 * @klass: the class of the object that we want to create
800 * Returns: A newly created object whose definition is
801 * looked up using @klass
804 mono_object_new (MonoDomain *domain, MonoClass *klass)
806 return mono_object_new_specific (mono_class_vtable (domain, klass));
810 * mono_object_new_specific:
811 * @vtable: the vtable of the object that we want to create
813 * Returns: A newly created object with class and domain specified
817 mono_object_new_specific (MonoVTable *vtable)
821 o = mono_object_allocate (vtable->klass->instance_size);
823 if (vtable->klass->has_finalize)
824 mono_object_register_finalizer (o);
830 * mono_object_new_from_token:
831 * @image: Context where the type_token is hosted
832 * @token: a token of the type that we want to create
834 * Returns: A newly created object whose definition is
835 * looked up using @token in the @image image
838 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
842 class = mono_class_get (image, token);
844 return mono_object_new (domain, class);
850 * @obj: the object to clone
852 * Returns: A newly created object who is a shallow copy of @obj
855 mono_object_clone (MonoObject *obj)
860 size = obj->vtable->klass->instance_size;
861 o = mono_object_allocate (size);
863 memcpy (o, obj, size);
865 if (obj->vtable->klass->has_finalize)
866 mono_object_register_finalizer (o);
872 * @array: the array to clone
874 * Returns: A newly created array who is a shallow copy of @array
877 mono_array_clone (MonoArray *array)
882 MonoClass *klass = array->obj.vtable->klass;
886 if (array->bounds == NULL) {
887 size = mono_array_length (array);
888 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
891 size *= mono_array_element_size (klass);
892 memcpy (o, array, sizeof (MonoArray) + size);
897 sizes = alloca (klass->rank * sizeof(guint32) * 2);
898 size = mono_array_element_size (klass);
899 for (i = 0; i < klass->rank; ++i) {
900 sizes [i] = array->bounds [i].length;
901 size *= array->bounds [i].length;
902 sizes [i + klass->rank] = array->bounds [i].lower_bound;
904 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
905 klass, sizes, sizes + klass->rank);
906 memcpy (o, array, sizeof(MonoArray) + size);
912 * mono_array_new_full:
913 * @domain: domain where the object is created
914 * @array_class: array class
915 * @lengths: lengths for each dimension in the array
916 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
918 * This routine creates a new array objects with the given dimensions,
919 * lower bounds and type.
922 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
923 guint32 *lengths, guint32 *lower_bounds)
925 guint32 byte_len, len;
928 MonoArrayBounds *bounds;
931 if (!array_class->inited)
932 mono_class_init (array_class);
934 byte_len = mono_array_element_size (array_class);
937 if (array_class->rank == 1 &&
938 (lower_bounds == NULL || lower_bounds [0] == 0)) {
943 bounds = GC_MALLOC (sizeof (MonoArrayBounds) * array_class->rank);
945 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
947 for (i = 0; i < array_class->rank; ++i) {
948 bounds [i].length = lengths [i];
953 for (i = 0; i < array_class->rank; ++i)
954 bounds [i].lower_bound = lower_bounds [i];
959 * Following three lines almost taken from mono_object_new ():
960 * they need to be kept in sync.
962 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
965 o->vtable = mono_class_vtable (domain, array_class);
967 array = (MonoArray*)o;
969 array->bounds = bounds;
970 array->max_length = len;
977 * @domain: domain where the object is created
978 * @eclass: element class
979 * @n: number of array elements
981 * This routine creates a new szarray with @n elements of type @eclass.
984 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
988 ac = mono_array_class_get (&eclass->byval_arg, 1);
989 g_assert (ac != NULL);
991 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
995 * mono_array_new_specific:
996 * @vtable: a vtable in the appropriate domain for an initialized class
997 * @n: number of array elements
999 * This routine is a fast alternative to mono_array_new() for code which
1000 * can be sure about the domain it operates in.
1003 mono_array_new_specific (MonoVTable *vtable, guint32 n)
1009 byte_len = n * mono_array_element_size (vtable->klass);
1010 #if CREATION_SPEEDUP
1011 if (vtable->klass->element_class->byval_arg.type >= MONO_TYPE_BOOLEAN && vtable->klass->element_class->byval_arg.type <= MONO_TYPE_R4) {
1012 o = GC_MALLOC_ATOMIC (sizeof (MonoArray) + byte_len);
1013 o->synchronisation = 0;
1014 memset (((MonoArray*)o)->vector, 0, byte_len);
1016 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1019 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
1025 ao = (MonoArray *)o;
1033 * mono_string_new_utf16:
1034 * @text: a pointer to an utf16 string
1035 * @len: the length of the string
1037 * Returns: A newly created string object which contains @text.
1040 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
1044 s = mono_string_new_size (domain, len);
1045 g_assert (s != NULL);
1047 memcpy (mono_string_chars (s), text, len * 2);
1053 * mono_string_new_size:
1054 * @text: a pointer to an utf16 string
1055 * @len: the length of the string
1057 * Returns: A newly created string object of @len
1060 mono_string_new_size (MonoDomain *domain, gint32 len)
1064 #if CREATION_SPEEDUP
1065 s = GC_MALLOC_ATOMIC (sizeof (MonoString) + ((len + 1) * 2));
1066 s->object.synchronisation = 0;
1067 mono_string_chars (s) [len] = 0;
1069 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
1074 s->object.vtable = mono_class_vtable (domain, mono_defaults.string_class);
1081 * mono_string_new_len:
1082 * @text: a pointer to an utf8 string
1083 * @length: number of bytes in @text to consider
1085 * Returns: A newly created string object which contains @text.
1088 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
1090 GError *error = NULL;
1091 MonoString *o = NULL;
1093 glong items_written;
1096 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
1099 o = mono_string_new_utf16 (domain, ut, items_written);
1101 g_error_free (error);
1110 * @text: a pointer to an utf8 string
1112 * Returns: A newly created string object which contains @text.
1115 mono_string_new (MonoDomain *domain, const char *text)
1117 GError *error = NULL;
1118 MonoString *o = NULL;
1120 glong items_written;
1125 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
1128 o = mono_string_new_utf16 (domain, ut, items_written);
1130 g_error_free (error);
1138 * mono_string_new_wrapper:
1139 * @text: pointer to utf8 characters.
1141 * Helper function to create a string object from @text in the current domain.
1144 mono_string_new_wrapper (const char *text)
1146 MonoDomain *domain = mono_domain_get ();
1149 return mono_string_new (domain, text);
1156 * @class: the class of the value
1157 * @value: a pointer to the unboxed data
1159 * Returns: A newly created object which contains @value.
1162 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
1167 g_assert (class->valuetype);
1169 size = mono_class_instance_size (class);
1170 res = mono_object_allocate (size);
1171 res->vtable = mono_class_vtable (domain, class);
1173 size = size - sizeof (MonoObject);
1175 #if NO_UNALIGNED_ACCESS
1176 memcpy ((char *)res + sizeof (MonoObject), value, size);
1180 *((guint8 *) res + sizeof (MonoObject)) = *(guint8 *) value;
1183 *(guint16 *)((guint8 *) res + sizeof (MonoObject)) = *(guint16 *) value;
1186 *(guint32 *)((guint8 *) res + sizeof (MonoObject)) = *(guint32 *) value;
1189 *(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
1192 memcpy ((char *)res + sizeof (MonoObject), value, size);
1195 if (class->has_finalize)
1196 mono_object_register_finalizer (res);
1201 * mono_object_isinst:
1203 * @klass: a pointer to a class
1205 * Returns: @obj if @obj is derived from @klass
1208 mono_object_isinst (MonoObject *obj, MonoClass *klass)
1220 mono_class_init (klass);
1222 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1223 if ((klass->interface_id <= oklass->max_interface_id) &&
1224 vt->interface_offsets [klass->interface_id])
1227 if (oklass == mono_defaults.transparent_proxy_class) {
1228 /* fixme: add check for IRemotingTypeInfo */
1229 oklass = ((MonoTransparentProxy *)obj)->klass;
1232 if (oklass->rank == klass->rank &&
1233 (oklass->cast_class->baseval - klass->cast_class->baseval) <=
1234 klass->cast_class->diffval)
1237 } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
1245 mono_string_is_interned_lookup (MonoString *str, int insert)
1247 MonoGHashTable *ldstr_table;
1250 char *ins = g_malloc (4 + str->length * 2);
1254 /* Encode the length */
1256 mono_metadata_encode_value (2 * str->length, p, &p);
1259 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
1260 bloblen = (p - ins) + 2 * str->length;
1262 * ins is stored in the hash table as a key and needs to have the same
1263 * representation as in the metadata: we swap the character bytes on big
1266 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1269 char *p2 = mono_string_chars (str);
1270 for (i = 0; i < str->length; ++i) {
1277 memcpy (p, mono_string_chars (str), str->length * 2);
1279 domain = ((MonoObject *)str)->vtable->domain;
1280 ldstr_table = domain->ldstr_table;
1281 mono_domain_lock (domain);
1282 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
1283 mono_domain_unlock (domain);
1288 mono_g_hash_table_insert (ldstr_table, ins, str);
1289 mono_domain_unlock (domain);
1292 mono_domain_unlock (domain);
1298 mono_string_is_interned (MonoString *o)
1300 return mono_string_is_interned_lookup (o, FALSE);
1304 mono_string_intern (MonoString *str)
1306 return mono_string_is_interned_lookup (str, TRUE);
1311 * @domain: the domain where the string will be used.
1312 * @image: a metadata context
1313 * @idx: index into the user string table.
1315 * Implementation for the ldstr opcode.
1318 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
1320 const char *str, *sig;
1324 if (image->assembly->dynamic) {
1325 MonoDynamicAssembly *assembly = image->assembly->dynamic;
1327 o = g_hash_table_lookup (assembly->tokens,
1328 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx));
1333 sig = str = mono_metadata_user_string (image, idx);
1335 mono_domain_lock (domain);
1336 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
1337 mono_domain_unlock (domain);
1341 len2 = mono_metadata_decode_blob_size (str, &str);
1344 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
1345 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1348 guint16 *p2 = (guint16*)mono_string_chars (o);
1349 for (i = 0; i < len2; ++i) {
1350 *p2 = GUINT16_FROM_LE (*p2);
1355 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
1356 mono_domain_unlock (domain);
1362 * mono_string_to_utf8:
1363 * @s: a System.String
1365 * Return the UTF8 representation for @s.
1366 * the resulting buffer nedds to be freed with g_free().
1369 mono_string_to_utf8 (MonoString *s)
1372 GError *error = NULL;
1378 return g_strdup ("");
1380 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
1382 g_warning (error->message);
1388 * mono_string_to_utf16:
1391 * Return an null-terminated array of the utf-16 chars
1392 * contained in @s. The result must be freed with g_free().
1393 * This is a temporary helper until our string implementation
1394 * is reworked to always include the null terminating char.
1397 mono_string_to_utf16 (MonoString *s)
1404 as = g_malloc ((s->length * 2) + 2);
1405 as [(s->length * 2)] = '\0';
1406 as [(s->length * 2) + 1] = '\0';
1409 return (gunichar2 *)(as);
1412 memcpy (as, mono_string_chars(s), s->length * 2);
1413 return (gunichar2 *)(as);
1417 * Converts a NULL terminated UTF16 string (LPWSTR) to a MonoString
1420 mono_string_from_utf16 (gunichar2 *data)
1422 MonoDomain *domain = mono_domain_get ();
1428 while (data [len]) len++;
1430 return mono_string_new_utf16 (domain, data, len);
1434 default_ex_handler (MonoException *ex)
1436 MonoObject *o = (MonoObject*)ex;
1437 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
1440 static MonoExceptionFunc ex_handler = default_ex_handler;
1443 mono_install_handler (MonoExceptionFunc func)
1445 ex_handler = func? func: default_ex_handler;
1449 * mono_raise_exception:
1450 * @ex: exception object
1452 * Signal the runtime that the exception @ex has been raised in unmanaged code.
1455 mono_raise_exception (MonoException *ex)
1461 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
1463 MonoWaitHandle *res;
1465 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
1467 res->handle = handle;
1473 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
1475 MonoAsyncResult *res;
1477 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
1480 res->async_state = state;
1481 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
1482 res->sync_completed = FALSE;
1483 res->completed = FALSE;
1489 mono_message_init (MonoDomain *domain,
1490 MonoMethodMessage *this,
1491 MonoReflectionMethod *method,
1492 MonoArray *out_args)
1494 MonoMethodSignature *sig = method->method->signature;
1500 this->method = method;
1502 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
1503 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
1505 names = g_new (char *, sig->param_count);
1506 mono_method_get_param_names (method->method, (const char **) names);
1507 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
1509 for (i = 0; i < sig->param_count; i++) {
1510 name = mono_string_new (domain, names [i]);
1511 mono_array_set (this->names, gpointer, i, name);
1516 for (i = 0, j = 0; i < sig->param_count; i++) {
1518 if (sig->params [i]->byref) {
1520 gpointer arg = mono_array_get (out_args, gpointer, j);
1521 mono_array_set (this->args, gpointer, i, arg);
1525 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
1531 mono_array_set (this->arg_types, guint8, i, arg_type);
1536 * mono_remoting_invoke:
1537 * @real_proxy: pointer to a RealProxy object
1538 * @msg: The MonoMethodMessage to execute
1539 * @exc: used to store exceptions
1540 * @out_args: used to store output arguments
1542 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
1543 * IMessage interface and it is not trivial to extract results from there. So
1544 * we call an helper method PrivateInvoke instead of calling
1545 * RealProxy::Invoke() directly.
1547 * Returns: the result object.
1550 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
1551 MonoObject **exc, MonoArray **out_args)
1553 static MonoMethod *im = NULL;
1556 /*static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;*/
1558 /* FIXME: make this domain dependent */
1563 klass = mono_defaults.real_proxy_class;
1565 for (i = 0; i < klass->method.count; ++i) {
1566 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
1567 klass->methods [i]->signature->param_count == 4) {
1568 im = klass->methods [i];
1576 pa [0] = real_proxy;
1581 return mono_runtime_invoke (im, NULL, pa, exc);
1585 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
1586 MonoObject **exc, MonoArray **out_args)
1588 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1590 return mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)target)->rp,
1591 msg, exc, out_args);
1594 MonoDomain *domain = mono_domain_get ();
1595 MonoMethod *method = msg->method->method;
1596 MonoMethodSignature *sig = method->signature;
1597 int i, j, outarg_count = 0;
1599 for (i = 0; i < sig->param_count; i++) {
1600 if (sig->params [i]->byref)
1604 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
1607 for (i = 0, j = 0; i < sig->param_count; i++) {
1608 if (sig->params [i]->byref) {
1610 arg = mono_array_get (msg->args, gpointer, i);
1611 mono_array_set (*out_args, gpointer, j, arg);
1616 return mono_runtime_invoke_array (method, target, msg->args, exc);
1621 mono_print_unhandled_exception (MonoObject *exc)
1623 char *message = (char *) "";
1627 gboolean free_message = FALSE;
1630 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
1631 klass = exc->vtable->klass;
1633 while (klass && method == NULL) {
1634 for (i = 0; i < klass->method.count; ++i) {
1635 method = klass->methods [i];
1636 if (!strcmp ("ToString", method->name) &&
1637 method->signature->param_count == 0 &&
1638 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
1639 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
1646 klass = klass->parent;
1651 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
1653 message = mono_string_to_utf8 (str);
1654 free_message = TRUE;
1659 * g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
1660 * exc->vtable->klass->name, message);
1662 g_printerr ("\nUnhandled Exception: %s\n", message);
1669 * mono_delegate_ctor:
1670 * @this: pointer to an uninitialized delegate object
1671 * @target: target object
1672 * @addr: pointer to native code
1674 * This is used to initialize a delegate. We also insert the method_info if
1675 * we find the info with mono_jit_info_table_find().
1678 mono_delegate_ctor (MonoObject *this, MonoObject *target, gpointer addr)
1680 MonoDomain *domain = mono_domain_get ();
1681 MonoDelegate *delegate = (MonoDelegate *)this;
1682 MonoMethod *method = NULL;
1689 class = this->vtable->klass;
1691 if ((ji = mono_jit_info_table_find (domain, addr))) {
1692 method = ji->method;
1693 delegate->method_info = mono_method_get_object (domain, method, NULL);
1696 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1698 method = mono_marshal_get_remoting_invoke (method);
1699 delegate->method_ptr = mono_compile_method (method);
1700 delegate->target = target;
1702 delegate->method_ptr = addr;
1703 delegate->target = target;
1708 * mono_method_call_message_new:
1710 * Translates arguments pointers into a Message.
1713 mono_method_call_message_new (MonoMethod *method, gpointer *params, MonoMethod *invoke,
1714 MonoDelegate **cb, MonoObject **state)
1716 MonoDomain *domain = mono_domain_get ();
1717 MonoMethodSignature *sig = method->signature;
1718 MonoMethodMessage *msg;
1721 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1724 mono_message_init (domain, msg, mono_method_get_object (domain, invoke, NULL), NULL);
1725 count = sig->param_count - 2;
1727 mono_message_init (domain, msg, mono_method_get_object (domain, method, NULL), NULL);
1728 count = sig->param_count;
1731 for (i = 0; i < count; i++) {
1736 if (sig->params [i]->byref)
1737 vpos = *((gpointer *)params [i]);
1741 type = sig->params [i]->type;
1742 class = mono_class_from_mono_type (sig->params [i]);
1744 if (class->valuetype)
1745 arg = mono_value_box (domain, class, vpos);
1747 arg = *((MonoObject **)vpos);
1749 mono_array_set (msg->args, gpointer, i, arg);
1753 *cb = *((MonoDelegate **)params [i]);
1755 *state = *((MonoObject **)params [i]);
1762 * mono_method_return_message_restore:
1764 * Restore results from message based processing back to arguments pointers
1767 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args)
1769 MonoMethodSignature *sig = method->signature;
1770 int i, j, type, size;
1772 for (i = 0, j = 0; i < sig->param_count; i++) {
1773 MonoType *pt = sig->params [i];
1775 size = mono_type_stack_size (pt, NULL);
1778 char *arg = mono_array_get (out_args, gpointer, j);
1782 case MONO_TYPE_VOID:
1783 g_assert_not_reached ();
1787 case MONO_TYPE_BOOLEAN:
1790 case MONO_TYPE_CHAR:
1797 case MONO_TYPE_VALUETYPE: {
1798 memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
1801 case MONO_TYPE_STRING:
1802 case MONO_TYPE_CLASS:
1803 case MONO_TYPE_ARRAY:
1804 case MONO_TYPE_SZARRAY:
1805 *((MonoObject **)params [i]) = (MonoObject *)arg;
1808 g_assert_not_reached ();
1817 * mono_load_remote_field:
1818 * @this: pointer to an object
1819 * @klass: klass of the object containing @field
1820 * @field: the field to load
1821 * @res: a storage to store the result
1823 * This method is called by the runtime on attempts to load fields of
1824 * transparent proxy objects. @this points to such TP, @klass is the class of
1825 * the object containing @field. @res is a storage location which can be
1826 * used to store the result.
1828 * Returns: an address pointing to the value of field.
1831 mono_load_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer *res)
1833 static MonoMethod *getter = NULL;
1834 MonoDomain *domain = mono_domain_get ();
1835 MonoClass *field_class;
1836 MonoMethodMessage *msg;
1837 MonoArray *out_args;
1841 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
1849 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
1850 MonoMethod *cm = mono_defaults.object_class->methods [i];
1852 if (!strcmp (cm->name, "FieldGetter")) {
1860 field_class = mono_class_from_mono_type (field->type);
1862 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1863 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
1864 mono_message_init (domain, msg, mono_method_get_object (domain, getter, NULL), out_args);
1866 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
1867 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
1869 mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)this)->rp, msg, &exc, &out_args);
1871 *res = mono_array_get (out_args, MonoObject *, 0);
1873 if (field_class->valuetype) {
1874 return ((char *)*res) + sizeof (MonoObject);
1880 * mono_store_remote_field:
1881 * @this: pointer to an object
1882 * @klass: klass of the object containing @field
1883 * @field: the field to load
1884 * @val: the value/object to store
1886 * This method is called by the runtime on attempts to store fields of
1887 * transparent proxy objects. @this points to such TP, @klass is the class of
1888 * the object containing @field. @val is the new value to store in @field.
1891 mono_store_remote_field (MonoObject *this, MonoClass *klass, MonoClassField *field, gpointer val)
1893 static MonoMethod *setter = NULL;
1894 MonoDomain *domain = mono_domain_get ();
1895 MonoClass *field_class;
1896 MonoMethodMessage *msg;
1897 MonoArray *out_args;
1901 g_assert (this->vtable->klass == mono_defaults.transparent_proxy_class);
1906 for (i = 0; i < mono_defaults.object_class->method.count; ++i) {
1907 MonoMethod *cm = mono_defaults.object_class->methods [i];
1909 if (!strcmp (cm->name, "FieldSetter")) {
1917 field_class = mono_class_from_mono_type (field->type);
1919 if (field_class->valuetype)
1920 arg = mono_value_box (domain, field_class, val);
1922 arg = *((MonoObject **)val);
1925 msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
1926 mono_message_init (domain, msg, mono_method_get_object (domain, setter, NULL), NULL);
1928 mono_array_set (msg->args, gpointer, 0, mono_string_new (domain, klass->name));
1929 mono_array_set (msg->args, gpointer, 1, mono_string_new (domain, field->name));
1930 mono_array_set (msg->args, gpointer, 2, arg);
1932 mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)this)->rp, msg, &exc, &out_args);