if (sub->flags & ACC_INTERFACE)
return (super == class_java_lang_Object);
+#if USES_NEW_SUBTYPE
result = fast_subtype_check(sub->vftbl, super->vftbl);
+#else
+ LOCK_CLASSRENUMBER_LOCK;
+
+ diffval = sub->vftbl->baseval - super->vftbl->baseval;
+ result = diffval <= (uint32_t) super->vftbl->diffval;
+
+ UNLOCK_CLASSRENUMBER_LOCK;
+#endif
}
return result;
#define REPLACEMENT_PATCH_SIZE 4 /* bytes */
+/* subtype ********************************************************************/
+
+#define USES_NEW_SUBTYPE 1
+
#endif /* _ARCH_H */
return result;
}
+#if USES_NEW_SUBTYPE
+/* fast_subtype_check **********************************************************
+
+ Checks if s is a subtype of t, using the restricted subtype relation (see
+ Cliff Click and John Rose: Fast subtype checking in the Hotspot JVM.)
+
+ RETURN VALUE:
+ 1......s is a subtype of t.
+ 0......otherwise
+
+*******************************************************************************/
+
+bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
+{
+ if (s->subtype_display[t->subtype_depth] == t)
+ return true;
+ if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
+ return false;
+ return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
+}
+#endif
/* builtin_fast_canstore *******************************************************
*******************************************************************************/
-bool fast_subtype_check(struct _vftbl *s, struct _vftbl *t)
-{
- if (s->subtype_display[t->subtype_depth] == t)
- return true;
- if (t->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]))
- return false;
- return s->subtype_depth >= t->subtype_depth && s->subtype_overflow[t->subtype_depth - DISPLAY_SIZE] == t;
-}
-
bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
{
arraydescriptor *desc;
if (valuevftbl == componentvftbl)
return 1;
+ LOCK_CLASSRENUMBER_LOCK;
+
baseval = componentvftbl->baseval;
if (baseval <= 0) {
(valuevftbl->interfacetable[baseval] != NULL));
}
else {
+#if USES_NEW_SUBTYPE
result = fast_subtype_check(valuevftbl, componentvftbl);
+#else
+ diffval = valuevftbl->baseval - componentvftbl->baseval;
+ result = diffval <= (uint32_t) componentvftbl->diffval;
+#endif
}
+
+ UNLOCK_CLASSRENUMBER_LOCK;
}
else if (valuedesc == NULL) {
/* {oa has dimension > 1} */
if (valuevftbl == elementvftbl)
return 1;
+ LOCK_CLASSRENUMBER_LOCK;
+
baseval = elementvftbl->baseval;
if (baseval <= 0) {
(valuevftbl->interfacetable[baseval] != NULL));
}
else {
+#if USES_NEW_SUBTYPE
result = fast_subtype_check(valuevftbl, elementvftbl);
+#else
+ diffval = valuevftbl->baseval - elementvftbl->baseval;
+ result = diffval <= (uint32_t) elementvftbl->diffval;
+#endif
}
+ UNLOCK_CLASSRENUMBER_LOCK;
+
return result;
}
if (valuevftbl == elementvftbl)
return 1;
+ LOCK_CLASSRENUMBER_LOCK;
+
+#if USES_NEW_SUBTYPE
result = fast_subtype_check(valuevftbl, elementvftbl);
+#else
+ diffval = valuevftbl->baseval - elementvftbl->baseval;
+ result = diffval <= (uint32_t) elementvftbl->diffval;
+#endif
+
+ UNLOCK_CLASSRENUMBER_LOCK;
return result;
}
* ICMD_BUILTIN3.)
*/
+#if USES_NEW_SUBTYPE
bool fast_subtype_check(struct _vftbl *, struct _vftbl *);
+#endif
bool builtin_instanceof(java_handle_t *obj, classinfo *c);
/* NOT AN OP */
#define REPLACEMENT_PATCH_SIZE 2 /* bytes */
+/* subtype ********************************************************************/
+
+#define USES_NEW_SUBTYPE 1
+
#endif /* _ARCH_H */
#define REPLACEMENT_PATCH_SIZE 2 /* bytes */
+/* subtype ********************************************************************/
+
+#define USES_NEW_SUBTYPE 1
+
#endif /* _ARCH_H */
static s4 interfaceindex; /* sequential numbering of interfaces */
static s4 classvalue;
+#if !USES_NEW_SUBTYPE
+java_object_t *linker_classrenumber_lock;
+#endif
+
#if defined(__cplusplus)
extern "C" {
#endif
interfaceindex = 0;
+#if defined(ENABLE_THREADS) && !USES_NEW_SUBTYPE
+ /* 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))
*******************************************************************************/
+#if USES_NEW_SUBTYPE
static int build_display_inner(classinfo *topc, classinfo *c, int i)
{
int depth;
c->vftbl->subtype_display[i] = NULL;
}
}
+#endif
static classinfo *link_class_intern(classinfo *c)
{
/* FIXME: this is completely useless now */
RT_TIMING_GET_TIME(time_subclasses);
+#if USES_NEW_SUBTYPE
build_display(c);
+#endif
/* revert the linking state and class is linked */
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;
+
}
};
+/* global variables ***********************************************************/
+
+/* This lock must be taken while renumbering classes or while atomically */
+/* accessing classes. */
+
+#if USES_NEW_SUBTYPE
+
+#define LOCK_CLASSRENUMBER_LOCK /* nothing */
+#define UNLOCK_CLASSRENUMBER_LOCK /* nothing */
+
+#else
+extern java_object_t *linker_classrenumber_lock;
+
+#define LOCK_CLASSRENUMBER_LOCK LOCK_MONITOR_ENTER(linker_classrenumber_lock)
+#define UNLOCK_CLASSRENUMBER_LOCK LOCK_MONITOR_EXIT(linker_classrenumber_lock)
+
+#endif
+
+
/* function prototypes ********************************************************/
#ifdef __cplusplus
#include "vm/class.hpp"
#include "vm/references.h"
+#if USES_NEW_SUBTYPE
#define DISPLAY_SIZE 4
+#endif
struct _vftbl {
methodptr *interfacetable[1]; /* interface table (access via macro) */
/* (-index for interfaces) */
s4 diffval; /* high - base for runtime type check */
+#if USES_NEW_SUBTYPE
s4 subtype_depth;
s4 subtype_offset;
struct _vftbl *subtype_display[DISPLAY_SIZE+1]; /* the last one is cache */
struct _vftbl **subtype_overflow;
+#endif
s4 *interfacevftbllength; /* length of interface vftbls */
methodptr table[1]; /* class vftbl */