/* 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.
#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
static s4 interfaceindex; /* sequential numbering of interfaces */
static s4 classvalue;
-java_object_t *linker_classrenumber_lock;
-
/* private functions **********************************************************/
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);
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);
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))
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. */
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");
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 */
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");
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
classinfo *cg;
classinfo *cs;
- cg = mg->class;
- cs = ms->class;
+ cg = mg->clazz;
+ cs = ms->clazz;
/* overriding a final method is illegal */
*******************************************************************************/
+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 */
MCOPY(am, im, methodinfo, 1);
am->vftblindex = (vftbllength++);
- am->class = c;
+ am->clazz = c;
am->flags |= ACC_MIRANDA;
noabstractmethod2:
(interfacetablelength - 1) * (interfacetablelength > 1));
c->vftbl = v;
- v->class = c;
+ v->clazz = c;
v->vftbllength = vftbllength;
v->interfacetablelength = interfacetablelength;
v->arraydesc = arraydesc;
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
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;
static void linker_compute_subclasses(classinfo *c)
{
- LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
#if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
threads_stopworld();
#endif
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)) {
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