-/* tables.c -
+/* vm/tables.c -
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
- M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
- P. Tomsich, J. Wenninger
+ Copyright (C) 1996-2005 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
This file is part of CACAO.
- the heap
- additional support functions
- $Id: tables.c 1087 2004-05-26 21:27:03Z twisti $
+ $Id: tables.c 1735 2004-12-07 14:33:27Z twisti $
*/
-#include "global.h"
-
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
+
#include "types.h"
-#include "main.h"
-#include "tables.h"
-#include "loader.h"
-#include "asmpart.h"
-#include "threads/thread.h"
-#include "threads/locks.h"
+#include "mm/memory.h"
+#include "native/native.h"
#include "toolbox/logging.h"
-#include "toolbox/memory.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/tables.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;
}
write utf symbol to stdout (debugging purposes)
-******************************************************************************/
+*******************************************************************************/
void utf_display(utf *u)
{
- char *endpos = utf_end(u); /* points behind utf string */
- char *utf_ptr = u->text; /* current position in utf text */
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
- if (!u)
+ if (!u) {
+ printf("NULL");
+ fflush(stdout);
return;
+ }
+
+ endpos = utf_end(u);
+ utf_ptr = u->text;
while (utf_ptr < endpos) {
/* read next unicode character */
}
-/********************* function: utf_display *********************************
+/* utf_display_classname *******************************************************
- write utf symbol to stdout (debugging purposes)
+ write utf symbol to stdout (debugging purposes)
-******************************************************************************/
+*******************************************************************************/
void utf_display_classname(utf *u)
{
- char *endpos = utf_end(u); /* points behind utf string */
- char *utf_ptr = u->text; /* current position in utf text */
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
- if (!u)
+ if (!u) {
+ printf("NULL");
+ fflush(stdout);
return;
+ }
+
+ endpos = utf_end(u);
+ utf_ptr = u->text;
while (utf_ptr < endpos) {
/* read next unicode character */
}
-/************************ function: utf_sprint *******************************
+/* utf_sprint ******************************************************************
- write utf symbol into c-string (debugging purposes)
+ write utf symbol into c-string (debugging purposes)
-******************************************************************************/
+*******************************************************************************/
void utf_sprint(char *buffer, utf *u)
{
- char *endpos = utf_end(u); /* points behind utf string */
- char *utf_ptr = u->text; /* current position in utf text */
- u2 pos = 0; /* position in c-string */
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+ u2 pos = 0; /* position in c-string */
+
+ if (!u) {
+ memcpy(buffer, "NULL", 5); /* 4 chars + terminating \0 */
+ return;
+ }
+
+ endpos = utf_end(u);
+ utf_ptr = u->text;
while (utf_ptr < endpos)
/* copy next unicode character */
}
-/************************ function: utf_sprint_classname *********************
+/* utf_sprint_classname ********************************************************
- write utf symbol into c-string (debugging purposes)
+ write utf symbol into c-string (debugging purposes)
-******************************************************************************/
+*******************************************************************************/
void utf_sprint_classname(char *buffer, utf *u)
{
- char *endpos = utf_end(u); /* points behind utf string */
- char *utf_ptr = u->text; /* current position in utf text */
- u2 pos = 0; /* position in c-string */
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+ u2 pos = 0; /* position in c-string */
+
+ if (!u) {
+ memcpy(buffer, "NULL", 5); /* 4 chars + terminating \0 */
+ return;
+ }
+
+ endpos = utf_end(u);
+ utf_ptr = u->text;
while (utf_ptr < endpos) {
/* copy next unicode character */
******************************************************************************/
-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->loaded) {
+ if (!class_load(c)) {
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ tables_unlock();
+#endif
+ return c;
+ }
+ }
+
+ /* link all referenced classes */
- if (!c->linked)
- class_link(c);
+ 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++;