X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=tables.c;h=9cbd95e9ae8a8ea4091834cbc91f074b72abf05b;hb=8614dad1cecffc80317d6c41be07611d6ff1f1ae;hp=69918a1a4437c5a14583f92962069d296d37c1f7;hpb=138a980ac316625bd575d9bdfb28c86a12906d17;p=cacao.git diff --git a/tables.c b/tables.c index 69918a1a4..9cbd95e9a 100644 --- a/tables.c +++ b/tables.c @@ -35,36 +35,40 @@ - the heap - additional support functions - $Id: tables.c 981 2004-03-26 00:34:51Z twisti $ + $Id: tables.c 1482 2004-11-11 14:39:13Z twisti $ */ +#include "global.h" + #include +#include #include #include #include #include +#include "builtin.h" +#include "exceptions.h" #include "types.h" -#include "global.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/loging.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 ********************************** ******************************************************************************/ @@ -107,11 +111,14 @@ void tables_init() 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 } @@ -121,7 +128,7 @@ void tables_init() *****************************************************************************/ -void tables_close(stringdeleter del) +void tables_close() { utf *u = NULL; literalstring *s; @@ -145,7 +152,7 @@ void tables_close(stringdeleter del) while (u) { /* process elements in external hash chain */ literalstring *nexts = s->hashlink; - del(s->string); + literalstring_free(s->string); FREE(s, literalstring); s = nexts; } @@ -162,15 +169,21 @@ void tables_close(stringdeleter del) 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 */ @@ -183,19 +196,25 @@ void utf_display(utf *u) } -/********************* 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 */ @@ -237,17 +256,25 @@ void log_plain_utf(utf *u) } -/************************ 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 */ @@ -258,11 +285,43 @@ void utf_sprint(char *buffer, utf *u) } +/* utf_sprint_classname ******************************************************** + + write utf symbol into c-string (debugging purposes) + +*******************************************************************************/ + +void utf_sprint_classname(char *buffer, utf *u) +{ + 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 */ + u2 c = utf_nextu2(&utf_ptr); + if (c == '/') c = '.'; + buffer[pos++] = c; + } + + /* terminate string */ + buffer[pos] = '\0'; +} + + /********************* Funktion: utf_fprint ********************************** write utf symbol into file -******************************************************************************/ +******************************************************************************/ void utf_fprint(FILE *file, utf *u) { @@ -282,6 +341,31 @@ 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. @@ -431,16 +515,16 @@ u4 unicode_hashkey(u2 *text, u2 len) ******************************************************************************/ -utf *utf_new(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); @@ -456,7 +540,8 @@ utf *utf_new(char *text, u2 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 */ @@ -474,19 +559,20 @@ utf *utf_new(char *text, u2 length) } #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)) { @@ -502,7 +588,8 @@ utf *utf_new(char *text, u2 length) 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 */ @@ -524,11 +611,29 @@ utf *utf_new(char *text, u2 length) 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_intern(text, length); + +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + tables_unlock(); +#endif + + return r; +} + + /********************* function: utf_new_char ******************************** creates a new utf symbol, the text for this symbol is passed @@ -742,7 +847,7 @@ u2 utf_nextu2(char **utf_ptr) 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) { @@ -886,22 +991,22 @@ is_valid_name_utf(utf *u) *******************************************************************************/ -classinfo *class_new(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; @@ -913,14 +1018,23 @@ classinfo *class_new(utf *u) /* 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; @@ -943,15 +1057,13 @@ classinfo *class_new(utf *u) 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; @@ -974,7 +1086,7 @@ classinfo *class_new(utf *u) /* 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); @@ -990,28 +1102,101 @@ classinfo *class_new(utf *u) 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 *classname) +{ + classinfo *c; + +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + tables_lock(); +#endif + + 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 c; +} + + /******************** Function: class_get ************************************** searches for the class with the specified name in the classes hashtable @@ -1019,32 +1204,25 @@ classinfo *class_new(utf *u) *******************************************************************************/ -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; iblength; 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; } @@ -1057,6 +1235,60 @@ classinfo *class_get(utf *u) 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. @@ -1068,28 +1300,34 @@ classinfo *class_array_of(classinfo *component) { 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 ******************************** @@ -1099,12 +1337,12 @@ classinfo *class_array_of(classinfo *component) *******************************************************************************/ -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 */ @@ -1112,21 +1350,21 @@ classinfo *class_multiarray_of(int dim,classinfo *element) 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 ****************************** @@ -1137,9 +1375,17 @@ classinfo *class_multiarray_of(int dim,classinfo *element) 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++;