Run time type check with relative numbering added. Checkcast and Instanceof
[cacao.git] / 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 -> sub = NULL;
699         c -> nextsub = NULL;
700         c -> interfacescount = 0;
701         c -> interfaces = NULL;
702         c -> fieldscount = 0;
703         c -> fields = NULL;
704         c -> methodscount = 0;
705         c -> methods = NULL;
706         c -> linked = false;
707         c -> index = 0;
708         c -> instancesize = 0;
709         c -> vftbl = NULL;
710         c -> initialized = false;
711         
712         unicode_setclasslink (u,c);
713         list_addlast (&unloadedclasses, c);
714                 
715         return c;
716 }
717
718
719
720 /******************** Funktion: class_getconstant *****************************
721
722         holt aus dem ConstantPool einer Klasse den Wert an der Stelle 'pos'.
723         Der Wert mu"s vom Typ 'ctype' sein, sonst wird das System angehalten.
724
725 ******************************************************************************/
726
727 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype) 
728 {
729         if (pos >= c->cpcount) 
730                 panic ("Attempt to access constant outside range");
731         if (c->cptags[pos] != ctype) {
732                 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
733                  (int) ctype, (int) c->cptags[pos] );
734                 error();
735                 }
736                 
737         return c->cpinfos[pos];
738 }
739
740
741 /********************* Funktion: class_constanttype ***************************
742
743         Findet heraus, welchen Typ ein Eintrag in den ConstantPool einer 
744         Klasse hat.
745         
746 ******************************************************************************/
747
748 u4 class_constanttype (classinfo *c, u4 pos)
749 {
750         if (pos >= c->cpcount) 
751                 panic ("Attempt to access constant outside range");
752         return c->cptags[pos];
753 }
754
755
756 /******************** Funktion: class_loadcpool *******************************
757
758         l"adt den gesammten ConstantPool einer Klasse.
759         
760         Dabei werden die einzelnen Eintr"age in ein wesentlich einfachers 
761         Format gebracht (Klassenreferenzen werden aufgel"ost, ...)
762         F"ur eine genaue "Ubersicht "uber das kompakte Format siehe: 'global.h' 
763
764 ******************************************************************************/
765
766 static void class_loadcpool (classinfo *c)
767 {
768
769         typedef struct forward_class {      /* Diese Strukturen dienen dazu, */
770                 struct forward_class *next;     /* die Infos, die beim ersten */
771                 u2 thisindex;                   /* Durchgang durch den ConstantPool */
772                 u2 name_index;                  /* gelesen werden, aufzunehmen. */
773         } forward_class;                    /* Erst nachdem der ganze Pool */ 
774                                         /* gelesen wurde, k"onnen alle */
775         typedef struct forward_string {     /* Felder kompletiert werden */
776                 struct forward_string *next;    /* (und das auch nur in der richtigen */
777                 u2 thisindex;                   /* Reihenfolge) */
778                 u2 string_index;
779         } forward_string;
780
781         typedef struct forward_nameandtype {
782                 struct forward_nameandtype *next;
783                 u2 thisindex;
784                 u2 name_index;
785                 u2 sig_index;
786         } forward_nameandtype;
787
788         typedef struct forward_fieldmethint {   
789                 struct forward_fieldmethint *next;
790                 u2 thisindex;
791                 u1 tag;
792                 u2 class_index;
793                 u2 nameandtype_index;
794         } forward_fieldmethint;
795
796
797
798         u4 idx;
799         long int dumpsize = dump_size ();
800
801         forward_class *forward_classes = NULL;
802         forward_string *forward_strings = NULL;
803         forward_nameandtype *forward_nameandtypes = NULL;
804         forward_fieldmethint *forward_fieldmethints = NULL;
805
806         u4 cpcount       = c -> cpcount = suck_u2();
807         u1 *cptags       = c -> cptags  = MNEW (u1, cpcount);
808         voidptr *cpinfos = c -> cpinfos =  MNEW (voidptr, cpcount);
809
810 #ifdef STATISTICS
811         count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
812 #endif
813
814         
815         for (idx=0; idx<cpcount; idx++) {
816                 cptags[idx] = CONSTANT_UNUSED;
817                 cpinfos[idx] = NULL;
818                 }
819
820                         
821                 /******* Erster Durchgang *******/
822                 /* Alle Eintr"age, die nicht unmittelbar aufgel"ost werden k"onnen, 
823                    werden einmal `auf Vorrat' in tempor"are Strukturen eingelesen,
824                    und dann am Ende nocheinmal durchgegangen */
825
826         idx = 1;
827         while (idx < cpcount) {
828                 u4 t = suck_u1 ();
829                 switch ( t ) {
830
831                         case CONSTANT_Class: { 
832                                 forward_class *nfc = DNEW(forward_class);
833
834                                 nfc -> next = forward_classes;                                                                                  
835                                 forward_classes = nfc;
836
837                                 nfc -> thisindex = idx;
838                                 nfc -> name_index = suck_u2 ();
839
840                                 idx++;
841                                 break;
842                                 }
843                         
844                         case CONSTANT_Fieldref:
845                         case CONSTANT_Methodref:
846                         case CONSTANT_InterfaceMethodref: {
847                                 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
848                                 
849                                 nff -> next = forward_fieldmethints;
850                                 forward_fieldmethints = nff;
851
852                                 nff -> thisindex = idx;
853                                 nff -> tag = t;
854                                 nff -> class_index = suck_u2 ();
855                                 nff -> nameandtype_index = suck_u2 ();
856
857                                 idx ++;                                         
858                                 break;
859                                 }
860                                 
861                         case CONSTANT_String: {
862                                 forward_string *nfs = DNEW (forward_string);
863                                 
864                                 nfs -> next = forward_strings;
865                                 forward_strings = nfs;
866                                 
867                                 nfs -> thisindex = idx;
868                                 nfs -> string_index = suck_u2 ();
869                                 
870                                 idx ++;
871                                 break;
872                                 }
873
874                         case CONSTANT_NameAndType: {
875                                 forward_nameandtype *nfn = DNEW (forward_nameandtype);
876                                 
877                                 nfn -> next = forward_nameandtypes;
878                                 forward_nameandtypes = nfn;
879                                 
880                                 nfn -> thisindex = idx;
881                                 nfn -> name_index = suck_u2 ();
882                                 nfn -> sig_index = suck_u2 ();
883                                 
884                                 idx ++;
885                                 break;
886                                 }
887
888                         case CONSTANT_Integer: {
889                                 constant_integer *ci = NEW (constant_integer);
890
891 #ifdef STATISTICS
892         count_const_pool_len += sizeof(constant_integer);
893 #endif
894
895                                 ci -> value = suck_s4 ();
896                                 cptags [idx] = CONSTANT_Integer;
897                                 cpinfos [idx] = ci;
898                                 idx ++;
899                                 
900                                 break;
901                                 }
902                                 
903                         case CONSTANT_Float: {
904                                 constant_float *cf = NEW (constant_float);
905
906 #ifdef STATISTICS
907         count_const_pool_len += sizeof(constant_float);
908 #endif
909
910                                 cf -> value = suck_float ();
911                                 cptags [idx] = CONSTANT_Float;
912                                 cpinfos[idx] = cf;
913                                 idx ++;
914                                 break;
915                                 }
916                                 
917                         case CONSTANT_Long: {
918                                 constant_long *cl = NEW(constant_long);
919                                         
920 #ifdef STATISTICS
921         count_const_pool_len += sizeof(constant_long);
922 #endif
923
924                                 cl -> value = suck_s8 ();
925                                 cptags [idx] = CONSTANT_Long;
926                                 cpinfos [idx] = cl;
927                                 idx += 2;
928                                 break;
929                                 }
930                         
931                         case CONSTANT_Double: {
932                                 constant_double *cd = NEW(constant_double);
933                                 
934 #ifdef STATISTICS
935         count_const_pool_len += sizeof(constant_double);
936 #endif
937
938                                 cd -> value = suck_double ();
939                                 cptags [idx] = CONSTANT_Double;
940                                 cpinfos [idx] = cd;
941                                 idx += 2;
942                                 break;
943                                 }
944                                 
945                         case CONSTANT_Utf8: {
946                                 unicode *u;
947
948                                 u = loadUtf8 ();
949
950                                 cptags [idx] = CONSTANT_Utf8;
951                                 cpinfos [idx] = u;
952                                 idx++;
953                                 break;
954                                 }
955                                                                                 
956                         default:
957                                 sprintf (logtext, "Unkown constant type: %d",(int) t);
958                                 error ();
959                 
960                         }  /* end switch */
961                         
962                 } /* end while */
963                 
964
965
966            /* Aufl"osen der noch unfertigen Eintr"age */
967
968         while (forward_classes) {
969                 unicode *name =
970                   class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
971                 
972                 if ( (name->length>0) && (name->text[0]=='[') ) {
973                         checkfielddescriptor (name); 
974
975                         cptags  [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
976                         cpinfos [forward_classes -> thisindex] = 
977                            buildarraydescriptor(name->text, name->length);
978
979                         }
980                 else {          
981                         cptags  [forward_classes -> thisindex] = CONSTANT_Class;
982                         cpinfos [forward_classes -> thisindex] = class_get (name);
983                         }
984                 forward_classes = forward_classes -> next;
985                 
986                 }
987
988         while (forward_strings) {
989                 unicode *text = 
990                   class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
991                         
992                 cptags   [forward_strings -> thisindex] = CONSTANT_String;
993                 cpinfos  [forward_strings -> thisindex] = text;
994                 
995                 forward_strings = forward_strings -> next;
996                 }       
997
998         while (forward_nameandtypes) {
999                 constant_nameandtype *cn = NEW (constant_nameandtype);  
1000
1001 #ifdef STATISTICS
1002                 count_const_pool_len += sizeof(constant_nameandtype);
1003 #endif
1004
1005                 cn -> name = class_getconstant 
1006                    (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1007                 cn -> descriptor = class_getconstant
1008                    (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1009                  
1010                 cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1011                 cpinfos  [forward_nameandtypes -> thisindex] = cn;
1012                 
1013                 forward_nameandtypes = forward_nameandtypes -> next;
1014                 }
1015
1016
1017         while (forward_fieldmethints)  {
1018                 constant_nameandtype *nat;
1019                 constant_FMIref *fmi = NEW (constant_FMIref);
1020
1021 #ifdef STATISTICS
1022                 count_const_pool_len += sizeof(constant_FMIref);
1023 #endif
1024
1025                 nat = class_getconstant
1026                         (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1027
1028                 fmi -> class = class_getconstant 
1029                         (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1030                 fmi -> name = nat -> name;
1031                 fmi -> descriptor = nat -> descriptor;
1032
1033                 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1034                 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1035         
1036                 switch (forward_fieldmethints -> tag) {
1037                 case CONSTANT_Fieldref:  checkfielddescriptor (fmi->descriptor);
1038                                          break;
1039                 case CONSTANT_InterfaceMethodref: 
1040                 case CONSTANT_Methodref: checkmethoddescriptor (fmi->descriptor);
1041                                          break;
1042                 }               
1043         
1044                 forward_fieldmethints = forward_fieldmethints -> next;
1045
1046                 }
1047
1048
1049         dump_release (dumpsize);
1050 }
1051
1052
1053 /********************** Funktion: class_load **********************************
1054
1055         l"adt alle Infos f"ur eine ganze Klasse aus einem ClassFile. Die
1056         'classinfo'-Struktur mu"s bereits angelegt worden sein.
1057         
1058         Die Superklasse und die Interfaces, die diese Klasse implementiert,
1059         m"ussen zu diesem Zeitpunkt noch nicht geladen sein, die 
1060         Verbindung dazu wird sp"ater in der Funktion 'class_link' hergestellt.
1061         
1062         Die gelesene Klasse wird dann aus der Liste 'unloadedclasses' ausgetragen
1063         und in die Liste 'unlinkedclasses' eingh"angt.
1064         
1065 ******************************************************************************/
1066
1067 static void class_load (classinfo *c)
1068 {
1069         u4 i;
1070         u4 mi,ma;
1071
1072
1073         if (loadverbose) {
1074                 sprintf (logtext, "Loading class: ");
1075                 unicode_sprint (logtext+strlen(logtext), c->name );
1076                 dolog();
1077                 }
1078
1079
1080         suck_start (c->name);
1081
1082         if (suck_u4() != MAGIC) panic("Can not find class-file signature");   
1083         mi = suck_u2(); 
1084         ma = suck_u2();
1085         if (ma != MAJOR_VERSION) {
1086                 sprintf (logtext, "Can only support major version %d, but not %d",
1087                                  MAJOR_VERSION, (int) ma);
1088                 error();
1089                 }
1090         if (mi > MINOR_VERSION)  {
1091                 sprintf (logtext, "Minor version %d is not yet supported.", (int) mi);
1092                 error();
1093                 }
1094
1095
1096         class_loadcpool (c);
1097         
1098         c -> flags = suck_u2 ();
1099         suck_u2 ();       /* this */
1100         
1101         if ( (i = suck_u2 () ) ) {
1102                 c -> super = class_getconstant (c, i, CONSTANT_Class);
1103                 }
1104         else {
1105                 c -> super = NULL;
1106                 }
1107                          
1108         c -> interfacescount = suck_u2 ();
1109         c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1110         for (i=0; i < c -> interfacescount; i++) {
1111                 c -> interfaces [i] = 
1112                       class_getconstant (c, suck_u2(), CONSTANT_Class);
1113                 }
1114
1115         c -> fieldscount = suck_u2 ();
1116         c -> fields = MNEW (fieldinfo, c -> fieldscount);
1117         for (i=0; i < c -> fieldscount; i++) {
1118                 field_load (&(c->fields[i]), c);
1119                 }
1120
1121         c -> methodscount = suck_u2 ();
1122         c -> methods = MNEW (methodinfo, c -> methodscount);
1123         for (i=0; i < c -> methodscount; i++) {
1124                 method_load (&(c -> methods [i]), c);
1125                 }
1126
1127 #ifdef STATISTICS
1128         count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1129         count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1130         count_class_infos += sizeof(methodinfo) * c -> methodscount;
1131 #endif
1132
1133
1134         skipattributes ( suck_u2() );
1135
1136
1137         suck_stop ();
1138
1139         list_remove (&unloadedclasses, c);
1140         list_addlast (&unlinkedclasses, c);
1141 }
1142
1143
1144
1145 /************** interne Funktion: class_highestinterface **********************
1146
1147         wird von der Funktion class_link ben"otigt, um festzustellen, wie gro"s
1148         die Interfacetable einer Klasse sein mu"s.
1149
1150 ******************************************************************************/
1151
1152 static s4 class_highestinterface (classinfo *c) 
1153 {
1154         s4 h;
1155         s4 i;
1156         
1157         if ( ! (c->flags & ACC_INTERFACE) ) {
1158                 sprintf (logtext, "Interface-methods count requested for non-interface:  ");
1159         unicode_sprint (logtext+strlen(logtext), c->name);
1160         error();
1161         }
1162     
1163     h = c->index;
1164         for (i=0; i<c->interfacescount; i++) {
1165                 s4 h2 = class_highestinterface (c->interfaces[i]);
1166                 if (h2>h) h=h2;
1167                 }
1168         return h;
1169 }
1170
1171
1172 /**************** Funktion: class_addinterface ********************************
1173
1174         wird von der Funktion class_link ben"otigt, um eine Virtual Function 
1175         Table f"ur ein Interface (und alle weiteren von diesem Interface
1176         implementierten Interfaces) in eine Klasse einzutragen.
1177
1178 ******************************************************************************/ 
1179
1180 static void class_addinterface (classinfo *c, classinfo *ic)
1181 {
1182         u4 i = ic->index;
1183         u4 j,m;
1184         vftbl *vftbl = c->vftbl;
1185         
1186         if (i>=vftbl->interfacetablelength) panic ("Interfacetable-Overflow");
1187         if (vftbl->interfacevftbl[i]) return;
1188
1189         if (ic->methodscount==0) {  /* wenn interface keine Methoden hat, dann 
1190                                        trotzdem eine Tabelle mit L"ange 1 anlegen,
1191                                        wegen Subclass-Tests */
1192                 vftbl -> interfacevftbllength[i] = 1;
1193                 vftbl -> interfacevftbl[i] = MNEW(methodptr, 1);
1194                 vftbl -> interfacevftbl[i][0] = NULL;
1195                 }
1196         else {
1197                 vftbl -> interfacevftbllength[i] = ic -> methodscount;
1198                 vftbl -> interfacevftbl[i] = MNEW(methodptr, ic -> methodscount); 
1199
1200 #ifdef STATISTICS
1201         count_vftbl_len += sizeof(methodptr) * ic -> methodscount;
1202 #endif
1203
1204                 for (j=0; j<ic->methodscount; j++) {
1205                         classinfo *sc = c;
1206                         while (sc) {
1207                                 for (m=0; m<sc->methodscount; m++) {
1208                                         methodinfo *mi = &(sc->methods[m]);
1209                                         if (method_canoverwrite (mi, &(ic->methods[j])) ) {
1210                                                 vftbl->interfacevftbl[i][j] = 
1211                                                          vftbl->table[mi->vftblindex];
1212                                                 goto foundmethod;
1213                                                 }
1214                                         }
1215                                 sc = sc->super;
1216                                 }
1217                          foundmethod: ;
1218                         }
1219                 }
1220                 
1221         for (j=0; j<ic->interfacescount; j++) 
1222                 class_addinterface(c, ic->interfaces[j]);
1223 }
1224
1225
1226 /********************** Funktion: class_link **********************************
1227
1228         versucht, eine Klasse in das System voll zu integrieren (linken). Dazu 
1229         m"ussen sowol die Superklasse, als auch alle implementierten
1230         Interfaces schon gelinkt sein.
1231         Diese Funktion berechnet sowohl die L"ange (in Bytes) einer Instanz 
1232         dieser Klasse, als auch die Virtual Function Tables f"ur normale
1233         Methoden als auch Interface-Methoden.
1234         
1235         Wenn die Klasse erfolgreich gelinkt werden kann, dann wird sie aus
1236         der Liste 'unlinkedclasses' ausgeh"angt, und in die Klasse 'linkedclasses'
1237         eingetragen.
1238         Wenn nicht, dann wird sie ans Ende der Liste 'unlinkedclasses' gestellt.
1239
1240         Achtung: Bei zyklischen Klassendefinitionen ger"at das Programm hier in
1241                  eine Endlosschleife!!  (Da muss ich mir noch was einfallen lassen)
1242
1243 ******************************************************************************/
1244
1245 static void class_link (classinfo *c)
1246 {
1247         u4 supervftbllength;          /* L"ange der VFTBL der Superklasse */
1248         u4 vftbllength;               /* L"ange der VFTBL dieser Klasse */
1249         classinfo *super = c->super;  
1250         classinfo *ic,*c2;            /* Hilfsvariablen */
1251         vftbl *v;
1252         u4 i;                          
1253
1254
1255                 /* schauen, ob alle "ubergeordneten Klassen schon fertig sind, 
1256                    und richtiges Initialisieren der lokalen Variablen */ 
1257
1258         for ( i=0; i<c->interfacescount; i++) {
1259                 ic = c->interfaces[i];
1260                 if ( !ic -> linked) {
1261                         list_remove (&unlinkedclasses,c );
1262                         list_addlast (&unlinkedclasses,c );
1263                         return; 
1264                         }
1265                 }
1266         
1267         if (! super) {
1268                 c -> index = 0;
1269                 c -> instancesize = sizeof (java_objectheader);
1270                 
1271                 vftbllength = supervftbllength = 0;
1272
1273                 c -> finalizer = NULL;
1274                 }
1275         else {
1276                 if ( !super -> linked ) {
1277                         list_remove (&unlinkedclasses,c );
1278                         list_addlast (&unlinkedclasses,c );
1279                         return; 
1280                         }
1281
1282                 if ( c->flags & ACC_INTERFACE)     c -> index = interfaceindex++;
1283                                         else       c -> index = super -> index + 1;
1284                 
1285                 c -> instancesize = super -> instancesize;
1286                 
1287                 vftbllength = supervftbllength = super -> vftbl -> vftbllength;
1288                 
1289                 c -> finalizer = super -> finalizer;
1290                 }
1291
1292
1293         if (linkverbose) {
1294                 sprintf (logtext, "Linking Class: ");
1295                 unicode_sprint (logtext+strlen(logtext), c->name );
1296                 dolog ();
1297                 }
1298
1299                 /* Erstellen der Virtual Function Table */
1300
1301         for (i=0; i < c->methodscount; i++) {
1302                 methodinfo *m = &(c->methods[i]);
1303                         
1304                 if (! (m->flags & ACC_STATIC) ) {
1305                         classinfo *sc = super;
1306                         while (sc) {
1307                                 int j;
1308                                 for (j=0; j < sc->methodscount; j++) {
1309                                         if ( method_canoverwrite (m, &(sc->methods[j])) ) {
1310                                                 m -> vftblindex = sc->methods[j].vftblindex;
1311                                                 goto foundvftblindex;
1312                                                 }
1313                                         }
1314                                 sc = sc->super;
1315                                 }
1316                         m -> vftblindex = (vftbllength++);
1317                   foundvftblindex: ;
1318                         }
1319                 }       
1320         
1321 #ifdef STATISTICS
1322         count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1323 #endif
1324
1325         c -> vftbl = v = (vftbl*) 
1326              mem_alloc (sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1));
1327         v -> class = c;
1328         v -> vftbllength = vftbllength;
1329         v -> interfacetablelength = 0;
1330         
1331         for (i=0; i < supervftbllength; i++) 
1332            v -> table[i] = super -> vftbl -> table[i];
1333         
1334         for (i=0; i < c->methodscount; i++) {
1335                 methodinfo *m = &(c->methods[i]);
1336                 if ( ! (m->flags & ACC_STATIC) ) {
1337                         v -> table[m->vftblindex] = m -> stubroutine;
1338                         }
1339                 }
1340
1341
1342                 /* Berechnen der Instanzengr"o"se und der Offsets der einzelnen 
1343                    Felder */
1344         
1345         for (i=0; i < c->fieldscount; i++) {
1346                 u4 dsize;
1347                 fieldinfo *f = &(c -> fields[i]);
1348                 
1349                 if ( ! (f->flags & ACC_STATIC) ) {
1350                         dsize = desc_typesize (f->descriptor);
1351                         c -> instancesize = ALIGN ( c->instancesize, dsize);
1352                         f -> offset = c -> instancesize;
1353                         c -> instancesize += dsize;
1354                         }
1355
1356                 }
1357
1358         
1359                 /* Berechnen der Virtual Function Tables f"ur alle Interfaces */
1360         
1361         c2 = c;
1362         while (c2) {
1363                 for (i=0; i<c2->interfacescount; i++) {
1364                         s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1365                         if ( h > v->interfacetablelength) v->interfacetablelength = h;
1366                         }
1367                 c2 = c2->super;
1368                 }
1369         v -> interfacevftbllength = MNEW (u4, v->interfacetablelength);
1370         v -> interfacevftbl = MNEW (methodptr *, v->interfacetablelength); 
1371
1372 #ifdef STATISTICS
1373         count_vftbl_len += (4 + sizeof(methodptr*)) * v->interfacetablelength;
1374 #endif
1375
1376         for (i=0; i < v->interfacetablelength; i++) {
1377                 v -> interfacevftbllength[i] = 0;
1378                 v -> interfacevftbl[i] = NULL;
1379                 }
1380         
1381         c2 = c;
1382         while (c2) {
1383                 for (i=0; i<c2->interfacescount; i++) {
1384                         class_addinterface (c, c2->interfaces[i]);
1385                         }
1386                 c2 = c2->super;
1387                 }
1388                 
1389
1390
1391                 /* Die finalizer-Methode suchen und eintragen (wenn vorhanden), 
1392                    aber nur bei Objekten ausser java.lang.Object */
1393
1394         if (super) {
1395                 methodinfo *fi;
1396                 static unicode *finame=NULL,*fidesc=NULL;
1397                 
1398                 if (!finame) finame = unicode_new_char ("finalize");
1399                 if (!fidesc) fidesc = unicode_new_char ("()V");
1400
1401                 fi = class_findmethod (c, finame, fidesc);
1402                 if (fi) {
1403                         if (! (fi->flags & ACC_STATIC) ) {
1404                                 c -> finalizer = fi;
1405                                 }
1406                         }
1407         }
1408         
1409         
1410                 /* Abschlie"sende Aktionen */
1411         
1412         c -> linked = true;     
1413
1414         list_remove (&unlinkedclasses, c);
1415         list_addlast (&linkedclasses, c);
1416 }
1417
1418
1419 /******************* Funktion: class_freepool *********************************
1420
1421         Gibt alle Resourcen, die der ConstantPool einer Klasse ben"otigt,
1422         wieder frei.
1423
1424 ******************************************************************************/
1425
1426 static void class_freecpool (classinfo *c)
1427 {
1428         u4 idx;
1429         u4 tag;
1430         voidptr info;
1431         
1432         for (idx=0; idx < c->cpcount; idx++) {
1433                 tag = c->cptags[idx];
1434                 info = c->cpinfos[idx];
1435                 
1436                 if (info != NULL) {
1437                         switch (tag) {
1438                         case CONSTANT_Fieldref:
1439                         case CONSTANT_Methodref:
1440                         case CONSTANT_InterfaceMethodref:
1441                                 FREE (info, constant_FMIref);
1442                                 break;
1443                         case CONSTANT_Integer:
1444                                 FREE (info, constant_integer);
1445                                 break;
1446                         case CONSTANT_Float:
1447                                 FREE (info, constant_float);
1448                                 break;
1449                         case CONSTANT_Long:
1450                                 FREE (info, constant_long);
1451                                 break;
1452                         case CONSTANT_Double:
1453                                 FREE (info, constant_double);
1454                                 break;
1455                         case CONSTANT_NameAndType:
1456                                 FREE (info, constant_nameandtype);
1457                                 break;
1458                         case CONSTANT_Arraydescriptor:
1459                                 freearraydescriptor (info);
1460                                 break;
1461                         }
1462                         }
1463                 }
1464
1465         MFREE (c -> cptags,  u1, c -> cpcount);
1466         MFREE (c -> cpinfos, voidptr, c -> cpcount);
1467 }
1468
1469
1470 /*********************** Funktion: class_free *********************************
1471
1472         Gibt alle Resourcen, die eine ganze Klasse ben"otigt, frei
1473
1474 ******************************************************************************/
1475
1476 static void class_free (classinfo *c)
1477 {
1478         u4 i;
1479         vftbl *v;
1480                 
1481         unicode_unlinkclass (c->name);
1482         
1483         class_freecpool (c);
1484
1485         MFREE (c->interfaces, classinfo*, c->interfacescount);
1486
1487         for (i=0; i < c->fieldscount; i++) field_free ( &(c->fields[i]) );
1488         MFREE (c->fields, fieldinfo, c->fieldscount);
1489         
1490         for (i=0; i < c->methodscount; i++) method_free ( &(c->methods[i]) );
1491         MFREE (c->methods, methodinfo, c->methodscount);
1492
1493         if ( (v = c->vftbl) ) {
1494                 for (i=0; i<v->interfacetablelength; i++) {
1495                         MFREE (v->interfacevftbl[i], methodptr, v->interfacevftbllength[i]);
1496                         }
1497                 MFREE (v->interfacevftbllength, u4, v->interfacetablelength);
1498                 MFREE (v->interfacevftbl, methodptr*, v->interfacetablelength);
1499
1500                 mem_free (v, sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1));
1501                 }
1502                 
1503         FREE (c, classinfo);
1504 }
1505
1506
1507 /************************* Funktion: class_findfield *************************
1508         
1509         sucht in einer 'classinfo'-Struktur nach einem Feld mit gew"unschtem
1510         Namen und Typ.
1511
1512 *****************************************************************************/
1513
1514 fieldinfo *class_findfield (classinfo *c, unicode *name, unicode *desc)
1515 {
1516         u4 i;
1517         for (i=0; i < c->fieldscount; i++) {
1518                 if ( (c->fields[i].name == name)  &&  (c->fields[i].descriptor == desc) )
1519                         return &(c->fields[i]);
1520                 }
1521         panic ("Can not find field given in CONSTANT_Fieldref");
1522         return NULL;
1523 }
1524
1525
1526 /************************* Funktion: class_findmethod *************************
1527         
1528         sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
1529         Namen und Typ.
1530         Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
1531
1532 *****************************************************************************/
1533
1534 methodinfo *class_findmethod (classinfo *c, unicode *name, unicode *desc)
1535 {
1536         u4 i;
1537         for (i=0; i < c->methodscount; i++) {
1538                 if (     (c->methods[i].name == name)  
1539                           && (    (desc == NULL) 
1540                               ||  (c->methods[i].descriptor == desc) 
1541                              )  
1542                    )
1543                         return &(c->methods[i]);
1544                 }
1545         return NULL;
1546 }
1547
1548
1549 /************************* Funktion: class_resolvemethod *************************
1550         
1551         sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
1552
1553 *****************************************************************************/
1554
1555
1556 methodinfo *class_resolvemethod (classinfo *c, unicode *name, unicode *desc)
1557 {
1558         while (c) {
1559                 methodinfo *m = class_findmethod (c, name, desc);
1560                 if (m) return m;
1561                 c = c->super;
1562                 }
1563         return NULL;
1564 }
1565         
1566
1567
1568 /************************* Funktion: class_issubclass ************************
1569
1570         "uberpr"uft, ob eine Klasse von einer anderen Klasse abgeleitet ist.            
1571         
1572 *****************************************************************************/
1573
1574 bool class_issubclass (classinfo *sub, classinfo *super)
1575 {
1576         for (;;) {
1577                 if (!sub) return false;
1578                 if (sub==super) return true;
1579                 sub = sub -> super;
1580                 }
1581 }
1582
1583
1584
1585 /****************** Initialisierungsfunktion f"ur eine Klasse ****************
1586
1587         In Java kann jede Klasse ein statische Initialisierungsfunktion haben.
1588         Diese Funktion mu"s aufgerufen werden, BEVOR irgendwelche Methoden der
1589         Klasse aufgerufen werden, oder auf statische Variablen zugegriffen
1590         wird.
1591
1592 ******************************************************************************/
1593
1594 #ifdef USE_THREADS
1595 extern int blockInts;
1596 #endif
1597
1598 void class_init (classinfo *c)
1599 {
1600         methodinfo *m;
1601         java_objectheader *exceptionptr;
1602         s4 i;
1603         int b;
1604
1605         if (!makeinitializations) return;
1606         if (c->initialized) return;
1607         c -> initialized = true;
1608         
1609         if (c->super) class_init (c->super);
1610         for (i=0; i < c->interfacescount; i++) class_init(c->interfaces[i]);
1611
1612         m = class_findmethod (c, 
1613                               unicode_new_char ("<clinit>"), 
1614                               unicode_new_char ("()V"));
1615         if (!m) {
1616                 if (initverbose) {
1617                         sprintf (logtext, "Class ");
1618                         unicode_sprint (logtext+strlen(logtext), c->name);
1619                         sprintf (logtext+strlen(logtext), " has no initializer");       
1620                         dolog ();
1621                         }
1622                 return;
1623                 }
1624                 
1625         if (! (m->flags & ACC_STATIC)) panic ("Class initializer is not static!");
1626         
1627         if (initverbose) {
1628                 sprintf (logtext, "Starting initializer for class: ");
1629                 unicode_sprint (logtext+strlen(logtext), c->name);
1630                 dolog ();
1631         }
1632
1633 #ifdef USE_THREADS
1634         b = blockInts;
1635         blockInts = 0;
1636 #endif
1637
1638         exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
1639
1640 #ifdef USE_THREADS
1641         assert(blockInts == 0);
1642         blockInts = b;
1643 #endif
1644
1645         if (exceptionptr) {     
1646                 printf ("#### Initializer has thrown: ");
1647                 unicode_display (exceptionptr->vftbl->class->name);
1648                 printf ("\n");
1649                 fflush (stdout);
1650                 }
1651
1652         if (initverbose) {
1653                 sprintf (logtext, "Finished initializer for class: ");
1654                 unicode_sprint (logtext+strlen(logtext), c->name);
1655                 dolog ();
1656         }
1657
1658 }
1659
1660
1661
1662
1663 /********* Funktion: class_showconstantpool   (nur f"ur Debug-Zwecke) ********/
1664
1665 void class_showconstantpool (classinfo *c) 
1666 {
1667         u4 i;
1668         voidptr e;
1669
1670         printf ("---- dump of constant pool ----\n");
1671
1672         for (i=0; i<c->cpcount; i++) {
1673                 printf ("#%d:  ", (int) i);
1674                 
1675                 e = c -> cpinfos [i];
1676                 if (e) {
1677                         
1678                         switch (c -> cptags [i]) {
1679                                 case CONSTANT_Class:
1680                                         printf ("Classreference -> ");
1681                                         unicode_display ( ((classinfo*)e) -> name );
1682                                         break;
1683                                 
1684                                 case CONSTANT_Fieldref:
1685                                         printf ("Fieldref -> "); goto displayFMI;
1686                                 case CONSTANT_Methodref:
1687                                         printf ("Methodref -> "); goto displayFMI;
1688                                 case CONSTANT_InterfaceMethodref:
1689                                         printf ("InterfaceMethod -> "); goto displayFMI;
1690                                   displayFMI:
1691                                         {
1692                                         constant_FMIref *fmi = e;
1693                                         unicode_display ( fmi->class->name );
1694                                         printf (".");
1695                                         unicode_display ( fmi->name);
1696                                         printf (" ");
1697                                         unicode_display ( fmi->descriptor );
1698                                     }
1699                                         break;
1700
1701                                 case CONSTANT_String:
1702                                         printf ("String -> ");
1703                                         unicode_display (e);
1704                                         break;
1705                                 case CONSTANT_Integer:
1706                                         printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
1707                                         break;
1708                                 case CONSTANT_Float:
1709                                         printf ("Float -> %f", ((constant_float*)e) -> value);
1710                                         break;
1711                                 case CONSTANT_Double:
1712                                         printf ("Double -> %f", ((constant_double*)e) -> value);
1713                                         break;
1714                                 case CONSTANT_Long:
1715                                         {
1716                                         u8 v = ((constant_long*)e) -> value;
1717 #if U8_AVAILABLE
1718                                         printf ("Long -> %ld", (long int) v);
1719 #else
1720                                         printf ("Long -> HI: %ld, LO: %ld\n", 
1721                                             (long int) v.high, (long int) v.low);
1722 #endif 
1723                                         }
1724                                         break;
1725                                 case CONSTANT_NameAndType:
1726                                         { constant_nameandtype *cnt = e;
1727                                           printf ("NameAndType: ");
1728                                           unicode_display (cnt->name);
1729                                           printf (" ");
1730                                           unicode_display (cnt->descriptor);
1731                                         }
1732                                         break;
1733                                 case CONSTANT_Utf8:
1734                                         printf ("Utf8 -> ");
1735                                         unicode_display (e);
1736                                         break;
1737                                 case CONSTANT_Arraydescriptor:  {
1738                                         printf ("Arraydescriptor: ");
1739                                         displayarraydescriptor (e);
1740                                         }
1741                                         break;
1742                                 default: 
1743                                         panic ("Invalid type of ConstantPool-Entry");
1744                                 }
1745                                 
1746                         }
1747
1748                 printf ("\n");
1749                 }
1750         
1751 }
1752
1753
1754
1755 /********** Funktion: class_showmethods   (nur f"ur Debug-Zwecke) ************/
1756
1757 void class_showmethods (classinfo *c)
1758 {
1759         u4 i;
1760         
1761         printf ("--------- Fields and Methods ----------------\n");
1762         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
1763
1764         printf ("This: "); unicode_display (c->name); printf ("\n");
1765         if (c->super) {
1766                 printf ("Super: "); unicode_display (c->super->name); printf ("\n");
1767                 }
1768         printf ("Index: %d\n", c->index);
1769         
1770         printf ("interfaces:\n");       
1771         for (i=0; i < c-> interfacescount; i++) {
1772                 printf ("   ");
1773                 unicode_display (c -> interfaces[i] -> name);
1774                 printf (" (%d)\n", c->interfaces[i] -> index);
1775                 }
1776
1777         printf ("fields:\n");           
1778         for (i=0; i < c -> fieldscount; i++) {
1779                 field_display (&(c -> fields[i]));
1780                 }
1781
1782         printf ("methods:\n");
1783         for (i=0; i < c -> methodscount; i++) {
1784                 methodinfo *m = &(c->methods[i]);
1785                 if ( !(m->flags & ACC_STATIC)) 
1786                         printf ("vftblindex: %d   ", m->vftblindex);
1787
1788                 method_display ( m );
1789
1790                 }
1791
1792         printf ("Virtual function table:\n");
1793         for (i=0; i<c->vftbl->vftbllength; i++) {
1794                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
1795                 }
1796
1797 }
1798
1799
1800
1801 /*****************************************************************************/
1802 /******************* Funktionen fuer den Class-loader generell ***************/
1803 /*****************************************************************************/
1804
1805
1806 /********************* Funktion: loader_load **********************************
1807
1808         l"adt und linkt die ge"unschte Klasse und alle davon 
1809         referenzierten Klassen und Interfaces
1810         Return: Einen Zeiger auf diese Klasse
1811
1812 ******************************************************************************/
1813
1814 classinfo *loader_load (unicode *topname)
1815 {
1816         classinfo *top;
1817         classinfo *c;
1818         long int starttime=0,stoptime=0;
1819         
1820         intsDisable();                           /* schani */
1821
1822         if (getloadingtime) starttime = getcputime();
1823
1824         top = class_get (topname);
1825
1826         while ( (c = list_first(&unloadedclasses)) ) {
1827                 class_load (c);
1828                 }
1829
1830         while ( (c = list_first(&unlinkedclasses)) ) {
1831                 class_link (c);
1832                 }
1833
1834         if (getloadingtime) {
1835                 stoptime = getcputime();
1836                 loadingtime += (stoptime-starttime);
1837                 }
1838
1839         intsRestore();                          /* schani */
1840
1841         return top;
1842 }
1843
1844
1845 /******************* interne Funktion: loader_createarrayclass ****************
1846
1847         Erzeugt (und linkt) eine Klasse f"ur die Arrays.
1848         
1849 ******************************************************************************/
1850
1851 static classinfo *loader_createarrayclass ()
1852 {
1853         classinfo *c;
1854         c = class_get ( unicode_new_char ("The_Array_Class") );
1855         
1856         list_remove (&unloadedclasses, c);
1857         list_addlast (&unlinkedclasses, c);
1858         c -> super = class_java_lang_Object;
1859         
1860         class_link (c);
1861         return c;
1862 }
1863
1864
1865
1866 /********************** Funktion: loader_init *********************************
1867
1868         Initialisiert alle Listen und l"adt alle Klassen, die vom System
1869         und vom Compiler direkt ben"otigt werden.
1870
1871 ******************************************************************************/
1872  
1873 void loader_init ()
1874 {
1875         interfaceindex = 0;
1876         
1877         list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
1878         list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
1879         list_init (&linkedclasses, OFFSET(classinfo, listnode) );
1880
1881
1882         class_java_lang_Object = 
1883                 loader_load ( unicode_new_char ("java/lang/Object") );
1884         class_java_lang_String = 
1885                 loader_load ( unicode_new_char ("java/lang/String") );
1886         class_java_lang_ClassCastException = 
1887                 loader_load ( unicode_new_char ("java/lang/ClassCastException") );
1888         class_java_lang_NullPointerException = 
1889                 loader_load ( unicode_new_char ("java/lang/NullPointerException") );
1890         class_java_lang_ArrayIndexOutOfBoundsException = loader_load ( 
1891              unicode_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
1892         class_java_lang_NegativeArraySizeException = loader_load ( 
1893              unicode_new_char ("java/lang/NegativeArraySizeException") );
1894         class_java_lang_OutOfMemoryError = loader_load ( 
1895              unicode_new_char ("java/lang/OutOfMemoryError") );
1896         class_java_lang_ArrayStoreException =
1897                 loader_load ( unicode_new_char ("java/lang/ArrayStoreException") );
1898         class_java_lang_ArithmeticException = 
1899                 loader_load ( unicode_new_char ("java/lang/ArithmeticException") );
1900         class_java_lang_ThreadDeath =                             /* schani */
1901                 loader_load ( unicode_new_char ("java/lang/ThreadDeath") );
1902
1903         class_array = loader_createarrayclass ();
1904
1905
1906         proto_java_lang_ClassCastException = 
1907                 builtin_new(class_java_lang_ClassCastException);
1908         heap_addreference ( (void**) &proto_java_lang_ClassCastException);
1909
1910         proto_java_lang_NullPointerException = 
1911                 builtin_new(class_java_lang_NullPointerException);
1912         heap_addreference ( (void**) &proto_java_lang_NullPointerException);
1913
1914         proto_java_lang_ArrayIndexOutOfBoundsException = 
1915                 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
1916         heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
1917
1918         proto_java_lang_NegativeArraySizeException = 
1919                 builtin_new(class_java_lang_NegativeArraySizeException);
1920         heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
1921
1922         proto_java_lang_OutOfMemoryError = 
1923                 builtin_new(class_java_lang_OutOfMemoryError);
1924         heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
1925
1926         proto_java_lang_ArithmeticException = 
1927                 builtin_new(class_java_lang_ArithmeticException);
1928         heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
1929
1930         proto_java_lang_ArrayStoreException = 
1931                 builtin_new(class_java_lang_ArrayStoreException);
1932         heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
1933
1934         proto_java_lang_ThreadDeath =                             /* schani */
1935                 builtin_new(class_java_lang_ThreadDeath);
1936         heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
1937 }
1938
1939
1940
1941
1942 /********************* Funktion: loader_initclasses ****************************
1943
1944         initialisiert alle geladenen aber noch nicht initialisierten Klassen
1945
1946 ******************************************************************************/
1947
1948 void loader_initclasses ()
1949 {
1950         classinfo *c;
1951         
1952         intsDisable();                     /* schani */
1953
1954         if (makeinitializations) {
1955                 c = list_first (&linkedclasses);
1956                 while (c) {
1957                         class_init (c);
1958                         c = list_next (&linkedclasses, c);
1959                         }
1960                 }
1961
1962         intsRestore();                      /* schani */
1963 }
1964
1965 static s4 classvalue = 0;
1966
1967 static void loader_compute_class_values (classinfo *c)
1968 {
1969         classinfo *subs;
1970
1971         c->vftbl->lowclassval = classvalue++;
1972         subs = c->sub;
1973         while (subs != NULL) {
1974                 loader_compute_class_values(subs);
1975                 subs = subs->nextsub;
1976                 }
1977         c->vftbl->highclassval = classvalue++;
1978 /*
1979         {
1980         int i;
1981         for (i = 0; i < c->index; i++)
1982                 printf(" ");
1983         printf("%3d  %3d  ", (int) c->vftbl->lowclassval, (int) c->vftbl->highclassval);
1984         unicode_display(c->name);
1985         printf("\n");
1986         }
1987 */
1988 }
1989
1990
1991 void loader_compute_subclasses ()
1992 {
1993         classinfo *c;
1994         
1995         intsDisable();                     /* schani */
1996
1997         c = list_first (&linkedclasses);
1998         while (c) {
1999                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2000                         c->nextsub = c->super->sub;
2001                         c->super->sub = c;
2002                         }
2003                 c = list_next (&linkedclasses, c);
2004                 }
2005
2006         loader_compute_class_values(class_java_lang_Object);
2007
2008         intsRestore();                      /* schani */
2009 }
2010
2011
2012
2013 /******************** Funktion: loader_close **********************************
2014
2015         gibt alle Resourcen wieder frei
2016         
2017 ******************************************************************************/
2018
2019 void loader_close ()
2020 {
2021         classinfo *c;
2022
2023         while ( (c=list_first(&unloadedclasses)) ) {
2024                 list_remove (&unloadedclasses,c);
2025                 class_free (c);
2026                 }
2027         while ( (c=list_first(&unlinkedclasses)) ) {
2028                 list_remove (&unlinkedclasses,c);
2029                 class_free (c);
2030                 }
2031         while ( (c=list_first(&linkedclasses)) ) {
2032                 list_remove (&linkedclasses,c);
2033                 class_free (c);
2034                 }
2035 }
2036