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/tabledefs.h>
15 #include <mono/metadata/loader.h>
16 #include <mono/metadata/object.h>
17 #include <mono/metadata/appdomain.h>
23 mono_runtime_object_init (MonoObject *this)
26 MonoMethod *method = NULL;
27 MonoClass *klass = this->vtable->klass;
29 for (i = 0; i < klass->method.count; ++i) {
30 if (!strcmp (".ctor", klass->methods [i]->name) &&
31 klass->methods [i]->signature->param_count == 0) {
32 method = klass->methods [i];
39 mono_runtime_invoke (method, this, NULL);
44 * @klass: klass that needs to be initialized
46 * This routine calls the class constructor for @class.
49 mono_runtime_class_init (MonoClass *klass)
53 for (i = 0; i < klass->method.count; ++i) {
54 MonoMethod *method = klass->methods [i];
55 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
56 (strcmp (".cctor", method->name) == 0)) {
57 mono_runtime_invoke (method, NULL, NULL);
61 /* No class constructor found */
65 static MonoInvokeFunc default_mono_runtime_invoke = NULL;
68 mono_runtime_invoke (MonoMethod *method, void *obj, void **params)
70 if (!default_mono_runtime_invoke) {
71 g_error ("runtime invoke called on uninitialized runtime");
74 return default_mono_runtime_invoke (method, obj, params);
78 mono_runtime_exec_main (MonoMethod *method, MonoArray *args)
84 if (method->signature->ret->type == MONO_TYPE_I4) {
86 res = mono_runtime_invoke (method, NULL, pa);
87 return *(guint32 *)((char *)res + sizeof (MonoObject));
89 mono_runtime_invoke (method, NULL, pa);
95 mono_install_runtime_invoke (MonoInvokeFunc func)
97 default_mono_runtime_invoke = func;
101 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params)
103 MonoMethodSignature *sig = method->signature;
107 pa = alloca (sizeof (gpointer) * params->bounds->length);
109 for (i = 0; i < params->bounds->length; i++) {
110 if (sig->params [i]->byref) {
114 switch (sig->params [i]->type) {
117 case MONO_TYPE_BOOLEAN:
127 case MONO_TYPE_VALUETYPE:
128 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
130 case MONO_TYPE_STRING:
131 case MONO_TYPE_OBJECT:
132 case MONO_TYPE_CLASS:
133 pa [i] = (char *)(((gpointer *)params->vector)[i]);
136 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
140 if (!strcmp (method->name, ".ctor")) {
141 obj = mono_object_new (mono_domain_get (), method->klass);
142 mono_runtime_invoke (method, obj, pa);
145 return mono_runtime_invoke (method, obj, pa);
149 * mono_object_allocate:
150 * @size: number of bytes to allocate
152 * This is a very simplistic routine until we have our GC-aware
155 * Returns: an allocated object of size @size, or NULL on failure.
158 mono_object_allocate (size_t size)
161 void *o = GC_debug_malloc (size, "object", 1);
163 void *o = calloc (1, size);
172 * Frees the memory used by the object. Debugging purposes
173 * only, as we will have our GC system.
176 mono_object_free (MonoObject *o)
179 g_error ("mono_object_free called with boehm gc.");
181 MonoClass *c = o->vtable->klass;
183 memset (o, 0, c->instance_size);
190 * @klass: the class of the object that we want to create
192 * Returns: A newly created object whose definition is
193 * looked up using @klass
196 mono_object_new (MonoDomain *domain, MonoClass *klass)
198 static guint32 uoid = 0;
202 mono_class_init (klass);
205 if (klass->ghcimpl) {
206 o = mono_object_allocate (klass->instance_size);
207 o->vtable = mono_class_vtable (domain, klass);
210 t = mono_object_allocate (klass->instance_size + 4);
212 o = (MonoObject *)(++t);
213 o->vtable = mono_class_vtable (domain, klass);
220 * mono_object_new_from_token:
221 * @image: Context where the type_token is hosted
222 * @token: a token of the type that we want to create
224 * Returns: A newly created object whose definition is
225 * looked up using @token in the @image image
228 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
232 class = mono_class_get (image, token);
234 return mono_object_new (domain, class);
240 * @obj: the object to clone
242 * Returns: A newly created object who is a shallow copy of @obj
245 mono_object_clone (MonoObject *obj)
250 size = obj->vtable->klass->instance_size;
251 o = mono_object_allocate (size);
253 memcpy (o, obj, size);
260 * @array: the array to clone
262 * Returns: A newly created array who is a shallow copy of @array
265 mono_array_clone (MonoArray *array)
270 MonoClass *klass = array->obj.vtable->klass;
272 sizes = alloca (klass->rank * sizeof(guint32) * 2);
273 size = mono_array_element_size (klass);
274 for (i = 0; i < klass->rank; ++i) {
275 sizes [i] = array->bounds [i].length;
276 size *= array->bounds [i].length;
277 sizes [i + klass->rank] = array->bounds [i].lower_bound;
279 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
280 klass, sizes, sizes + klass->rank);
281 memcpy (o, array, sizeof(MonoArray) + size);
287 * mono_array_new_full:
288 * @domain: domain where the object is created
289 * @array_class: array class
290 * @lengths: lengths for each dimension in the array
291 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
293 * This routine creates a new array objects with the given dimensions,
294 * lower bounds and type.
297 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
298 guint32 *lengths, guint32 *lower_bounds)
303 MonoArrayBounds *bounds;
306 if (!array_class->inited)
307 mono_class_init (array_class);
309 byte_len = mono_array_element_size (array_class);
312 bounds = GC_debug_malloc (sizeof (MonoArrayBounds) * array_class->rank, "bounds", 0);
314 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
316 for (i = 0; i < array_class->rank; ++i) {
317 bounds [i].length = lengths [i];
318 byte_len *= lengths [i];
322 for (i = 0; i < array_class->rank; ++i)
323 bounds [i].lower_bound = lower_bounds [i];
325 * Following three lines almost taken from mono_object_new ():
326 * they need to be kept in sync.
328 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
331 o->vtable = mono_class_vtable (domain, array_class);
333 array = (MonoArray*)o;
335 array->bounds = bounds;
336 array->max_length = bounds [0].length;
343 * @domain: domain where the object is created
344 * @eclass: element class
345 * @n: number of array elements
347 * This routine creates a new szarray with @n elements of type @eclass.
350 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
354 ac = mono_array_class_get (&eclass->byval_arg, 1);
355 g_assert (ac != NULL);
357 return mono_array_new_full (domain, ac, &n, NULL);
361 * mono_string_new_utf16:
362 * @text: a pointer to an utf16 string
363 * @len: the length of the string
365 * Returns: A newly created string object which contains @text.
368 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
373 s = (MonoString*)mono_object_new (domain, mono_defaults.string_class);
374 g_assert (s != NULL);
376 ca = (MonoArray *)mono_array_new (domain, mono_defaults.char_class, len);
377 g_assert (ca != NULL);
382 memcpy (ca->vector, text, len * 2);
388 * mono_string_new_len:
389 * @text: a pointer to an utf8 string
390 * @length: number of bytes in @text to consider
392 * Returns: A newly created string object which contains @text.
395 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
397 GError *error = NULL;
398 MonoString *o = NULL;
403 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
406 o = mono_string_new_utf16 (domain, ut, items_written);
408 g_error_free (error);
417 * @text: a pointer to an utf8 string
419 * Returns: A newly created string object which contains @text.
422 mono_string_new (MonoDomain *domain, const char *text)
424 GError *error = NULL;
425 MonoString *o = NULL;
432 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
435 o = mono_string_new_utf16 (domain, ut, items_written);
437 g_error_free (error);
445 * mono_string_new_wrapper:
446 * @text: pointer to utf8 characters.
448 * Helper function to create a string object from @text in the current domain.
451 mono_string_new_wrapper (const char *text)
453 MonoDomain *domain = mono_domain_get ();
455 return mono_string_new (domain, text);
460 * @class: the class of the value
461 * @value: a pointer to the unboxed data
463 * Returns: A newly created object which contains @value.
466 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
471 g_assert (class->valuetype);
473 size = mono_class_instance_size (class);
474 res = mono_object_allocate (size);
475 res->vtable = mono_class_vtable (domain, class);
477 size = size - sizeof (MonoObject);
479 memcpy ((char *)res + sizeof (MonoObject), value, size);
485 * mono_object_isinst:
487 * @klass: a pointer to a class
489 * Returns: @obj if @obj is derived from @klass
492 mono_object_isinst (MonoObject *obj, MonoClass *klass)
504 mono_class_init (klass);
506 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
507 if ((klass->interface_id <= oklass->max_interface_id) &&
508 vt->interface_offsets [klass->interface_id])
511 if (oklass == mono_defaults.transparent_proxy_class) {
512 /* fixme: add check for IRemotingTypeInfo */
513 MonoRealProxy *rp = ((MonoTransparentProxy *)obj)->rp;
515 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
516 oklass = mono_class_from_mono_type (type);
518 if (oklass->rank && oklass->rank == klass->rank) {
519 if ((oklass->element_class->baseval - klass->element_class->baseval) <=
520 klass->element_class->diffval)
522 } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
530 mono_string_is_interned_lookup (MonoString *str, int insert)
532 MonoGHashTable *ldstr_table;
534 char *ins = g_malloc (4 + str->length * 2);
538 /* Encode the length */
540 mono_metadata_encode_value (2 * str->length, p, &p);
543 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
544 bloblen = (p - ins) + 2 * str->length;
546 * ins is stored in the hash table as a key and needs to have the same
547 * representation as in the metadata: we swap the character bytes on big
550 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
553 char *p2 = mono_array_addr (str->c_str, char, 0);
554 for (i = 0; i < str->length; ++i) {
561 memcpy (p, str->c_str->vector, str->length * 2);
563 ldstr_table = ((MonoObject *)str)->vtable->domain->ldstr_table;
564 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
569 mono_g_hash_table_insert (ldstr_table, ins, str);
577 mono_string_is_interned (MonoString *o)
579 return mono_string_is_interned_lookup (o, FALSE);
583 mono_string_intern (MonoString *str)
585 return mono_string_is_interned_lookup (str, TRUE);
590 * @domain: the domain where the string will be used.
591 * @image: a metadata context
592 * @idx: index into the user string table.
594 * Implementation for the ldstr opcode.
597 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
599 const char *str, *sig;
603 sig = str = mono_metadata_user_string (image, idx);
605 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig)))
608 len2 = mono_metadata_decode_blob_size (str, &str);
611 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
612 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
615 guint16 *p2 = (guint16*)mono_array_addr (o->c_str, guint16, 0);
616 for (i = 0; i < len2; ++i) {
617 *p2 = GUINT16_FROM_LE (*p2);
622 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
628 * mono_string_to_utf8:
629 * @s: a System.String
631 * Return the UTF8 representation for @s.
632 * the resulting buffer nedds to be freed with g_free().
635 mono_string_to_utf8 (MonoString *s)
638 GError *error = NULL;
640 g_assert (s != NULL);
642 if (!s->length || !s->c_str)
643 return g_strdup ("");
645 vector = (char*)s->c_str->vector;
647 g_assert (vector != NULL);
649 as = g_utf16_to_utf8 ((gunichar2 *)vector, s->length, NULL, NULL, &error);
651 g_warning (error->message);
657 * mono_string_to_utf16:
660 * Return an null-terminated array of the utf-16 chars
661 * contained in @s. The result must be freed with g_free().
662 * This is a temporary helper until our string implementation
663 * is reworked to always include the null terminating char.
666 mono_string_to_utf16 (MonoString *s)
670 g_assert (s != NULL);
672 as = g_malloc ((s->length * 2) + 2);
673 as [(s->length * 2)] = '\0';
674 as [(s->length * 2) + 1] = '\0';
676 if (!s->length || !s->c_str) {
677 return (gunichar2 *)(as);
680 memcpy (as, mono_string_chars(s), s->length * 2);
682 return (gunichar2 *)(as);
686 default_ex_handler (MonoException *ex)
688 MonoObject *o = (MonoObject*)ex;
689 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
692 static MonoExceptionFunc ex_handler = default_ex_handler;
695 mono_install_handler (MonoExceptionFunc func)
697 ex_handler = func? func: default_ex_handler;
701 * mono_raise_exception:
702 * @ex: exception object
704 * Signal the runtime that the exception @ex has been raised in unmanaged code.
707 mono_raise_exception (MonoException *ex)
713 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
717 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
719 res->handle = handle;
725 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
727 MonoAsyncResult *res;
729 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
732 res->async_state = state;
733 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
734 res->sync_completed = FALSE;
735 res->completed = FALSE;
741 mono_message_init (MonoDomain *domain,
742 MonoMethodMessage *this,
743 MonoReflectionMethod *method,
746 MonoMethodSignature *sig = method->method->signature;
752 this->method = method;
754 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
755 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
757 names = g_new (char *, sig->param_count);
758 mono_method_get_param_names (method->method, (const char **) names);
759 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
761 for (i = 0; i < sig->param_count; i++) {
762 name = mono_string_new (domain, names [i]);
763 mono_array_set (this->names, gpointer, i, name);
768 for (i = 0, j = 0; i < sig->param_count; i++) {
770 if (sig->params [i]->byref) {
772 gpointer arg = mono_array_get (out_args, gpointer, j);
773 mono_array_set (this->args, gpointer, i, arg);
777 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
783 mono_array_set (this->arg_types, guint8, i, arg_type);
788 * mono_remoting_invoke:
789 * @real_proxy: pointer to a RealProxy object
790 * @msg: The MonoMethodMessage to execute
791 * @exc: used to store exceptions
792 * @out_args: used to store output arguments
794 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
795 * IMessage interface and it is not trivial to extract results from there. So
796 * we call an helper method PrivateInvoke instead of calling
797 * RealProxy::Invoke() directly.
799 * Returns: the result object.
802 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
803 MonoObject **exc, MonoArray **out_args)
805 static MonoMethod *im = NULL;
808 //static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;
810 /* fixme: make this domain dependent */
815 klass = mono_defaults.real_proxy_class;
817 for (i = 0; i < klass->method.count; ++i) {
818 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
819 klass->methods [i]->signature->param_count == 4) {
820 im = klass->methods [i];
833 return mono_runtime_invoke (im, NULL, pa);
837 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
838 MonoObject **exc, MonoArray **out_args)
840 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
842 return mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)target)->rp,
846 MonoDomain *domain = mono_domain_get ();
847 MonoMethod *method = msg->method->method;
848 MonoMethodSignature *sig = method->signature;
850 int i, j, outarg_count = 0;
852 for (i = 0; i < sig->param_count; i++) {
853 if (sig->params [i]->byref)
857 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
860 for (i = 0, j = 0; i < sig->param_count; i++) {
861 if (sig->params [i]->byref) {
863 arg = mono_array_get (msg->args, gpointer, i);
864 mono_array_set (*out_args, gpointer, j, arg);
869 return mono_runtime_invoke_array (method, target, msg->args);