Merge from subtype branch.
[cacao.git] / src / vm / linker.cpp
index e1c5e611eaf6257295299771b63ac2ee85f23d57..5fd4869b6598cbe249a2bcd595e35056b73adebc 100644 (file)
@@ -94,8 +94,6 @@ classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool c
 static s4 interfaceindex;       /* sequential numbering of interfaces         */
 static s4 classvalue;
 
-Mutex *linker_classrenumber_mutex;
-
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -125,12 +123,6 @@ void linker_preinit(void)
 
        interfaceindex = 0;
 
-#if defined(ENABLE_THREADS)
-       /* create the global mutex */
-
-       linker_classrenumber_mutex = new Mutex();
-#endif
-
        /* Link the most basic classes. */
 
        if (!link_class(class_java_lang_Object))
@@ -527,6 +519,68 @@ static bool linker_overwrite_method(methodinfo *mg,
        
 *******************************************************************************/
 
+static int build_display_inner(classinfo *topc, classinfo *c, int i)
+{
+       int depth;
+       if (!c)
+               return 0;
+       do {
+               if (c->vftbl->arraydesc)
+               {
+                       arraydescriptor *a = c->vftbl->arraydesc;
+                       if (a->elementvftbl && a->elementvftbl->clazz->super)
+                       {
+                               classinfo *cls = a->elementvftbl->clazz->super;
+                               int n;
+                               for (n=0; n<a->dimension; n++)
+                                       cls = class_array_of(cls, true);
+                               depth = build_display_inner(topc, cls, i+1);
+                               break;
+                       }
+                       if (a->componentvftbl && a->elementvftbl)
+                       {
+                               depth = build_display_inner(topc, a->componentvftbl->clazz, i+1);
+                               break;
+                       }
+               }
+               depth = build_display_inner(topc, c->super, i+1);
+       } while (false);
+       if (depth >= DISPLAY_SIZE)
+       {
+               if (depth == DISPLAY_SIZE)
+               {
+                       topc->vftbl->subtype_overflow = MNEW(vftbl_t *, i+1);
+#if defined(ENABLE_STATISTICS)
+                       if (opt_stat)
+                               count_vftbl_len += sizeof(void*) * (i+1);
+#endif
+               }
+               topc->vftbl->subtype_overflow[depth - DISPLAY_SIZE] = c->vftbl;
+               return depth + 1;
+       }
+       topc->vftbl->subtype_display[depth] = c->vftbl;
+       return depth + 1;
+}
+
+static void build_display(classinfo *c)
+{
+       int depth;
+       int i;
+
+       depth = build_display_inner(c, c, 0) - 1;
+       c->vftbl->subtype_depth = depth;
+       if (depth >= DISPLAY_SIZE)
+       {
+               c->vftbl->subtype_offset = OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]);
+       }
+       else
+       {
+               c->vftbl->subtype_offset = OFFSET(vftbl_t, subtype_display[0]) + sizeof(void*) * depth;
+               for (i=depth+1; i<=DISPLAY_SIZE; i++)
+                       c->vftbl->subtype_display[i] = NULL;
+       }
+}
+
 static classinfo *link_class_intern(classinfo *c)
 {
        classinfo *super;             /* super class                              */
@@ -921,8 +975,11 @@ static classinfo *link_class_intern(classinfo *c)
 
        linker_compute_subclasses(c);
 
+       /* FIXME: this is completely useless now */
        RT_TIMING_GET_TIME(time_subclasses);
 
+       build_display(c);
+
        /* revert the linking state and class is linked */
 
        c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
@@ -1122,11 +1179,11 @@ static arraydescriptor *link_array(classinfo *c)
 
 static void linker_compute_subclasses(classinfo *c)
 {
-       linker_classrenumber_mutex->lock();
 
        if (!(c->flags & ACC_INTERFACE)) {
                c->nextsub = NULL;
                c->sub     = NULL;
+               c->vftbl->baseval = 1; /* so it does not look like an interface */
        }
 
        if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
@@ -1136,11 +1193,6 @@ static void linker_compute_subclasses(classinfo *c)
 
        classvalue = 0;
 
-       /* compute class values */
-
-       linker_compute_class_values(class_java_lang_Object);
-
-       linker_classrenumber_mutex->unlock();
 }