3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
32 Contains support functions for:
33 - Reading of Java class files
36 - additional support functions
38 $Id: tables.c 1843 2005-01-04 11:21:02Z twisti $
45 #include <sys/types.h>
50 #include "mm/memory.h"
51 #include "native/native.h"
52 #include "toolbox/logging.h"
53 #include "vm/builtin.h"
54 #include "vm/exceptions.h"
55 #include "vm/global.h"
56 #include "vm/loader.h"
57 #include "vm/options.h"
58 #include "vm/statistics.h"
59 #include "vm/tables.h"
62 hashtable utf_hash; /* hashtable for utf8-symbols */
63 hashtable string_hash; /* hashtable for javastrings */
64 hashtable class_hash; /* hashtable for classes */
66 list unlinkedclasses; /* this is only used for eager class loading */
69 /******************************************************************************
70 *********************** hashtable functions **********************************
71 ******************************************************************************/
73 /* hashsize must be power of 2 */
75 #define UTF_HASHSTART 16384 /* initial size of utf-hash */
76 #define HASHSTART 2048 /* initial size of javastring and class-hash */
79 /******************** function: init_hashtable ******************************
81 Initializes a hashtable structure and allocates memory.
82 The parameter size specifies the initial size of the hashtable.
84 *****************************************************************************/
86 void init_hashtable(hashtable *hash, u4 size)
92 hash->ptr = MNEW(void*, size);
95 for (i = 0; i < size; i++) hash->ptr[i] = NULL;
99 /*********************** function: tables_init *****************************
101 creates hashtables for symboltables
102 (called once at startup)
104 *****************************************************************************/
108 init_hashtable(&utf_hash, UTF_HASHSTART); /* hashtable for utf8-symbols */
109 init_hashtable(&string_hash, HASHSTART); /* hashtable for javastrings */
110 init_hashtable(&class_hash, HASHSTART); /* hashtable for classes */
113 /* list_init(&unlinkedclasses, OFFSET(classinfo, listnode)); */
115 #if defined(STATISTICS)
117 count_utf_len += sizeof(utf*) * utf_hash.size;
122 /********************** function: tables_close ******************************
124 free memory for hashtables
126 *****************************************************************************/
134 /* dispose utf symbols */
135 for (i = 0; i < utf_hash.size; i++) {
138 /* process elements in external hash chain */
139 utf *nextu = u->hashlink;
140 MFREE(u->text, u1, u->blength);
146 /* dispose javastrings */
147 for (i = 0; i < string_hash.size; i++) {
148 s = string_hash.ptr[i];
150 /* process elements in external hash chain */
151 literalstring *nexts = s->hashlink;
152 literalstring_free(s->string);
153 FREE(s, literalstring);
158 /* dispose hashtable structures */
159 MFREE(utf_hash.ptr, void*, utf_hash.size);
160 MFREE(string_hash.ptr, void*, string_hash.size);
161 MFREE(class_hash.ptr, void*, class_hash.size);
165 /********************* function: utf_display *********************************
167 write utf symbol to stdout (debugging purposes)
169 *******************************************************************************/
171 void utf_display(utf *u)
173 char *endpos; /* points behind utf string */
174 char *utf_ptr; /* current position in utf text */
185 while (utf_ptr < endpos) {
186 /* read next unicode character */
187 u2 c = utf_nextu2(&utf_ptr);
188 if (c >= 32 && c <= 127) printf("%c", c);
196 /* utf_display_classname *******************************************************
198 write utf symbol to stdout (debugging purposes)
200 *******************************************************************************/
202 void utf_display_classname(utf *u)
204 char *endpos; /* points behind utf string */
205 char *utf_ptr; /* current position in utf text */
216 while (utf_ptr < endpos) {
217 /* read next unicode character */
218 u2 c = utf_nextu2(&utf_ptr);
219 if (c == '/') c = '.';
220 if (c >= 32 && c <= 127) printf("%c", c);
228 /************************* function: log_utf *********************************
232 ******************************************************************************/
236 char buf[MAXLOGTEXT];
242 /********************** function: log_plain_utf ******************************
244 log utf symbol (without printing "LOG: " and newline)
246 ******************************************************************************/
248 void log_plain_utf(utf *u)
250 char buf[MAXLOGTEXT];
252 dolog_plain("%s", buf);
256 /* utf_sprint ******************************************************************
258 write utf symbol into c-string (debugging purposes)
260 *******************************************************************************/
262 void utf_sprint(char *buffer, utf *u)
264 char *endpos; /* points behind utf string */
265 char *utf_ptr; /* current position in utf text */
266 u2 pos = 0; /* position in c-string */
269 memcpy(buffer, "NULL", 5); /* 4 chars + terminating \0 */
276 while (utf_ptr < endpos)
277 /* copy next unicode character */
278 buffer[pos++] = utf_nextu2(&utf_ptr);
280 /* terminate string */
285 /* utf_sprint_classname ********************************************************
287 write utf symbol into c-string (debugging purposes)
289 *******************************************************************************/
291 void utf_sprint_classname(char *buffer, utf *u)
293 char *endpos; /* points behind utf string */
294 char *utf_ptr; /* current position in utf text */
295 u2 pos = 0; /* position in c-string */
298 memcpy(buffer, "NULL", 5); /* 4 chars + terminating \0 */
305 while (utf_ptr < endpos) {
306 /* copy next unicode character */
307 u2 c = utf_nextu2(&utf_ptr);
308 if (c == '/') c = '.';
312 /* terminate string */
317 /********************* Funktion: utf_fprint **********************************
319 write utf symbol into file
321 ******************************************************************************/
323 void utf_fprint(FILE *file, utf *u)
325 char *endpos = utf_end(u); /* points behind utf string */
326 char *utf_ptr = u->text; /* current position in utf text */
331 while (utf_ptr < endpos) {
332 /* read next unicode character */
333 u2 c = utf_nextu2(&utf_ptr);
335 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
336 else fprintf(file, "?");
341 /********************* Funktion: utf_fprint **********************************
343 write utf symbol into file
345 ******************************************************************************/
347 void utf_fprint_classname(FILE *file, utf *u)
349 char *endpos = utf_end(u); /* points behind utf string */
350 char *utf_ptr = u->text; /* current position in utf text */
355 while (utf_ptr < endpos) {
356 /* read next unicode character */
357 u2 c = utf_nextu2(&utf_ptr);
358 if (c == '/') c = '.';
360 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
361 else fprintf(file, "?");
366 /****************** internal function: utf_hashkey *****************************
368 The hashkey is computed from the utf-text by using up to 8 characters.
369 For utf-symbols longer than 15 characters 3 characters are taken from
370 the beginning and the end, 2 characters are taken from the middle.
372 *******************************************************************************/
374 #define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
375 #define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
377 static u4 utf_hashkey(const char *text, u4 length)
379 const char *start_pos = text; /* pointer to utf text */
384 case 0: /* empty string */
387 case 1: return fbs(0);
388 case 2: return fbs(0) ^ nbs(3);
389 case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
390 case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
391 case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
392 case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
393 case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
394 case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
401 return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
410 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
419 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
431 return a ^ nbs(9) ^ nbs(10);
443 return a ^ nbs(9) ^ nbs(10);
454 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
465 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
467 default: /* 3 characters from beginning */
473 /* 2 characters from middle */
474 text = start_pos + (length / 2);
479 /* 3 characters from end */
480 text = start_pos + length - 4;
485 return a ^ nbs(10) ^ nbs(11);
490 /*************************** function: utf_hashkey ***************************
492 compute the hashkey of a unicode string
494 ******************************************************************************/
496 u4 unicode_hashkey(u2 *text, u2 len)
498 return utf_hashkey((char*) text, len);
502 /************************ function: utf_new **********************************
504 Creates a new utf-symbol, the text of the symbol is passed as a
505 u1-array. The function searches the utf-hashtable for a utf-symbol
506 with this text. On success the element returned, otherwise a new
507 hashtable element is created.
509 If the number of entries in the hashtable exceeds twice the size of the
510 hashtable slots a reorganization of the hashtable is done and the utf
511 symbols are copied to a new hashtable with doubled size.
513 ******************************************************************************/
515 utf *utf_new_intern(const char *text, u2 length);
517 utf *utf_new(const char *text, u2 length)
521 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
525 r = utf_new_intern(text, length);
527 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
535 utf *utf_new_intern(const char *text, u2 length)
537 u4 key; /* hashkey computed from utf-text */
538 u4 slot; /* slot in hashtable */
539 utf *u; /* hashtable element */
547 key = utf_hashkey(text, length);
548 slot = key & (utf_hash.size-1);
549 u = utf_hash.ptr[slot];
551 /* search external hash chain for utf-symbol */
553 if (u->blength == length) {
555 /* compare text of hashtable elements */
556 for (i = 0; i < length; i++)
557 if (text[i] != u->text[i]) goto nomatch;
561 count_utf_new_found++;
563 /* log_text("symbol found in hash table");*/
564 /* symbol found in hashtable */
575 u = u->hashlink; /* next element in external chain */
580 count_utf_len += sizeof(utf) + length;
583 /* location in hashtable found, create new utf element */
585 u->blength = length; /* length in bytes of utfstring */
586 u->hashlink = utf_hash.ptr[slot]; /* link in external hashchain */
587 u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
588 memcpy(u->text, text, length); /* copy utf-text */
589 u->text[length] = '\0';
590 utf_hash.ptr[slot] = u; /* insert symbol into table */
592 utf_hash.entries++; /* update number of entries */
594 if (utf_hash.entries > (utf_hash.size * 2)) {
596 /* reorganization of hashtable, average length of
597 the external chains is approx. 2 */
601 hashtable newhash; /* the new hashtable */
603 /* create new hashtable, double the size */
604 init_hashtable(&newhash, utf_hash.size * 2);
605 newhash.entries = utf_hash.entries;
609 count_utf_len += sizeof(utf*) * utf_hash.size;
612 /* transfer elements to new hashtable */
613 for (i = 0; i < utf_hash.size; i++) {
614 u = (utf *) utf_hash.ptr[i];
616 utf *nextu = u->hashlink;
617 u4 slot = utf_hashkey(u->text, u->blength) & (newhash.size - 1);
619 u->hashlink = (utf *) newhash.ptr[slot];
620 newhash.ptr[slot] = u;
622 /* follow link in external hash chain */
627 /* dispose old table */
628 MFREE(utf_hash.ptr, void*, utf_hash.size);
636 /********************* function: utf_new_char ********************************
638 creates a new utf symbol, the text for this symbol is passed
639 as a c-string ( = char* )
641 ******************************************************************************/
643 utf *utf_new_char(const char *text)
645 return utf_new(text, strlen(text));
649 /********************* function: utf_new_char ********************************
651 creates a new utf symbol, the text for this symbol is passed
652 as a c-string ( = char* )
653 "." characters are going to be replaced by "/". since the above function is
654 used often, this is a separte function, instead of an if
656 ******************************************************************************/
658 utf *utf_new_char_classname(const char *text)
660 if (strchr(text, '.')) {
661 char *txt = strdup(text);
662 char *end = txt + strlen(txt);
665 for (c = txt; c < end; c++)
666 if (*c == '.') *c = '/';
667 tmpRes = utf_new(txt, strlen(txt));
672 return utf_new(text, strlen(text));
676 /************************** Funktion: utf_show ******************************
678 writes the utf symbols in the utfhash to stdout and
679 displays the number of external hash chains grouped
680 according to the chainlength
683 *****************************************************************************/
688 #define CHAIN_LIMIT 20 /* limit for seperated enumeration */
690 u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
691 u4 max_chainlength = 0; /* maximum length of the chains */
692 u4 sum_chainlength = 0; /* sum of the chainlengths */
693 u4 beyond_limit = 0; /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
696 printf ("UTF-HASH:\n");
698 /* show element of utf-hashtable */
699 for (i=0; i<utf_hash.size; i++) {
700 utf *u = utf_hash.ptr[i];
702 printf ("SLOT %d: ", (int) i);
714 printf ("UTF-HASH: %d slots for %d entries\n",
715 (int) utf_hash.size, (int) utf_hash.entries );
718 if (utf_hash.entries == 0)
721 printf("chains:\n chainlength number of chains %% of utfstrings\n");
723 for (i=0;i<CHAIN_LIMIT;i++)
726 /* count numbers of hashchains according to their length */
727 for (i=0; i<utf_hash.size; i++) {
729 utf *u = (utf*) utf_hash.ptr[i];
732 /* determine chainlength */
738 /* update sum of all chainlengths */
739 sum_chainlength+=chain_length;
741 /* determine the maximum length of the chains */
742 if (chain_length>max_chainlength)
743 max_chainlength = chain_length;
745 /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
746 if (chain_length>=CHAIN_LIMIT) {
747 beyond_limit+=chain_length;
748 chain_length=CHAIN_LIMIT-1;
751 /* update number of hashchains of current length */
752 chain_count[chain_length]++;
755 /* display results */
756 for (i=1;i<CHAIN_LIMIT-1;i++)
757 printf(" %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/utf_hash.entries));
759 printf(" >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/utf_hash.entries);
762 printf("max. chainlength:%5d\n",max_chainlength);
764 /* avg. chainlength = sum of chainlengths / number of chains */
765 printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (utf_hash.size-chain_count[0]));
768 /******************************************************************************
769 *********************** Misc support functions ********************************
770 ******************************************************************************/
773 /******************** Function: desc_to_type **********************************
775 Determines the corresponding Java base data type for a given type
778 ******************************************************************************/
780 u2 desc_to_type(utf *descriptor)
782 char *utf_ptr = descriptor->text; /* current position in utf text */
783 char logtext[MAXLOGTEXT];
785 if (descriptor->blength < 1) panic("Type-Descriptor is empty string");
787 switch (*utf_ptr++) {
792 case 'Z': return TYPE_INT;
793 case 'D': return TYPE_DOUBLE;
794 case 'F': return TYPE_FLOAT;
795 case 'J': return TYPE_LONG;
797 case '[': return TYPE_ADDRESS;
800 sprintf(logtext, "Invalid Type-Descriptor: ");
801 utf_sprint(logtext+strlen(logtext), descriptor);
808 /********************** Function: desc_typesize *******************************
810 Calculates the lenght in bytes needed for a data element of the type given
811 by its type descriptor.
813 ******************************************************************************/
815 u2 desc_typesize(utf *descriptor)
817 switch (desc_to_type(descriptor)) {
818 case TYPE_INT: return 4;
819 case TYPE_LONG: return 8;
820 case TYPE_FLOAT: return 4;
821 case TYPE_DOUBLE: return 8;
822 case TYPE_ADDRESS: return sizeof(voidptr);
828 /********************** function: utf_nextu2 *********************************
830 read the next unicode character from the utf string and
831 increment the utf-string pointer accordingly
833 ******************************************************************************/
835 u2 utf_nextu2(char **utf_ptr)
837 /* uncompressed unicode character */
839 /* current position in utf text */
840 unsigned char *utf = (unsigned char *) (*utf_ptr);
841 /* bytes representing the unicode character */
842 unsigned char ch1, ch2, ch3;
843 /* number of bytes used to represent the unicode character */
846 switch ((ch1 = utf[0]) >> 4) {
847 default: /* 1 byte */
851 case 0xD: /* 2 bytes */
852 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
853 unsigned char high = ch1 & 0x1F;
854 unsigned char low = ch2 & 0x3F;
855 unicode_char = (high << 6) + low;
860 case 0xE: /* 2 or 3 bytes */
861 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
862 if (((ch3 = utf[2]) & 0xC0) == 0x80) {
863 unsigned char low = ch3 & 0x3f;
864 unsigned char mid = ch2 & 0x3f;
865 unsigned char high = ch1 & 0x0f;
866 unicode_char = (((high << 6) + mid) << 6) + low;
874 /* update position in utf-text */
875 *utf_ptr = (char *) (utf + len);
880 /********************* function: is_valid_utf ********************************
882 return true if the given string is a valid UTF-8 string
884 utf_ptr...points to first character
885 end_pos...points after last character
887 ******************************************************************************/
889 static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26};
892 is_valid_utf(char *utf_ptr,char *end_pos)
899 if (end_pos < utf_ptr) return false;
900 bytes = end_pos - utf_ptr;
903 /*dolog("%c %02x",c,c);*/
904 if (!c) return false; /* 0x00 is not allowed */
905 if ((c & 0x80) == 0) continue; /* ASCII */
907 if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
908 else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
909 else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
910 else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
911 else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
912 else return false; /* invalid leading byte */
914 if (len > 2) return false; /* Java limitation */
916 v = (unsigned long)c & (0x3f >> len);
918 if ((bytes -= len) < 0) return false; /* missing bytes */
920 for (i = len; i--; ) {
922 /*dolog(" %c %02x",c,c);*/
923 if ((c & 0xc0) != 0x80) /* 10xx xxxx */
925 v = (v<<6) | (c & 0x3f);
928 /* dolog("v=%d",v);*/
931 if (len != 1) return false; /* Java special */
934 /* Sun Java seems to allow overlong UTF-8 encodings */
936 if (v < min_codepoint[len]) { /* overlong UTF-8 */
938 fprintf(stderr,"WARNING: Overlong UTF-8 sequence found.\n");
939 /* XXX change this to panic? */
943 /* surrogates in UTF-8 seem to be allowed in Java classfiles */
944 /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
946 /* even these seem to be allowed */
947 /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
953 /********************* function: is_valid_name *******************************
955 return true if the given string may be used as a class/field/method name.
956 (Currently this only disallows empty strings and control characters.)
958 NOTE: The string is assumed to have passed is_valid_utf!
960 utf_ptr...points to first character
961 end_pos...points after last character
963 ******************************************************************************/
966 is_valid_name(char *utf_ptr,char *end_pos)
968 if (end_pos <= utf_ptr) return false; /* disallow empty names */
970 while (utf_ptr < end_pos) {
971 unsigned char c = *utf_ptr++;
973 if (c < 0x20) return false; /* disallow control characters */
974 if (c == 0xc0 && (unsigned char)*utf_ptr == 0x80) return false; /* disallow zero */
980 is_valid_name_utf(utf *u)
982 return is_valid_name(u->text,utf_end(u));
985 /******************** Function: class_new **************************************
987 searches for the class with the specified name in the classes hashtable,
988 if there is no such class a new classinfo structure is created and inserted
989 into the list of classes to be loaded
991 *******************************************************************************/
993 classinfo *class_new_intern(utf *classname)
995 classinfo *c; /* hashtable element */
996 u4 key; /* hashkey computed from classname */
997 u4 slot; /* slot in hashtable */
1000 key = utf_hashkey(classname->text, classname->blength);
1001 slot = key & (class_hash.size - 1);
1002 c = class_hash.ptr[slot];
1004 /* search external hash chain for the class */
1006 if (c->name->blength == classname->blength) {
1007 for (i = 0; i < classname->blength; i++)
1008 if (classname->text[i] != c->name->text[i]) goto nomatch;
1010 /* class found in hashtable */
1015 c = c->hashlink; /* next element in external chain */
1018 /* location in hashtable found, create new classinfo structure */
1020 #if defined(STATISTICS)
1022 count_class_infos += sizeof(classinfo);
1026 char logtext[MAXLOGTEXT];
1027 sprintf(logtext, "Creating class: ");
1028 utf_sprint_classname(logtext + strlen(logtext), classname);
1032 c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
1033 /*c=NEW(classinfo);*/
1036 c->name = classname;
1037 c->packagename = NULL;
1044 c->interfacescount = 0;
1045 c->interfaces = NULL;
1048 c->methodscount = 0;
1053 c->instancesize = 0;
1054 c->header.vftbl = NULL;
1055 c->innerclasscount = 0;
1056 c->innerclass = NULL;
1058 c->initialized = false;
1059 c->initializing = false;
1060 c->classvftbl = false;
1063 c->classloader = NULL;
1064 c->sourcefile = NULL;
1066 /* insert class into the hashtable */
1067 c->hashlink = class_hash.ptr[slot];
1068 class_hash.ptr[slot] = c;
1070 /* update number of hashtable-entries */
1071 class_hash.entries++;
1073 if (class_hash.entries > (class_hash.size * 2)) {
1075 /* reorganization of hashtable, average length of
1076 the external chains is approx. 2 */
1080 hashtable newhash; /* the new hashtable */
1082 /* create new hashtable, double the size */
1083 init_hashtable(&newhash, class_hash.size * 2);
1084 newhash.entries = class_hash.entries;
1086 /* transfer elements to new hashtable */
1087 for (i = 0; i < class_hash.size; i++) {
1088 c = (classinfo *) class_hash.ptr[i];
1090 classinfo *nextc = c->hashlink;
1091 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
1093 c->hashlink = newhash.ptr[slot];
1094 newhash.ptr[slot] = c;
1100 /* dispose old table */
1101 MFREE(class_hash.ptr, void*, class_hash.size);
1102 class_hash = newhash;
1105 /* Array classes need further initialization. */
1106 if (c->name->text[0] == '[') {
1107 /* Array classes are not loaded from classfiles. */
1110 c->packagename = array_packagename;
1113 /* Find the package name */
1114 /* Classes in the unnamed package keep packagename == NULL. */
1115 char *p = utf_end(c->name) - 1;
1116 char *start = c->name->text;
1117 for (;p > start; --p) {
1119 c->packagename = utf_new (start, p - start);
1124 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1125 initObjectLock(&c->header);
1132 classinfo *class_new(utf *classname)
1136 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1140 c = class_new_intern(classname);
1142 /* we support eager class loading and linking on demand */
1148 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
1151 if (!class_load(c)) {
1152 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1159 /* link all referenced classes */
1161 tc = list_first(&unlinkedclasses);
1164 /* skip the current loaded/linked class */
1166 if (!class_link(tc)) {
1167 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1174 /* we need a tmp variable here, because list_remove sets prev and
1176 tmp = list_next(&unlinkedclasses, tc);
1177 list_remove(&unlinkedclasses, tc);
1182 if (!class_link(c)) {
1183 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1191 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1199 /******************** Function: class_get **************************************
1201 searches for the class with the specified name in the classes hashtable
1202 if there is no such class NULL is returned
1204 *******************************************************************************/
1206 classinfo *class_get(utf *classname)
1208 classinfo *c; /* hashtable element */
1209 u4 key; /* hashkey computed from classname */
1210 u4 slot; /* slot in hashtable */
1213 key = utf_hashkey(classname->text, classname->blength);
1214 slot = key & (class_hash.size-1);
1215 c = class_hash.ptr[slot];
1217 /* search external hash-chain */
1219 if (c->name->blength == classname->blength) {
1220 /* compare classnames */
1221 for (i = 0; i < classname->blength; i++)
1222 if (classname->text[i] != c->name->text[i])
1225 /* class found in hashtable */
1233 /* class not found */
1238 /* class_remove ****************************************************************
1240 removes the class entry wth the specified name in the classes hashtable,
1241 furthermore the class' resources are freed
1242 if there is no such class false is returned
1244 *******************************************************************************/
1246 bool class_remove(classinfo *c)
1248 classinfo *tc; /* hashtable element */
1250 u4 key; /* hashkey computed from classname */
1251 u4 slot; /* slot in hashtable */
1254 key = utf_hashkey(c->name->text, c->name->blength);
1255 slot = key & (class_hash.size - 1);
1256 tc = class_hash.ptr[slot];
1259 /* search external hash-chain */
1261 if (tc->name->blength == c->name->blength) {
1263 /* compare classnames */
1264 for (i = 0; i < c->name->blength; i++)
1265 if (tc->name->text[i] != c->name->text[i])
1268 /* class found in hashtable */
1270 class_hash.ptr[slot] = tc->hashlink;
1273 pc->hashlink = tc->hashlink;
1286 /* class not found */
1291 /***************** Function: class_array_of ***********************************
1293 Returns an array class with the given component class.
1294 The array class is dynamically created if neccessary.
1296 *******************************************************************************/
1298 classinfo *class_array_of(classinfo *component)
1304 /* Assemble the array class name */
1305 namelen = component->name->blength;
1307 if (component->name->text[0] == '[') {
1308 /* the component is itself an array */
1309 namebuf = DMNEW(char, namelen + 1);
1311 memcpy(namebuf + 1, component->name->text, namelen);
1315 /* the component is a non-array class */
1316 namebuf = DMNEW(char, namelen + 3);
1319 memcpy(namebuf + 2, component->name->text, namelen);
1320 namebuf[2 + namelen] = ';';
1324 /* load this class ;-) and link it */
1325 c = class_new(utf_new(namebuf, namelen));
1332 /*************** Function: class_multiarray_of ********************************
1334 Returns an array class with the given dimension and element class.
1335 The array class is dynamically created if neccessary.
1337 *******************************************************************************/
1339 classinfo *class_multiarray_of(int dim, classinfo *element)
1345 panic("Invalid array dimension requested");
1347 /* Assemble the array class name */
1348 namelen = element->name->blength;
1350 if (element->name->text[0] == '[') {
1351 /* the element is itself an array */
1352 namebuf = DMNEW(char, namelen + dim);
1353 memcpy(namebuf + dim, element->name->text, namelen);
1357 /* the element is a non-array class */
1358 namebuf = DMNEW(char, namelen + 2 + dim);
1360 memcpy(namebuf + dim + 1, element->name->text, namelen);
1361 namelen += (2 + dim);
1362 namebuf[namelen - 1] = ';';
1364 memset(namebuf, '[', dim);
1366 return class_new(utf_new(namebuf, namelen));
1369 /************************** function: utf_strlen ******************************
1371 determine number of unicode characters in the utf string
1373 *******************************************************************************/
1375 u4 utf_strlen(utf *u)
1377 char *endpos; /* points behind utf string */
1378 char *utf_ptr; /* current position in utf text */
1379 u4 len = 0; /* number of unicode characters */
1382 *exceptionptr = new_nullpointerexception();
1386 endpos = utf_end(u);
1389 while (utf_ptr < endpos) {
1391 /* next unicode character */
1392 utf_nextu2(&utf_ptr);
1395 if (utf_ptr != endpos)
1396 /* string ended abruptly */
1397 panic("illegal utf string");
1404 * These are local overrides for various environment variables in Emacs.
1405 * Please do not remove this and leave it at the end of the file, where
1406 * Emacs will automagically detect them.
1407 * ---------------------------------------------------------------------
1410 * indent-tabs-mode: t