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 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
19 #include <limits.h> /* for PAGESIZE */
26 default_runtime_object_init (MonoObject *o)
31 MonoRuntimeObjectInit mono_runtime_object_init = default_runtime_object_init;
32 MonoRuntimeExecMain mono_runtime_exec_main = NULL;
35 mono_install_runtime_object_init (MonoRuntimeObjectInit func)
37 mono_runtime_object_init = func? func: default_runtime_object_init;
41 mono_install_runtime_exec_main (MonoRuntimeExecMain func)
43 mono_runtime_exec_main = func;
47 * mono_object_allocate:
48 * @size: number of bytes to allocate
50 * This is a very simplistic routine until we have our GC-aware
53 * Returns: an allocated object of size @size, or NULL on failure.
56 mono_object_allocate (size_t size)
58 void *o = calloc (1, size);
66 * Frees the memory used by the object. Debugging purposes
67 * only, as we will have our GC system.
70 mono_object_free (MonoObject *o)
72 MonoClass *c = o->klass;
74 memset (o, 0, c->instance_size);
80 * @klass: the class of the object that we want to create
82 * Returns: A newly created object whose definition is
83 * looked up using @klass
86 mono_object_new (MonoClass *klass)
91 mono_class_init (klass);
93 o = mono_object_allocate (klass->instance_size);
100 * mono_object_new_from_token:
101 * @image: Context where the type_token is hosted
102 * @token: a token of the type that we want to create
104 * Returns: A newly created object whose definition is
105 * looked up using @token in the @image image
108 mono_object_new_from_token (MonoImage *image, guint32 token)
112 class = mono_class_get (image, token);
114 return mono_object_new (class);
120 * @obj: the object to clone
122 * Returns: A newly created object who is a shallow copy of @obj
125 mono_object_clone (MonoObject *obj)
130 size = obj->klass->instance_size;
131 o = mono_object_allocate (size);
132 /* FIXME: handle arrays... */
134 memcpy (o, obj, size);
140 mono_array_new_full (MonoClass *array_class, guint32 *lengths, guint32 *lower_bounds)
145 MonoArrayBounds *bounds;
148 if (!array_class->inited)
149 mono_class_init (array_class);
150 byte_len = mono_array_element_size (array_class);
152 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
153 for (i = 0; i < array_class->rank; ++i) {
154 bounds [i].length = lengths [i];
155 byte_len *= lengths [i];
159 for (i = 0; i < array_class->rank; ++i)
160 bounds [i].lower_bound = lower_bounds [i];
162 * Following three lines almost taken from mono_object_new ():
163 * they need to be kept in sync.
165 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
168 o->klass = array_class;
170 array = (MonoArray*)o;
172 array->bounds = bounds;
173 array->max_length = bounds [0].length;
180 * @image: image where the object is being referenced
181 * @eclass: element class
182 * @n: number of array elements
184 * This routine creates a new szarray with @n elements of type @token
187 mono_array_new (MonoClass *eclass, guint32 n)
191 ac = mono_array_class_get (eclass, 1);
192 g_assert (ac != NULL);
194 return mono_array_new_full (ac, &n, NULL);
198 * mono_string_new_utf16:
199 * @text: a pointer to an utf16 string
200 * @len: the length of the string
202 * Returns: A newly created string object which contains @text.
205 mono_string_new_utf16 (const guint16 *text, gint32 len)
210 s = (MonoString*)mono_object_new (mono_defaults.string_class);
211 g_assert (s != NULL);
213 ca = (MonoArray *)mono_array_new (mono_defaults.string_class, len);
214 g_assert (ca != NULL);
219 memcpy (ca->vector, text, len * 2);
226 * @text: a pointer to an utf8 string
228 * Returns: A newly created string object which contains @text.
231 mono_string_new (const char *text)
233 GError *error = NULL;
234 MonoString *o = NULL;
241 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
244 o = mono_string_new_utf16 (ut, items_written);
246 g_error_free (error);
255 * @class: the class of the value
256 * @value: a pointer to the unboxed data
258 * Returns: A newly created object which contains @value.
261 mono_value_box (MonoClass *class, gpointer value)
266 g_assert (class->valuetype);
268 size = mono_class_instance_size (class);
269 res = mono_object_allocate (size);
272 size = size - sizeof (MonoObject);
274 memcpy ((char *)res + sizeof (MonoObject), value, size);
280 * mono_object_isinst:
282 * @klass: a pointer to a class
284 * Returns: @obj if @obj is derived from @klass
287 mono_object_isinst (MonoObject *obj, MonoClass *klass)
297 mono_class_init (klass);
299 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
300 if ((klass->interface_id <= oklass->max_interface_id) &&
301 oklass->interface_offsets [klass->interface_id])
304 if ((oklass->baseval - klass->baseval) <= klass->diffval)
311 static GHashTable *ldstr_table = NULL;
314 ldstr_hash (const char* str)
318 len = mono_metadata_decode_blob_size (str, &str);
322 * FIXME: The distribution may not be so nice with lots of
323 * null chars in the string.
325 for (str += 1; str < end; str++)
326 h = (h << 5) - h + *str;
331 ldstr_equal (const char *str1, const char *str2) {
333 if ((len=mono_metadata_decode_blob_size (str1, &str1)) !=
334 mono_metadata_decode_blob_size (str2, &str2))
336 return memcmp (str1, str2, len) == 0;
345 check_interned (gpointer key, MonoString *value, InternCheck *check)
347 if (value == check->obj)
348 check->found = value;
352 mono_string_is_interned (MonoString *o)
358 * Yes, this is slow. Our System.String implementation needs to be redone.
359 * And GLib needs foreach() methods that can be stopped halfway.
361 g_hash_table_foreach (ldstr_table, (GHFunc)check_interned, &check);
366 mono_string_intern (MonoString *str)
369 char *ins = g_malloc (4 + str->length * 2);
372 /* Encode the length */
374 mono_metadata_encode_value (str->length, p, &p);
375 memcpy (p, str->c_str->vector, str->length * 2);
377 if ((res = g_hash_table_lookup (ldstr_table, str))) {
381 g_hash_table_insert (ldstr_table, ins, str);
386 mono_ldstr (MonoImage *image, guint32 index)
388 const char *str, *sig;
393 ldstr_table = g_hash_table_new ((GHashFunc)ldstr_hash, (GCompareFunc)ldstr_equal);
395 sig = str = mono_metadata_user_string (image, index);
397 if ((o = g_hash_table_lookup (ldstr_table, str)))
400 len2 = mono_metadata_decode_blob_size (str, &str);
401 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
402 #define SWAP16(x) (x) = GUINT16_FROM_LE ((x))
407 /* FIXME: it will be better to just add WRITE and after get it to previous state */
408 mprotect ((void *) ((int) str & ~(PAGESIZE - 1)), len2 + ((int) str & (PAGESIZE - 1)),
409 PROT_READ | PROT_WRITE | PROT_EXEC);
411 /* printf ("swap %p\n", str); */
412 for (i = 0, s = (guint16 *) str; i < len2; i++, s++) {
413 *s = ((*s & 0xff) << 8) | (*s >> 8);
421 o = mono_string_new_utf16 ((guint16*)str, len2);
422 g_hash_table_insert (ldstr_table, (gpointer)sig, o);
428 mono_string_to_utf8 (MonoString *s)
431 GError *error = NULL;
433 g_assert (s != NULL);
435 if (!s->length || !s->c_str)
436 return g_strdup ("");
438 vector = (char*)s->c_str->vector;
440 g_assert (vector != NULL);
442 as = g_utf16_to_utf8 (vector, s->length, NULL, NULL, &error);
450 mono_string_to_utf16 (MonoString *s)
454 g_assert (s != NULL);
456 as = g_malloc ((s->length * 2) + 2);
457 as [(s->length * 2)] = '\0';
458 as [(s->length * 2) + 1] = '\0';
460 if (!s->length || !s->c_str) {
464 memcpy (as, mono_string_chars(s), s->length * 2);
470 default_ex_handler (MonoException *ex)
472 MonoObject *o = (MonoObject*)ex;
473 g_error ("Exception %s.%s raised in C code", o->klass->name_space, o->klass->name);
476 static MonoExceptionFunc ex_handler = default_ex_handler;
479 mono_install_handler (MonoExceptionFunc func)
481 ex_handler = func? func: default_ex_handler;
485 mono_raise_exception (MonoException *ex)