static s4 interfaceindex; /* sequential numbering of interfaces */
static s4 classvalue;
+#if !USES_NEW_SUBTYPE
java_object_t *linker_classrenumber_lock;
+#endif
/* private functions **********************************************************/
interfaceindex = 0;
-#if defined(ENABLE_THREADS)
+#if defined(ENABLE_THREADS) && !USES_NEW_SUBTYPE
/* create the global lock object */
linker_classrenumber_lock = NEW(java_object_t);
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 */
}
+#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.
+
+*******************************************************************************/
+
+static classinfo *build_display(classinfo *c)
+{
+ int depth, i;
+ int depth_fixed;
+ classinfo *super;
+
+ do {
+ /* Handle arrays. */
+ 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);
+ super = cls;
+ break;
+ }
+ if (a->componentvftbl && a->elementvftbl) {
+ super = a->componentvftbl->clazz;
+ break;
+ }
+ }
+ /* Normal classes. */
+ super = c->super;
+ } while (false);
+ 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(vftbl_t*) * (depth - DISPLAY_SIZE + 1);
+#endif
+ 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;
+ }
+
+ 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;
+
+ return c;
+}
+#endif
+
/* link_class_intern ***********************************************************
Tries to link a class. The function calculates the length in bytes
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;
linker_compute_subclasses(c);
+ /* FIXME: this is completely useless now */
RT_TIMING_GET_TIME(time_subclasses);
+#if USES_NEW_SUBTYPE
+ if (!build_display(c))
+ return NULL;
+#endif
+
/* 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
+ 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
- LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+ UNLOCK_CLASSRENUMBER_LOCK;
#if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
threads_startworld();