-/* 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"
#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"
#include "vm/jit/asmpart.h"
#include "vm/jit/stubs.hpp"
+#include <vector>
+#include <utility>
+
/* debugging macros ***********************************************************/
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
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
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))
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))
if (c == NULL) {
exceptions_throw_nullpointerexception();
- return NULL;
+ return 0;
}
LOCK_MONITOR_ENTER(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;
}
}
-/* 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 = malloc(sizeof(void*) * (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)
{
/* 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 */
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;
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 ***************************************************
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)) {
classvalue = 0;
+#if !USES_NEW_SUBTYPE
+ /* compute class values */
+
+ linker_compute_class_values(class_java_lang_Object);
+#endif
+
+ UNLOCK_CLASSRENUMBER_LOCK;
+
}
* Emacs will automagically detect them.
* ---------------------------------------------------------------------
* Local variables:
- * mode: c
+ * mode: c++
* indent-tabs-mode: t
* c-basic-offset: 4
* tab-width: 4