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