preparations for the typechecker
[cacao.git] / src / vm / tables.c
1 /* tables.c - 
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28
29    Changes: Mark Probst
30             Andreas Krall
31
32    Contains support functions for:
33        - Reading of Java class files
34        - Unicode symbols
35        - the heap
36        - additional support functions
37
38    $Id: tables.c 687 2003-12-04 22:29:54Z edwin $
39
40 */
41
42 #include <string.h>
43 #include <assert.h>
44 #include <sys/types.h>
45 #include <sys/mman.h>
46 #include <unistd.h>
47 #include "types.h"
48 #include "global.h"
49 #include "tables.h"
50 #include "asmpart.h"
51 #include "threads/thread.h"
52 #include "threads/locks.h"
53 #include "toolbox/loging.h"
54 #include "toolbox/memory.h"
55
56
57 /* statistics */
58 int count_utf_len = 0;         /* size of utf hash                  */
59 int count_utf_new = 0;         /* calls of utf_new                  */
60 int count_utf_new_found  = 0;  /* calls of utf_new with fast return */
61
62 hashtable utf_hash;     /* hashtable for utf8-symbols */
63 hashtable string_hash;  /* hashtable for javastrings  */
64 hashtable class_hash;   /* hashtable for classes      */
65
66 /******************************************************************************
67  *********************** hashtable functions **********************************
68  ******************************************************************************/
69
70 /* hashsize must be power of 2 */
71
72 #define UTF_HASHSTART   16384   /* initial size of utf-hash */    
73 #define HASHSTART        2048   /* initial size of javastring and class-hash */
74
75
76 /******************** function: init_hashtable ******************************
77
78     Initializes a hashtable structure and allocates memory.
79     The parameter size specifies the initial size of the hashtable.
80         
81 *****************************************************************************/
82
83 void init_hashtable(hashtable *hash, u4 size)
84 {
85         u4 i;
86
87         hash->entries = 0;
88         hash->size    = size;
89         hash->ptr     = MNEW(void*, size);
90
91         /* clear table */
92         for (i = 0; i < size; i++) hash->ptr[i] = NULL;
93 }
94
95 /*********************** function: tables_init  *****************************
96
97     creates hashtables for symboltables 
98         (called once at startup)                         
99         
100 *****************************************************************************/
101
102 void tables_init ()
103 {
104         init_hashtable(&utf_hash,    UTF_HASHSTART);  /* hashtable for utf8-symbols */
105         init_hashtable(&string_hash, HASHSTART);      /* hashtable for javastrings */
106         init_hashtable(&class_hash,  HASHSTART);      /* hashtable for classes */ 
107         
108 #ifdef STATISTICS
109         count_utf_len += sizeof(utf*) * utf_hash.size;
110 #endif
111
112 }
113
114 /********************** function: tables_close ******************************
115
116         free memory for hashtables                    
117         
118 *****************************************************************************/
119
120 void tables_close (stringdeleter del)
121 {
122         utf *u; 
123         literalstring *s;
124         u4 i;
125         
126         /* dispose utf symbols */
127         for (i=0; i<utf_hash.size; i++) {
128                 u = utf_hash.ptr[i];
129                 while (u) {
130                         /* process elements in external hash chain */
131                         utf *nextu = u->hashlink;
132                         MFREE (u->text, u1, u->blength);
133                         FREE (u, utf);
134                         u = nextu;
135                 }       
136         }
137
138         /* dispose javastrings */
139         for (i=0; i<string_hash.size; i++) {
140                 s = string_hash.ptr[i];
141                 while (u) {
142                         /* process elements in external hash chain */
143                         literalstring *nexts = s->hashlink;
144                         del(s->string);
145                         FREE(s, literalstring);
146                         s = nexts;
147                 }       
148         }
149
150         /* dispose hashtable structures */
151         MFREE (utf_hash.ptr,    void*, utf_hash.size);
152         MFREE (string_hash.ptr, void*, string_hash.size);
153         MFREE (class_hash.ptr,  void*, class_hash.size);
154 }
155
156 /********************* function: utf_display *********************************
157
158         write utf symbol to stdout (debugging purposes)
159
160 ******************************************************************************/
161
162 void utf_display (utf *u)
163 {
164     char *endpos  = utf_end(u);  /* points behind utf string       */
165     char *utf_ptr = u->text;     /* current position in utf text   */
166         if (u==NULL) return;
167     while (utf_ptr<endpos) {
168
169                 /* read next unicode character */                
170                 u2 c = utf_nextu2(&utf_ptr);                            
171                 if (c>=32 && c<=127) printf ("%c",c);
172                 else printf ("?");
173         }
174
175         fflush (stdout);
176 }
177
178 /************************ function: utf_sprint *******************************
179         
180     write utf symbol into c-string (debugging purposes)                                          
181
182 ******************************************************************************/ 
183
184 void utf_sprint (char *buffer, utf *u)
185 {
186     char *endpos  = utf_end(u);  /* points behind utf string       */
187     char *utf_ptr = u->text;     /* current position in utf text   */ 
188     u2 pos = 0;                  /* position in c-string           */
189
190     while (utf_ptr<endpos) 
191                 /* copy next unicode character */       
192                 buffer[pos++] = utf_nextu2(&utf_ptr);
193
194     /* terminate string */
195     buffer[pos] = '\0';
196 }
197
198
199 /********************* Funktion: utf_fprint **********************************
200         
201     write utf symbol into file          
202
203 ******************************************************************************/ 
204
205 void utf_fprint (FILE *file, utf *u)
206 {
207     char *endpos  = utf_end(u);  /* points behind utf string       */
208     char *utf_ptr = u->text;     /* current position in utf text   */ 
209     if (u==NULL) return;
210     while (utf_ptr<endpos) { 
211                 /* read next unicode character */                
212                 u2 c = utf_nextu2(&utf_ptr);                            
213
214                 if (c>=32 && c<=127) fprintf (file,"%c",c);
215                 else fprintf (file,"?");
216         }
217
218
219
220 /****************** internal function: utf_hashkey ***************************
221
222         The hashkey is computed from the utf-text by using up to 8 characters.
223         For utf-symbols longer than 15 characters 3 characters are taken from
224         the beginning and the end, 2 characters are taken from the middle.
225
226 ******************************************************************************/ 
227
228 #define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val  */
229 #define fbs(val) ((u4) *(  text) << val) /* get first byte, left shift by val */
230
231 static u4 utf_hashkey (char *text, u4 length)
232 {
233         char *start_pos = text; /* pointer to utf text */
234         u4 a;
235
236         switch (length) {               
237                 
238         case 0: /* empty string */
239                 return 0;
240
241         case 1: return fbs(0);
242         case 2: return fbs(0) ^ nbs(3);
243         case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
244         case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
245         case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
246         case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
247         case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
248         case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
249
250         case 9: a = fbs(0) ^ nbs(1) ^ nbs(2);                
251                 text++; 
252                 return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
253
254         case 10: a = fbs(0);
255                 text++;
256                 a^= nbs(2) ^ nbs(3) ^ nbs(4);
257                 text++;
258                 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
259
260         case 11: a = fbs(0);
261                 text++;
262                 a^= nbs(2) ^ nbs(3) ^ nbs(4);
263                 text++;
264                 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
265
266         case 12: a = fbs(0);
267                 text+=2;
268                 a^= nbs(2) ^ nbs(3);
269                 text+=1;
270                 a^= nbs(5) ^ nbs(6) ^ nbs(7);
271                 text+=1;
272                 return a ^ nbs(9) ^ nbs(10);       
273
274         case 13: a = fbs(0) ^ nbs(1);
275                 text+=1;        
276                 a^= nbs(3) ^ nbs(4);
277                 text+=2;        
278                 a^= nbs(7) ^ nbs(8);
279                 text+=2;
280                 return a ^ nbs(9) ^ nbs(10);
281
282         case 14: a = fbs(0);
283                 text+=2;        
284                 a^= nbs(3) ^ nbs(4);
285                 text+=2;        
286                 a^= nbs(7) ^ nbs(8);
287                 text+=2;
288                 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
289
290         case 15: a = fbs(0);
291                 text+=2;        
292                 a^= nbs(3) ^ nbs(4);
293                 text+=2;        
294                 a^= nbs(7) ^ nbs(8);
295                 text+=2;
296                 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
297
298         default:  /* 3 characters from beginning */
299                 a = fbs(0);
300                 text+=2;
301                 a^= nbs(3) ^ nbs(4);
302
303                 /* 2 characters from middle */
304                 text = start_pos + (length / 2);
305                 a^= fbs(5);
306                 text+=2;
307                 a^= nbs(6);     
308
309                 /* 3 characters from end */
310                 text = start_pos + length - 4;
311
312                 a^= fbs(7);
313                 text+=1;
314
315                 return a ^ nbs(10) ^ nbs(11);
316     }
317 }
318
319
320 /*************************** function: utf_hashkey ***************************
321
322     compute the hashkey of a unicode string
323
324 ******************************************************************************/ 
325
326 u4 unicode_hashkey (u2 *text, u2 len)
327 {
328         return utf_hashkey((char*) text, len);
329 }
330
331 /************************ function: utf_new **********************************
332
333         Creates a new utf-symbol, the text of the symbol is passed as a 
334         u1-array. The function searches the utf-hashtable for a utf-symbol 
335         with this text. On success the element returned, otherwise a new 
336         hashtable element is created.
337
338         If the number of entries in the hashtable exceeds twice the size of the
339         hashtable slots a reorganization of the hashtable is done and the utf 
340         symbols are copied to a new hashtable with doubled size.
341
342 ******************************************************************************/
343
344 utf *utf_new (char *text, u2 length)
345 {
346         u4 key;            /* hashkey computed from utf-text */
347         u4 slot;           /* slot in hashtable */
348         utf *u;            /* hashtable element */
349         u2 i;
350         
351 /*      log_text("utf_new entered");*/
352 #ifdef STATISTICS
353         count_utf_new++;
354 #endif
355
356         key  = utf_hashkey (text, length);
357         slot = key & (utf_hash.size-1);
358         u    = utf_hash.ptr[slot];
359
360         /* search external hash chain for utf-symbol */
361         while (u) {
362                 if (u->blength == length) {
363
364                         /* compare text of hashtable elements */
365                         for (i=0; i<length; i++)
366                                 if (text[i] != u->text[i]) goto nomatch;
367                         
368 #ifdef STATISTICS
369                         count_utf_new_found++;
370 #endif
371 /*                      log_text("symbol found in hash table");*/
372                         /* symbol found in hashtable */
373 /*                                      utf_display(u);
374                                         {
375                                                 utf blup;
376                                                 blup.blength=length;
377                                                 blup.text=text;
378                                                 utf_display(&blup);
379                                         }*/
380                         return u;
381                 }
382         nomatch:
383                 u = u->hashlink; /* next element in external chain */
384         }
385
386 #ifdef STATISTICS
387         count_utf_len += sizeof(utf) + length;
388 #endif
389
390         /* location in hashtable found, create new utf element */
391         u = NEW (utf);
392         u->blength  = length;             /* length in bytes of utfstring */
393         u->hashlink = utf_hash.ptr[slot]; /* link in external hashchain   */            
394         u->text     = mem_alloc(length/*JOWENN*/+1);  /* allocate memory for utf-text */
395         memcpy(u->text,text,length);      /* copy utf-text                */
396         u->text[length]='\0';/*JOWENN*/
397         utf_hash.ptr[slot] = u;           /* insert symbol into table     */ 
398
399         utf_hash.entries++;               /* update number of entries     */
400
401         if ( utf_hash.entries > (utf_hash.size*2)) { 
402
403         /* reorganization of hashtable, average length of 
404            the external chains is approx. 2                */  
405
406                 u4 i;
407                 utf *u;
408                 hashtable newhash; /* the new hashtable */
409
410                 /* create new hashtable, double the size */
411                 init_hashtable(&newhash, utf_hash.size*2);
412                 newhash.entries=utf_hash.entries;
413
414 #ifdef STATISTICS
415                 count_utf_len += sizeof(utf*) * utf_hash.size;
416 #endif
417
418                 /* transfer elements to new hashtable */
419                 for (i=0; i<utf_hash.size; i++) {
420                         u = (utf*) utf_hash.ptr[i];
421                         while (u) {
422                                 utf *nextu = u -> hashlink;
423                                 u4 slot = (utf_hashkey(u->text,u->blength)) & (newhash.size-1);
424                                                 
425                                 u->hashlink = (utf*) newhash.ptr[slot];
426                                 newhash.ptr[slot] = u;
427
428                                 /* follow link in external hash chain */
429                                 u = nextu;
430                         }
431                 }
432         
433                 /* dispose old table */
434                 MFREE (utf_hash.ptr, void*, utf_hash.size);
435                 utf_hash = newhash;
436         }
437                 /*utf_display(u);*/
438         return u;
439 }
440
441
442 /********************* function: utf_new_char ********************************
443
444     creates a new utf symbol, the text for this symbol is passed
445     as a c-string ( = char* )
446
447 ******************************************************************************/
448
449 utf *utf_new_char (char *text)
450 {
451         return utf_new(text, strlen(text));
452 }
453
454
455 /********************* function: utf_new_char ********************************
456
457     creates a new utf symbol, the text for this symbol is passed
458     as a c-string ( = char* )
459     "." characters are going to be replaced by "/". since the above function is
460     used often, this is a separte function, instead of an if
461
462 ******************************************************************************/
463
464 utf *utf_new_char_classname (char *text)
465 {
466         if (strchr(text,'.')) {
467                 char *txt=strdup(text);
468                 char *end=txt+strlen(txt);
469                 char *c;
470                 utf *tmpRes;
471                 for (c=txt;c<end;c++)
472                         if (*c=='.') *c='/';
473                 tmpRes=utf_new(txt,strlen(txt));
474                 free(txt);
475                 return tmpRes;
476         }
477         else
478         return utf_new(text, strlen(text));
479 }
480
481 /************************** Funktion: utf_show ******************************
482
483     writes the utf symbols in the utfhash to stdout and
484     displays the number of external hash chains grouped 
485     according to the chainlength
486     (debugging purposes)
487
488 *****************************************************************************/
489
490 void utf_show ()
491 {
492
493 #define CHAIN_LIMIT 20               /* limit for seperated enumeration */
494
495         u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
496         u4 max_chainlength = 0;      /* maximum length of the chains */
497         u4 sum_chainlength = 0;      /* sum of the chainlengths */
498         u4 beyond_limit = 0;         /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
499         u4 i;
500
501         printf ("UTF-HASH:\n");
502
503         /* show element of utf-hashtable */
504         for (i=0; i<utf_hash.size; i++) {
505                 utf *u = utf_hash.ptr[i];
506                 if (u) {
507                         printf ("SLOT %d: ", (int) i);
508                         while (u) {
509                                 printf ("'");
510                                 utf_display (u);
511                                 printf ("' ");
512                                 u = u->hashlink;
513                         }       
514                         printf ("\n");
515                 }
516                 
517         }
518
519         printf ("UTF-HASH: %d slots for %d entries\n", 
520                         (int) utf_hash.size, (int) utf_hash.entries );
521
522
523         if (utf_hash.entries == 0)
524                 return;
525
526         printf("chains:\n  chainlength    number of chains    %% of utfstrings\n");
527
528         for (i=0;i<CHAIN_LIMIT;i++)
529                 chain_count[i]=0;
530
531         /* count numbers of hashchains according to their length */
532         for (i=0; i<utf_hash.size; i++) {
533                   
534                 utf *u = (utf*) utf_hash.ptr[i];
535                 u4 chain_length = 0;
536
537                 /* determine chainlength */
538                 while (u) {
539                         u = u->hashlink;
540                         chain_length++;
541                 }
542
543                 /* update sum of all chainlengths */
544                 sum_chainlength+=chain_length;
545
546                 /* determine the maximum length of the chains */
547                 if (chain_length>max_chainlength)
548                         max_chainlength = chain_length;
549
550                 /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
551                 if (chain_length>=CHAIN_LIMIT) {
552                         beyond_limit+=chain_length;
553                         chain_length=CHAIN_LIMIT-1;
554                 }
555
556                 /* update number of hashchains of current length */
557                 chain_count[chain_length]++;
558         }
559
560         /* display results */  
561         for (i=1;i<CHAIN_LIMIT-1;i++) 
562                 printf("       %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/utf_hash.entries));
563           
564         printf("     >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/utf_hash.entries);
565
566
567         printf("max. chainlength:%5d\n",max_chainlength);
568
569         /* avg. chainlength = sum of chainlengths / number of chains */
570         printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (utf_hash.size-chain_count[0]));
571 }
572
573 /******************************************************************************
574 *********************** Misc support functions ********************************
575 ******************************************************************************/
576
577
578 /******************** Function: desc_to_type **********************************
579    
580         Determines the corresponding Java base data type for a given type
581         descriptor.
582         
583 ******************************************************************************/
584
585 u2 desc_to_type(utf *descriptor)
586 {
587         char *utf_ptr = descriptor->text;  /* current position in utf text */
588
589         if (descriptor->blength < 1) panic("Type-Descriptor is empty string");
590         
591         switch (*utf_ptr++) {
592         case 'B': 
593         case 'C':
594         case 'I':
595         case 'S':  
596         case 'Z':  return TYPE_INT;
597         case 'D':  return TYPE_DOUBLE;
598         case 'F':  return TYPE_FLOAT;
599         case 'J':  return TYPE_LONG;
600         case 'L':
601         case '[':  return TYPE_ADDRESS;
602         }
603                         
604         sprintf(logtext, "Invalid Type-Descriptor: ");
605         utf_sprint(logtext+strlen(logtext), descriptor);
606         error();
607
608         return 0;
609 }
610
611
612 /********************** Function: desc_typesize *******************************
613
614         Calculates the lenght in bytes needed for a data element of the type given
615         by its type descriptor.
616         
617 ******************************************************************************/
618
619 u2 desc_typesize (utf *descriptor)
620 {
621         switch (desc_to_type(descriptor)) {
622         case TYPE_INT:     return 4;
623         case TYPE_LONG:    return 8;
624         case TYPE_FLOAT:   return 4;
625         case TYPE_DOUBLE:  return 8;
626         case TYPE_ADDRESS: return sizeof(voidptr);
627         default:           return 0;
628         }
629 }
630
631
632 /********************** function: utf_nextu2 *********************************
633
634     read the next unicode character from the utf string and
635     increment the utf-string pointer accordingly
636
637 ******************************************************************************/
638
639 u2 utf_nextu2(char **utf_ptr) 
640 {
641     /* uncompressed unicode character */
642     u2 unicode_char;    
643     /* current position in utf text */  
644     unsigned char *utf = (unsigned char *) (*utf_ptr);  
645     /* bytes representing the unicode character */
646     unsigned char ch1, ch2, ch3;
647     /* number of bytes used to represent the unicode character */
648     int len;            
649         
650     switch ((ch1 = utf[0]) >> 4) {
651         default: /* 1 byte */
652                 (*utf_ptr)++;
653                 return ch1;
654         case 0xC: 
655         case 0xD: /* 2 bytes */
656                 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
657                         unsigned char high = ch1 & 0x1F;
658                         unsigned char low  = ch2 & 0x3F;
659                         unicode_char = (high << 6) + low;
660                         len = 2;
661                 } 
662                 break;
663
664         case 0xE: /* 2 or 3 bytes */
665                 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
666                         if (((ch3 = utf[2]) & 0xC0) == 0x80) {
667                                 unsigned char low  = ch3 & 0x3f;
668                                 unsigned char mid  = ch2 & 0x3f;
669                                 unsigned char high = ch1 & 0x0f;
670                                 unicode_char = (((high << 6) + mid) << 6) + low;
671                                 len = 3;
672                         } else
673                                 len = 2;                                           
674                 }
675                 break;
676     }
677
678     /* update position in utf-text */
679     *utf_ptr = (char *) (utf + len);
680     return unicode_char;
681 }
682
683  
684 /******************** Function: class_new **************************************
685
686     searches for the class with the specified name in the classes hashtable,
687     if there is no such class a new classinfo structure is created and inserted
688     into the list of classes to be loaded
689
690 *******************************************************************************/
691
692 classinfo *class_new(utf *u)
693 {
694         classinfo *c;     /* hashtable element */ 
695         u4 key;           /* hashkey computed from classname */   
696         u4 slot;          /* slot in hashtable */
697         u2 i;
698
699         key  = utf_hashkey (u->text, u->blength);
700         slot = key & (class_hash.size-1);
701         c    = class_hash.ptr[slot];
702
703         /* search external hash chain for the class */
704         while (c) {
705                 if (c->name->blength == u->blength) {
706                         for (i=0; i<u->blength; i++) 
707                                 if (u->text[i] != c->name->text[i]) goto nomatch;
708                                                 
709                         /* class found in hashtable */                                                                  
710                         return c;
711                 }
712                         
713         nomatch:
714                 c = c->hashlink; /* next element in external chain */
715         }
716
717         /* location in hashtable found, create new classinfo structure */
718
719 #ifdef STATISTICS
720         count_class_infos += sizeof(classinfo);
721 #endif
722
723         c = GCNEW (classinfo,1); /*JOWENN: NEW*/
724         c -> vmClass = 0;
725         c -> flags = 0;
726         c -> name = u;
727         c -> cpcount = 0;
728         c -> cptags = NULL;
729         c -> cpinfos = NULL;
730         c -> super = NULL;
731         c -> sub = NULL;
732         c -> nextsub = NULL;
733         c -> interfacescount = 0;
734         c -> interfaces = NULL;
735         c -> fieldscount = 0;
736         c -> fields = NULL;
737         c -> methodscount = 0;
738         c -> methods = NULL;
739         c -> linked = false;
740         c -> loaded = false;
741         c -> index = 0;
742         c -> instancesize = 0;
743         c -> header.vftbl = NULL;
744         c -> innerclasscount = 0;
745         c -> innerclass = NULL;
746         c -> vftbl = NULL;
747         c -> initialized = false;
748         c -> classvftbl = false;
749     c -> classUsed = 0;
750     c -> impldBy = NULL;
751         
752         /* prepare loading of the class */
753         list_addlast(&unloadedclasses, c);
754
755         /* insert class into the hashtable */
756         c->hashlink = class_hash.ptr[slot];
757         class_hash.ptr[slot] = c;
758
759         /* update number of hashtable-entries */
760         class_hash.entries++;
761
762         if (class_hash.entries > (class_hash.size*2)) {  
763
764                 /* reorganization of hashtable, average length of 
765                    the external chains is approx. 2                */  
766
767                 u4 i;
768                 classinfo *c;
769                 hashtable newhash;  /* the new hashtable */
770
771                 /* create new hashtable, double the size */
772                 init_hashtable(&newhash, class_hash.size*2);
773                 newhash.entries = class_hash.entries;
774
775                 /* transfer elements to new hashtable */
776                 for (i = 0; i < class_hash.size; i++) {
777                         c = (classinfo*) class_hash.ptr[i];
778                         while (c) {
779                                 classinfo *nextc = c->hashlink;
780                                 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
781                                                 
782                                 c->hashlink = newhash.ptr[slot];
783                                 newhash.ptr[slot] = c;
784
785                                 c = nextc;
786                         }
787                 }
788         
789                 /* dispose old table */ 
790                 MFREE(class_hash.ptr, void*, class_hash.size);
791                 class_hash = newhash;
792         }
793                         
794     /* Array classes need further initialization. */
795     if (u->text[0] == '[')
796         class_new_array(c);
797         
798         return c;
799 }
800
801 /******************** Function: class_get **************************************
802
803     searches for the class with the specified name in the classes hashtable
804     if there is no such class NULL is returned
805
806 *******************************************************************************/
807
808 classinfo *class_get(utf *u)
809 {
810         classinfo *c;  /* hashtable element */ 
811         u4 key;        /* hashkey computed from classname */   
812         u4 slot;       /* slot in hashtable */
813         u2 i;  
814
815         key  = utf_hashkey (u->text, u->blength);
816         slot = key & (class_hash.size-1);
817         c    = class_hash.ptr[slot];
818
819 /*
820         log_text("class_get: looking for class:");
821         utf_display(u); */
822         /* search external hash-chain */
823         while (c) {
824                 if (c->name->blength == u->blength) {
825                         
826                         /* compare classnames */
827                         for (i=0; i<u->blength; i++) 
828                                 if (u->text[i] != c->name->text[i]) goto nomatch;
829 /*
830                         log_text("class_get: class found");
831                         utf_display(u);
832                         log_text("");
833                         utf_display(c->name); */
834                         /* class found in hashtable */                          
835                         return c;
836                 }
837                         
838         nomatch:
839                 c = c->hashlink;
840         }
841
842         /* class not found */
843         return NULL;
844 }
845
846 /***************** Function: class_array_of ***********************************
847
848     Returns an array class with the given component class.
849     The array class is dynamically created if neccessary.
850
851 *******************************************************************************/
852
853 classinfo *class_array_of(classinfo *component)
854 {
855     int namelen;
856     char *namebuf;
857
858     /* Assemble the array class name */
859     namelen = component->name->blength;
860     
861     if (component->name->text[0] == '[') {
862         /* the component is itself an array */
863         namebuf = DMNEW(char,namelen+1);
864         namebuf[0] = '[';
865         memcpy(namebuf+1,component->name->text,namelen);
866         namelen++;
867     }
868     else {
869         /* the component is a non-array class */
870         namebuf = DMNEW(char,namelen+3);
871         namebuf[0] = '[';
872         namebuf[1] = 'L';
873         memcpy(namebuf+2,component->name->text,namelen);
874         namebuf[2+namelen] = ';';
875         namelen+=3;
876     }
877
878     return class_new( utf_new(namebuf,namelen) );
879 }
880
881 /*************** Function: class_multiarray_of ********************************
882
883     Returns an array class with the given dimension and element class.
884     The array class is dynamically created if neccessary.
885
886 *******************************************************************************/
887
888 classinfo *class_multiarray_of(int dim,classinfo *element)
889 {
890     int namelen;
891     char *namebuf;
892
893         if (dim<1)
894                 panic("Invalid array dimension requested");
895
896     /* Assemble the array class name */
897     namelen = element->name->blength;
898     
899     if (element->name->text[0] == '[') {
900         /* the element is itself an array */
901         namebuf = DMNEW(char,namelen+dim);
902         memcpy(namebuf+dim,element->name->text,namelen);
903         namelen += dim;
904     }
905     else {
906         /* the element is a non-array class */
907         namebuf = DMNEW(char,namelen+2+dim);
908         namebuf[dim] = 'L';
909         memcpy(namebuf+dim+1,element->name->text,namelen);
910         namelen += (2+dim);
911         namebuf[namelen-1] = ';';
912     }
913         memset(namebuf,'[',dim);
914
915     return class_new( utf_new(namebuf,namelen) );
916 }
917
918 /************************** function: utf_strlen ******************************
919
920     determine number of unicode characters in the utf string
921
922 *******************************************************************************/
923
924 u4 utf_strlen(utf *u) 
925 {
926     char *endpos  = utf_end(u);  /* points behind utf string       */
927     char *utf_ptr = u->text;     /* current position in utf text   */
928     u4 len = 0;                  /* number of unicode characters   */
929
930     while (utf_ptr<endpos) {
931                 len++;
932                 /* next unicode character */
933                 utf_nextu2(&utf_ptr);
934     }
935
936     if (utf_ptr!=endpos)
937         /* string ended abruptly */
938                 panic("illegal utf string"); 
939
940     return len;
941 }
942
943
944 /*
945  * These are local overrides for various environment variables in Emacs.
946  * Please do not remove this and leave it at the end of the file, where
947  * Emacs will automagically detect them.
948  * ---------------------------------------------------------------------
949  * Local variables:
950  * mode: c
951  * indent-tabs-mode: t
952  * c-basic-offset: 4
953  * tab-width: 4
954  * End:
955  */