Mon Apr 29 12:47:36 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / object.c
index 29b1405b7418e02f6882e774133a22549adbe38d..a7f45a0a635b177922699ee6fb9432cb2cd5abde 100644 (file)
@@ -16,6 +16,7 @@
 #include <mono/metadata/tokentype.h>
 #include <mono/metadata/loader.h>
 #include <mono/metadata/object.h>
+#include <mono/metadata/gc.h>
 #include <mono/metadata/appdomain.h>
 #if HAVE_BOEHM_GC
 #include <gc/gc.h>
@@ -23,6 +24,9 @@
 
 MonoStats mono_stats;
 
+/* next object id for object hashcode */
+static guint32 uoid = 0;
+
 void
 mono_runtime_object_init (MonoObject *this)
 {
@@ -208,7 +212,7 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
                        break;
                }
                case MONO_TYPE_STRING: {
-                       gpointer *val = (gpointer*)t;
+                       //gpointer *val = (gpointer*)t;
                        //*val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
                        break;
                }
@@ -332,39 +336,40 @@ MonoObject*
 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params)
 {
        MonoMethodSignature *sig = method->signature;
-       gpointer *pa;
+       gpointer *pa = NULL;
        int i;
+               
+       if (NULL != params) {
+               pa = alloca (sizeof (gpointer) * mono_array_length (params));
+               for (i = 0; i < mono_array_length (params); i++) {
+                       if (sig->params [i]->byref) {
+                               /* nothing to do */
+                       }
 
-       pa = alloca (sizeof (gpointer) * mono_array_length (params));
-
-       for (i = 0; i < mono_array_length (params); i++) {
-               if (sig->params [i]->byref) {
-                       /* nothing to do */
-               }
-
-               switch (sig->params [i]->type) {
-               case MONO_TYPE_U1:
-               case MONO_TYPE_I1:
-               case MONO_TYPE_BOOLEAN:
-               case MONO_TYPE_U2:
-               case MONO_TYPE_I2:
-               case MONO_TYPE_CHAR:
-               case MONO_TYPE_U:
-               case MONO_TYPE_I:
-               case MONO_TYPE_U4:
-               case MONO_TYPE_I4:
-               case MONO_TYPE_U8:
-               case MONO_TYPE_I8:
-               case MONO_TYPE_VALUETYPE:
-                       pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
-                       break;
-               case MONO_TYPE_STRING:
-               case MONO_TYPE_OBJECT:
-               case MONO_TYPE_CLASS:
-                       pa [i] = (char *)(((gpointer *)params->vector)[i]);
-                       break;
-               default:
-                       g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
+                       switch (sig->params [i]->type) {
+                       case MONO_TYPE_U1:
+                       case MONO_TYPE_I1:
+                       case MONO_TYPE_BOOLEAN:
+                       case MONO_TYPE_U2:
+                       case MONO_TYPE_I2:
+                       case MONO_TYPE_CHAR:
+                       case MONO_TYPE_U:
+                       case MONO_TYPE_I:
+                       case MONO_TYPE_U4:
+                       case MONO_TYPE_I4:
+                       case MONO_TYPE_U8:
+                       case MONO_TYPE_I8:
+                       case MONO_TYPE_VALUETYPE:
+                               pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
+                               break;
+                       case MONO_TYPE_STRING:
+                       case MONO_TYPE_OBJECT:
+                       case MONO_TYPE_CLASS:
+                               pa [i] = (char *)(((gpointer *)params->vector)[i]);
+                               break;
+                       default:
+                               g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
+                       }
                }
        }
 
@@ -389,7 +394,8 @@ void *
 mono_object_allocate (size_t size)
 {
 #if HAVE_BOEHM_GC
-       void *o = GC_debug_malloc (size, "object", 1);
+       /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
+       void *o = GC_malloc (size);
 #else
        void *o = calloc (1, size);
 #endif
@@ -426,24 +432,38 @@ mono_object_free (MonoObject *o)
 MonoObject *
 mono_object_new (MonoDomain *domain, MonoClass *klass)
 {
-       static guint32 uoid = 0;
-       MonoObject *o;
+       return mono_object_new_specific (mono_class_vtable (domain, klass));
+}
 
-       mono_stats.new_object_count++;
+/**
+ * mono_object_new_specific:
+ * @vtable: the vtable of the object that we want to create
+ *
+ * Returns: A newly created object with class and domain specified
+ * by @vtable
+ */
+MonoObject *
+mono_object_new_specific (MonoVTable *vtable)
+{
+       MonoObject *o;
 
-       if (!klass->inited)
-               mono_class_init (klass);
+       mono_stats.new_object_count++;          /* thread safe? */
 
-       if (klass->ghcimpl) {
-               o = mono_object_allocate (klass->instance_size);
-       } else {
+       /* if the returned pointer is not the same as the address returned by GC_malloc(), 
+        * we need to change also metadata/gc.c to take into account the new offset.
+        */
+       if (vtable->klass->ghcimpl)
+               o = mono_object_allocate (vtable->klass->instance_size);
+       else {
                guint32 *t;
-               t = mono_object_allocate (klass->instance_size + 4);
+               t = mono_object_allocate (vtable->klass->instance_size + 4);
                *t = ++uoid;
                o = (MonoObject *)(++t);
        }
-       o->vtable = mono_class_vtable (domain, klass);
-
+       o->vtable = vtable;
+       if (vtable->klass->has_finalize)
+               mono_object_register_finalizer (o);
+       
        return o;
 }
 
@@ -483,6 +503,8 @@ mono_object_clone (MonoObject *obj)
 
        memcpy (o, obj, size);
 
+       if (obj->vtable->klass->has_finalize)
+               mono_object_register_finalizer (o);
        return o;
 }
 
@@ -551,12 +573,13 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
        byte_len = mono_array_element_size (array_class);
        len = 1;
 
-       if (array_class->this_arg.type == MONO_TYPE_SZARRAY) {
+       if (array_class->rank == 1 &&
+           (lower_bounds == NULL || lower_bounds [0] == 0)) {
                bounds = NULL;
                len = lengths [0];
        } else {
        #if HAVE_BOEHM_GC
-               bounds = GC_debug_malloc (sizeof (MonoArrayBounds) * array_class->rank, "bounds", 0);
+               bounds = GC_malloc (sizeof (MonoArrayBounds) * array_class->rank);
        #else
                bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
        #endif
@@ -604,7 +627,35 @@ mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
        ac = mono_array_class_get (&eclass->byval_arg, 1);
        g_assert (ac != NULL);
 
-       return mono_array_new_full (domain, ac, &n, NULL);
+       return mono_array_new_specific (mono_class_vtable (domain, ac), n);
+}
+
+/*
+ * mono_array_new_specific:
+ * @vtable: a vtable in the appropriate domain for an initialized class
+ * @n: number of array elements
+ *
+ * This routine is a fast alternative to mono_array_new() for code which
+ * can be sure about the domain it operates in.
+ */
+MonoArray *
+mono_array_new_specific (MonoVTable *vtable, guint32 n)
+{
+       MonoObject *o;
+       MonoArray *ao;
+       gsize byte_len;
+
+       byte_len = n * mono_array_element_size (vtable->klass);
+       o = mono_object_allocate (sizeof (MonoArray) + byte_len);
+       if (!o)
+               G_BREAKPOINT ();
+       o->vtable = vtable;
+
+       ao = (MonoArray *)o;
+       ao->bounds = NULL;
+       ao->max_length = n;
+
+       return ao;
 }
 
 /**
@@ -618,12 +669,11 @@ MonoString *
 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
 {
        MonoString *s;
-       MonoArray *ca;
        
        s = mono_string_new_size (domain, len);
        g_assert (s != NULL);
 
-       memcpy (s->c_str->vector, text, len * 2);
+       memcpy (mono_string_chars (s), text, len * 2);
 
        return s;
 }
@@ -639,15 +689,22 @@ MonoString *
 mono_string_new_size (MonoDomain *domain, gint32 len)
 {
        MonoString *s;
-       MonoArray *ca;
 
-       s = (MonoString*)mono_object_new (domain, mono_defaults.string_class);
-       g_assert (s != NULL);
+       /* 
+        * enable to get a good speedup: we still need to figure out
+        * how the sync structure is freed.
+        */
+#ifdef 0 && HAVE_BOEHM_GC
+       s = GC_malloc_atomic (sizeof (MonoString) + ((len + 1) * 2));
+       s->object.synchronisation = 0;
+       mono_string_chars (s) [len] = 0;
+#else
+       s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
+#endif
+       if (!s)
+               G_BREAKPOINT ();
 
-       ca = (MonoArray *)mono_array_new (domain, mono_defaults.char_class, len);
-       g_assert (ca != NULL);
-       
-       s->c_str = ca;
+       s->object.vtable = mono_class_vtable (domain, mono_defaults.string_class);
        s->length = len;
 
        return s;
@@ -747,6 +804,8 @@ mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
 
        memcpy ((char *)res + sizeof (MonoObject), value, size);
 
+       if (class->has_finalize)
+               mono_object_register_finalizer (res);
        return res;
 }
 
@@ -819,7 +878,7 @@ mono_string_is_interned_lookup (MonoString *str, int insert)
 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
        {
                int i;
-               char *p2 = mono_array_addr (str->c_str, char, 0);
+               char *p2 = mono_string_chars (str);
                for (i = 0; i < str->length; ++i) {
                        *p++ = p2 [1];
                        *p++ = p2 [0];
@@ -827,7 +886,7 @@ mono_string_is_interned_lookup (MonoString *str, int insert)
                }
        }
 #else
-       memcpy (p, str->c_str->vector, str->length * 2);
+       memcpy (p, mono_string_chars (str), str->length * 2);
 #endif
        domain = ((MonoObject *)str)->vtable->domain;
        ldstr_table = domain->ldstr_table;
@@ -912,19 +971,15 @@ mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
 char *
 mono_string_to_utf8 (MonoString *s)
 {
-       char *as, *vector;
+       char *as;
        GError *error = NULL;
 
        g_assert (s != NULL);
 
-       if (!s->length || !s->c_str)
+       if (!s->length)
                return g_strdup ("");
 
-       vector = (char*)s->c_str->vector;
-
-       g_assert (vector != NULL);
-
-       as = g_utf16_to_utf8 ((gunichar2 *)vector, s->length, NULL, NULL, &error);
+       as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
        if (error)
                g_warning (error->message);
 
@@ -951,7 +1006,7 @@ mono_string_to_utf16 (MonoString *s)
        as [(s->length * 2)] = '\0';
        as [(s->length * 2) + 1] = '\0';
 
-       if (!s->length || !s->c_str) {
+       if (!s->length) {
                return (gunichar2 *)(as);
        }
        
@@ -1124,7 +1179,6 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
                MonoDomain *domain = mono_domain_get (); 
                MonoMethod *method = msg->method->method;
                MonoMethodSignature *sig = method->signature;
-               MonoObject *res;
                int i, j, outarg_count = 0;
 
                for (i = 0; i < sig->param_count; i++) {