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_malloc (size);
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);
196 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
197 for (i = 0; i < array_class->rank; ++i) {
198 bounds [i].length = lengths [i];
199 byte_len *= lengths [i];
203 for (i = 0; i < array_class->rank; ++i)
204 bounds [i].lower_bound = lower_bounds [i];
206 * Following three lines almost taken from mono_object_new ():
207 * they need to be kept in sync.
209 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
212 o->vtable = mono_class_vtable (domain, array_class);
214 array = (MonoArray*)o;
216 array->bounds = bounds;
217 array->max_length = bounds [0].length;
224 * @image: image where the object is being referenced
225 * @eclass: element class
226 * @n: number of array elements
228 * This routine creates a new szarray with @n elements of type @token
231 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
235 ac = mono_array_class_get (&eclass->byval_arg, 1);
236 g_assert (ac != NULL);
238 return mono_array_new_full (domain, ac, &n, NULL);
242 * mono_string_new_utf16:
243 * @text: a pointer to an utf16 string
244 * @len: the length of the string
246 * Returns: A newly created string object which contains @text.
249 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
254 s = (MonoString*)mono_object_new (domain, mono_defaults.string_class);
255 g_assert (s != NULL);
257 ca = (MonoArray *)mono_array_new (domain, mono_defaults.char_class, len);
258 g_assert (ca != NULL);
263 memcpy (ca->vector, text, len * 2);
269 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
271 GError *error = NULL;
272 MonoString *o = NULL;
277 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
280 o = mono_string_new_utf16 (domain, ut, items_written);
282 g_error_free (error);
291 * @text: a pointer to an utf8 string
293 * Returns: A newly created string object which contains @text.
296 mono_string_new (MonoDomain *domain, const char *text)
298 GError *error = NULL;
299 MonoString *o = NULL;
306 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
309 o = mono_string_new_utf16 (domain, ut, items_written);
311 g_error_free (error);
320 * @class: the class of the value
321 * @value: a pointer to the unboxed data
323 * Returns: A newly created object which contains @value.
326 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
331 g_assert (class->valuetype);
333 size = mono_class_instance_size (class);
334 res = mono_object_allocate (size);
335 res->vtable = mono_class_vtable (domain, class);
337 size = size - sizeof (MonoObject);
339 memcpy ((char *)res + sizeof (MonoObject), value, size);
345 * mono_object_isinst:
347 * @klass: a pointer to a class
349 * Returns: @obj if @obj is derived from @klass
352 mono_object_isinst (MonoObject *obj, MonoClass *klass)
364 mono_class_init (klass);
366 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
367 if ((klass->interface_id <= oklass->max_interface_id) &&
368 vt->interface_offsets [klass->interface_id])
371 if (oklass->rank && oklass->rank == klass->rank) {
372 if ((oklass->element_class->baseval - klass->element_class->baseval) <=
373 klass->element_class->diffval)
375 } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
389 check_interned (gpointer key, MonoString *value, InternCheck *check)
391 if (value == check->obj)
392 check->found = value;
396 mono_string_is_interned (MonoString *o)
403 * Yes, this is slow. Our System.String implementation needs to be redone.
404 * And GLib needs foreach() methods that can be stopped halfway.
406 g_hash_table_foreach (((MonoObject *)o)->vtable->domain->ldstr_table, (GHFunc)check_interned, &check);
411 mono_string_intern (MonoString *str)
413 GHashTable *ldstr_table;
415 char *ins = g_malloc (4 + str->length * 2);
419 /* Encode the length */
421 mono_metadata_encode_value (2 * str->length, p, &p);
424 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
425 bloblen = (p - ins) + 2 * str->length;
427 * ins is stored in the hash table as a key and needs to have the same
428 * representation as in the metadata: we swap the character bytes on big
431 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
434 char *p2 = mono_array_addr (str->c_str, char, 0);
435 for (i = 0; i < str->length; ++i) {
442 memcpy (p, str->c_str->vector, str->length * 2);
444 ldstr_table = ((MonoObject *)str)->vtable->domain->ldstr_table;
445 if ((res = g_hash_table_lookup (ldstr_table, ins))) {
449 g_hash_table_insert (ldstr_table, ins, str);
454 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 index)
456 const char *str, *sig;
460 sig = str = mono_metadata_user_string (image, index);
461 len2 = mono_metadata_decode_blob_size (str, &str);
463 if ((o = g_hash_table_lookup (domain->ldstr_table, sig)))
468 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
469 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
472 guint16 *p2 = (guint16*)mono_array_addr (o->c_str, guint16, 0);
473 for (i = 0; i < len2; ++i) {
474 *p2 = GUINT16_FROM_LE (*p2);
479 g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
485 mono_string_to_utf8 (MonoString *s)
488 GError *error = NULL;
490 g_assert (s != NULL);
492 if (!s->length || !s->c_str)
493 return g_strdup ("");
495 vector = (char*)s->c_str->vector;
497 g_assert (vector != NULL);
499 as = g_utf16_to_utf8 ((gunichar2 *)vector, s->length, NULL, NULL, &error);
501 g_warning (error->message);
507 mono_string_to_utf16 (MonoString *s)
511 g_assert (s != NULL);
513 as = g_malloc ((s->length * 2) + 2);
514 as [(s->length * 2)] = '\0';
515 as [(s->length * 2) + 1] = '\0';
517 if (!s->length || !s->c_str) {
521 memcpy (as, mono_string_chars(s), s->length * 2);
527 default_ex_handler (MonoException *ex)
529 MonoObject *o = (MonoObject*)ex;
530 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
533 static MonoExceptionFunc ex_handler = default_ex_handler;
536 mono_install_handler (MonoExceptionFunc func)
538 ex_handler = func? func: default_ex_handler;
542 mono_raise_exception (MonoException *ex)