Proper x86_64 mnemonics
[cacao.git] / src / vmcore / linker.c
index ad3d160c943611fcd36f8507f675cb81d8ba555c..08589bfdb82ab32525d5fc3e3ad524fb0d5f190e 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vmcore/linker.c - class linker functions
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -83,7 +81,7 @@ classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool c
 #endif
 
 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
-#define INLINELOG(code)  do { if (opt_inline_debug_log) { code } } while (0)
+#define INLINELOG(code)  do { if (opt_TraceInlining) { code } } while (0)
 #else
 #define INLINELOG(code)
 #endif
@@ -94,8 +92,6 @@ classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool c
 static s4 interfaceindex;       /* sequential numbering of interfaces         */
 static s4 classvalue;
 
-java_object_t *linker_classrenumber_lock;
-
 
 /* private functions **********************************************************/
 
@@ -132,10 +128,17 @@ struct dummy_alignment_double_t {
 
 void linker_preinit(void)
 {
+       TRACESUBSYSTEMINITIALIZATION("linker_preinit");
+
        /* Check for if alignment for long and double matches what we
           assume for the current architecture. */
 
 #if defined(__I386__) || (defined(__ARM__) && !defined(__ARM_EABI__)) || (defined(__POWERPC__) && defined(__DARWIN__)) || defined(__M68K__)
+       /* Define a define here which is later checked when we use this
+          offset. */
+
+# define LINKER_ALIGNMENT_LONG_DOUBLE 4
+
        if (OFFSET(dummy_alignment_long_t, l) != 4)
                vm_abort("linker_preinit: long alignment is different from what assumed: %d != %d",
                                 OFFSET(dummy_alignment_long_t, l), 4);
@@ -144,6 +147,9 @@ void linker_preinit(void)
                vm_abort("linker_preinit: double alignment is different from what assumed: %d != %d",
                                 OFFSET(dummy_alignment_double_t, d), 4);
 #else
+
+# define LINKER_ALIGNMENT_LONG_DOUBLE 8
+
        if (OFFSET(dummy_alignment_long_t, l) != 8)
                vm_abort("linker_preinit: long alignment is different from what assumed: %d != %d",
                                 OFFSET(dummy_alignment_long_t, l), 8);
@@ -157,14 +163,6 @@ void linker_preinit(void)
 
        interfaceindex = 0;
 
-#if defined(ENABLE_THREADS)
-       /* create the global lock object */
-
-       linker_classrenumber_lock = NEW(java_object_t);
-
-       LOCK_INIT_OBJECT_LOCK(linker_classrenumber_lock);
-#endif
-
        /* Link the most basic classes. */
 
        if (!link_class(class_java_lang_Object))
@@ -188,6 +186,8 @@ void linker_preinit(void)
 
 void linker_init(void)
 {
+       TRACESUBSYSTEMINITIALIZATION("linker_init");
+
        /* Link java.lang.Class as first class of the system, because we
        need it's vftbl for all other classes so we can use a class as
        object. */
@@ -258,7 +258,7 @@ void linker_init(void)
        if (!link_class(class_java_lang_Throwable))
                vm_abort("linker_init: linking failed");
 
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
        if (!link_class(class_java_lang_VMSystem))
                vm_abort("linker_init: linking failed");
 
@@ -269,6 +269,16 @@ void linker_init(void)
                vm_abort("linker_init: linking failed");
 #endif
 
+       /* Important system exceptions. */
+
+       if (!link_class(class_java_lang_Exception))
+               vm_abort("linker_init: linking failed");
+
+       if (!link_class(class_java_lang_ClassNotFoundException))
+               vm_abort("linker_init: linking failed");
+
+       if (!link_class(class_java_lang_RuntimeException))
+               vm_abort("linker_init: linking failed");
 
        /* some classes which may be used more often */
 
@@ -285,6 +295,17 @@ void linker_init(void)
        if (!link_class(class_java_lang_reflect_Method))
                vm_abort("linker_init: linking failed");
 
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       if (!link_class(class_java_lang_reflect_VMConstructor))
+               vm_abort("linker_init: linking failed");
+
+       if (!link_class(class_java_lang_reflect_VMField))
+               vm_abort("linker_init: linking failed");
+
+       if (!link_class(class_java_lang_reflect_VMMethod))
+               vm_abort("linker_init: linking failed");
+# endif
+
        if (!link_class(class_java_security_PrivilegedAction))
                vm_abort("linker_init: linking failed");
 
@@ -294,7 +315,7 @@ void linker_init(void)
        if (!link_class(class_java_util_HashMap))
                vm_abort("linker_init: linking failed");
 
-# if defined(WITH_CLASSPATH_SUN)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
        if (!link_class(class_sun_reflect_MagicAccessorImpl))
                vm_abort("linker_init: linking failed");
 # endif
@@ -458,8 +479,8 @@ static bool linker_overwrite_method(methodinfo *mg,
        classinfo *cg;
        classinfo *cs;
 
-       cg = mg->class;
-       cs = ms->class;
+       cg = mg->clazz;
+       cs = ms->clazz;
 
        /* overriding a final method is illegal */
 
@@ -526,6 +547,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 = malloc(sizeof(void*) * (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                              */
@@ -756,7 +839,7 @@ static classinfo *link_class_intern(classinfo *c)
                                        MCOPY(am, im, methodinfo, 1);
 
                                        am->vftblindex  = (vftbllength++);
-                                       am->class       = c;
+                                       am->clazz       = c;
                                        am->flags      |= ACC_MIRANDA;
 
                                noabstractmethod2:
@@ -797,7 +880,7 @@ static classinfo *link_class_intern(classinfo *c)
                                         (interfacetablelength - 1) * (interfacetablelength > 1));
 
        c->vftbl                = v;
-       v->class                = c;
+       v->clazz                = c;
        v->vftbllength          = vftbllength;
        v->interfacetablelength = interfacetablelength;
        v->arraydesc            = arraydesc;
@@ -875,15 +958,24 @@ static classinfo *link_class_intern(classinfo *c)
                        dsize = descriptor_typesize(f->parseddesc);
 
 #if defined(__I386__) || (defined(__ARM__) && !defined(__ARM_EABI__)) || (defined(__POWERPC__) && defined(__DARWIN__)) || defined(__M68K__)
-                       /* On i386 and ARM we align double and s8 fields to
-                          4-bytes.  This matches what GCC does for struct
-                          members. We must do the same as gcc here because the
-                          offsets in native header structs like java_lang_Double
-                          must match the offsets of the Java fields
-                          (eg. java.lang.Double.value).  */
+                       /* On some architectures and configurations we need to
+                          align long (int64_t) and double fields to 4-bytes to
+                          match what GCC does for struct members.  We must do the
+                          same as GCC here because the offsets in native header
+                          structs like java_lang_Double must match the offsets of
+                          the Java fields (eg. java.lang.Double.value). */
+
+# if LINKER_ALIGNMENT_LONG_DOUBLE != 4
+#  error alignment of long and double is not 4
+# endif
 
                        c->instancesize = MEMORY_ALIGN(c->instancesize, 4);
 #else
+
+# if LINKER_ALIGNMENT_LONG_DOUBLE != 8
+#  error alignment of long and double is not 8
+# endif
+
                        c->instancesize = MEMORY_ALIGN(c->instancesize, dsize);
 #endif
 
@@ -933,8 +1025,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;
@@ -1134,8 +1229,6 @@ static arraydescriptor *link_array(classinfo *c)
 
 static void linker_compute_subclasses(classinfo *c)
 {
-       LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
 #if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
        threads_stopworld();
 #endif
@@ -1143,6 +1236,7 @@ static void linker_compute_subclasses(classinfo *c)
        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)) {
@@ -1152,12 +1246,6 @@ static void linker_compute_subclasses(classinfo *c)
 
        classvalue = 0;
 
-       /* compute class values */
-
-       linker_compute_class_values(class_java_lang_Object);
-
-       LOCK_MONITOR_EXIT(linker_classrenumber_lock);
-
 #if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
        threads_startworld();
 #endif