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 default_runtime_object_init (MonoObject *o)
28 MonoRuntimeObjectInit mono_runtime_object_init = default_runtime_object_init;
29 MonoRuntimeExecMain mono_runtime_exec_main = NULL;
32 mono_install_runtime_object_init (MonoRuntimeObjectInit func)
34 mono_runtime_object_init = func? func: default_runtime_object_init;
38 mono_install_runtime_exec_main (MonoRuntimeExecMain func)
40 mono_runtime_exec_main = func;
44 * mono_object_allocate:
45 * @size: number of bytes to allocate
47 * This is a very simplistic routine until we have our GC-aware
50 * Returns: an allocated object of size @size, or NULL on failure.
53 mono_object_allocate (size_t size)
56 void *o = GC_debug_malloc (size, "object", 1);
58 void *o = calloc (1, size);
67 * Frees the memory used by the object. Debugging purposes
68 * only, as we will have our GC system.
71 mono_object_free (MonoObject *o)
74 g_error ("mono_object_free called with boehm gc.");
76 MonoClass *c = o->vtable->klass;
78 memset (o, 0, c->instance_size);
85 * @klass: the class of the object that we want to create
87 * Returns: A newly created object whose definition is
88 * looked up using @klass
91 mono_object_new (MonoDomain *domain, MonoClass *klass)
93 static guint32 uoid = 0;
97 mono_class_init (klass);
100 if (klass->ghcimpl) {
101 o = mono_object_allocate (klass->instance_size);
102 o->vtable = mono_class_vtable (domain, klass);
105 t = mono_object_allocate (klass->instance_size + 4);
107 o = (MonoObject *)(++t);
108 o->vtable = mono_class_vtable (domain, klass);
115 * mono_object_new_from_token:
116 * @image: Context where the type_token is hosted
117 * @token: a token of the type that we want to create
119 * Returns: A newly created object whose definition is
120 * looked up using @token in the @image image
123 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
127 class = mono_class_get (image, token);
129 return mono_object_new (domain, class);
135 * @obj: the object to clone
137 * Returns: A newly created object who is a shallow copy of @obj
140 mono_object_clone (MonoObject *obj)
145 size = obj->vtable->klass->instance_size;
146 o = mono_object_allocate (size);
148 memcpy (o, obj, size);
155 * @array: the array to clone
157 * Returns: A newly created array who is a shallow copy of @array
160 mono_array_clone (MonoArray *array)
165 MonoClass *klass = array->obj.vtable->klass;
167 sizes = alloca (klass->rank * sizeof(guint32) * 2);
168 size = mono_array_element_size (klass);
169 for (i = 0; i < klass->rank; ++i) {
170 sizes [i] = array->bounds [i].length;
171 size *= array->bounds [i].length;
172 sizes [i + klass->rank] = array->bounds [i].lower_bound;
174 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
175 klass, sizes, sizes + klass->rank);
176 memcpy (o, array, sizeof(MonoArray) + size);
182 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
183 guint32 *lengths, guint32 *lower_bounds)
188 MonoArrayBounds *bounds;
191 if (!array_class->inited)
192 mono_class_init (array_class);
194 byte_len = mono_array_element_size (array_class);
197 bounds = GC_debug_malloc (sizeof (MonoArrayBounds) * array_class->rank, "bounds", 0);
199 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
201 for (i = 0; i < array_class->rank; ++i) {
202 bounds [i].length = lengths [i];
203 byte_len *= lengths [i];
207 for (i = 0; i < array_class->rank; ++i)
208 bounds [i].lower_bound = lower_bounds [i];
210 * Following three lines almost taken from mono_object_new ():
211 * they need to be kept in sync.
213 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
216 o->vtable = mono_class_vtable (domain, array_class);
218 array = (MonoArray*)o;
220 array->bounds = bounds;
221 array->max_length = bounds [0].length;
228 * @image: image where the object is being referenced
229 * @eclass: element class
230 * @n: number of array elements
232 * This routine creates a new szarray with @n elements of type @token
235 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
239 ac = mono_array_class_get (&eclass->byval_arg, 1);
240 g_assert (ac != NULL);
242 return mono_array_new_full (domain, ac, &n, NULL);
246 * mono_string_new_utf16:
247 * @text: a pointer to an utf16 string
248 * @len: the length of the string
250 * Returns: A newly created string object which contains @text.
253 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
258 s = (MonoString*)mono_object_new (domain, mono_defaults.string_class);
259 g_assert (s != NULL);
261 ca = (MonoArray *)mono_array_new (domain, mono_defaults.char_class, len);
262 g_assert (ca != NULL);
267 memcpy (ca->vector, text, len * 2);
273 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
275 GError *error = NULL;
276 MonoString *o = NULL;
281 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
284 o = mono_string_new_utf16 (domain, ut, items_written);
286 g_error_free (error);
295 * @text: a pointer to an utf8 string
297 * Returns: A newly created string object which contains @text.
300 mono_string_new (MonoDomain *domain, const char *text)
302 GError *error = NULL;
303 MonoString *o = NULL;
310 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
313 o = mono_string_new_utf16 (domain, ut, items_written);
315 g_error_free (error);
323 mono_string_new_wrapper (const char *text)
325 MonoDomain *domain = mono_domain_get ();
327 return mono_string_new (domain, text);
332 * @class: the class of the value
333 * @value: a pointer to the unboxed data
335 * Returns: A newly created object which contains @value.
338 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
343 g_assert (class->valuetype);
345 size = mono_class_instance_size (class);
346 res = mono_object_allocate (size);
347 res->vtable = mono_class_vtable (domain, class);
349 size = size - sizeof (MonoObject);
351 memcpy ((char *)res + sizeof (MonoObject), value, size);
357 * mono_object_isinst:
359 * @klass: a pointer to a class
361 * Returns: @obj if @obj is derived from @klass
364 mono_object_isinst (MonoObject *obj, MonoClass *klass)
376 mono_class_init (klass);
378 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
379 if ((klass->interface_id <= oklass->max_interface_id) &&
380 vt->interface_offsets [klass->interface_id])
383 if (oklass == mono_defaults.transparent_proxy_class) {
384 /* fixme: add check for IRemotingTypeInfo */
385 MonoRealProxy *rp = ((MonoTransparentProxy *)obj)->rp;
387 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
388 oklass = mono_class_from_mono_type (type);
390 if (oklass->rank && oklass->rank == klass->rank) {
391 if ((oklass->element_class->baseval - klass->element_class->baseval) <=
392 klass->element_class->diffval)
394 } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
402 mono_string_is_interned_lookup (MonoString *str, int insert)
404 MonoGHashTable *ldstr_table;
406 char *ins = g_malloc (4 + str->length * 2);
410 /* Encode the length */
412 mono_metadata_encode_value (2 * str->length, p, &p);
415 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
416 bloblen = (p - ins) + 2 * str->length;
418 * ins is stored in the hash table as a key and needs to have the same
419 * representation as in the metadata: we swap the character bytes on big
422 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
425 char *p2 = mono_array_addr (str->c_str, char, 0);
426 for (i = 0; i < str->length; ++i) {
433 memcpy (p, str->c_str->vector, str->length * 2);
435 ldstr_table = ((MonoObject *)str)->vtable->domain->ldstr_table;
436 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
441 mono_g_hash_table_insert (ldstr_table, ins, str);
449 mono_string_is_interned (MonoString *o)
451 return mono_string_is_interned_lookup (o, FALSE);
455 mono_string_intern (MonoString *str)
457 return mono_string_is_interned_lookup (str, TRUE);
461 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 index)
463 const char *str, *sig;
467 sig = str = mono_metadata_user_string (image, index);
469 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig)))
472 len2 = mono_metadata_decode_blob_size (str, &str);
475 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
476 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
479 guint16 *p2 = (guint16*)mono_array_addr (o->c_str, guint16, 0);
480 for (i = 0; i < len2; ++i) {
481 *p2 = GUINT16_FROM_LE (*p2);
486 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
492 mono_string_to_utf8 (MonoString *s)
495 GError *error = NULL;
497 g_assert (s != NULL);
499 if (!s->length || !s->c_str)
500 return g_strdup ("");
502 vector = (char*)s->c_str->vector;
504 g_assert (vector != NULL);
506 as = g_utf16_to_utf8 ((gunichar2 *)vector, s->length, NULL, NULL, &error);
508 g_warning (error->message);
514 mono_string_to_utf16 (MonoString *s)
518 g_assert (s != NULL);
520 as = g_malloc ((s->length * 2) + 2);
521 as [(s->length * 2)] = '\0';
522 as [(s->length * 2) + 1] = '\0';
524 if (!s->length || !s->c_str) {
525 return (gunichar2 *)(as);
528 memcpy (as, mono_string_chars(s), s->length * 2);
530 return (gunichar2 *)(as);
534 default_ex_handler (MonoException *ex)
536 MonoObject *o = (MonoObject*)ex;
537 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
540 static MonoExceptionFunc ex_handler = default_ex_handler;
543 mono_install_handler (MonoExceptionFunc func)
545 ex_handler = func? func: default_ex_handler;
549 mono_raise_exception (MonoException *ex)
555 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
559 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
561 res->handle = handle;
567 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
569 MonoAsyncResult *res;
571 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
574 res->async_state = state;
575 res->handle = mono_wait_handle_new (domain, handle);
576 res->sync_completed = FALSE;
577 res->completed = FALSE;