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