#include "vm/jit/argument.h"
+#include "vmcore/options.h"
+
/* debug **********************************************************************/
-#if !defined(NDEBUG) && 0
-# define TRACELOCALREF(message) log_println("%s", message)
+#if !defined(NDEBUG)
+# define DEBUGLOCALREF(message, index) \
+ do { \
+ if (opt_DebugLocalReferences) { \
+ localref_table *dlrt = LOCALREFTABLE; \
+ log_start(); \
+ log_print("[local reference %-12s: lrt=%016p frame=%d capacity=%d used=%d", message, dlrt, dlrt->localframes, dlrt->capacity, dlrt->used); \
+ if (index >= 0) \
+ log_print(" localref=%p object=%p", &(dlrt->refs[index]), dlrt->refs[index]); \
+ log_print("]"); \
+ log_finish(); \
+ } \
+ } while (0)
#else
-# define TRACELOCALREF(message)
+# define DEBUGLOCALREF(message, index)
#endif
#endif
+/* some forward declarations **************************************************/
+
+static bool localref_check_uncleared();
+
+
/* localref_table_init *********************************************************
Initializes the local references table of the current thread.
{
localref_table *lrt;
- TRACELOCALREF("table init");
-
assert(LOCALREFTABLE == NULL);
#if !defined(ENABLE_GC_BOEHM)
localref_table_add(lrt);
+ DEBUGLOCALREF("table init", -1);
+
return true;
}
{
localref_table *lrt;
- TRACELOCALREF("table destroy");
-
lrt = LOCALREFTABLE;
-
- assert(lrt);
+ assert(lrt != NULL);
assert(lrt->prev == NULL);
+ DEBUGLOCALREF("table destroy", -1);
+
#if !defined(ENABLE_GC_BOEHM)
FREE(lrt, localref_table);
#endif
/* add given local references table to this thread */
LOCALREFTABLE = lrt;
+
+ /*DEBUGLOCALREF("table add", -1);*/
}
{
localref_table *lrt;
+#if !defined(NDEBUG)
+ /* check for uncleared local references */
+
+ localref_check_uncleared();
+#endif
+
/* get current local reference table from thread */
lrt = LOCALREFTABLE;
-
assert(lrt != NULL);
assert(lrt->localframes == 1);
+ /*DEBUGLOCALREF("table remove", -1);*/
+
lrt = lrt->prev;
LOCALREFTABLE = lrt;
localref_table *nlrt;
int32_t additionalrefs;
- TRACELOCALREF("frame push");
-
/* get current local reference table from thread */
lrt = LOCALREFTABLE;
-
assert(lrt != NULL);
assert(capacity > 0);
LOCALREFTABLE = nlrt;
+ DEBUGLOCALREF("frame push", -1);
+
return true;
}
int32_t additionalrefs;
#endif
- TRACELOCALREF("frame pop all");
-
/* get current local reference table from thread */
lrt = LOCALREFTABLE;
-
assert(lrt != NULL);
localframes = lrt->localframes;
plrt = lrt->prev;
+ DEBUGLOCALREF("frame pop", -1);
+
/* clear all reference entries */
MSET(lrt->refs, 0, void*, lrt->capacity);
}
#endif
- /* XXX: assert that we are in a GC critical section! */
-
- /* XXX: this is only an ugly hack */
-#if defined(ENABLE_HANDLES)
- if (LOCALREFTABLE == NULL) {
- h = NEW(java_handle_t);
- h->heap_object = o;
- log_println("localref_add: WARNING: added preliminary localref %p for %p", h, o);
- return h;
- }
-#endif
-
/* get current local reference table from thread */
lrt = LOCALREFTABLE;
-
assert(lrt != NULL);
+ /* XXX: assert that we are in a GC critical section! */
/* Check if we have space for the requested reference? No,
allocate a new frame. This is actually not what the spec says,
but for compatibility reasons... */
if (lrt->used == lrt->capacity) {
- if (!localref_frame_push(16))
+ if (!localref_frame_push(64))
assert(0);
/* get the new local reference table */
h = (java_handle_t *) o;
#endif
-#if 0
- {
- int count = 0;
- for (lrt = LOCALREFTABLE; lrt != NULL; lrt = lrt->prev)
- count += lrt->used;
- log_println("added localref %p for %p (total count %d)", h, o, count);
- /*localref_dump();*/
- }
-#endif
+ /*DEBUGLOCALREF("entry add", i);*/
return h;
}
/* get local reference table from thread */
lrt = LOCALREFTABLE;
-
assert(lrt != NULL);
localframes = lrt->localframes;
#endif
if (h == localref) {
+ DEBUGLOCALREF("entry delete", i);
+
lrt->refs[i] = NULL;
lrt->used--;
/* get local reference table from thread */
lrt = LOCALREFTABLE;
-
assert(lrt != NULL);
assert(m != NULL);
/* get local reference table from thread */
lrt = LOCALREFTABLE;
-
assert(lrt != NULL);
assert(m != NULL);
ret.a = (void *) h->heap_object;
argument_jitreturn_store(md, return_regs, ret);
-#if !defined(NDEBUG)
+#if !defined(NDEBUG) && 0
/* removing the entry from the local reference table is not really
necesarry, but gives us warnings if the entry does not exist. */
#endif /* !defined(NDEBUG) */
+/* localref_check_uncleared ****************************************************
+
+ Checks the topmost local reference table for uncleared references.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+static bool localref_check_uncleared()
+{
+ localref_table *lrt;
+ int32_t localframes;
+ int32_t lrt_uncleared;
+ int32_t lrt_used;
+ int i;
+
+ /* get current local reference table from thread */
+
+ lrt = LOCALREFTABLE;
+ assert(lrt != NULL);
+ assert(lrt->localframes > 0);
+
+ localframes = lrt->localframes;
+ lrt_uncleared = 0;
+ lrt_used = 0;
+
+ for (; localframes > 0; localframes--) {
+ lrt_used += lrt->used;
+
+ for (i = 0; i < lrt->capacity; i++) {
+ if (lrt->refs[i] != NULL)
+ lrt_uncleared++;
+ }
+
+ lrt = lrt->prev;
+ }
+
+ if (lrt_uncleared != lrt_used) {
+ localref_dump();
+ vm_abort("localref_check_uncleared: (uncleared=%d) != (used=%d)", lrt_uncleared, lrt_used);
+ }
+
+ if (lrt_uncleared <= 1)
+ return true;
+ else {
+ /*log_println("localref_check_uncleared: %d uncleared local references", lrt_uncleared);*/
+ return false;
+ }
+}
+#endif
+
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where
/* NOTE: For better readability keep these alpha-sorted. */
int opt_DebugExceptions = 0;
+int opt_DebugLocalReferences = 0;
int opt_DebugLocks = 0;
int opt_DebugPackage = 0;
int opt_DebugPatcher = 0;
enum {
OPT_DebugExceptions,
+ OPT_DebugLocalReferences,
OPT_DebugLocks,
OPT_DebugPackage,
OPT_DebugPatcher,
option_t options_XX[] = {
{ "DebugExceptions", OPT_DebugExceptions, OPT_TYPE_BOOLEAN, "debug exceptions" },
+ { "DebugLocalReferences", OPT_DebugLocalReferences, OPT_TYPE_BOOLEAN, "print debug information for local reference tables" },
{ "DebugLocks", OPT_DebugLocks, OPT_TYPE_BOOLEAN, "print debug information for locks" },
{ "DebugPackage", OPT_DebugPackage, OPT_TYPE_BOOLEAN, "debug Java boot-packages" },
{ "DebugPatcher", OPT_DebugPatcher, OPT_TYPE_BOOLEAN, "debug JIT code patching" },
opt_DebugExceptions = enable;
break;
+ case OPT_DebugLocalReferences:
+ opt_DebugLocalReferences = enable;
+ break;
+
case OPT_DebugLocks:
opt_DebugLocks = enable;
break;