- the heap
- additional support functions
- $Id: tables.c 724 2003-12-09 18:56:11Z edwin $
+ $Id: tables.c 1372 2004-08-01 21:56:10Z stefan $
*/
+#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 "global.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 **********************************
******************************************************************************/
for (i = 0; i < size; i++) hash->ptr[i] = NULL;
}
+
/*********************** function: tables_init *****************************
creates hashtables for symboltables
*****************************************************************************/
-void tables_init ()
+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
}
+
/********************** function: tables_close ******************************
free memory for hashtables
*****************************************************************************/
-void tables_close (stringdeleter del)
+void tables_close()
{
- utf *u;
+ utf *u = NULL;
literalstring *s;
u4 i;
/* dispose utf symbols */
- for (i=0; i<utf_hash.size; i++) {
+ for (i = 0; i < utf_hash.size; i++) {
u = utf_hash.ptr[i];
while (u) {
/* process elements in external hash chain */
utf *nextu = u->hashlink;
- MFREE (u->text, u1, u->blength);
- FREE (u, utf);
+ MFREE(u->text, u1, u->blength);
+ FREE(u, utf);
u = nextu;
}
}
/* dispose javastrings */
- for (i=0; i<string_hash.size; i++) {
+ for (i = 0; i < string_hash.size; i++) {
s = string_hash.ptr[i];
while (u) {
/* process elements in external hash chain */
literalstring *nexts = s->hashlink;
- del(s->string);
+ literalstring_free(s->string);
FREE(s, literalstring);
s = nexts;
}
}
/* dispose hashtable structures */
- MFREE (utf_hash.ptr, void*, utf_hash.size);
- MFREE (string_hash.ptr, void*, string_hash.size);
- MFREE (class_hash.ptr, void*, class_hash.size);
+ MFREE(utf_hash.ptr, void*, utf_hash.size);
+ MFREE(string_hash.ptr, void*, string_hash.size);
+ MFREE(class_hash.ptr, void*, class_hash.size);
}
+
/********************* function: utf_display *********************************
write utf symbol to stdout (debugging purposes)
******************************************************************************/
-void utf_display (utf *u)
+void utf_display(utf *u)
{
char *endpos = utf_end(u); /* points behind utf string */
char *utf_ptr = u->text; /* current position in utf text */
- if (u==NULL) return;
- while (utf_ptr<endpos) {
+ if (!u)
+ return;
+
+ while (utf_ptr < endpos) {
/* read next unicode character */
- u2 c = utf_nextu2(&utf_ptr);
- if (c>=32 && c<=127) printf ("%c",c);
- else printf ("?");
+ u2 c = utf_nextu2(&utf_ptr);
+ if (c >= 32 && c <= 127) printf("%c", c);
+ else printf("?");
}
- fflush (stdout);
+ fflush(stdout);
}
+
+/********************* function: utf_display *********************************
+
+ 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 */
+
+ 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) printf("%c", c);
+ else printf("?");
+ }
+
+ fflush(stdout);
+}
+
+
/************************* function: log_utf *********************************
log utf symbol
void log_utf(utf *u)
{
char buf[MAXLOGTEXT];
- utf_sprint(buf,u);
- dolog(buf);
+ utf_sprint(buf, u);
+ dolog("%s", buf);
}
+
/********************** function: log_plain_utf ******************************
log utf symbol (without printing "LOG: " and newline)
void log_plain_utf(utf *u)
{
char buf[MAXLOGTEXT];
- utf_sprint(buf,u);
- dolog_plain(buf);
+ utf_sprint(buf, u);
+ dolog_plain("%s", buf);
}
+
/************************ function: utf_sprint *******************************
write utf symbol into c-string (debugging purposes)
-******************************************************************************/
+******************************************************************************/
-void utf_sprint (char *buffer, utf *u)
+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 */
- while (utf_ptr<endpos)
+ while (utf_ptr < endpos)
/* copy next unicode character */
buffer[pos++] = utf_nextu2(&utf_ptr);
}
+/************************ function: utf_sprint_classname *********************
+
+ 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 */
+
+ 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)
+void utf_fprint(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==NULL) return;
- while (utf_ptr<endpos) {
+
+ if (!u)
+ return;
+
+ while (utf_ptr < endpos) {
+ /* read next unicode character */
+ u2 c = utf_nextu2(&utf_ptr);
+
+ if (c >= 32 && c <= 127) fprintf(file, "%c", c);
+ else fprintf(file, "?");
+ }
+}
+
+
+/********************* 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,"?");
+ if (c >= 32 && c <= 127) fprintf(file, "%c", c);
+ else fprintf(file, "?");
}
-}
+}
/****************** internal function: utf_hashkey ***************************
#define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
#define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
-static u4 utf_hashkey (char *text, u4 length)
+static u4 utf_hashkey(char *text, u4 length)
{
char *start_pos = text; /* pointer to utf text */
u4 a;
case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
- case 9: a = fbs(0) ^ nbs(1) ^ nbs(2);
- text++;
+ case 9:
+ a = fbs(0);
+ a ^= nbs(1);
+ a ^= nbs(2);
+ text++;
return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
- case 10: a = fbs(0);
+ case 10:
+ a = fbs(0);
text++;
- a^= nbs(2) ^ nbs(3) ^ nbs(4);
+ a ^= nbs(2);
+ a ^= nbs(3);
+ a ^= nbs(4);
text++;
return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
- case 11: a = fbs(0);
+ case 11:
+ a = fbs(0);
text++;
- a^= nbs(2) ^ nbs(3) ^ nbs(4);
+ a ^= nbs(2);
+ a ^= nbs(3);
+ a ^= nbs(4);
text++;
return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
- case 12: a = fbs(0);
- text+=2;
- a^= nbs(2) ^ nbs(3);
- text+=1;
- a^= nbs(5) ^ nbs(6) ^ nbs(7);
- text+=1;
- return a ^ nbs(9) ^ nbs(10);
-
- case 13: a = fbs(0) ^ nbs(1);
- text+=1;
- a^= nbs(3) ^ nbs(4);
- text+=2;
- a^= nbs(7) ^ nbs(8);
- text+=2;
+ case 12:
+ a = fbs(0);
+ text += 2;
+ a ^= nbs(2);
+ a ^= nbs(3);
+ text++;
+ a ^= nbs(5);
+ a ^= nbs(6);
+ a ^= nbs(7);
+ text++;
+ return a ^ nbs(9) ^ nbs(10);
+
+ case 13:
+ a = fbs(0);
+ a ^= nbs(1);
+ text++;
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text += 2;
+ a ^= nbs(7);
+ a ^= nbs(8);
+ text += 2;
return a ^ nbs(9) ^ nbs(10);
- case 14: a = fbs(0);
- text+=2;
- a^= nbs(3) ^ nbs(4);
- text+=2;
- a^= nbs(7) ^ nbs(8);
- text+=2;
+ case 14:
+ a = fbs(0);
+ text += 2;
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text += 2;
+ a ^= nbs(7);
+ a ^= nbs(8);
+ text += 2;
return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
- case 15: a = fbs(0);
- text+=2;
- a^= nbs(3) ^ nbs(4);
- text+=2;
- a^= nbs(7) ^ nbs(8);
- text+=2;
+ case 15:
+ a = fbs(0);
+ text += 2;
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text += 2;
+ a ^= nbs(7);
+ a ^= nbs(8);
+ text += 2;
return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
default: /* 3 characters from beginning */
a = fbs(0);
- text+=2;
- a^= nbs(3) ^ nbs(4);
+ text += 2;
+ a ^= nbs(3);
+ a ^= nbs(4);
/* 2 characters from middle */
text = start_pos + (length / 2);
- a^= fbs(5);
- text+=2;
- a^= nbs(6);
+ a ^= fbs(5);
+ text += 2;
+ a ^= nbs(6);
/* 3 characters from end */
text = start_pos + length - 4;
- a^= fbs(7);
- text+=1;
+ a ^= fbs(7);
+ text++;
return a ^ nbs(10) ^ nbs(11);
}
******************************************************************************/
-u4 unicode_hashkey (u2 *text, u2 len)
+u4 unicode_hashkey(u2 *text, u2 len)
{
return utf_hashkey((char*) text, len);
}
+
/************************ function: utf_new **********************************
Creates a new utf-symbol, the text of the symbol is passed as a
******************************************************************************/
-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);
+ key = utf_hashkey(text, length);
slot = key & (utf_hash.size-1);
u = utf_hash.ptr[slot];
if (u->blength == length) {
/* compare text of hashtable elements */
- for (i=0; i<length; i++)
+ for (i = 0; i < length; i++)
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)) {
+ if (utf_hash.entries > (utf_hash.size * 2)) {
/* reorganization of hashtable, average length of
the external chains is approx. 2 */
hashtable newhash; /* the new hashtable */
/* create new hashtable, double the size */
- init_hashtable(&newhash, utf_hash.size*2);
- newhash.entries=utf_hash.entries;
+ init_hashtable(&newhash, 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 */
- for (i=0; i<utf_hash.size; i++) {
- u = (utf*) utf_hash.ptr[i];
+ for (i = 0; i < utf_hash.size; i++) {
+ u = (utf *) utf_hash.ptr[i];
while (u) {
- utf *nextu = u -> hashlink;
- u4 slot = (utf_hashkey(u->text,u->blength)) & (newhash.size-1);
+ utf *nextu = u->hashlink;
+ u4 slot = utf_hashkey(u->text, u->blength) & (newhash.size - 1);
- u->hashlink = (utf*) newhash.ptr[slot];
+ u->hashlink = (utf *) newhash.ptr[slot];
newhash.ptr[slot] = u;
/* follow link in external hash chain */
}
/* dispose old table */
- MFREE (utf_hash.ptr, void*, utf_hash.size);
+ 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
******************************************************************************/
-utf *utf_new_char (char *text)
+utf *utf_new_char(char *text)
{
return utf_new(text, strlen(text));
}
******************************************************************************/
-utf *utf_new_char_classname (char *text)
+utf *utf_new_char_classname(char *text)
{
- if (strchr(text,'.')) {
- char *txt=strdup(text);
- char *end=txt+strlen(txt);
+ if (strchr(text, '.')) {
+ char *txt = strdup(text);
+ char *end = txt + strlen(txt);
char *c;
utf *tmpRes;
- for (c=txt;c<end;c++)
- if (*c=='.') *c='/';
- tmpRes=utf_new(txt,strlen(txt));
+ for (c = txt; c < end; c++)
+ if (*c == '.') *c = '/';
+ tmpRes = utf_new(txt, strlen(txt));
free(txt);
return tmpRes;
- }
- else
- return utf_new(text, strlen(text));
+
+ } else
+ return utf_new(text, strlen(text));
}
+
/************************** Funktion: utf_show ******************************
writes the utf symbols in the utfhash to stdout and
*****************************************************************************/
-void utf_show ()
+void utf_show()
{
#define CHAIN_LIMIT 20 /* limit for seperated enumeration */
sprintf(logtext, "Invalid Type-Descriptor: ");
utf_sprint(logtext+strlen(logtext), descriptor);
- error(logtext);
+ error("%s",logtext);
return 0;
}
******************************************************************************/
-u2 desc_typesize (utf *descriptor)
+u2 desc_typesize(utf *descriptor)
{
switch (desc_to_type(descriptor)) {
case TYPE_INT: return 4;
u2 utf_nextu2(char **utf_ptr)
{
/* uncompressed unicode character */
- u2 unicode_char;
+ u2 unicode_char = 0;
/* current position in utf text */
- unsigned char *utf = (unsigned char *) (*utf_ptr);
+ unsigned char *utf = (unsigned char *) (*utf_ptr);
/* bytes representing the unicode character */
unsigned char ch1, ch2, ch3;
/* number of bytes used to represent the unicode character */
- int len;
+ int len = 0;
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) {
unsigned char low = ch2 & 0x3F;
unicode_char = (high << 6) + low;
len = 2;
- }
+ }
break;
case 0xE: /* 2 or 3 bytes */
return unicode_char;
}
+
/********************* function: is_valid_utf ********************************
return true if the given string is a valid UTF-8 string
if (len != 1) return false; /* Java special */
}
else {
- if (v < min_codepoint[len]) return false; /* overlong UTF-8 */
+ /* Sun Java seems to allow overlong UTF-8 encodings */
+
+ if (v < min_codepoint[len]) { /* overlong UTF-8 */
+ if (!opt_liberalutf)
+ fprintf(stderr,"WARNING: Overlong UTF-8 sequence found.\n");
+ /* XXX change this to panic? */
+ }
}
/* surrogates in UTF-8 seem to be allowed in Java classfiles */
return true;
}
+/********************* function: is_valid_name *******************************
+
+ return true if the given string may be used as a class/field/method name.
+ (Currently this only disallows empty strings and control characters.)
+
+ NOTE: The string is assumed to have passed is_valid_utf!
+
+ utf_ptr...points to first character
+ end_pos...points after last character
+
+******************************************************************************/
+
+bool
+is_valid_name(char *utf_ptr,char *end_pos)
+{
+ if (end_pos <= utf_ptr) return false; /* disallow empty names */
+
+ while (utf_ptr < end_pos) {
+ unsigned char c = *utf_ptr++;
+
+ if (c < 0x20) return false; /* disallow control characters */
+ if (c == 0xc0 && (unsigned char)*utf_ptr == 0x80) return false; /* disallow zero */
+ }
+ return true;
+}
+
+bool
+is_valid_name_utf(utf *u)
+{
+ return is_valid_name(u->text,utf_end(u));
+}
+
/******************** Function: class_new **************************************
searches for the class with the specified name in the classes hashtable,
*******************************************************************************/
-classinfo *class_new(utf *u)
+classinfo *class_new_intern(utf *classname)
{
- classinfo *c; /* hashtable element */
- u4 key; /* hashkey computed from 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);
- slot = key & (class_hash.size-1);
+ 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 */
+ /* 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
- c = GCNEW (classinfo,1); /*JOWENN: NEW*/
- c -> vmClass = 0;
- c -> flags = 0;
- c -> name = u;
- c -> cpcount = 0;
- c -> cptags = NULL;
- c -> cpinfos = NULL;
- c -> super = NULL;
- c -> sub = NULL;
- c -> nextsub = NULL;
- c -> interfacescount = 0;
- c -> interfaces = NULL;
- c -> fieldscount = 0;
- c -> fields = NULL;
- c -> methodscount = 0;
- c -> methods = NULL;
- c -> linked = false;
- c -> loaded = false;
- c -> index = 0;
- c -> instancesize = 0;
- c -> header.vftbl = NULL;
- c -> innerclasscount = 0;
- c -> innerclass = NULL;
- c -> vftbl = NULL;
- c -> initialized = false;
- c -> classvftbl = false;
- c -> classUsed = 0;
- c -> impldBy = NULL;
-
- /* prepare loading of the class */
- list_addlast(&unloadedclasses, c);
+ 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 = classname;
+ c->packagename = NULL;
+ c->cpcount = 0;
+ c->cptags = NULL;
+ c->cpinfos = NULL;
+ c->super = NULL;
+ c->sub = NULL;
+ c->nextsub = NULL;
+ c->interfacescount = 0;
+ c->interfaces = NULL;
+ c->fieldscount = 0;
+ c->fields = NULL;
+ c->methodscount = 0;
+ c->methods = NULL;
+ c->linked = false;
+ c->loaded = false;
+ c->index = 0;
+ c->instancesize = 0;
+ c->header.vftbl = NULL;
+ c->innerclasscount = 0;
+ 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;
+
/* insert class into the hashtable */
c->hashlink = class_hash.ptr[slot];
class_hash.ptr[slot] = c;
/* update number of hashtable-entries */
class_hash.entries++;
- if (class_hash.entries > (class_hash.size*2)) {
+ if (class_hash.entries > (class_hash.size * 2)) {
/* reorganization of hashtable, average length of
the external chains is approx. 2 */
hashtable newhash; /* the new hashtable */
/* create new hashtable, double the size */
- init_hashtable(&newhash, class_hash.size*2);
+ init_hashtable(&newhash, class_hash.size * 2);
newhash.entries = class_hash.entries;
/* 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 {
+ /* 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) {
+ if (*p == '.') {
+ 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
*******************************************************************************/
-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 ******************************
{
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 */
+ u4 len = 0; /* number of unicode characters */
- while (utf_ptr<endpos) {
+ while (utf_ptr < endpos) {
len++;
/* next unicode character */
utf_nextu2(&utf_ptr);
}
- if (utf_ptr!=endpos)
+ if (utf_ptr != endpos)
/* string ended abruptly */
panic("illegal utf string");