- the heap
- additional support functions
- $Id: tables.c 1087 2004-05-26 21:27:03Z twisti $
+ $Id: tables.c 1445 2004-11-05 13:55:33Z twisti $
*/
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
+#include "builtin.h"
+#include "exceptions.h"
#include "types.h"
-#include "main.h"
+#include "native.h"
+#include "options.h"
#include "tables.h"
#include "loader.h"
#include "asmpart.h"
+#include "statistics.h"
#include "threads/thread.h"
#include "threads/locks.h"
#include "toolbox/logging.h"
#include "toolbox/memory.h"
-/* statistics */
-int count_utf_len = 0; /* size of utf hash */
-int count_utf_new = 0; /* calls of utf_new */
-int count_utf_new_found = 0; /* calls of utf_new with fast return */
-
hashtable utf_hash; /* hashtable for utf8-symbols */
hashtable string_hash; /* hashtable for javastrings */
hashtable class_hash; /* hashtable for classes */
+list unlinkedclasses; /* this is only used for eager class loading */
+
+
/******************************************************************************
*********************** hashtable functions **********************************
******************************************************************************/
init_hashtable(&utf_hash, UTF_HASHSTART); /* hashtable for utf8-symbols */
init_hashtable(&string_hash, HASHSTART); /* hashtable for javastrings */
init_hashtable(&class_hash, HASHSTART); /* hashtable for classes */
-
-#ifdef STATISTICS
+
+/* if (opt_eager) */
+/* list_init(&unlinkedclasses, OFFSET(classinfo, listnode)); */
+
+#if defined(STATISTICS)
if (opt_stat)
count_utf_len += sizeof(utf*) * utf_hash.size;
#endif
-
}
*****************************************************************************/
-void tables_close(stringdeleter del)
+void tables_close()
{
utf *u = NULL;
literalstring *s;
while (u) {
/* process elements in external hash chain */
literalstring *nexts = s->hashlink;
- del(s->string);
+ literalstring_free(s->string);
FREE(s, literalstring);
s = nexts;
}
******************************************************************************/
-utf *utf_new_int(char *text, u2 length)
+utf *utf_new_intern(char *text, u2 length)
{
u4 key; /* hashkey computed from utf-text */
u4 slot; /* slot in hashtable */
tables_lock();
#endif
- r = utf_new_int(text, length);
+ r = utf_new_intern(text, length);
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
tables_unlock();
switch ((ch1 = utf[0]) >> 4) {
default: /* 1 byte */
(*utf_ptr)++;
- return ch1;
+ return (u2) ch1;
case 0xC:
case 0xD: /* 2 bytes */
if (((ch2 = utf[1]) & 0xC0) == 0x80) {
*******************************************************************************/
-classinfo *class_new_int(utf *classname)
+classinfo *class_new_intern(utf *classname)
{
classinfo *c; /* hashtable element */
u4 key; /* hashkey computed from classname */
/* location in hashtable found, create new classinfo structure */
-#ifdef STATISTICS
+#if defined(STATISTICS)
if (opt_stat)
count_class_infos += sizeof(classinfo);
#endif
c->innerclass = NULL;
c->vftbl = NULL;
c->initialized = false;
+ c->initializing = false;
c->classvftbl = false;
c->classUsed = 0;
c->impldBy = NULL;
}
}
}
-
- /* we support eager class loading and linking on demand */
-
- if (opt_eager) {
- /* all super classes are loaded implicitly */
-/* if (!c->loaded) */
-/* class_load(c); */
-
-/* if (!c->linked) */
-/* class_link(c); */
- }
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ initObjectLock(&c->header);
+#endif
return c;
}
tables_lock();
#endif
- c = class_new_int(classname);
+ c = class_new_intern(classname);
/* we support eager class loading and linking on demand */
if (opt_eager) {
- if (!c->loaded)
- class_load(c);
+ classinfo *tc;
+ classinfo *tmp;
+
+ list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
- if (!c->linked)
- class_link(c);
+ if (!c->loaded) {
+ if (!class_load(c)) {
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ tables_unlock();
+#endif
+ return c;
+ }
+ }
+
+ /* link all referenced classes */
+
+ tc = list_first(&unlinkedclasses);
+
+ while (tc) {
+ /* skip the current loaded/linked class */
+ if (tc != c) {
+ if (!class_link(tc)) {
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ tables_unlock();
+#endif
+ return c;
+ }
+ }
+
+ /* we need a tmp variable here, because list_remove sets prev and
+ next to NULL */
+ tmp = list_next(&unlinkedclasses, tc);
+ list_remove(&unlinkedclasses, tc);
+ tc = tmp;
+ }
+
+ if (!c->linked) {
+ if (!class_link(c)) {
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ tables_unlock();
+#endif
+ return c;
+ }
+ }
}
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
*******************************************************************************/
-classinfo *class_get(utf *u)
+classinfo *class_get(utf *classname)
{
classinfo *c; /* hashtable element */
u4 key; /* hashkey computed from classname */
u4 slot; /* slot in hashtable */
u2 i;
- key = utf_hashkey (u->text, u->blength);
+ key = utf_hashkey(classname->text, classname->blength);
slot = key & (class_hash.size-1);
c = class_hash.ptr[slot];
/* search external hash-chain */
while (c) {
- if (c->name->blength == u->blength) {
-
+ if (c->name->blength == classname->blength) {
/* compare classnames */
- for (i=0; i<u->blength; i++)
- if (u->text[i] != c->name->text[i]) goto nomatch;
+ for (i = 0; i < classname->blength; i++)
+ if (classname->text[i] != c->name->text[i])
+ goto nomatch;
/* class found in hashtable */
return c;
}
+/* class_remove ****************************************************************
+
+ removes the class entry wth the specified name in the classes hashtable,
+ furthermore the class' resources are freed
+ if there is no such class false is returned
+
+*******************************************************************************/
+
+bool class_remove(classinfo *c)
+{
+ classinfo *tc; /* hashtable element */
+ classinfo *pc;
+ u4 key; /* hashkey computed from classname */
+ u4 slot; /* slot in hashtable */
+ u2 i;
+
+ key = utf_hashkey(c->name->text, c->name->blength);
+ slot = key & (class_hash.size - 1);
+ tc = class_hash.ptr[slot];
+ pc = NULL;
+
+ /* search external hash-chain */
+ while (tc) {
+ if (tc->name->blength == c->name->blength) {
+
+ /* compare classnames */
+ for (i = 0; i < c->name->blength; i++)
+ if (tc->name->text[i] != c->name->text[i])
+ goto nomatch;
+
+ /* class found in hashtable */
+ if (!pc) {
+ class_hash.ptr[slot] = tc->hashlink;
+
+ } else {
+ pc->hashlink = tc->hashlink;
+ }
+
+ class_free(tc);
+
+ return true;
+ }
+
+ nomatch:
+ pc = tc;
+ tc = tc->hashlink;
+ }
+
+ /* class not found */
+ return false;
+}
+
+
/***************** Function: class_array_of ***********************************
Returns an array class with the given component class.
u4 utf_strlen(utf *u)
{
- char *endpos = utf_end(u); /* points behind utf string */
- char *utf_ptr = u->text; /* current position in utf text */
- u4 len = 0; /* number of unicode characters */
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+ u4 len = 0; /* number of unicode characters */
+
+ if (!u) {
+ *exceptionptr = new_nullpointerexception();
+ return 0;
+ }
+
+ endpos = utf_end(u);
+ utf_ptr = u->text;
while (utf_ptr < endpos) {
len++;