Fri Mar 29 18:09:08 CET 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / class.c
index 9e91bc120ab694cad45abbded35a5f2b780f05ea..363f1c11877ffd058fb9ed8f7ae14cd21c53a847 100644 (file)
@@ -28,6 +28,9 @@
 #include <mono/metadata/object.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/mono-endian.h>
+#if HAVE_BOEHM_GC
+#include <gc/gc.h>
+#endif
 
 #define CSIZE(x) (sizeof (x) / 4)
 
@@ -41,6 +44,13 @@ default_trampoline (MonoMethod *method)
        return method;
 }
 
+static gpointer
+default_remoting_trampoline (MonoMethod *method)
+{
+       g_error ("remoting not installed");
+       return NULL;
+}
+
 static void
 default_runtime_class_init (MonoClass *klass)
 {
@@ -48,6 +58,7 @@ default_runtime_class_init (MonoClass *klass)
 }
 
 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
+static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
 static MonoRuntimeClassInit mono_runtime_class_init = default_runtime_class_init;
 
 void
@@ -56,6 +67,12 @@ mono_install_trampoline (MonoTrampoline func)
        arch_create_jit_trampoline = func? func: default_trampoline;
 }
 
+void
+mono_install_remoting_trampoline (MonoTrampoline func) 
+{
+       arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
+}
+
 void
 mono_install_runtime_class_init (MonoRuntimeClassInit func)
 {
@@ -231,7 +248,6 @@ class_compute_field_layout (MonoClass *class)
        case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
                for (i = 0; i < top; i++){
                        int size, align;
-                       int idx = class->field.first + i;
 
                        /*
                         * There must be info about all the fields in a type if it
@@ -367,6 +383,7 @@ mono_class_init (MonoClass *class)
        MonoMethod **vtable = class->vtable;
        int i, max_iid, cur_slot = 0;
        static MonoMethod *default_ghc = NULL;
+       static int ghc_slot = -1;
 
        g_assert (class);
 
@@ -523,11 +540,13 @@ mono_class_init (MonoClass *class)
 
                        for (l = 0; l < ic->method.count; l++) {
                                MonoMethod *im = ic->methods [l];                                               
-                               char *qname;
+                               char *qname, *fqname;
+                               
+                               qname = g_strconcat (ic->name, ".", im->name, NULL); 
                                if (ic->name_space && ic->name_space [0])
-                                       qname = g_strconcat (ic->name_space, ".", ic->name, ".", im->name, NULL);
+                                       fqname = g_strconcat (ic->name_space, ".", ic->name, ".", im->name, NULL);
                                else
-                                       qname = g_strconcat (ic->name, ".", im->name, NULL); 
+                                       fqname = NULL;
 
                                for (j = 0; j < class->method.count; ++j) {
                                        MonoMethod *cm = class->methods [j];
@@ -535,7 +554,7 @@ mono_class_init (MonoClass *class)
                                        if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
                                                continue;
                                        
-                                       if (!strcmp (cm->name, qname) &&
+                                       if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
                                            mono_metadata_signature_equal (cm->signature, im->signature)) {
                                                g_assert (io + l <= class->vtable_size);
                                                vtable [io + l] = cm;
@@ -543,6 +562,7 @@ mono_class_init (MonoClass *class)
                                        }
                                }
                                g_free (qname);
+                               g_free (fqname);
                        }
 
                        
@@ -676,23 +696,41 @@ mono_class_init (MonoClass *class)
        class->inited = 1;
        class->init_pending = 0;
 
-#define GHC_SLOT 2
-
        if (!default_ghc) {
                if (class == mono_defaults.object_class) { 
-                       default_ghc = vtable [GHC_SLOT];
-                       g_assert (!strcmp (default_ghc->name, "GetHashCode"));
+                      
+                       for (i = 0; i < class->vtable_size; ++i) {
+                               MonoMethod *cm = vtable [i];
+              
+                               if (!strcmp (cm->name, "GetHashCode")) {
+                                       ghc_slot = i;
+                                       break;
+                               }
+                       }
+
+                       g_assert (ghc_slot > 0);
+
+                       default_ghc = vtable [ghc_slot];
                }
        }
        
        class->ghcimpl = 1;
        if (class != mono_defaults.object_class) { 
-               if (vtable [GHC_SLOT] == default_ghc) {
+
+               if (vtable [ghc_slot] == default_ghc) {
                        class->ghcimpl = 0;
                }
+
        }
 }
 
+#if HAVE_BOEHM_GC
+static void
+vtable_finalizer (void *obj, void *data) {
+       g_print ("%s finalized (%p)\n", (char*)data, obj);
+}
+#endif
+
 /**
  * mono_class_vtable:
  * @domain: the application domain
@@ -711,7 +749,7 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
        guint32 cols [MONO_CONSTANT_SIZE];
        const char *p;
        char *t;
-       int i;
+       int i, len;
 
        g_assert (class);
 
@@ -719,21 +757,33 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
        if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
                g_assert_not_reached ();
 
-       if ((vt = g_hash_table_lookup (domain->class_vtable_hash, class)))
+       if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class)))
                return vt;
        
        if (!class->inited)
                mono_class_init (class);
                
+#if HAVE_BOEHM_GC
+       vt = GC_malloc (sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer));
+       /*vt = GC_debug_malloc (sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer), class->name, 1);*/
+       GC_register_finalizer (vt, vtable_finalizer, "vtable", NULL, NULL);
+#else
        vt = g_malloc0 (sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer));
+#endif
        vt->klass = class;
        vt->domain = domain;
 
        if (class->class_size) {
+#if HAVE_BOEHM_GC
+               vt->data = GC_malloc (class->class_size + 8);
+               /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
+               GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);
+#else
                vt->data = g_malloc0 (class->class_size + 8);
+#endif
                /* align: fixme not 64 bit clean */
                if (((guint32)vt->data) & 0x7)
-                       vt->data += 8 - (((guint32)vt->data) & 0x7);
+                       vt->data = (char*)vt->data + 8 - (((guint32)vt->data) & 0x7);
        }
 
        for (i = class->field.first; i < class->field.last; ++i) {
@@ -749,7 +799,7 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
                }
                mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE);
                p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]);
-               mono_metadata_decode_blob_size (p, &p);
+               len = mono_metadata_decode_blob_size (p, &p);
                t = (char*)vt->data + field->offset;
                /* should we check that the type matches? */
                switch (cols [MONO_CONSTANT_TYPE]) {
@@ -788,7 +838,8 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
                        break;
                }
                case MONO_TYPE_STRING: {
-                       g_warning ("we don't handle strings in constant table");
+                       gpointer *val = (gpointer*)t;
+                       *val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
                        break;
                }
                case MONO_TYPE_CLASS:
@@ -819,13 +870,60 @@ mono_class_vtable (MonoDomain *domain, MonoClass *class)
                        vt->vtable [i] = arch_create_jit_trampoline (cm);
        }
 
-       g_hash_table_insert (domain->class_vtable_hash, class, vt);
+       mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
 
        mono_runtime_class_init (class);
 
        return vt;
 }
 
+/**
+ * mono_class_proxy_vtable:
+ * @domain: the application domain
+ * @class: the class to proxy
+ *
+ * Creates a vtable for transparent proxies. It is basically
+ * a copy of the real vtable of @class, but all function pointers invoke
+ * the remoting functions, and vtable->klass points to the 
+ * transparent proxy class, and not to @class.
+ */
+MonoVTable *
+mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
+{
+       MonoVTable *vt, *pvt;
+       int i, vtsize;
+
+       if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
+               return pvt;
+
+       vt = mono_class_vtable (domain, class);
+       vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
+
+#if HAVE_BOEHM_GC
+       pvt = GC_malloc (vtsize);
+       GC_register_finalizer (vt, vtable_finalizer, "vtable", NULL, NULL);
+#else
+       pvt = g_malloc0 (vtsize);
+#endif
+       
+       memcpy (pvt, vt, vtsize);
+
+       pvt->klass = mono_defaults.transparent_proxy_class;
+
+       /* initialize vtable */
+       for (i = 0; i < class->vtable_size; ++i) {
+               MonoMethod *cm;
+              
+               if ((cm = class->vtable [i]))
+                       pvt->vtable [i] = arch_create_remoting_trampoline (cm);
+       }
+
+       mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
+
+       return pvt;
+}
+
+
 /*
  * Compute a relative numbering of the class hierarchy as described in
  * "Java for Large-Scale Scientific Computations?"
@@ -943,14 +1041,38 @@ mono_class_setup_mono_type (MonoClass *class)
 void
 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
 {
+       gboolean system_namespace;
+
+       system_namespace = !strcmp (class->name_space, "System");
+
        /* if root of the hierarchy */
-       if (!strcmp (class->name_space, "System") && !strcmp (class->name, "Object")) {
+       if (system_namespace && !strcmp (class->name, "Object")) {
                class->parent = NULL;
                class->instance_size = sizeof (MonoObject);
-       } else if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
+               return;
+       }
+
+       if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
                int rnum = 0;
                class->parent = parent;
-               if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) && (strcmp (class->parent->name_space, "System") == 0)))
+
+               class->marshalbyref = parent->marshalbyref;
+               class->contextbound  = parent->contextbound;
+               class->delegate  = parent->delegate;
+               
+               if (system_namespace) {
+                       if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
+                               class->marshalbyref = 1;
+
+                       if (*class->name == 'M' && !strcmp (class->name, "ContextBoundObject")) 
+                               class->contextbound  = 1;
+
+                       if (*class->name == 'D' && !strcmp (class->name, "Delegate")) 
+                               class->delegate  = 1;
+               }
+
+               if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) && 
+                                               (strcmp (class->parent->name_space, "System") == 0)))
                        class->valuetype = 1;
                if (((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
                        class->valuetype = class->enumtype = 1;
@@ -1083,8 +1205,8 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
        return class;
 }
 
-static MonoClass *
-mono_create_ptr_class (MonoType *type)
+MonoClass *
+mono_ptr_class_get (MonoType *type)
 {
        MonoClass *result;
        MonoClass *el_class;
@@ -1100,7 +1222,7 @@ mono_create_ptr_class (MonoType *type)
        result->parent = NULL; /* no parent for PTR types */
        result->name = "System";
        result->name_space = "MonoPtrFakeClass";
-       result->image = NULL;
+       result->image = el_class->image;
        result->inited = TRUE;
        /* Can pointers get boxed? */
        result->instance_size = sizeof (gpointer);
@@ -1160,7 +1282,7 @@ mono_class_from_mono_type (MonoType *type)
        case MONO_TYPE_ARRAY:
                return mono_array_class_get (type->data.array->type, type->data.array->rank);
        case MONO_TYPE_PTR:
-               return mono_create_ptr_class (type->data.type);
+               return mono_ptr_class_get (type->data.type);
        case MONO_TYPE_SZARRAY:
                return mono_array_class_get (type->data.type, 1);
        case MONO_TYPE_CLASS: