-/* 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 1019 2004-04-10 13:33:21Z 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 "toolbox/loging.h"
-#include "toolbox/memory.h"
+#include "types.h"
+#include "mm/memory.h"
+#include "native/native.h"
+#include "toolbox/logging.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
- count_utf_len += sizeof(utf*) * utf_hash.size;
-#endif
+/* 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 */
write utf symbol into file
-******************************************************************************/
+******************************************************************************/
void utf_fprint(FILE *file, utf *u)
{
}
+/********************* Funktion: utf_fprint **********************************
+
+ write utf symbol into file
+
+******************************************************************************/
+
+void utf_fprint_classname(FILE *file, utf *u)
+{
+ char *endpos = utf_end(u); /* points behind utf string */
+ char *utf_ptr = u->text; /* current position in utf text */
+
+ if (!u)
+ return;
+
+ while (utf_ptr < endpos) {
+ /* read next unicode character */
+ u2 c = utf_nextu2(&utf_ptr);
+ if (c == '/') c = '.';
+
+ if (c >= 32 && c <= 127) fprintf(file, "%c", c);
+ else fprintf(file, "?");
+ }
+}
+
+
/****************** internal function: utf_hashkey ***************************
The hashkey is computed from the utf-text by using up to 8 characters.
******************************************************************************/
-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 */
utf *u; /* hashtable element */
u2 i;
-/* log_text("utf_new entered");*/
#ifdef STATISTICS
- count_utf_new++;
+ if (opt_stat)
+ count_utf_new++;
#endif
key = utf_hashkey(text, length);
if (text[i] != u->text[i]) goto nomatch;
#ifdef STATISTICS
- count_utf_new_found++;
+ if (opt_stat)
+ count_utf_new_found++;
#endif
/* log_text("symbol found in hash table");*/
/* symbol found in hashtable */
}
#ifdef STATISTICS
- count_utf_len += sizeof(utf) + length;
+ if (opt_stat)
+ count_utf_len += sizeof(utf) + length;
#endif
/* location in hashtable found, create new utf element */
- u = NEW (utf);
- u->blength = length; /* length in bytes of utfstring */
- u->hashlink = utf_hash.ptr[slot]; /* link in external hashchain */
- u->text = mem_alloc(length/*JOWENN*/+1); /* allocate memory for utf-text */
- memcpy(u->text,text,length); /* copy utf-text */
- u->text[length] = '\0';/*JOWENN*/
- utf_hash.ptr[slot] = u; /* insert symbol into table */
+ u = NEW(utf);
+ u->blength = length; /* length in bytes of utfstring */
+ u->hashlink = utf_hash.ptr[slot]; /* link in external hashchain */
+ u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
+ memcpy(u->text, text, length); /* copy utf-text */
+ u->text[length] = '\0';
+ utf_hash.ptr[slot] = u; /* insert symbol into table */
- utf_hash.entries++; /* update number of entries */
+ utf_hash.entries++; /* update number of entries */
if (utf_hash.entries > (utf_hash.size * 2)) {
newhash.entries = utf_hash.entries;
#ifdef STATISTICS
- count_utf_len += sizeof(utf*) * utf_hash.size;
+ if (opt_stat)
+ count_utf_len += sizeof(utf*) * utf_hash.size;
#endif
/* transfer elements to new hashtable */
MFREE(utf_hash.ptr, void*, utf_hash.size);
utf_hash = newhash;
}
- /*utf_display(u);*/
+
return u;
}
+
utf *utf_new(char *text, u2 length)
{
utf *r;
+
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
tables_lock();
#endif
- r = utf_new_int(text, length);
+
+ r = utf_new_intern(text, length);
+
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
tables_unlock();
#endif
+
return r;
}
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 *u)
+classinfo *class_new_intern(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 for the class */
while (c) {
- if (c->name->blength == u->blength) {
- for (i = 0; i < u->blength; i++)
- if (u->text[i] != c->name->text[i]) goto nomatch;
+ if (c->name->blength == classname->blength) {
+ for (i = 0; i < classname->blength; i++)
+ if (classname->text[i] != c->name->text[i]) goto nomatch;
/* class found in hashtable */
return c;
/* location in hashtable found, create new classinfo structure */
-#ifdef STATISTICS
- count_class_infos += sizeof(classinfo);
+#if defined(STATISTICS)
+ if (opt_stat)
+ count_class_infos += sizeof(classinfo);
#endif
+ if (initverbose) {
+ char logtext[MAXLOGTEXT];
+ sprintf(logtext, "Creating class: ");
+ utf_sprint_classname(logtext + strlen(logtext), classname);
+ log_text(logtext);
+ }
+
c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
+ /*c=NEW(classinfo);*/
c->vmClass = 0;
c->flags = 0;
- c->name = u;
+ c->name = classname;
c->packagename = NULL;
c->cpcount = 0;
c->cptags = NULL;
c->innerclass = NULL;
c->vftbl = NULL;
c->initialized = false;
+ c->initializing = false;
c->classvftbl = false;
c->classUsed = 0;
c->impldBy = NULL;
c->classloader = NULL;
c->sourcefile = NULL;
- /* prepare loading of the class */
- list_addlast(&unloadedclasses, c);
-
/* insert class into the hashtable */
c->hashlink = class_hash.ptr[slot];
class_hash.ptr[slot] = c;
/* transfer elements to new hashtable */
for (i = 0; i < class_hash.size; i++) {
- c = (classinfo*) class_hash.ptr[i];
+ c = (classinfo *) class_hash.ptr[i];
while (c) {
classinfo *nextc = c->hashlink;
u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
MFREE(class_hash.ptr, void*, class_hash.size);
class_hash = newhash;
}
-
+
/* Array classes need further initialization. */
- if (u->text[0] == '[') {
+ if (c->name->text[0] == '[') {
+ /* Array classes are not loaded from classfiles. */
+ c->loaded = true;
class_new_array(c);
c->packagename = array_packagename;
- }
- else {
+
+ } else {
/* Find the package name */
/* Classes in the unnamed package keep packagename == NULL. */
char *p = utf_end(c->name) - 1;
char *start = c->name->text;
- for (;p > start; --p)
+ for (;p > start; --p) {
if (*p == '.') {
- c->packagename = utf_new(start,p-start);
+ c->packagename = utf_new(start, p - start);
break;
}
+ }
}
-
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ initObjectLock(&c->header);
+#endif
+
return c;
}
-classinfo *class_new(utf *u)
+
+classinfo *class_new(utf *classname)
{
- classinfo *r;
+ classinfo *c;
+
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
tables_lock();
#endif
- r = class_new_int(u);
+
+ c = class_new_intern(classname);
+
+ /* we support eager class loading and linking on demand */
+
+ if (opt_eager) {
+ 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 */
+
+ 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)
tables_unlock();
#endif
- return r;
+
+ return c;
}
*******************************************************************************/
-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];
-/*
- log_text("class_get: looking for class:");
- utf_display(u); */
/* 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;
-/*
- log_text("class_get: class found");
- utf_display(u);
- log_text("");
- utf_display(c->name); */
+ for (i = 0; i < classname->blength; i++)
+ if (classname->text[i] != c->name->text[i])
+ goto nomatch;
+
/* class found in hashtable */
return c;
}
return NULL;
}
+
+/* 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.
{
int namelen;
char *namebuf;
+ classinfo *c;
/* Assemble the array class name */
namelen = component->name->blength;
if (component->name->text[0] == '[') {
/* the component is itself an array */
- namebuf = DMNEW(char,namelen+1);
+ namebuf = DMNEW(char, namelen + 1);
namebuf[0] = '[';
- memcpy(namebuf+1,component->name->text,namelen);
+ memcpy(namebuf + 1, component->name->text, namelen);
namelen++;
- }
- else {
+
+ } else {
/* the component is a non-array class */
- namebuf = DMNEW(char,namelen+3);
+ namebuf = DMNEW(char, namelen + 3);
namebuf[0] = '[';
namebuf[1] = 'L';
- memcpy(namebuf+2,component->name->text,namelen);
- namebuf[2+namelen] = ';';
- namelen+=3;
+ memcpy(namebuf + 2, component->name->text, namelen);
+ namebuf[2 + namelen] = ';';
+ namelen += 3;
}
- return class_new( utf_new(namebuf,namelen) );
+ /* load this class ;-) and link it */
+ c = class_new(utf_new(namebuf, namelen));
+ c->loaded = 1;
+ class_link(c);
+
+ return c;
}
/*************** Function: class_multiarray_of ********************************
*******************************************************************************/
-classinfo *class_multiarray_of(int dim,classinfo *element)
+classinfo *class_multiarray_of(int dim, classinfo *element)
{
int namelen;
char *namebuf;
- if (dim<1)
+ if (dim < 1)
panic("Invalid array dimension requested");
/* Assemble the array class name */
if (element->name->text[0] == '[') {
/* the element is itself an array */
- namebuf = DMNEW(char,namelen+dim);
- memcpy(namebuf+dim,element->name->text,namelen);
+ namebuf = DMNEW(char, namelen + dim);
+ memcpy(namebuf + dim, element->name->text, namelen);
namelen += dim;
}
else {
/* the element is a non-array class */
- namebuf = DMNEW(char,namelen+2+dim);
+ namebuf = DMNEW(char, namelen + 2 + dim);
namebuf[dim] = 'L';
- memcpy(namebuf+dim+1,element->name->text,namelen);
- namelen += (2+dim);
- namebuf[namelen-1] = ';';
+ memcpy(namebuf + dim + 1, element->name->text, namelen);
+ namelen += (2 + dim);
+ namebuf[namelen - 1] = ';';
}
- memset(namebuf,'[',dim);
+ memset(namebuf, '[', dim);
- return class_new( utf_new(namebuf,namelen) );
+ return class_new(utf_new(namebuf, namelen));
}
/************************** function: utf_strlen ******************************
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++;