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