PR149: Used wrong class loader.
[cacao.git] / src / vm / linker.cpp
index 5fd4869b6598cbe249a2bcd595e35056b73adebc..aa6cc39bc98a4799ed92bd710e4db67a09628b43 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/linker.c - class linker functions
+/* src/vm/linker.cpp - class linker functions
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996, 2011
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 #include "vm/types.h"
 
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
 #include "native/native.hpp"
 
 #include "threads/lock.hpp"
 #include "threads/mutex.hpp"
 
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
 
 #include "vm/access.hpp"
 #include "vm/array.hpp"
@@ -45,6 +45,7 @@
 #include "vm/classcache.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/globals.hpp"
+#include "vm/hook.hpp"
 #include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/primitive.hpp"
@@ -55,6 +56,9 @@
 #include "vm/jit/asmpart.h"
 #include "vm/jit/stubs.hpp"
 
+#include <vector>
+#include <utility>
+
 
 /* debugging macros ***********************************************************/
 
@@ -94,6 +98,10 @@ classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool c
 static s4 interfaceindex;       /* sequential numbering of interfaces         */
 static s4 classvalue;
 
+#if !USES_NEW_SUBTYPE
+Mutex *linker_classrenumber_lock;
+#endif
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -108,6 +116,9 @@ static bool linker_addinterface(classinfo *c, classinfo *ic);
 static s4 class_highestinterface(classinfo *c);
 
 
+typedef std::vector<std::pair<java_object_t**, utf*> > deferred_strings_vec_t;
+static deferred_strings_vec_t deferred_strings;
+
 /* linker_init *****************************************************************
 
    Initializes the linker subsystem and links classes required for the
@@ -123,6 +134,12 @@ void linker_preinit(void)
 
        interfaceindex = 0;
 
+#if defined(ENABLE_THREADS) && !USES_NEW_SUBTYPE
+       /* create the global mutex */
+
+       linker_classrenumber_lock = new Mutex();
+#endif
+
        /* Link the most basic classes. */
 
        if (!link_class(class_java_lang_Object))
@@ -281,6 +298,12 @@ void linker_init(void)
 
        if (!link_class(class_sun_reflect_MagicAccessorImpl))
                vm_abort("linker_init: linking failed");
+
+       if (!link_class(class_sun_reflect_MethodAccessorImpl))
+               vm_abort("linker_init: linking failed");
+
+       if (!link_class(class_sun_reflect_ConstructorAccessorImpl))
+               vm_abort("linker_init: linking failed");
 # endif
 
        if (!link_class(arrayclass_java_lang_Object))
@@ -366,7 +389,7 @@ classinfo *link_class(classinfo *c)
 
        if (c == NULL) {
                exceptions_throw_nullpointerexception();
-               return NULL;
+               return 0;
        }
 
        LOCK_MONITOR_ENTER(c);
@@ -415,6 +438,10 @@ classinfo *link_class(classinfo *c)
 
        RT_TIMING_TIME_DIFF(time_start,time_end,RT_TIMING_LINK_TOTAL);
 
+       // Hook point just after a class was linked.
+       if (!Hook::class_linked(r))
+               return 0;
+
        return r;
 }
 
@@ -511,75 +538,84 @@ static bool linker_overwrite_method(methodinfo *mg,
 }
 
 
-/* link_class_intern ***********************************************************
+#if USES_NEW_SUBTYPE
+/* build_display ***************************************************************
+
+   Builds the entire display for a class. This entails filling the fixed part
+   as well as allocating and initializing the overflow part.
+
+   See Cliff Click and John Rose: Fast subtype checking in the Hotspot JVM.
 
-   Tries to link a class. The function calculates the length in bytes
-   that an instance of this class requires as well as the VTBL for
-   methods and interface methods.
-       
 *******************************************************************************/
 
-static int build_display_inner(classinfo *topc, classinfo *c, int i)
+static classinfo *build_display(classinfo *c)
 {
-       int depth;
-       if (!c)
-               return 0;
+       int depth, i;
+       int depth_fixed;
+       classinfo *super;
+
        do {
-               if (c->vftbl->arraydesc)
-               {
+               /* Handle arrays. */
+               if (c->vftbl->arraydesc) {
                        arraydescriptor *a = c->vftbl->arraydesc;
-                       if (a->elementvftbl && a->elementvftbl->clazz->super)
-                       {
+                       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);
+                               super = cls;
                                break;
                        }
-                       if (a->componentvftbl && a->elementvftbl)
-                       {
-                               depth = build_display_inner(topc, a->componentvftbl->clazz, i+1);
+                       if (a->componentvftbl && a->elementvftbl) {
+                               super = a->componentvftbl->clazz;
                                break;
                        }
                }
-               depth = build_display_inner(topc, c->super, i+1);
+               /* Normal classes. */
+               super = c->super;
        } while (false);
-       if (depth >= DISPLAY_SIZE)
-       {
-               if (depth == DISPLAY_SIZE)
-               {
-                       topc->vftbl->subtype_overflow = MNEW(vftbl_t *, i+1);
+       if (super) {
+               if (!link_class(super))
+                       return NULL;
+               depth = super->vftbl->subtype_depth + 1;
+       } else
+               /* java.lang.Object doesn't have a super class. */
+               depth = 0;
+
+       /* Now copy super's display, append c->vftbl and initialize the remaining fields. */
+       if (depth >= DISPLAY_SIZE) {
+               c->vftbl->subtype_overflow = MNEW(vftbl_t *, depth - DISPLAY_SIZE + 1);
 #if defined(ENABLE_STATISTICS)
-                       if (opt_stat)
-                               count_vftbl_len += sizeof(void*) * (i+1);
+               if (opt_stat)
+                       count_vftbl_len += sizeof(vftbl_t*) * (depth - DISPLAY_SIZE + 1);
 #endif
-               }
-               topc->vftbl->subtype_overflow[depth - DISPLAY_SIZE] = c->vftbl;
-               return depth + 1;
+               memcpy(c->vftbl->subtype_overflow, super->vftbl->subtype_overflow, sizeof(vftbl_t*) * (depth - DISPLAY_SIZE));
+               c->vftbl->subtype_overflow[depth - DISPLAY_SIZE] = c->vftbl;
+               depth_fixed = DISPLAY_SIZE;
+       }
+       else {
+               depth_fixed = depth;
+               c->vftbl->subtype_display[depth] = c->vftbl;
        }
-       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;
+       if (super)
+               memcpy(c->vftbl->subtype_display, super->vftbl->subtype_display, sizeof(vftbl_t*) * depth_fixed);
+       for (i=depth_fixed+1; i<=DISPLAY_SIZE; i++)
+               c->vftbl->subtype_display[i] = NULL;
+       c->vftbl->subtype_offset = OFFSET(vftbl_t, subtype_display[0]) + sizeof(vftbl_t*) * depth_fixed;
        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;
-       }
+
+       return c;
 }
+#endif
+
+/* link_class_intern ***********************************************************
+
+   Tries to link a class. The function calculates the length in bytes
+   that an instance of this class requires as well as the VTBL for
+   methods and interface methods.
+       
+*******************************************************************************/
 
 static classinfo *link_class_intern(classinfo *c)
 {
@@ -978,7 +1014,10 @@ static classinfo *link_class_intern(classinfo *c)
        /* FIXME: this is completely useless now */
        RT_TIMING_GET_TIME(time_subclasses);
 
-       build_display(c);
+#if USES_NEW_SUBTYPE
+       if (!build_display(c))
+               return NULL;
+#endif
 
        /* revert the linking state and class is linked */
 
@@ -1086,8 +1125,8 @@ static arraydescriptor *link_array(classinfo *c)
                        desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
 
                        if (compvftbl->arraydesc->dimension >= 255) {
-                               log_text("Creating array of dimension >255");
-                               assert(0);
+                               exceptions_throw_illegalargumentexception();
+                               return NULL;
                        }
 
                        desc->dimension = compvftbl->arraydesc->dimension + 1;
@@ -1164,6 +1203,24 @@ static arraydescriptor *link_array(classinfo *c)
        return desc;
 }
 
+/* linker_create_string_later **************************************************
+
+   A hack so we can initialize java.lang.String objects during initialization.
+
+*******************************************************************************/
+void linker_create_string_later(java_object_t **a, utf *u)
+{
+       deferred_strings.push_back(std::make_pair(a, u));
+}
+
+void linker_initialize_deferred_strings()
+{
+       deferred_strings_vec_t::const_iterator it = deferred_strings.begin();
+       for (; it != deferred_strings.end(); ++it)
+               *it->first = literalstring_new(it->second);
+       deferred_strings.clear();
+}
+
 
 /* linker_compute_subclasses ***************************************************
 
@@ -1180,10 +1237,14 @@ static arraydescriptor *link_array(classinfo *c)
 static void linker_compute_subclasses(classinfo *c)
 {
 
+       LOCK_CLASSRENUMBER_LOCK;
+
        if (!(c->flags & ACC_INTERFACE)) {
                c->nextsub = NULL;
                c->sub     = NULL;
+#if USES_NEW_SUBTYPE
                c->vftbl->baseval = 1; /* so it does not look like an interface */
+#endif
        }
 
        if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
@@ -1193,6 +1254,14 @@ static void linker_compute_subclasses(classinfo *c)
 
        classvalue = 0;
 
+#if !USES_NEW_SUBTYPE
+       /* compute class values */
+
+       linker_compute_class_values(class_java_lang_Object);
+#endif
+
+       UNLOCK_CLASSRENUMBER_LOCK;
+
 }
 
 
@@ -1369,7 +1438,7 @@ static s4 class_highestinterface(classinfo *c)
  * Emacs will automagically detect them.
  * ---------------------------------------------------------------------
  * Local variables:
- * mode: c
+ * mode: c++
  * indent-tabs-mode: t
  * c-basic-offset: 4
  * tab-width: 4