9b58781060b1e91090a6343d6c6b9dceef55c842
[cacao.git] / loader.c
1 /* loader.c ********************************************************************
2
3         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
4
5         See file COPYRIGHT for information on usage and disclaimer of warranties
6
7         Contains the functions of the class loader.
8
9         Author:  Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at
10         Changes: Mark Probst         EMAIL: cacao@complang.tuwien.ac.at
11
12         Last Change: 1997/06/03
13
14 *******************************************************************************/
15
16
17 #include <assert.h>
18
19 #include "global.h"
20 #include "loader.h"
21
22 #include "tables.h"
23 #include "native.h"
24 #include "builtin.h"
25 #include "jit.h"
26 #ifdef OLD_COMPILER
27 #include "compiler.h"
28 #endif
29 #include "asmpart.h"
30
31 #include "threads/thread.h"                        /* schani */
32
33
34 /* global variables ***********************************************************/
35
36 extern bool newcompiler;        /* true if new compiler is used               */                
37
38 int count_class_infos = 0;      /* variables for measurements                 */
39 int count_const_pool_len = 0;
40 int count_vftbl_len = 0;
41 int count_all_methods = 0;
42 int count_vmcode_len = 0;
43 int count_extable_len = 0;
44
45 bool loadverbose = false;    /* switches for debug messages                   */
46 bool linkverbose = false;
47 bool initverbose = false;
48
49 bool makeinitializations = true;
50
51 bool getloadingtime = false;
52 long int loadingtime = 0;
53
54
55 static s4 interfaceindex;    /* sequential numbering of interfaces            */ 
56
57 static list unloadedclasses; /* list of all referenced but not loaded classes */
58 static list unlinkedclasses; /* list of all loaded but not linked classes     */
59        list linkedclasses;   /* list of all completely linked classes         */
60
61
62
63 /* important system classes ***************************************************/
64
65 classinfo *class_java_lang_Object;
66 classinfo *class_java_lang_String;
67 classinfo *class_java_lang_ClassCastException;
68 classinfo *class_java_lang_NullPointerException;
69 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
70 classinfo *class_java_lang_NegativeArraySizeException;
71 classinfo *class_java_lang_OutOfMemoryError;
72 classinfo *class_java_lang_ArithmeticException;
73 classinfo *class_java_lang_ArrayStoreException;
74 classinfo *class_java_lang_ThreadDeath;                 /* schani */
75
76 classinfo *class_array;
77
78
79 /* instances of important system classes **************************************/
80
81 java_objectheader *proto_java_lang_ClassCastException;
82 java_objectheader *proto_java_lang_NullPointerException;
83 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
84 java_objectheader *proto_java_lang_NegativeArraySizeException;
85 java_objectheader *proto_java_lang_OutOfMemoryError;
86 java_objectheader *proto_java_lang_ArithmeticException;
87 java_objectheader *proto_java_lang_ArrayStoreException;
88 java_objectheader *proto_java_lang_ThreadDeath;         /* schani */
89
90
91
92
93 /******************************************************************************/
94 /******************* Einige Support-Funkionen *********************************/
95 /******************************************************************************/
96
97
98 /********** interne Funktion: printflags  (nur zu Debug-Zwecken) **************/
99
100 static void printflags (u2 f)
101 {
102    if ( f & ACC_PUBLIC )       printf (" PUBLIC");
103    if ( f & ACC_PRIVATE )      printf (" PRIVATE");
104    if ( f & ACC_PROTECTED )    printf (" PROTECTED");
105    if ( f & ACC_STATIC )       printf (" STATIC");
106    if ( f & ACC_FINAL )        printf (" FINAL");
107    if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
108    if ( f & ACC_VOLATILE )     printf (" VOLATILE");
109    if ( f & ACC_TRANSIENT )    printf (" TRANSIENT");
110    if ( f & ACC_NATIVE )       printf (" NATIVE");
111    if ( f & ACC_INTERFACE )    printf (" INTERFACE");
112    if ( f & ACC_ABSTRACT )     printf (" ABSTRACT");
113 }
114
115
116 /************************* Funktion: skipattribute *****************************
117
118         "uberliest im ClassFile eine (1) 'attribute'-Struktur 
119
120 *******************************************************************************/
121
122 static void skipattribute ()
123 {
124         suck_u2 ();
125         skip_nbytes(suck_u4()); 
126 }
127
128 /********************** Funktion: skipattributebody ****************************
129
130         "uberliest im Classfile ein attribut, wobei die 16-bit - attribute_name - 
131         Referenz schon gelesen worden ist.
132         
133 *******************************************************************************/
134
135 static void skipattributebody ()
136 {
137         skip_nbytes(suck_u4());
138 }
139
140
141 /************************* Funktion: skipattributes ****************************
142
143         "uberliest im ClassFile eine gew"unschte Anzahl von attribute-Strukturen
144         
145 *******************************************************************************/
146
147 static void skipattributes (u4 num)
148 {
149         u4 i;
150         for (i = 0; i < num; i++)
151                 skipattribute();
152 }
153
154
155
156 /************************** Funktion: loadUtf8 *********************************
157
158         liest aus dem ClassFile einen Utf8-String (=komprimierter unicode-text) 
159         und legt daf"ur ein unicode-Symbol an. 
160         Return: Zeiger auf das Symbol 
161
162 *******************************************************************************/
163
164 #define MAXUNICODELEN 5000
165 static u2 unicodebuffer[MAXUNICODELEN];
166
167 static unicode *loadUtf8 ()
168 {
169         u4 unicodelen;
170         u4 letter;
171
172         u4 utflen;
173         u4 b1,b2,b3;
174
175         unicodelen = 0;
176
177         utflen = suck_u2 ();
178         while (utflen > 0) {
179                 b1 = suck_u1 ();
180                 utflen --;
181                 if (b1<0x80) letter = b1;
182                 else {
183                         b2 = suck_u1 ();
184                         utflen --;
185                         if (b1<0xe0) letter = ((b1 & 0x1f) << 6) | (b2 & 0x3f);
186                         else {
187                                 b3 = suck_u1 ();
188                                 utflen --;
189                                 letter = ((b1 & 0x0f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f);
190                                 }
191                         }       
192         
193
194                 if (unicodelen >= MAXUNICODELEN) {
195                         panic ("String constant too long");
196                         }
197                 
198                 unicodebuffer[unicodelen++] = letter;                   
199                 }
200
201         
202         return unicode_new_u2 (unicodebuffer, unicodelen);
203 }
204
205
206
207 /******************** interne Funktion: checkfieldtype ************************/
208
209 static void checkfieldtype (u2 *text, u4 *count, u4 length)
210 {
211         u4 l;
212
213         if (*count >= length) panic ("Type-descriptor exceeds unicode length");
214         
215         l = text[(*count)++];
216         
217         switch (l) {
218                 default: panic ("Invalid symbol in type descriptor");
219                          return;
220                 case 'B':
221                 case 'C':
222                 case 'D':
223                 case 'F':
224                 case 'I':
225                 case 'J':
226                 case 'S':
227                 case 'Z': return;
228                 
229                 case '[': checkfieldtype (text, count, length);
230                           return;
231                           
232                 case 'L': 
233                         {
234                         u4 tlen,tstart = *count;
235                         
236                         if (*count >= length) 
237                            panic ("Objecttype descriptor of length zero");
238                         
239                         while ( text[*count] != ';' ) {
240                                 (*count)++;
241                                 if (*count >= length) 
242                                    panic ("Missing ';' in objecttype-descriptor");
243                                 }
244                         
245                         tlen = (*count) - tstart;
246                         (*count)++;
247
248                         if (tlen == 0) panic ("Objecttype descriptor with empty name");
249                                         
250                         class_get ( unicode_new_u2 (text+tstart, tlen) );
251                         }
252                 }       
253 }
254
255
256 /******************* Funktion: checkfielddescriptor ****************************
257
258         "uberpr"uft, ob ein Field-Descriptor ein g"ultiges Format hat.
259         Wenn nicht, dann wird das System angehalten.
260         Au"serdem werden alle Klassen, die hier referenziert werden, 
261         in die Liste zu ladender Klassen eingetragen.
262         
263 *******************************************************************************/
264
265 void checkfielddescriptor (unicode *d)
266 {
267         u4 count=0;
268         checkfieldtype (d->text, &count, d->length);
269         if (count != d->length) panic ("Invalid type-descritor encountered");
270 }
271
272
273 /******************* Funktion: checkmethoddescriptor ***************************
274
275         "uberpr"uft, ob ein Method-Descriptor ein g"ultiges Format hat.
276         Wenn nicht, dann wird das System angehalten.
277         Au"serdem werden alle Klassen, die hier referenziert werden, 
278         in die Liste zu ladender Klassen eingetragen.
279         
280 *******************************************************************************/
281
282 void checkmethoddescriptor (unicode *d)
283 {
284         u2 *text=d->text;
285         u4 length=d->length;
286         u4 count=0;
287         
288         if (length<2) panic ("Method descriptor too short");
289         if (text[0] != '(') panic ("Missing '(' in method descriptor");
290         count=1;
291         
292         while (text[count] != ')') {
293                 checkfieldtype (text,&count,length);
294                 if ( count > length-2 ) panic ("Unexpected end of descriptor");
295                 }
296                 
297         count++;
298         if (text[count] == 'V') count++;
299         else                    checkfieldtype (text, &count,length);
300                 
301         if (count != length) panic ("Method-descriptor has exceeding chars");
302 }
303
304
305 /******************** Funktion: buildarraydescriptor ***************************
306
307         erzeugt zu einem namentlich als u2-String vorliegenden Arraytyp eine
308         entsprechende constant_arraydescriptor - Struktur 
309         
310 *******************************************************************************/
311
312 static constant_arraydescriptor * buildarraydescriptor(u2 *name, u4 namelen)
313 {
314         constant_arraydescriptor *d;
315         
316         if (name[0]!='[') panic ("Attempt to build arraydescriptor for non-array");
317         d = NEW (constant_arraydescriptor);
318         d -> objectclass = NULL;
319         d -> elementdescriptor = NULL;
320
321 #ifdef STATISTICS
322         count_const_pool_len += sizeof(constant_arraydescriptor);
323 #endif
324
325         switch (name[1]) {
326         case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
327         case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
328         case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
329         case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
330         case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
331         case 'I': d -> arraytype = ARRAYTYPE_INT; break;
332         case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
333         case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
334
335         case '[':
336                 d -> arraytype = ARRAYTYPE_ARRAY; 
337                 d -> elementdescriptor = buildarraydescriptor (name+1, namelen-1);
338                 break;
339                 
340         case 'L':
341                 d -> arraytype = ARRAYTYPE_OBJECT;
342                 d -> objectclass = class_get ( unicode_new_u2 (name+2, namelen-3) );
343                 break;
344         }
345         return d;
346 }
347
348
349 /******************* Funktion: freearraydescriptor *****************************
350
351         entfernt eine mit buildarraydescriptor erzeugte Struktur wieder 
352         aus dem Speicher
353         
354 *******************************************************************************/
355
356 static void freearraydescriptor (constant_arraydescriptor *d)
357 {
358         while (d) {
359                 constant_arraydescriptor *n = d->elementdescriptor;
360                 FREE (d, constant_arraydescriptor);
361                 d = n;
362                 }
363 }
364
365 /*********************** Funktion: displayarraydescriptor *********************/
366
367 static void displayarraydescriptor (constant_arraydescriptor *d)
368 {
369         switch (d->arraytype) {
370         case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
371         case ARRAYTYPE_BYTE: printf ("byte[]"); break;
372         case ARRAYTYPE_CHAR: printf ("char[]"); break;
373         case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
374         case ARRAYTYPE_FLOAT: printf ("float[]"); break;
375         case ARRAYTYPE_INT: printf ("int[]"); break;
376         case ARRAYTYPE_LONG: printf ("long[]"); break;
377         case ARRAYTYPE_SHORT: printf ("short[]"); break;
378         case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
379         case ARRAYTYPE_OBJECT: unicode_display(d->objectclass->name); printf("[]"); break;
380         }
381 }
382
383
384
385 /******************************************************************************/
386 /******************** Funktionen fuer Fields **********************************/
387 /******************************************************************************/
388
389
390 /************************ Funktion: field_load *********************************
391
392         l"adt alle Informationen f"ur eine Feld einer Methode aus dem ClassFile,
393         und f"ullt mit diesen Infos eine schon existierende 'fieldinfo'-Struktur.
394         Bei 'static'-Fields wird auch noch ein Platz auf dem Datensegment
395         reserviert.
396
397 *******************************************************************************/
398
399 static void field_load (fieldinfo *f, classinfo *c)
400 {
401         u4 attrnum,i;
402         u4 jtype;
403
404         f -> flags = suck_u2 ();
405         f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
406         f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
407         f -> type = jtype = desc_to_type (f->descriptor);
408         f -> offset = 0;
409
410         switch (f->type) {
411         case TYPE_INT:        f->value.i = 0; break;
412         case TYPE_FLOAT:      f->value.f = 0.0; break;
413         case TYPE_DOUBLE:     f->value.d = 0.0; break;
414         case TYPE_ADDRESS:    f->value.a = NULL; 
415                               heap_addreference (&(f->value.a));
416                               break;
417         case TYPE_LONG:
418 #if U8_AVAILABLE
419                 f->value.l = 0; break;
420 #else
421                 f->value.l.low = 0; f->value.l.high = 0; break;
422 #endif 
423         }
424         
425         attrnum = suck_u2();
426         for (i=0; i<attrnum; i++) {
427                 u4 pindex;
428                 unicode *aname;
429
430                 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
431
432                 if ( aname != unicode_new_char ("ConstantValue") ) {
433                         skipattributebody ();
434                         }
435                 else {
436                         suck_u4();
437                         pindex = suck_u2();
438                                 
439                         switch (jtype) {
440                                 case TYPE_INT: {
441                                         constant_integer *ci = 
442                                                 class_getconstant(c, pindex, CONSTANT_Integer);
443                                         f->value.i = ci -> value;
444                                         }
445                                         break;
446                                         
447                                 case TYPE_LONG: {
448                                         constant_long *cl = 
449                                            class_getconstant(c, pindex, CONSTANT_Long);
450         
451                                         f->value.l = cl -> value;
452                                         }
453                                         break;
454
455                                 case TYPE_FLOAT: {
456                                         constant_float *cf = 
457                                             class_getconstant(c, pindex, CONSTANT_Float);
458         
459                                         f->value.f = cf->value;
460                                         }
461                                         break;
462                                                                                         
463                                 case TYPE_DOUBLE: {
464                                         constant_double *cd = 
465                                             class_getconstant(c, pindex, CONSTANT_Double);
466         
467                                         f->value.d = cd->value;
468                                         }
469                                         break;
470                                                 
471                                 case TYPE_ADDRESS: {
472                                         unicode *u = 
473                                                 class_getconstant(c, pindex, CONSTANT_String);
474                                         f->value.a = literalstring_new(u);
475                                         }
476                                         break;
477         
478                                 default: 
479                                         log_text ("Invalid Constant - Type");
480
481                                 }
482
483                         }
484                 }
485                 
486 }
487
488
489 /********************** Funktion: field_free **********************************/
490
491 static void field_free (fieldinfo *f)
492 {
493 }
494
495
496 /************** Funktion: field_display (nur zu Debug-Zwecken) ****************/
497
498 static void field_display (fieldinfo *f)
499 {
500         printf ("   ");
501         printflags (f -> flags);
502         printf (" ");
503         unicode_display (f -> name);
504         printf (" ");
505         unicode_display (f -> descriptor);      
506         printf (" offset: %ld\n", (long int) (f -> offset) );
507 }
508
509
510
511
512 /******************************************************************************/
513 /************************* Funktionen f"ur Methods ****************************/ 
514 /******************************************************************************/
515
516
517 /*********************** Funktion: method_load *********************************
518
519         l"adt die Infos f"ur eine Methode aus dem ClassFile und f"ullt damit 
520         eine schon existierende 'methodinfo'-Struktur aus.
521         Bei allen native-Methoden wird au"serdem gleich der richtige 
522         Funktionszeiger eingetragen, bei JavaVM-Methoden einstweilen ein
523         Zeiger auf den Compiler 
524         
525 *******************************************************************************/
526
527 static void method_load (methodinfo *m, classinfo *c)
528 {
529         u4 attrnum,i,e;
530         
531 #ifdef STATISTICS
532         count_all_methods++;
533 #endif
534
535         m -> class = c;
536         
537         m -> flags = suck_u2 ();
538         m -> name =  class_getconstant (c, suck_u2(), CONSTANT_Utf8);
539         m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
540         
541         m -> jcode = NULL;
542         m -> exceptiontable = NULL;
543         m -> entrypoint = NULL;
544         m -> mcode = NULL;
545         m -> stubroutine = NULL;
546         
547         if (! (m->flags & ACC_NATIVE) ) {
548                 m -> stubroutine = createcompilerstub (m);
549                 }
550         else {
551                 functionptr f = native_findfunction 
552                        (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
553                 if (f) {
554 #ifdef OLD_COMPILER
555                 if (newcompiler)
556 #endif
557                         m -> stubroutine = createnativestub (f, m);
558 #ifdef OLD_COMPILER
559                 else
560                         m -> stubroutine = oldcreatenativestub (f, m);
561 #endif
562                         }
563                 }
564         
565         
566         attrnum = suck_u2();
567         for (i=0; i<attrnum; i++) {
568                 unicode *aname;
569
570                 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
571
572                 if ( aname != unicode_new_char("Code"))  {
573                         skipattributebody ();
574                         }
575                 else {
576                         if (m -> jcode) panic ("Two code-attributes for one method!");
577                         
578                         suck_u4();
579                         m -> maxstack = suck_u2();
580                         m -> maxlocals = suck_u2();
581                         m -> jcodelength = suck_u4();
582                         m -> jcode = MNEW (u1, m->jcodelength);
583                         suck_nbytes (m->jcode, m->jcodelength);
584                         m -> exceptiontablelength = suck_u2 ();
585                         m -> exceptiontable = 
586                            MNEW (exceptiontable, m->exceptiontablelength);
587
588 #ifdef STATISTICS
589         count_vmcode_len += m->jcodelength + 18;
590         count_extable_len += 8 * m->exceptiontablelength;
591 #endif
592
593                         for (e=0; e < m->exceptiontablelength; e++) {
594                                 u4 idx;
595                                 m -> exceptiontable[e].startpc = suck_u2();
596                                 m -> exceptiontable[e].endpc = suck_u2();
597                                 m -> exceptiontable[e].handlerpc = suck_u2();
598
599                                 idx = suck_u2();
600                                 if (!idx) m -> exceptiontable[e].catchtype = NULL;
601                                 else {
602                                         m -> exceptiontable[e].catchtype = 
603                                       class_getconstant (c, idx, CONSTANT_Class);
604                                         }
605                                 }                       
606
607                         skipattributes ( suck_u2() );
608                         }
609                         
610                 }
611
612
613 }
614
615
616 /********************* Funktion: method_free ***********************************
617
618         gibt allen Speicher, der extra f"ur eine Methode angefordert wurde,
619         wieder frei
620
621 *******************************************************************************/
622
623 static void method_free (methodinfo *m)
624 {
625         if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
626         if (m->exceptiontable) 
627                 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
628         if (m->mcode) CFREE (m->mcode, m->mcodelength);
629         if (m->stubroutine) {
630                 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
631                 else                       removecompilerstub (m->stubroutine);
632                 }
633 }
634
635
636 /************** Funktion: method_display  (nur zu Debug-Zwecken) **************/
637
638 void method_display (methodinfo *m)
639 {
640         printf ("   ");
641         printflags (m -> flags);
642         printf (" ");
643         unicode_display (m -> name);
644         printf (" "); 
645         unicode_display (m -> descriptor);
646         printf ("\n");
647 }
648
649
650 /******************** Funktion: method_canoverwrite ****************************
651
652         "uberpr"ft, ob eine Methode mit einer anderen typ- und namensidentisch 
653         ist (also mit einer Methodendefinition eine andere "uberschrieben 
654         werden kann).
655         
656 *******************************************************************************/  
657
658 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
659 {
660         if (m->name != old->name) return false;
661         if (m->descriptor != old->descriptor) return false;
662         if (m->flags & ACC_STATIC) return false;
663         return true;
664 }
665
666
667
668
669 /******************************************************************************/
670 /************************ Funktionen fuer Class *******************************/
671 /******************************************************************************/
672
673
674 /******************** Funktion: class_get **************************************
675
676         Sucht im System die Klasse mit dem gew"unschten Namen, oder erzeugt
677         eine neue 'classinfo'-Struktur (und h"angt sie in die Liste der zu
678         ladenen Klassen ein).
679
680 *******************************************************************************/
681
682 classinfo *class_get (unicode *u)
683 {
684         classinfo *c;
685         
686         if (u->class) return u->class;
687         
688 #ifdef STATISTICS
689         count_class_infos += sizeof(classinfo);
690 #endif
691
692         c = NEW (classinfo);
693         c -> flags = 0;
694         c -> name = u;
695         c -> cpcount = 0;
696         c -> cptags = NULL;
697         c -> cpinfos = NULL;
698         c -> super = NULL;
699         c -> sub = NULL;
700         c -> nextsub = NULL;
701         c -> interfacescount = 0;
702         c -> interfaces = NULL;
703         c -> fieldscount = 0;
704         c -> fields = NULL;
705         c -> methodscount = 0;
706         c -> methods = NULL;
707         c -> linked = false;
708         c -> index = 0;
709         c -> instancesize = 0;
710         c -> header.vftbl = NULL;
711         c -> vftbl = NULL;
712         c -> initialized = false;
713         
714         unicode_setclasslink (u,c);
715         list_addlast (&unloadedclasses, c);
716                 
717         return c;
718 }
719
720
721
722 /******************** Funktion: class_getconstant ******************************
723
724         holt aus dem ConstantPool einer Klasse den Wert an der Stelle 'pos'.
725         Der Wert mu"s vom Typ 'ctype' sein, sonst wird das System angehalten.
726
727 *******************************************************************************/
728
729 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype) 
730 {
731         if (pos >= c->cpcount) 
732                 panic ("Attempt to access constant outside range");
733         if (c->cptags[pos] != ctype) {
734                 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
735                  (int) ctype, (int) c->cptags[pos] );
736                 error();
737                 }
738                 
739         return c->cpinfos[pos];
740 }
741
742
743 /********************* Funktion: class_constanttype ****************************
744
745         Findet heraus, welchen Typ ein Eintrag in den ConstantPool einer 
746         Klasse hat.
747         
748 *******************************************************************************/
749
750 u4 class_constanttype (classinfo *c, u4 pos)
751 {
752         if (pos >= c->cpcount) 
753                 panic ("Attempt to access constant outside range");
754         return c->cptags[pos];
755 }
756
757
758 /******************** Funktion: class_loadcpool ********************************
759
760         l"adt den gesammten ConstantPool einer Klasse.
761         
762         Dabei werden die einzelnen Eintr"age in ein wesentlich einfachers 
763         Format gebracht (Klassenreferenzen werden aufgel"ost, ...)
764         F"ur eine genaue "Ubersicht "uber das kompakte Format siehe: 'global.h' 
765
766 *******************************************************************************/
767
768 static void class_loadcpool (classinfo *c)
769 {
770
771         typedef struct forward_class {      /* Diese Strukturen dienen dazu, */
772                 struct forward_class *next;     /* die Infos, die beim ersten */
773                 u2 thisindex;                   /* Durchgang durch den ConstantPool */
774                 u2 name_index;                  /* gelesen werden, aufzunehmen. */
775         } forward_class;                    /* Erst nachdem der ganze Pool */ 
776                                         /* gelesen wurde, k"onnen alle */
777         typedef struct forward_string {     /* Felder kompletiert werden */
778                 struct forward_string *next;    /* (und das auch nur in der richtigen */
779                 u2 thisindex;                   /* Reihenfolge) */
780                 u2 string_index;
781         } forward_string;
782
783         typedef struct forward_nameandtype {
784                 struct forward_nameandtype *next;
785                 u2 thisindex;
786                 u2 name_index;
787                 u2 sig_index;
788         } forward_nameandtype;
789
790         typedef struct forward_fieldmethint {   
791                 struct forward_fieldmethint *next;
792                 u2 thisindex;
793                 u1 tag;
794                 u2 class_index;
795                 u2 nameandtype_index;
796         } forward_fieldmethint;
797
798
799
800         u4 idx;
801         long int dumpsize = dump_size ();
802
803         forward_class *forward_classes = NULL;
804         forward_string *forward_strings = NULL;
805         forward_nameandtype *forward_nameandtypes = NULL;
806         forward_fieldmethint *forward_fieldmethints = NULL;
807
808         u4 cpcount       = c -> cpcount = suck_u2();
809         u1 *cptags       = c -> cptags  = MNEW (u1, cpcount);
810         voidptr *cpinfos = c -> cpinfos =  MNEW (voidptr, cpcount);
811
812 #ifdef STATISTICS
813         count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
814 #endif
815
816         
817         for (idx=0; idx<cpcount; idx++) {
818                 cptags[idx] = CONSTANT_UNUSED;
819                 cpinfos[idx] = NULL;
820                 }
821
822                         
823                 /******* Erster Durchgang *******/
824                 /* Alle Eintr"age, die nicht unmittelbar aufgel"ost werden k"onnen, 
825                    werden einmal `auf Vorrat' in tempor"are Strukturen eingelesen,
826                    und dann am Ende nocheinmal durchgegangen */
827
828         idx = 1;
829         while (idx < cpcount) {
830                 u4 t = suck_u1 ();
831                 switch ( t ) {
832
833                         case CONSTANT_Class: { 
834                                 forward_class *nfc = DNEW(forward_class);
835
836                                 nfc -> next = forward_classes;                                                                                  
837                                 forward_classes = nfc;
838
839                                 nfc -> thisindex = idx;
840                                 nfc -> name_index = suck_u2 ();
841
842                                 idx++;
843                                 break;
844                                 }
845                         
846                         case CONSTANT_Fieldref:
847                         case CONSTANT_Methodref:
848                         case CONSTANT_InterfaceMethodref: {
849                                 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
850                                 
851                                 nff -> next = forward_fieldmethints;
852                                 forward_fieldmethints = nff;
853
854                                 nff -> thisindex = idx;
855                                 nff -> tag = t;
856                                 nff -> class_index = suck_u2 ();
857                                 nff -> nameandtype_index = suck_u2 ();
858
859                                 idx ++;                                         
860                                 break;
861                                 }
862                                 
863                         case CONSTANT_String: {
864                                 forward_string *nfs = DNEW (forward_string);
865                                 
866                                 nfs -> next = forward_strings;
867                                 forward_strings = nfs;
868                                 
869                                 nfs -> thisindex = idx;
870                                 nfs -> string_index = suck_u2 ();
871                                 
872                                 idx ++;
873                                 break;
874                                 }
875
876                         case CONSTANT_NameAndType: {
877                                 forward_nameandtype *nfn = DNEW (forward_nameandtype);
878                                 
879                                 nfn -> next = forward_nameandtypes;
880                                 forward_nameandtypes = nfn;
881                                 
882                                 nfn -> thisindex = idx;
883                                 nfn -> name_index = suck_u2 ();
884                                 nfn -> sig_index = suck_u2 ();
885                                 
886                                 idx ++;
887                                 break;
888                                 }
889
890                         case CONSTANT_Integer: {
891                                 constant_integer *ci = NEW (constant_integer);
892
893 #ifdef STATISTICS
894         count_const_pool_len += sizeof(constant_integer);
895 #endif
896
897                                 ci -> value = suck_s4 ();
898                                 cptags [idx] = CONSTANT_Integer;
899                                 cpinfos [idx] = ci;
900                                 idx ++;
901                                 
902                                 break;
903                                 }
904                                 
905                         case CONSTANT_Float: {
906                                 constant_float *cf = NEW (constant_float);
907
908 #ifdef STATISTICS
909         count_const_pool_len += sizeof(constant_float);
910 #endif
911
912                                 cf -> value = suck_float ();
913                                 cptags [idx] = CONSTANT_Float;
914                                 cpinfos[idx] = cf;
915                                 idx ++;
916                                 break;
917                                 }
918                                 
919                         case CONSTANT_Long: {
920                                 constant_long *cl = NEW(constant_long);
921                                         
922 #ifdef STATISTICS
923         count_const_pool_len += sizeof(constant_long);
924 #endif
925
926                                 cl -> value = suck_s8 ();
927                                 cptags [idx] = CONSTANT_Long;
928                                 cpinfos [idx] = cl;
929                                 idx += 2;
930                                 break;
931                                 }
932                         
933                         case CONSTANT_Double: {
934                                 constant_double *cd = NEW(constant_double);
935                                 
936 #ifdef STATISTICS
937         count_const_pool_len += sizeof(constant_double);
938 #endif
939
940                                 cd -> value = suck_double ();
941                                 cptags [idx] = CONSTANT_Double;
942                                 cpinfos [idx] = cd;
943                                 idx += 2;
944                                 break;
945                                 }
946                                 
947                         case CONSTANT_Utf8: {
948                                 unicode *u;
949
950                                 u = loadUtf8 ();
951
952                                 cptags [idx] = CONSTANT_Utf8;
953                                 cpinfos [idx] = u;
954                                 idx++;
955                                 break;
956                                 }
957                                                                                 
958                         default:
959                                 sprintf (logtext, "Unkown constant type: %d",(int) t);
960                                 error ();
961                 
962                         }  /* end switch */
963                         
964                 } /* end while */
965                 
966
967
968            /* Aufl"osen der noch unfertigen Eintr"age */
969
970         while (forward_classes) {
971                 unicode *name =
972                   class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
973                 
974                 if ( (name->length>0) && (name->text[0]=='[') ) {
975                         checkfielddescriptor (name); 
976
977                         cptags  [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
978                         cpinfos [forward_classes -> thisindex] = 
979                            buildarraydescriptor(name->text, name->length);
980
981                         }
982                 else {          
983                         cptags  [forward_classes -> thisindex] = CONSTANT_Class;
984                         cpinfos [forward_classes -> thisindex] = class_get (name);
985                         }
986                 forward_classes = forward_classes -> next;
987                 
988                 }
989
990         while (forward_strings) {
991                 unicode *text = 
992                   class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
993                         
994                 cptags   [forward_strings -> thisindex] = CONSTANT_String;
995                 cpinfos  [forward_strings -> thisindex] = text;
996                 
997                 forward_strings = forward_strings -> next;
998                 }       
999
1000         while (forward_nameandtypes) {
1001                 constant_nameandtype *cn = NEW (constant_nameandtype);  
1002
1003 #ifdef STATISTICS
1004                 count_const_pool_len += sizeof(constant_nameandtype);
1005 #endif
1006
1007                 cn -> name = class_getconstant 
1008                    (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1009                 cn -> descriptor = class_getconstant
1010                    (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1011                  
1012                 cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1013                 cpinfos  [forward_nameandtypes -> thisindex] = cn;
1014                 
1015                 forward_nameandtypes = forward_nameandtypes -> next;
1016                 }
1017
1018
1019         while (forward_fieldmethints)  {
1020                 constant_nameandtype *nat;
1021                 constant_FMIref *fmi = NEW (constant_FMIref);
1022
1023 #ifdef STATISTICS
1024                 count_const_pool_len += sizeof(constant_FMIref);
1025 #endif
1026
1027                 nat = class_getconstant
1028                         (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1029
1030                 fmi -> class = class_getconstant 
1031                         (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1032                 fmi -> name = nat -> name;
1033                 fmi -> descriptor = nat -> descriptor;
1034
1035                 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1036                 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1037         
1038                 switch (forward_fieldmethints -> tag) {
1039                 case CONSTANT_Fieldref:  checkfielddescriptor (fmi->descriptor);
1040                                          break;
1041                 case CONSTANT_InterfaceMethodref: 
1042                 case CONSTANT_Methodref: checkmethoddescriptor (fmi->descriptor);
1043                                          break;
1044                 }               
1045         
1046                 forward_fieldmethints = forward_fieldmethints -> next;
1047
1048                 }
1049
1050
1051         dump_release (dumpsize);
1052 }
1053
1054
1055 /********************** Funktion: class_load ***********************************
1056
1057         l"adt alle Infos f"ur eine ganze Klasse aus einem ClassFile. Die
1058         'classinfo'-Struktur mu"s bereits angelegt worden sein.
1059         
1060         Die Superklasse und die Interfaces, die diese Klasse implementiert,
1061         m"ussen zu diesem Zeitpunkt noch nicht geladen sein, die 
1062         Verbindung dazu wird sp"ater in der Funktion 'class_link' hergestellt.
1063         
1064         Die gelesene Klasse wird dann aus der Liste 'unloadedclasses' ausgetragen
1065         und in die Liste 'unlinkedclasses' eingh"angt.
1066         
1067 *******************************************************************************/
1068
1069 static void class_load (classinfo *c)
1070 {
1071         u4 i;
1072         u4 mi,ma;
1073
1074
1075         if (loadverbose) {
1076                 sprintf (logtext, "Loading class: ");
1077                 unicode_sprint (logtext+strlen(logtext), c->name );
1078                 dolog();
1079                 }
1080
1081
1082         suck_start (c->name);
1083
1084         if (suck_u4() != MAGIC) panic("Can not find class-file signature");   
1085         mi = suck_u2(); 
1086         ma = suck_u2();
1087         if (ma != MAJOR_VERSION) {
1088                 sprintf (logtext, "Can only support major version %d, but not %d",
1089                                  MAJOR_VERSION, (int) ma);
1090                 error();
1091                 }
1092         if (mi > MINOR_VERSION)  {
1093                 sprintf (logtext, "Minor version %d is not yet supported.", (int) mi);
1094                 error();
1095                 }
1096
1097
1098         class_loadcpool (c);
1099         
1100         c -> flags = suck_u2 ();
1101         suck_u2 ();       /* this */
1102         
1103         if ( (i = suck_u2 () ) ) {
1104                 c -> super = class_getconstant (c, i, CONSTANT_Class);
1105                 }
1106         else {
1107                 c -> super = NULL;
1108                 }
1109                          
1110         c -> interfacescount = suck_u2 ();
1111         c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1112         for (i=0; i < c -> interfacescount; i++) {
1113                 c -> interfaces [i] = 
1114                       class_getconstant (c, suck_u2(), CONSTANT_Class);
1115                 }
1116
1117         c -> fieldscount = suck_u2 ();
1118         c -> fields = MNEW (fieldinfo, c -> fieldscount);
1119         for (i=0; i < c -> fieldscount; i++) {
1120                 field_load (&(c->fields[i]), c);
1121                 }
1122
1123         c -> methodscount = suck_u2 ();
1124         c -> methods = MNEW (methodinfo, c -> methodscount);
1125         for (i=0; i < c -> methodscount; i++) {
1126                 method_load (&(c -> methods [i]), c);
1127                 }
1128
1129 #ifdef STATISTICS
1130         count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1131         count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1132         count_class_infos += sizeof(methodinfo) * c -> methodscount;
1133 #endif
1134
1135
1136         skipattributes ( suck_u2() );
1137
1138
1139         suck_stop ();
1140
1141         list_remove (&unloadedclasses, c);
1142         list_addlast (&unlinkedclasses, c);
1143 }
1144
1145
1146
1147 /************** interne Funktion: class_highestinterface ***********************
1148
1149         wird von der Funktion class_link ben"otigt, um festzustellen, wie gro"s
1150         die Interfacetable einer Klasse sein mu"s.
1151
1152 *******************************************************************************/
1153
1154 static s4 class_highestinterface (classinfo *c) 
1155 {
1156         s4 h;
1157         s4 i;
1158         
1159         if ( ! (c->flags & ACC_INTERFACE) ) {
1160                 sprintf (logtext, "Interface-methods count requested for non-interface:  ");
1161         unicode_sprint (logtext+strlen(logtext), c->name);
1162         error();
1163         }
1164     
1165     h = c->index;
1166         for (i=0; i<c->interfacescount; i++) {
1167                 s4 h2 = class_highestinterface (c->interfaces[i]);
1168                 if (h2>h) h=h2;
1169                 }
1170         return h;
1171 }
1172
1173
1174 /* class_addinterface **********************************************************
1175
1176         wird von der Funktion class_link ben"otigt, um eine Virtual Function 
1177         Table f"ur ein Interface (und alle weiteren von diesem Interface
1178         implementierten Interfaces) in eine Klasse einzutragen.
1179
1180 *******************************************************************************/        
1181
1182 static void class_addinterface (classinfo *c, classinfo *ic)
1183 {
1184         s4     j, m;
1185         s4     i     = ic->index;
1186         vftbl *vftbl = c->vftbl;
1187         
1188         if (i >= vftbl->interfacetablelength)
1189                 panic ("Inernal error: interfacetable overflow");
1190         if (vftbl->interfacetable[-i])
1191                 return;
1192
1193         if (ic->methodscount == 0) {  /* fake entry needed for subtype test */
1194                 vftbl->interfacevftbllength[i] = 1;
1195                 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1196                 vftbl->interfacetable[-i][0] = NULL;
1197                 }
1198         else {
1199                 vftbl->interfacevftbllength[i] = ic->methodscount;
1200                 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount); 
1201
1202 #ifdef STATISTICS
1203         count_vftbl_len += sizeof(methodptr) *
1204                                  (ic->methodscount + (ic->methodscount == 0));
1205 #endif
1206
1207                 for (j=0; j<ic->methodscount; j++) {
1208                         classinfo *sc = c;
1209                         while (sc) {
1210                                 for (m = 0; m < sc->methodscount; m++) {
1211                                         methodinfo *mi = &(sc->methods[m]);
1212                                         if (method_canoverwrite(mi, &(ic->methods[j]))) {
1213                                                 vftbl->interfacetable[-i][j] = 
1214                                                                           vftbl->table[mi->vftblindex];
1215                                                 goto foundmethod;
1216                                                 }
1217                                         }
1218                                 sc = sc->super;
1219                                 }
1220                          foundmethod: ;
1221                         }
1222                 }
1223
1224         for (j = 0; j < ic->interfacescount; j++) 
1225                 class_addinterface(c, ic->interfaces[j]);
1226 }
1227
1228
1229 /********************** Funktion: class_link ***********************************
1230
1231         versucht, eine Klasse in das System voll zu integrieren (linken). Dazu 
1232         m"ussen sowol die Superklasse, als auch alle implementierten
1233         Interfaces schon gelinkt sein.
1234         Diese Funktion berechnet sowohl die L"ange (in Bytes) einer Instanz 
1235         dieser Klasse, als auch die Virtual Function Tables f"ur normale
1236         Methoden als auch Interface-Methoden.
1237         
1238         Wenn die Klasse erfolgreich gelinkt werden kann, dann wird sie aus
1239         der Liste 'unlinkedclasses' ausgeh"angt, und in die Klasse 'linkedclasses'
1240         eingetragen.
1241         Wenn nicht, dann wird sie ans Ende der Liste 'unlinkedclasses' gestellt.
1242
1243         Achtung: Bei zyklischen Klassendefinitionen ger"at das Programm hier in
1244                  eine Endlosschleife!!  (Da muss ich mir noch was einfallen lassen)
1245
1246 *******************************************************************************/
1247
1248 static void class_link (classinfo *c)
1249 {
1250         s4 supervftbllength;          /* vftbllegnth of super class               */
1251         s4 vftbllength;               /* vftbllength of current class             */
1252         s4 interfacetablelength;      /* interface table length                   */
1253         classinfo *super = c->super;  /* super class                              */
1254         classinfo *ic, *c2;           /* intermediate class variables             */
1255         vftbl *v;                     /* vftbl of current class                   */
1256         s4 i;                         /* interface/method/field counter           */                     
1257
1258
1259         /*  check if all superclasses are already linked, if not put c at end of
1260             unlinked list and return. Additionally initialize class fields.       */
1261
1262         /*  check interfaces */
1263
1264         for (i = 0; i < c->interfacescount; i++) {
1265                 ic = c->interfaces[i];
1266                 if (!ic->linked) {
1267                         list_remove(&unlinkedclasses, c);
1268                         list_addlast(&unlinkedclasses, c);
1269                         return; 
1270                         }
1271                 }
1272         
1273         /*  check super class */
1274
1275         if (super == NULL) {          /* class java.long.Object */
1276                 c->index = 0;
1277                 c->instancesize = sizeof(java_objectheader);
1278                 
1279                 vftbllength = supervftbllength = 0;
1280
1281                 c->finalizer = NULL;
1282                 }
1283         else {
1284                 if (!super->linked) {
1285                         list_remove(&unlinkedclasses, c);
1286                         list_addlast(&unlinkedclasses, c);
1287                         return; 
1288                         }
1289
1290                 if (c->flags & ACC_INTERFACE)
1291                         c->index = interfaceindex++;
1292                 else
1293                         c->index = super->index + 1;
1294                 
1295                 c->instancesize = super->instancesize;
1296                 
1297                 vftbllength = supervftbllength = super->vftbl->vftbllength;
1298                 
1299                 c->finalizer = super->finalizer;
1300                 }
1301
1302
1303         if (linkverbose) {
1304                 sprintf (logtext, "Linking Class: ");
1305                 unicode_sprint (logtext+strlen(logtext), c->name );
1306                 dolog ();
1307                 }
1308
1309         /* compute vftbl length */
1310
1311         for (i = 0; i < c->methodscount; i++) {
1312                 methodinfo *m = &(c->methods[i]);
1313                         
1314                 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1315                         classinfo *sc = super;
1316                         while (sc) {
1317                                 int j;
1318                                 for (j = 0; j < sc->methodscount; j++) {
1319                                         if (method_canoverwrite(m, &(sc->methods[j]))) {
1320                                                 m->vftblindex = sc->methods[j].vftblindex;
1321                                                 goto foundvftblindex;
1322                                                 }
1323                                         }
1324                                 sc = sc->super;
1325                                 }
1326                         m->vftblindex = (vftbllength++);
1327 foundvftblindex: ;
1328                         }
1329                 }       
1330         
1331 #ifdef STATISTICS
1332         count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1333 #endif
1334
1335         /* compute interfacetable length */
1336
1337         interfacetablelength = 0;
1338         c2 = c;
1339         while (c2) {
1340                 for (i = 0; i < c2->interfacescount; i++) {
1341                         s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1342                         if (h > interfacetablelength)
1343                                 interfacetablelength = h;
1344                         }
1345                 c2 = c2->super;
1346                 }
1347
1348         /* allocate virtual function table */
1349
1350         v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1351                     (vftbllength - 1) + sizeof(methodptr*) *
1352                     (interfacetablelength - (interfacetablelength > 0)));
1353         v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1354                                          (interfacetablelength > 1));
1355         c->header.vftbl = c->vftbl = v;
1356         v->class = c;
1357         v->vftbllength = vftbllength;
1358         v->interfacetablelength = interfacetablelength;
1359
1360         /* copy virtual function table of super class */
1361
1362         for (i = 0; i < supervftbllength; i++) 
1363            v->table[i] = super->vftbl->table[i];
1364         
1365         /* add method stubs into virtual function table */
1366
1367         for (i = 0; i < c->methodscount; i++) {
1368                 methodinfo *m = &(c->methods[i]);
1369                 if (!(m->flags & ACC_STATIC)) {
1370                         v->table[m->vftblindex] = m->stubroutine;
1371                         }
1372                 }
1373
1374         /* compute instance size and offset of each field */
1375         
1376         for (i = 0; i < c->fieldscount; i++) {
1377                 s4 dsize;
1378                 fieldinfo *f = &(c->fields[i]);
1379                 
1380                 if (!(f->flags & ACC_STATIC) ) {
1381                         dsize = desc_typesize (f->descriptor);
1382                         c->instancesize = ALIGN (c->instancesize, dsize);
1383                         f->offset = c->instancesize;
1384                         c->instancesize += dsize;
1385                         }
1386                 }
1387
1388         /* initialize interfacetable and interfacevftbllength */
1389         
1390         v->interfacevftbllength = MNEW (s4, interfacetablelength);
1391
1392 #ifdef STATISTICS
1393         count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1394 #endif
1395
1396         for (i = 0; i < interfacetablelength; i++) {
1397                 v->interfacevftbllength[i] = 0;
1398                 v->interfacetable[-i] = NULL;
1399                 }
1400         
1401         /* add interfaces */
1402         
1403         for (c2 = c; c2 != NULL; c2 = c2->super)
1404                 for (i = 0; i < c2->interfacescount; i++) {
1405                         class_addinterface (c, c2->interfaces[i]);
1406                         }
1407
1408         /* add finalizer method (not for java.lang.Object) */
1409
1410         if (super != NULL) {
1411                 methodinfo *fi;
1412                 static unicode *finame = NULL;
1413                 static unicode *fidesc = NULL;
1414
1415                 if (finame == NULL)
1416                         finame = unicode_new_char("finalize");
1417                 if (fidesc == NULL)
1418                         fidesc = unicode_new_char("()V");
1419
1420                 fi = class_findmethod (c, finame, fidesc);
1421                 if (fi != NULL) {
1422                         if (!(fi->flags & ACC_STATIC)) {
1423                                 c->finalizer = fi;
1424                                 }
1425                         }
1426                 }
1427
1428         /* final tasks */
1429
1430         c->linked = true;       
1431
1432         list_remove (&unlinkedclasses, c);
1433         list_addlast (&linkedclasses, c);
1434 }
1435
1436
1437 /******************* Funktion: class_freepool **********************************
1438
1439         Gibt alle Resourcen, die der ConstantPool einer Klasse ben"otigt,
1440         wieder frei.
1441
1442 *******************************************************************************/
1443
1444 static void class_freecpool (classinfo *c)
1445 {
1446         u4 idx;
1447         u4 tag;
1448         voidptr info;
1449         
1450         for (idx=0; idx < c->cpcount; idx++) {
1451                 tag = c->cptags[idx];
1452                 info = c->cpinfos[idx];
1453                 
1454                 if (info != NULL) {
1455                         switch (tag) {
1456                         case CONSTANT_Fieldref:
1457                         case CONSTANT_Methodref:
1458                         case CONSTANT_InterfaceMethodref:
1459                                 FREE (info, constant_FMIref);
1460                                 break;
1461                         case CONSTANT_Integer:
1462                                 FREE (info, constant_integer);
1463                                 break;
1464                         case CONSTANT_Float:
1465                                 FREE (info, constant_float);
1466                                 break;
1467                         case CONSTANT_Long:
1468                                 FREE (info, constant_long);
1469                                 break;
1470                         case CONSTANT_Double:
1471                                 FREE (info, constant_double);
1472                                 break;
1473                         case CONSTANT_NameAndType:
1474                                 FREE (info, constant_nameandtype);
1475                                 break;
1476                         case CONSTANT_Arraydescriptor:
1477                                 freearraydescriptor (info);
1478                                 break;
1479                         }
1480                         }
1481                 }
1482
1483         MFREE (c -> cptags,  u1, c -> cpcount);
1484         MFREE (c -> cpinfos, voidptr, c -> cpcount);
1485 }
1486
1487
1488 /*********************** Funktion: class_free **********************************
1489
1490         Gibt alle Resourcen, die eine ganze Klasse ben"otigt, frei
1491
1492 *******************************************************************************/
1493
1494 static void class_free (classinfo *c)
1495 {
1496         s4 i;
1497         vftbl *v;
1498                 
1499         unicode_unlinkclass (c->name);
1500         
1501         class_freecpool (c);
1502
1503         MFREE (c->interfaces, classinfo*, c->interfacescount);
1504
1505         for (i = 0; i < c->fieldscount; i++)
1506                 field_free(&(c->fields[i]));
1507         MFREE (c->fields, fieldinfo, c->fieldscount);
1508         
1509         for (i = 0; i < c->methodscount; i++)
1510                 method_free(&(c->methods[i]));
1511         MFREE (c->methods, methodinfo, c->methodscount);
1512
1513         if ((v = c->vftbl) != NULL) {
1514                 for (i = 0; i < v->interfacetablelength; i++) {
1515                         MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1516                         }
1517                 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1518
1519                 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1520                     sizeof(methodptr*) * (v->interfacetablelength -
1521                                          (v->interfacetablelength > 0));
1522                 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1523                                              (v->interfacetablelength > 1));
1524                 mem_free (v, i);
1525                 }
1526                 
1527         FREE (c, classinfo);
1528 }
1529
1530
1531 /************************* Funktion: class_findfield ***************************
1532         
1533         sucht in einer 'classinfo'-Struktur nach einem Feld mit gew"unschtem
1534         Namen und Typ.
1535
1536 *******************************************************************************/
1537
1538 fieldinfo *class_findfield (classinfo *c, unicode *name, unicode *desc)
1539 {
1540         s4 i;
1541         for (i = 0; i < c->fieldscount; i++) {
1542                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1543                         return &(c->fields[i]);
1544                 }
1545         panic ("Can not find field given in CONSTANT_Fieldref");
1546         return NULL;
1547 }
1548
1549
1550 /************************* Funktion: class_findmethod **************************
1551         
1552         sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
1553         Namen und Typ.
1554         Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
1555
1556 *******************************************************************************/
1557
1558 methodinfo *class_findmethod (classinfo *c, unicode *name, unicode *desc)
1559 {
1560         s4 i;
1561         for (i = 0; i < c->methodscount; i++) {
1562                 if ((c->methods[i].name == name) && ((desc == NULL) ||
1563                                                    (c->methods[i].descriptor == desc)))
1564                         return &(c->methods[i]);
1565                 }
1566         return NULL;
1567 }
1568
1569
1570 /************************* Funktion: class_resolvemethod ***********************
1571         
1572         sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
1573
1574 *******************************************************************************/
1575
1576
1577 methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *desc)
1578 {
1579         while (c) {
1580                 methodinfo *m = class_findmethod (c, name, desc);
1581                 if (m) return m;
1582                 c = c->super;
1583                 }
1584         return NULL;
1585 }
1586         
1587
1588
1589 /************************* Funktion: class_issubclass **************************
1590
1591         "uberpr"uft, ob eine Klasse von einer anderen Klasse abgeleitet ist.            
1592         
1593 *******************************************************************************/
1594
1595 bool class_issubclass (classinfo *sub, classinfo *super)
1596 {
1597         for (;;) {
1598                 if (!sub) return false;
1599                 if (sub==super) return true;
1600                 sub = sub -> super;
1601                 }
1602 }
1603
1604
1605
1606 /****************** Initialisierungsfunktion f"ur eine Klasse ******************
1607
1608         In Java kann jede Klasse ein statische Initialisierungsfunktion haben.
1609         Diese Funktion mu"s aufgerufen werden, BEVOR irgendwelche Methoden der
1610         Klasse aufgerufen werden, oder auf statische Variablen zugegriffen
1611         wird.
1612
1613 *******************************************************************************/
1614
1615 #ifdef USE_THREADS
1616 extern int blockInts;
1617 #endif
1618
1619 void class_init (classinfo *c)
1620 {
1621         methodinfo *m;
1622         java_objectheader *exceptionptr;
1623         s4 i;
1624         int b;
1625
1626         if (!makeinitializations) return;
1627         if (c->initialized) return;
1628         c -> initialized = true;
1629         
1630         if (c->super) class_init (c->super);
1631         for (i=0; i < c->interfacescount; i++) class_init(c->interfaces[i]);
1632
1633         m = class_findmethod (c, 
1634                               unicode_new_char ("<clinit>"), 
1635                               unicode_new_char ("()V"));
1636         if (!m) {
1637                 if (initverbose) {
1638                         sprintf (logtext, "Class ");
1639                         unicode_sprint (logtext+strlen(logtext), c->name);
1640                         sprintf (logtext+strlen(logtext), " has no initializer");       
1641                         dolog ();
1642                         }
1643                 return;
1644                 }
1645                 
1646         if (! (m->flags & ACC_STATIC)) panic ("Class initializer is not static!");
1647         
1648         if (initverbose) {
1649                 sprintf (logtext, "Starting initializer for class: ");
1650                 unicode_sprint (logtext+strlen(logtext), c->name);
1651                 dolog ();
1652         }
1653
1654 #ifdef USE_THREADS
1655         b = blockInts;
1656         blockInts = 0;
1657 #endif
1658
1659         exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
1660
1661 #ifdef USE_THREADS
1662         assert(blockInts == 0);
1663         blockInts = b;
1664 #endif
1665
1666         if (exceptionptr) {     
1667                 printf ("#### Initializer has thrown: ");
1668                 unicode_display (exceptionptr->vftbl->class->name);
1669                 printf ("\n");
1670                 fflush (stdout);
1671                 }
1672
1673         if (initverbose) {
1674                 sprintf (logtext, "Finished initializer for class: ");
1675                 unicode_sprint (logtext+strlen(logtext), c->name);
1676                 dolog ();
1677         }
1678
1679 }
1680
1681
1682
1683
1684 /********* Funktion: class_showconstantpool   (nur f"ur Debug-Zwecke) *********/
1685
1686 void class_showconstantpool (classinfo *c) 
1687 {
1688         u4 i;
1689         voidptr e;
1690
1691         printf ("---- dump of constant pool ----\n");
1692
1693         for (i=0; i<c->cpcount; i++) {
1694                 printf ("#%d:  ", (int) i);
1695                 
1696                 e = c -> cpinfos [i];
1697                 if (e) {
1698                         
1699                         switch (c -> cptags [i]) {
1700                                 case CONSTANT_Class:
1701                                         printf ("Classreference -> ");
1702                                         unicode_display ( ((classinfo*)e) -> name );
1703                                         break;
1704                                 
1705                                 case CONSTANT_Fieldref:
1706                                         printf ("Fieldref -> "); goto displayFMI;
1707                                 case CONSTANT_Methodref:
1708                                         printf ("Methodref -> "); goto displayFMI;
1709                                 case CONSTANT_InterfaceMethodref:
1710                                         printf ("InterfaceMethod -> "); goto displayFMI;
1711                                   displayFMI:
1712                                         {
1713                                         constant_FMIref *fmi = e;
1714                                         unicode_display ( fmi->class->name );
1715                                         printf (".");
1716                                         unicode_display ( fmi->name);
1717                                         printf (" ");
1718                                         unicode_display ( fmi->descriptor );
1719                                     }
1720                                         break;
1721
1722                                 case CONSTANT_String:
1723                                         printf ("String -> ");
1724                                         unicode_display (e);
1725                                         break;
1726                                 case CONSTANT_Integer:
1727                                         printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
1728                                         break;
1729                                 case CONSTANT_Float:
1730                                         printf ("Float -> %f", ((constant_float*)e) -> value);
1731                                         break;
1732                                 case CONSTANT_Double:
1733                                         printf ("Double -> %f", ((constant_double*)e) -> value);
1734                                         break;
1735                                 case CONSTANT_Long:
1736                                         {
1737                                         u8 v = ((constant_long*)e) -> value;
1738 #if U8_AVAILABLE
1739                                         printf ("Long -> %ld", (long int) v);
1740 #else
1741                                         printf ("Long -> HI: %ld, LO: %ld\n", 
1742                                             (long int) v.high, (long int) v.low);
1743 #endif 
1744                                         }
1745                                         break;
1746                                 case CONSTANT_NameAndType:
1747                                         { constant_nameandtype *cnt = e;
1748                                           printf ("NameAndType: ");
1749                                           unicode_display (cnt->name);
1750                                           printf (" ");
1751                                           unicode_display (cnt->descriptor);
1752                                         }
1753                                         break;
1754                                 case CONSTANT_Utf8:
1755                                         printf ("Utf8 -> ");
1756                                         unicode_display (e);
1757                                         break;
1758                                 case CONSTANT_Arraydescriptor:  {
1759                                         printf ("Arraydescriptor: ");
1760                                         displayarraydescriptor (e);
1761                                         }
1762                                         break;
1763                                 default: 
1764                                         panic ("Invalid type of ConstantPool-Entry");
1765                                 }
1766                                 
1767                         }
1768
1769                 printf ("\n");
1770                 }
1771         
1772 }
1773
1774
1775
1776 /********** Funktion: class_showmethods   (nur f"ur Debug-Zwecke) *************/
1777
1778 void class_showmethods (classinfo *c)
1779 {
1780         s4 i;
1781         
1782         printf ("--------- Fields and Methods ----------------\n");
1783         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
1784
1785         printf ("This: "); unicode_display (c->name); printf ("\n");
1786         if (c->super) {
1787                 printf ("Super: "); unicode_display (c->super->name); printf ("\n");
1788                 }
1789         printf ("Index: %d\n", c->index);
1790         
1791         printf ("interfaces:\n");       
1792         for (i=0; i < c-> interfacescount; i++) {
1793                 printf ("   ");
1794                 unicode_display (c -> interfaces[i] -> name);
1795                 printf (" (%d)\n", c->interfaces[i] -> index);
1796                 }
1797
1798         printf ("fields:\n");           
1799         for (i=0; i < c -> fieldscount; i++) {
1800                 field_display (&(c -> fields[i]));
1801                 }
1802
1803         printf ("methods:\n");
1804         for (i=0; i < c -> methodscount; i++) {
1805                 methodinfo *m = &(c->methods[i]);
1806                 if ( !(m->flags & ACC_STATIC)) 
1807                         printf ("vftblindex: %d   ", m->vftblindex);
1808
1809                 method_display ( m );
1810
1811                 }
1812
1813         printf ("Virtual function table:\n");
1814         for (i=0; i<c->vftbl->vftbllength; i++) {
1815                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
1816                 }
1817
1818 }
1819
1820
1821
1822 /******************************************************************************/
1823 /******************* Funktionen fuer den Class-loader generell ****************/
1824 /******************************************************************************/
1825
1826
1827 /********************* Funktion: loader_load ***********************************
1828
1829         l"adt und linkt die ge"unschte Klasse und alle davon 
1830         referenzierten Klassen und Interfaces
1831         Return: Einen Zeiger auf diese Klasse
1832
1833 *******************************************************************************/
1834
1835 classinfo *loader_load (unicode *topname)
1836 {
1837         classinfo *top;
1838         classinfo *c;
1839         long int starttime=0,stoptime=0;
1840         
1841         intsDisable();                           /* schani */
1842
1843         if (getloadingtime) starttime = getcputime();
1844
1845         top = class_get (topname);
1846
1847         while ( (c = list_first(&unloadedclasses)) ) {
1848                 class_load (c);
1849                 }
1850
1851         while ( (c = list_first(&unlinkedclasses)) ) {
1852                 class_link (c);
1853                 }
1854
1855         if (getloadingtime) {
1856                 stoptime = getcputime();
1857                 loadingtime += (stoptime-starttime);
1858                 }
1859
1860         intsRestore();                          /* schani */
1861
1862         return top;
1863 }
1864
1865
1866 /******************* interne Funktion: loader_createarrayclass *****************
1867
1868         Erzeugt (und linkt) eine Klasse f"ur die Arrays.
1869         
1870 *******************************************************************************/
1871
1872 static classinfo *loader_createarrayclass ()
1873 {
1874         classinfo *c;
1875         c = class_get ( unicode_new_char ("The_Array_Class") );
1876         
1877         list_remove (&unloadedclasses, c);
1878         list_addlast (&unlinkedclasses, c);
1879         c -> super = class_java_lang_Object;
1880         
1881         class_link (c);
1882         return c;
1883 }
1884
1885
1886
1887 /********************** Funktion: loader_init **********************************
1888
1889         Initialisiert alle Listen und l"adt alle Klassen, die vom System
1890         und vom Compiler direkt ben"otigt werden.
1891
1892 *******************************************************************************/
1893  
1894 void loader_init ()
1895 {
1896         interfaceindex = 0;
1897         
1898         list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
1899         list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
1900         list_init (&linkedclasses, OFFSET(classinfo, listnode) );
1901
1902
1903         class_java_lang_Object = 
1904                 loader_load ( unicode_new_char ("java/lang/Object") );
1905         class_java_lang_String = 
1906                 loader_load ( unicode_new_char ("java/lang/String") );
1907         class_java_lang_ClassCastException = 
1908                 loader_load ( unicode_new_char ("java/lang/ClassCastException") );
1909         class_java_lang_NullPointerException = 
1910                 loader_load ( unicode_new_char ("java/lang/NullPointerException") );
1911         class_java_lang_ArrayIndexOutOfBoundsException = loader_load ( 
1912              unicode_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
1913         class_java_lang_NegativeArraySizeException = loader_load ( 
1914              unicode_new_char ("java/lang/NegativeArraySizeException") );
1915         class_java_lang_OutOfMemoryError = loader_load ( 
1916              unicode_new_char ("java/lang/OutOfMemoryError") );
1917         class_java_lang_ArrayStoreException =
1918                 loader_load ( unicode_new_char ("java/lang/ArrayStoreException") );
1919         class_java_lang_ArithmeticException = 
1920                 loader_load ( unicode_new_char ("java/lang/ArithmeticException") );
1921         class_java_lang_ThreadDeath =                             /* schani */
1922                 loader_load ( unicode_new_char ("java/lang/ThreadDeath") );
1923
1924         class_array = loader_createarrayclass ();
1925
1926
1927         proto_java_lang_ClassCastException = 
1928                 builtin_new(class_java_lang_ClassCastException);
1929         heap_addreference ( (void**) &proto_java_lang_ClassCastException);
1930
1931         proto_java_lang_NullPointerException = 
1932                 builtin_new(class_java_lang_NullPointerException);
1933         heap_addreference ( (void**) &proto_java_lang_NullPointerException);
1934
1935         proto_java_lang_ArrayIndexOutOfBoundsException = 
1936                 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
1937         heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
1938
1939         proto_java_lang_NegativeArraySizeException = 
1940                 builtin_new(class_java_lang_NegativeArraySizeException);
1941         heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
1942
1943         proto_java_lang_OutOfMemoryError = 
1944                 builtin_new(class_java_lang_OutOfMemoryError);
1945         heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
1946
1947         proto_java_lang_ArithmeticException = 
1948                 builtin_new(class_java_lang_ArithmeticException);
1949         heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
1950
1951         proto_java_lang_ArrayStoreException = 
1952                 builtin_new(class_java_lang_ArrayStoreException);
1953         heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
1954
1955         proto_java_lang_ThreadDeath =                             /* schani */
1956                 builtin_new(class_java_lang_ThreadDeath);
1957         heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
1958 }
1959
1960
1961
1962
1963 /********************* Funktion: loader_initclasses ****************************
1964
1965         initialisiert alle geladenen aber noch nicht initialisierten Klassen
1966
1967 *******************************************************************************/
1968
1969 void loader_initclasses ()
1970 {
1971         classinfo *c;
1972         
1973         intsDisable();                     /* schani */
1974
1975         if (makeinitializations) {
1976                 c = list_first (&linkedclasses);
1977                 while (c) {
1978                         class_init (c);
1979                         c = list_next (&linkedclasses, c);
1980                         }
1981                 }
1982
1983         intsRestore();                      /* schani */
1984 }
1985
1986 static s4 classvalue = 0;
1987
1988 static void loader_compute_class_values (classinfo *c)
1989 {
1990         classinfo *subs;
1991
1992         c->vftbl->baseval = ++classvalue;
1993         subs = c->sub;
1994         while (subs != NULL) {
1995                 loader_compute_class_values(subs);
1996                 subs = subs->nextsub;
1997                 }
1998         c->vftbl->diffval = classvalue - c->vftbl->baseval;
1999 /*
2000         {
2001         int i;
2002         for (i = 0; i < c->index; i++)
2003                 printf(" ");
2004         printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
2005         unicode_display(c->name);
2006         printf("\n");
2007         }
2008 */
2009 }
2010
2011
2012 void loader_compute_subclasses ()
2013 {
2014         classinfo *c;
2015         
2016         intsDisable();                     /* schani */
2017
2018         c = list_first (&linkedclasses);
2019         while (c) {
2020                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2021                         c->nextsub = c->super->sub;
2022                         c->super->sub = c;
2023                         }
2024                 c = list_next (&linkedclasses, c);
2025                 }
2026
2027         loader_compute_class_values(class_java_lang_Object);
2028
2029         intsRestore();                      /* schani */
2030 }
2031
2032
2033
2034 /******************** Funktion: loader_close ***********************************
2035
2036         gibt alle Resourcen wieder frei
2037         
2038 *******************************************************************************/
2039
2040 void loader_close ()
2041 {
2042         classinfo *c;
2043
2044         while ( (c=list_first(&unloadedclasses)) ) {
2045                 list_remove (&unloadedclasses,c);
2046                 class_free (c);
2047                 }
2048         while ( (c=list_first(&unlinkedclasses)) ) {
2049                 list_remove (&unlinkedclasses,c);
2050                 class_free (c);
2051                 }
2052         while ( (c=list_first(&linkedclasses)) ) {
2053                 list_remove (&linkedclasses,c);
2054                 class_free (c);
2055                 }
2056 }
2057
2058
2059 /*
2060  * These are local overrides for various environment variables in Emacs.
2061  * Please do not remove this and leave it at the end of the file, where
2062  * Emacs will automagically detect them.
2063  * ---------------------------------------------------------------------
2064  * Local variables:
2065  * mode: c
2066  * indent-tabs-mode: t
2067  * c-basic-offset: 4
2068  * tab-width: 4
2069  * End:
2070  */