jdk1.2 and loader optimisation
[cacao.git] / src / vm / loader.c
1
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 #include "native.h"
23 #include "tables.h"
24 #include "builtin.h"
25 #include "jit.h"
26 #ifdef OLD_COMPILER
27 #include "compiler.h"
28 #endif
29 #include "asmpart.h"
30
31 #include "threads/thread.h"                        /* schani */
32 #include <sys/stat.h>
33
34 /* global variables ***********************************************************/
35
36 extern bool newcompiler;        /* true if new compiler is used               */                
37
38 int count_class_infos = 0;      /* variables for measurements                 */
39 int count_const_pool_len = 0;
40 int count_vftbl_len = 0;
41 int count_all_methods = 0;
42 int count_vmcode_len = 0;
43 int count_extable_len = 0;
44
45 bool loadverbose = false;    /* switches for debug messages                   */
46 bool linkverbose = false;
47 bool initverbose = false;
48
49 bool makeinitializations = true;
50
51 bool getloadingtime  = false;   /* to measure the runtime                     */
52 long int loadingtime = 0;
53
54 static s4 interfaceindex;    /* sequential numbering of interfaces            */ 
55
56 list unloadedclasses; /* list of all referenced but not loaded classes */
57 list unlinkedclasses; /* list of all loaded but not linked classes     */
58 list linkedclasses;   /* list of all completely linked classes         */
59
60
61 /* utf-symbols for pointer comparison of frequently used strings */
62
63 static utf *utf_innerclasses;           /* InnerClasses                    */
64 static utf *utf_constantvalue;          /* ConstantValue                   */
65 static utf *utf_code;                       /* Code                            */
66 static utf *utf_finalize;                   /* finalize                            */
67 static utf *utf_fidesc;                     /* ()V                                     */
68 static utf *utf_clinit;                     /* <clinit>                            */
69 static utf *utf_initsystemclass;        /* initializeSystemClass   */
70 static utf *utf_systemclass;            /* java/lang/System        */
71
72 /* important system classes ***************************************************/
73
74 classinfo *class_java_lang_Object;
75 classinfo *class_java_lang_String;
76 classinfo *class_java_lang_ClassCastException;
77 classinfo *class_java_lang_NullPointerException;
78 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
79 classinfo *class_java_lang_NegativeArraySizeException;
80 classinfo *class_java_lang_OutOfMemoryError;
81 classinfo *class_java_lang_ArithmeticException;
82 classinfo *class_java_lang_ArrayStoreException;
83 classinfo *class_java_lang_ThreadDeath;                 /* schani */
84 classinfo *class_array = NULL;
85
86 /******************************************************************************
87
88    structure for primitive classes: contains the class for wrapping the 
89    primitive type, the primitive class, the name of the class for wrapping, 
90    the one character type signature and the name of the primitive class
91  
92  ******************************************************************************/
93  
94 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { 
95                 { NULL, NULL, "java/lang/Double",    'D', "double"  },
96                 { NULL, NULL, "java/lang/Float",     'F', "float"   },
97                 { NULL, NULL, "java/lang/Character", 'C', "char"    },
98                 { NULL, NULL, "java/lang/Integer",   'I', "int"     },
99                 { NULL, NULL, "java/lang/Long",      'J', "long"    },
100                 { NULL, NULL, "java/lang/Byte",      'B', "byte"    },
101                 { NULL, NULL, "java/lang/Short",     'S', "short"   },
102                 { NULL, NULL, "java/lang/Boolean",   'Z', "boolean" },
103                 { NULL, NULL, "java/lang/Void",      'V', "void"    }};
104
105 /* instances of important system classes **************************************/
106
107 java_objectheader *proto_java_lang_ClassCastException;
108 java_objectheader *proto_java_lang_NullPointerException;
109 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
110 java_objectheader *proto_java_lang_NegativeArraySizeException;
111 java_objectheader *proto_java_lang_OutOfMemoryError;
112 java_objectheader *proto_java_lang_ArithmeticException;
113 java_objectheader *proto_java_lang_ArrayStoreException;
114 java_objectheader *proto_java_lang_ThreadDeath;         /* schani */
115
116
117 /************* functions for reading classdata ********************************
118
119     getting classdata in blocks of variable size
120     (8,16,32,64-bit integer or float)
121
122 *******************************************************************************/
123
124 static char *classpath    = "";     /* searchpath for classfiles              */
125 static u1 *classbuffer    = NULL;   /* pointer to buffer with classfile-data  */
126 static u1 *classbuf_pos;            /* current position in classfile buffer   */
127 static int classbuffer_size;        /* size of classfile-data                 */
128
129 /* transfer block of classfile data into a buffer */
130 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len);classbuf_pos+=len;
131
132 /* skip block of classfile data */
133 #define skip_nbytes(len) classbuf_pos += len;
134
135 #define suck_u1() (*++classbuf_pos)
136 #define suck_s8() (s8) suck_u8()
137 #define suck_s2() (s2) suck_u2()
138 #define suck_s4() (s4) suck_u4()
139 #define suck_s1() (s1) suck_u1()
140 #define suck_u2() (u2) ((suck_u1()<<8)+suck_u1())
141 #define suck_u4() (u4) ((((u4)suck_u1())<<24)+(((u4)suck_u1())<<16)+(((u4)suck_u1())<<8)+((u4)suck_u1()))
142
143 /* get u8 from classfile data */
144 static u8 suck_u8 ()
145 {
146 #if U8_AVAILABLE
147         u8 lo,hi;
148         hi = suck_u4();
149         lo = suck_u4();
150         return (hi<<32) + lo;
151 #else
152         u8 v;
153         v.high = suck_u4();
154         v.low = suck_u4();
155         return v;
156 #endif
157 }
158
159 /* get float from classfile data */
160 static float suck_float ()
161 {
162         float f;
163
164 #if !WORDS_BIGENDIAN 
165                 u1 buffer[4];
166                 u2 i;
167                 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
168                 memcpy ( (u1*) (&f), buffer, 4);
169 #else 
170                 suck_nbytes ( (u1*) (&f), 4 );
171 #endif
172
173         PANICIF (sizeof(float) != 4, "Incompatible float-format");
174         
175         return f;
176 }
177
178 /* get double from classfile data */
179 static double suck_double ()
180 {
181         double d;
182
183 #if !WORDS_BIGENDIAN 
184                 u1 buffer[8];
185                 u2 i;   
186                 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
187                 memcpy ( (u1*) (&d), buffer, 8);
188 #else 
189                 suck_nbytes ( (u1*) (&d), 8 );
190 #endif
191
192         PANICIF (sizeof(double) != 8, "Incompatible double-format" );
193         
194         return d;
195 }
196
197 /************************** function: suck_init ******************************
198
199         called once at startup, sets the searchpath for the classfiles
200
201 ******************************************************************************/
202
203 void suck_init (char *cpath)
204 {
205         classpath   = cpath;
206         classbuffer = NULL;
207 }
208
209
210 /************************** function: suck_start ******************************
211
212         open file for the specified class and the read classfile data,
213         all directory of the searchpath are used to find the classfile
214         ( <classname>.class)
215         
216 ******************************************************************************/
217
218
219 bool suck_start (utf *classname)
220 {
221 #define MAXFILENAME 1000               /* maximum length of a filename */
222         
223         char filename[MAXFILENAME+10]; /* room for '.class' */  
224         char *pathpos;                 /* position in searchpath */
225         FILE *classfile;
226         u2 filenamelen;
227         u2 c;
228
229         if (classbuffer)               /* classbuffer already valid */
230                 return true;
231
232         pathpos = classpath;
233         
234         while (*pathpos) {
235                 /* pointer to the next utf8-character */
236                 char *utf_ptr = classname->text; 
237
238                 /* skip path separator */
239                 while ( *pathpos == ':' ) pathpos++;
240  
241                 /* extract directory from searchpath */
242                 filenamelen=0;
243                 while ( (*pathpos) && (*pathpos!=':') ) {
244                     PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
245                         
246                         filename[filenamelen++] = *(pathpos++);
247                         }
248
249                 filename[filenamelen++] = '/';  
250    
251                 /* add classname to filename */
252                 while (utf_ptr<utf_end(classname)) {
253                         PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
254                         
255                         c = *utf_ptr++;
256                         if (c=='/') c = '/';     
257                         else {
258                                 if ( c<=' ' || c>'z') { 
259                                         /* invalid character */
260                                         c = '?'; 
261                                         }
262                                 }
263                         
264                         filename[filenamelen++] = c;    
265                         }
266       
267                 /* add suffix */
268                 strcpy (filename+filenamelen, ".class");
269
270                 classfile = fopen(filename, "r");
271                 if (classfile) {
272                         /* file exists */
273                         struct stat buffer;
274                         int err;
275         
276                         /* determine size of classfile */
277                         err = stat (filename, &buffer);
278
279                         if (!err) {
280                                 /* read classfile data */                               
281                                 classbuffer_size = buffer.st_size;                              
282                                 classbuffer      = MNEW(u1,classbuffer_size);
283                                 classbuf_pos     = classbuffer-1;
284                                 fread(classbuffer, 1, classbuffer_size, classfile);
285                                 fclose(classfile);
286                                 return true;
287                         }
288                 }
289         }
290
291         sprintf (logtext,"Can not open class file '%s'", filename);
292         error();
293
294         return false;
295 }
296
297
298 /************************** function: suck_stop *******************************
299
300         free memory for buffer with classfile data
301         
302 ******************************************************************************/
303
304 void suck_stop ()
305 {
306         /* determine number of bytes of classdata not retrieved by suck-operations */
307         int classdata_left = (classbuffer+classbuffer_size)-classbuf_pos-1;
308
309         if (classdata_left>0) {         
310                         /* surplus */           
311                         sprintf (logtext,"There are %d access bytes at end of classfile",
312                                  classdata_left);
313                         dolog();
314         }
315
316         /* free memory */
317         MFREE(classbuffer,u1,classbuffer_size);
318         classbuffer = NULL;
319 }
320
321 /******************************************************************************/
322 /******************* Einige Support-Funkionen *********************************/
323 /******************************************************************************/
324
325
326 /********** interne Funktion: printflags  (nur zu Debug-Zwecken) **************/
327
328 static void printflags (u2 f)
329 {
330    if ( f & ACC_PUBLIC )       printf (" PUBLIC");
331    if ( f & ACC_PRIVATE )      printf (" PRIVATE");
332    if ( f & ACC_PROTECTED )    printf (" PROTECTED");
333    if ( f & ACC_STATIC )       printf (" STATIC");
334    if ( f & ACC_FINAL )        printf (" FINAL");
335    if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
336    if ( f & ACC_VOLATILE )     printf (" VOLATILE");
337    if ( f & ACC_TRANSIENT )    printf (" TRANSIENT");
338    if ( f & ACC_NATIVE )       printf (" NATIVE");
339    if ( f & ACC_INTERFACE )    printf (" INTERFACE");
340    if ( f & ACC_ABSTRACT )     printf (" ABSTRACT");
341 }
342
343
344 /************************* Funktion: skipattribute *****************************
345
346         "uberliest im ClassFile eine (1) 'attribute'-Struktur 
347
348 *******************************************************************************/
349
350 static void skipattribute ()
351 {
352         suck_u2 ();
353         skip_nbytes(suck_u4()); 
354 }
355
356 /********************** Funktion: skipattributebody ****************************
357
358         "uberliest im Classfile ein attribut, wobei die 16-bit - attribute_name - 
359         Referenz schon gelesen worden ist.
360         
361 *******************************************************************************/
362
363 static void skipattributebody ()
364 {
365         skip_nbytes(suck_u4());
366 }
367
368 /************************* Funktion: skipattributes ****************************
369
370         "uberliest im ClassFile eine gew"unschte Anzahl von attribute-Strukturen
371         
372 *******************************************************************************/
373
374 static void skipattributes (u4 num)
375 {
376         u4 i;
377         for (i = 0; i < num; i++)
378                 skipattribute();
379 }
380
381 /******************** function: innerclass_getconstant ************************
382
383     like class_getconstant, but if cptags is ZERO null is returned                                       
384         
385 *******************************************************************************/
386
387 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype) 
388 {
389         /* invalid position in constantpool */
390         if (pos >= c->cpcount) 
391                 panic ("Attempt to access constant outside range");
392
393         /* constantpool entry of type 0 */      
394         if (!c->cptags[pos])
395                 return NULL;
396
397         /* check type of constantpool entry */
398         if (c->cptags[pos] != ctype) {
399                 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
400                  (int) ctype, (int) c->cptags[pos] );
401                 error();
402                 }
403                 
404         return c->cpinfos[pos];
405 }
406
407 /************************ function: attribute_load ****************************
408
409     read attributes from classfile
410         
411 *******************************************************************************/
412
413 static void attribute_load (u4 num, classinfo *c)
414 {
415         u4 i,j;
416
417         for (i = 0; i < num; i++) {
418                 /* retrieve attribute name */   
419                 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
420
421                 if ( aname == utf_innerclasses)  {                      
422                         /* innerclasses attribute */
423                                 
424                         /* skip attribute length */                                             
425                         suck_u4(); 
426                         /* number of records */
427                         c->innerclasscount = suck_u2();
428                         /* allocate memory for innerclass structure */
429                         c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
430
431                         for (j=0;j<c->innerclasscount;j++) {
432                                 
433                                 /*  The innerclass structure contains a class with an encoded name, 
434                                     its defining scope, its simple name  and a bitmask of the access flags. 
435                                     If an inner class is not a member, its outer_class is NULL, 
436                                     if a class is anonymous, its name is NULL.                              */
437                                                                 
438                                 innerclassinfo *info = c->innerclass + j;
439
440                                 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
441                                 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
442                                 info->name  = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8);        /* CONSTANT_Utf8_info index  */
443                                 info->flags = suck_u2 ();                                                 /* access_flags bitmask      */
444                         }
445                 } else {
446                         /* unknown attribute */
447                         skipattributebody ();
448                 }
449         }
450 }
451
452 /******************* function: checkfielddescriptor ****************************
453
454         checks whether a field-descriptor is valid and aborts otherwise
455         all referenced classes are inserted into the list of unloaded classes
456         
457 *******************************************************************************/
458
459 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
460 {
461         char *tstart;  /* pointer to start of classname */
462         char ch;
463         
464         switch (*utf_ptr++) {
465         case 'B':
466         case 'C':
467         case 'I':
468         case 'S':
469         case 'Z':  
470         case 'J':  
471         case 'F':  
472         case 'D':
473                 /* primitive type */  
474                 break;
475
476         case 'L':
477                 /* save start of classname */
478                 tstart = utf_ptr;  
479                 
480                 /* determine length of classname */
481                 while ( *utf_ptr++ != ';' )
482                         if (utf_ptr>=end_pos) 
483                                 panic ("Missing ';' in objecttype-descriptor");
484
485                 /* cause loading of referenced class */                 
486                 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
487                 break;
488
489         case '[' : 
490                 /* array type */
491                 while ((ch = *utf_ptr++)=='[') 
492                         /* skip */ ;
493
494                 /* component type of array */
495                 switch (ch) {
496                 case 'B':
497                 case 'C':
498                 case 'I':
499                 case 'S':
500                 case 'Z':  
501                 case 'J':  
502                 case 'F':  
503                 case 'D':
504                         /* primitive type */  
505                         break;
506                         
507                 case 'L':
508                         /* save start of classname */
509                         tstart = utf_ptr;
510                         
511                         /* determine length of classname */
512                         while ( *utf_ptr++ != ';' )
513                                 if (utf_ptr>=end_pos) 
514                                         panic ("Missing ';' in objecttype-descriptor");
515
516                         /* cause loading of referenced class */                 
517                         class_new ( utf_new(tstart, utf_ptr-tstart-1) );
518                         break;
519
520                 default:   
521                         panic ("Ill formed methodtype-descriptor");
522                 }
523                 break;
524                         
525         default:   
526                 panic ("Ill formed methodtype-descriptor");
527         }                       
528
529         /* exceeding characters */              
530         if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
531 }
532
533
534 /******************* function: checkmethoddescriptor ***************************
535
536     checks whether a method-descriptor is valid and aborts otherwise
537     all referenced classes are inserted into the list of unloaded classes       
538         
539 *******************************************************************************/
540
541 static void checkmethoddescriptor (utf *d)
542 {
543         char *utf_ptr = d->text;     /* current position in utf text   */
544         char *end_pos = utf_end(d);  /* points behind utf string       */
545         char *tstart;                /* pointer to start of classname  */
546         char c,ch;
547
548         /* method descriptor must start with parenthesis */
549         if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
550
551         /* check arguments */
552         while ((c = *utf_ptr++) != ')') {
553                 switch (c) {
554                 case 'B':
555                 case 'C':
556                 case 'I':
557                 case 'S':
558                 case 'Z':  
559                 case 'J':  
560                 case 'F':  
561                 case 'D':
562                         /* primitive type */  
563                         break;
564
565                 case 'L':
566                         /* save start of classname */ 
567                         tstart = utf_ptr;
568                         
569                         /* determine length of classname */
570                         while ( *utf_ptr++ != ';' )
571                                 if (utf_ptr>=end_pos) 
572                                         panic ("Missing ';' in objecttype-descriptor");
573                         
574                         /* cause loading of referenced class */
575                         class_new ( utf_new(tstart, utf_ptr-tstart-1) );
576                         break;
577            
578                 case '[' :
579                         /* array type */ 
580                         while ((ch = *utf_ptr++)=='[') 
581                                 /* skip */ ;
582
583                         /* component type of array */
584                         switch (ch) {
585                         case 'B':
586                         case 'C':
587                         case 'I':
588                         case 'S':
589                         case 'Z':  
590                         case 'J':  
591                         case 'F':  
592                         case 'D':
593                                 /* primitive type */  
594                                 break;
595
596                         case 'L':
597                                 /* save start of classname */
598                                 tstart = utf_ptr;
599                         
600                                 /* determine length of classname */     
601                                 while ( *utf_ptr++ != ';' )
602                                         if (utf_ptr>=end_pos) 
603                                                 panic ("Missing ';' in objecttype-descriptor");
604
605                                 /* cause loading of referenced class */
606                                 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
607                                 break;
608
609                         default:   
610                                 panic ("Ill formed methodtype-descriptor");
611                         } 
612                         break;
613                         
614                 default:   
615                         panic ("Ill formed methodtype-descriptor");
616                 }                       
617         }
618
619         /* check returntype */
620         if (*utf_ptr=='V') {
621                 /* returntype void */
622                 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
623         }
624         else
625                 /* treat as field-descriptor */
626                 checkfielddescriptor (utf_ptr,end_pos);
627 }
628
629
630 /******************** Funktion: buildarraydescriptor ***************************
631
632         erzeugt zu einem namentlich als utf-String vorliegenden Arraytyp eine
633         entsprechende constant_arraydescriptor - Struktur 
634         
635 *******************************************************************************/
636
637 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
638 {
639         constant_arraydescriptor *d;
640         
641         if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
642
643         d = NEW (constant_arraydescriptor);
644         d -> objectclass = NULL;
645         d -> elementdescriptor = NULL;
646
647 #ifdef STATISTICS
648         count_const_pool_len += sizeof(constant_arraydescriptor);
649 #endif
650
651         switch (*utf_ptr) {
652         case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
653         case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
654         case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
655         case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
656         case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
657         case 'I': d -> arraytype = ARRAYTYPE_INT; break;
658         case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
659         case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
660
661         case '[':
662                 d -> arraytype = ARRAYTYPE_ARRAY; 
663                 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
664                 break;
665                 
666         case 'L':
667                 d -> arraytype = ARRAYTYPE_OBJECT;
668                 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
669                 break;
670         }
671         return d;
672 }
673
674
675 /******************* Funktion: freearraydescriptor *****************************
676
677         entfernt eine mit buildarraydescriptor erzeugte Struktur wieder 
678         aus dem Speicher
679         
680 *******************************************************************************/
681
682 static void freearraydescriptor (constant_arraydescriptor *d)
683 {
684         while (d) {
685                 constant_arraydescriptor *n = d->elementdescriptor;
686                 FREE (d, constant_arraydescriptor);
687                 d = n;
688                 }
689 }
690
691 /*********************** Funktion: displayarraydescriptor *********************/
692
693 static void displayarraydescriptor (constant_arraydescriptor *d)
694 {
695         switch (d->arraytype) {
696         case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
697         case ARRAYTYPE_BYTE: printf ("byte[]"); break;
698         case ARRAYTYPE_CHAR: printf ("char[]"); break;
699         case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
700         case ARRAYTYPE_FLOAT: printf ("float[]"); break;
701         case ARRAYTYPE_INT: printf ("int[]"); break;
702         case ARRAYTYPE_LONG: printf ("long[]"); break;
703         case ARRAYTYPE_SHORT: printf ("short[]"); break;
704         case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
705         case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
706         }
707 }
708
709
710
711 /******************************************************************************/
712 /******************** Funktionen fuer Fields **********************************/
713 /******************************************************************************/
714
715
716 /************************ Funktion: field_load *********************************
717
718         l"adt alle Informationen f"ur eine Feld einer Methode aus dem ClassFile,
719         und f"ullt mit diesen Infos eine schon existierende 'fieldinfo'-Struktur.
720         Bei 'static'-Fields wird auch noch ein Platz auf dem Datensegment
721         reserviert.
722
723 *******************************************************************************/
724
725 static void field_load (fieldinfo *f, classinfo *c)
726 {
727         u4 attrnum,i;
728         u4 jtype;
729
730         f -> flags = suck_u2 ();                                           /* ACC flags                   */
731         f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);       /* name of field               */
732         f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor           */
733         f -> type = jtype = desc_to_type (f->descriptor);                  /* data type                   */
734         f -> offset = 0;                                                   /* offset from start of object */
735         
736         switch (f->type) {
737         case TYPE_INT:        f->value.i = 0; break;
738         case TYPE_FLOAT:      f->value.f = 0.0; break;
739         case TYPE_DOUBLE:     f->value.d = 0.0; break;
740         case TYPE_ADDRESS:    f->value.a = NULL;                              
741                               heap_addreference (&(f->value.a));           /* make global reference (GC)  */    
742                               break;
743         case TYPE_LONG:
744 #if U8_AVAILABLE
745                 f->value.l = 0; break;
746 #else
747                 f->value.l.low = 0; f->value.l.high = 0; break;
748 #endif 
749         }
750
751         /* read attributes */
752         attrnum = suck_u2();
753         for (i=0; i<attrnum; i++) {
754                 u4 pindex;
755                 utf *aname;
756
757                 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
758                 
759                 if ( aname != utf_constantvalue ) {
760                         /* unknown attribute */
761                         skipattributebody ();
762                         }
763                 else {
764                         /* constant value attribute */
765                         
766                         /* skip attribute length */
767                         suck_u4();
768                         /* index of value in constantpool */            
769                         pindex = suck_u2();
770                 
771                         /* initialize field with value from constantpool */             
772                         switch (jtype) {
773                                 case TYPE_INT: {
774                                         constant_integer *ci = 
775                                                 class_getconstant(c, pindex, CONSTANT_Integer);
776                                         f->value.i = ci -> value;
777                                         }
778                                         break;
779                                         
780                                 case TYPE_LONG: {
781                                         constant_long *cl = 
782                                            class_getconstant(c, pindex, CONSTANT_Long);
783         
784                                         f->value.l = cl -> value;
785                                         }
786                                         break;
787
788                                 case TYPE_FLOAT: {
789                                         constant_float *cf = 
790                                             class_getconstant(c, pindex, CONSTANT_Float);
791         
792                                         f->value.f = cf->value;
793                                         }
794                                         break;
795                                                                                         
796                                 case TYPE_DOUBLE: {
797                                         constant_double *cd = 
798                                             class_getconstant(c, pindex, CONSTANT_Double);
799         
800                                         f->value.d = cd->value;
801                                         }
802                                         break;
803                                                 
804                                 case TYPE_ADDRESS: { 
805                                         utf *u = class_getconstant(c, pindex, CONSTANT_String);
806                                         /* create javastring from compressed utf8-string */                                     
807                                         f->value.a = literalstring_new(u);
808                                         }
809                                         break;
810         
811                                 default: 
812                                         log_text ("Invalid Constant - Type");
813
814                                 }
815
816                         }
817                 }
818 }
819
820
821 /********************** function: field_free **********************************/
822
823 static void field_free (fieldinfo *f)
824 {
825         /* empty */
826 }
827
828
829 /************** Funktion: field_display (nur zu Debug-Zwecken) ****************/
830
831 static void field_display (fieldinfo *f)
832 {
833         printf ("   ");
834         printflags (f -> flags);
835         printf (" ");
836         utf_display (f -> name);
837         printf (" ");
838         utf_display (f -> descriptor);  
839         printf (" offset: %ld\n", (long int) (f -> offset) );
840 }
841
842
843 /******************************************************************************/
844 /************************* Funktionen f"ur Methods ****************************/ 
845 /******************************************************************************/
846
847
848 /*********************** Funktion: method_load *********************************
849
850         l"adt die Infos f"ur eine Methode aus dem ClassFile und f"ullt damit 
851         eine schon existierende 'methodinfo'-Struktur aus.
852         Bei allen native-Methoden wird au"serdem gleich der richtige 
853         Funktionszeiger eingetragen, bei JavaVM-Methoden einstweilen ein
854         Zeiger auf den Compiler 
855         
856 *******************************************************************************/
857
858 static void method_load (methodinfo *m, classinfo *c)
859 {
860         u4 attrnum,i,e;
861         
862 #ifdef STATISTICS
863         count_all_methods++;
864 #endif
865
866         m -> class = c;
867         
868         m -> flags = suck_u2 ();
869         m -> name =  class_getconstant (c, suck_u2(), CONSTANT_Utf8);
870         m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
871         
872         m -> jcode = NULL;
873         m -> exceptiontable = NULL;
874         m -> entrypoint = NULL;
875         m -> mcode = NULL;
876         m -> stubroutine = NULL;
877         
878         if (! (m->flags & ACC_NATIVE) ) {
879                 m -> stubroutine = createcompilerstub (m);
880                 }
881         else {
882
883                 functionptr f = native_findfunction 
884                        (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
885                 if (f) {
886 #ifdef OLD_COMPILER
887                 if (newcompiler)
888 #endif
889                         m -> stubroutine = createnativestub (f, m);
890 #ifdef OLD_COMPILER
891                 else
892                         m -> stubroutine = oldcreatenativestub (f, m);
893 #endif
894                         }
895                 }
896         
897         
898         attrnum = suck_u2();
899         for (i=0; i<attrnum; i++) {
900                 utf *aname;
901
902                 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
903
904                 if ( aname != utf_code)  {
905                         skipattributebody ();
906                         }
907                 else {
908                         if (m -> jcode) panic ("Two code-attributes for one method!");
909                         
910                         suck_u4();
911                         m -> maxstack = suck_u2();
912                         m -> maxlocals = suck_u2();
913                         m -> jcodelength = suck_u4();
914                         m -> jcode = MNEW (u1, m->jcodelength);
915                         suck_nbytes (m->jcode, m->jcodelength);
916                         m -> exceptiontablelength = suck_u2 ();
917                         m -> exceptiontable = 
918                            MNEW (exceptiontable, m->exceptiontablelength);
919
920 #ifdef STATISTICS
921         count_vmcode_len += m->jcodelength + 18;
922         count_extable_len += 8 * m->exceptiontablelength;
923 #endif
924
925                         for (e=0; e < m->exceptiontablelength; e++) {
926                                 u4 idx;
927                                 m -> exceptiontable[e].startpc = suck_u2();
928                                 m -> exceptiontable[e].endpc = suck_u2();
929                                 m -> exceptiontable[e].handlerpc = suck_u2();
930
931                                 idx = suck_u2();
932                                 if (!idx) m -> exceptiontable[e].catchtype = NULL;
933                                 else {
934                                         m -> exceptiontable[e].catchtype = 
935                                       class_getconstant (c, idx, CONSTANT_Class);
936                                         }
937                                 }                       
938
939                         skipattributes ( suck_u2() );
940                         }
941                         
942                 }
943
944 }
945
946 /********************* Funktion: method_free ***********************************
947
948         gibt allen Speicher, der extra f"ur eine Methode angefordert wurde,
949         wieder frei
950
951 *******************************************************************************/
952
953 static void method_free (methodinfo *m)
954 {
955         if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
956         if (m->exceptiontable) 
957                 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
958         if (m->mcode) CFREE (m->mcode, m->mcodelength);
959         if (m->stubroutine) {
960                 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
961                 else                       removecompilerstub (m->stubroutine);
962                 }
963 }
964
965
966 /************** Funktion: method_display  (nur zu Debug-Zwecken) **************/
967
968 void method_display (methodinfo *m)
969 {
970         printf ("   ");
971         printflags (m -> flags);
972         printf (" ");
973         utf_display (m -> name);
974         printf (" "); 
975         utf_display (m -> descriptor);
976         printf ("\n");
977 }
978
979
980 /******************** Funktion: method_canoverwrite ****************************
981
982         "uberpr"ft, ob eine Methode mit einer anderen typ- und namensidentisch 
983         ist (also mit einer Methodendefinition eine andere "uberschrieben 
984         werden kann).
985         
986 *******************************************************************************/  
987
988 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
989 {
990         if (m->name != old->name) return false;
991         if (m->descriptor != old->descriptor) return false;
992         if (m->flags & ACC_STATIC) return false;
993         return true;
994 }
995
996
997
998
999 /******************************************************************************/
1000 /************************ Funktionen fuer Class *******************************/
1001 /******************************************************************************/
1002
1003
1004 /******************** function: class_getconstant ******************************
1005
1006         retrieves the value at position 'pos' of the constantpool of a class
1007         if the type of the value is other than 'ctype' the system is stopped
1008
1009 *******************************************************************************/
1010
1011 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype) 
1012 {
1013         /* invalid position in constantpool */  
1014         if (pos >= c->cpcount) 
1015                 panic ("Attempt to access constant outside range");
1016
1017         /* check type of constantpool entry */
1018         if (c->cptags[pos] != ctype) {
1019                 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1020                  (int) ctype, (int) c->cptags[pos] );
1021                 error();
1022                 }
1023                 
1024         return c->cpinfos[pos];
1025 }
1026
1027
1028 /********************* Funktion: class_constanttype ****************************
1029
1030         Findet heraus, welchen Typ ein Eintrag in den ConstantPool einer 
1031         Klasse hat.
1032         
1033 *******************************************************************************/
1034
1035 u4 class_constanttype (classinfo *c, u4 pos)
1036 {
1037         if (pos >= c->cpcount) 
1038                 panic ("Attempt to access constant outside range");
1039         return c->cptags[pos];
1040 }
1041
1042
1043 /******************** function: class_loadcpool ********************************
1044
1045         loads the constantpool of a class, 
1046         the entries are transformed into a simpler format 
1047         by resolving references
1048         (a detailed overview of the compact structures can be found in global.h)        
1049
1050 *******************************************************************************/
1051
1052 static void class_loadcpool (classinfo *c)
1053 {
1054
1055         /* The following structures are used to save information which cannot be 
1056            processed during the first pass. After the complete constantpool has 
1057            been traversed the references can be resolved. 
1058            (only in specific order)                                                */
1059         
1060         /* CONSTANT_Class_info entries */
1061         typedef struct forward_class {      
1062                 struct forward_class *next; 
1063                 u2 thisindex;               
1064                 u2 name_index;              
1065         } forward_class;                    
1066                                         
1067         /* CONSTANT_String */                                      
1068         typedef struct forward_string { 
1069                 struct forward_string *next; 
1070                 u2 thisindex;                
1071                 u2 string_index;
1072         } forward_string;
1073
1074         /* CONSTANT_NameAndType */
1075         typedef struct forward_nameandtype {
1076                 struct forward_nameandtype *next;
1077                 u2 thisindex;
1078                 u2 name_index;
1079                 u2 sig_index;
1080         } forward_nameandtype;
1081
1082         /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1083         typedef struct forward_fieldmethint {   
1084                 struct forward_fieldmethint *next;
1085                 u2 thisindex;
1086                 u1 tag;
1087                 u2 class_index;
1088                 u2 nameandtype_index;
1089         } forward_fieldmethint;
1090
1091
1092         u4 idx;
1093         long int dumpsize = dump_size ();
1094
1095         forward_class *forward_classes = NULL;
1096         forward_string *forward_strings = NULL;
1097         forward_nameandtype *forward_nameandtypes = NULL;
1098         forward_fieldmethint *forward_fieldmethints = NULL;
1099
1100         /* number of entries in the constant_pool table  */
1101         u4 cpcount       = c -> cpcount = suck_u2();
1102         /* allocate memory */
1103         u1 *cptags       = c -> cptags  = MNEW (u1, cpcount);
1104         voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1105
1106 #ifdef STATISTICS
1107         count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1108 #endif
1109         
1110         /* initialize constantpool */
1111         for (idx=0; idx<cpcount; idx++) {
1112                 cptags[idx] = CONSTANT_UNUSED;
1113                 cpinfos[idx] = NULL;
1114                 }
1115
1116                         
1117                 /******* first pass *******/
1118                 /* entries which cannot be resolved now are written into 
1119                    temporary structures and traversed again later        */
1120                    
1121         idx = 1;
1122         while (idx < cpcount) {
1123                 /* get constant type */
1124                 u4 t = suck_u1 (); 
1125                 switch ( t ) {
1126
1127                         case CONSTANT_Class: { 
1128                                 forward_class *nfc = DNEW(forward_class);
1129
1130                                 nfc -> next = forward_classes;                                                                                  
1131                                 forward_classes = nfc;
1132
1133                                 nfc -> thisindex = idx;
1134                                 /* reference to CONSTANT_NameAndType */
1135                                 nfc -> name_index = suck_u2 (); 
1136
1137                                 idx++;
1138                                 break;
1139                                 }
1140                         
1141                         case CONSTANT_Fieldref:
1142                         case CONSTANT_Methodref:
1143                         case CONSTANT_InterfaceMethodref: { 
1144                                 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1145                                 
1146                                 nff -> next = forward_fieldmethints;
1147                                 forward_fieldmethints = nff;
1148
1149                                 nff -> thisindex = idx;
1150                                 /* constant type */
1151                                 nff -> tag = t;
1152                                 /* class or interface type that contains the declaration of the field or method */
1153                                 nff -> class_index = suck_u2 (); 
1154                                 /* name and descriptor of the field or method */
1155                                 nff -> nameandtype_index = suck_u2 ();
1156
1157                                 idx ++;
1158                                 break;
1159                                 }
1160                                 
1161                         case CONSTANT_String: {
1162                                 forward_string *nfs = DNEW (forward_string);
1163                                 
1164                                 nfs -> next = forward_strings;
1165                                 forward_strings = nfs;
1166                                 
1167                                 nfs -> thisindex = idx;
1168                                 /* reference to CONSTANT_Utf8_info with string characters */
1169                                 nfs -> string_index = suck_u2 ();
1170                                 
1171                                 idx ++;
1172                                 break;
1173                                 }
1174
1175                         case CONSTANT_NameAndType: {
1176                                 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1177                                 
1178                                 nfn -> next = forward_nameandtypes;
1179                                 forward_nameandtypes = nfn;
1180                                 
1181                                 nfn -> thisindex = idx;
1182                                 /* reference to CONSTANT_Utf8_info containing simple name */
1183                                 nfn -> name_index = suck_u2 ();
1184                                 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1185                                 nfn -> sig_index = suck_u2 ();
1186                                 
1187                                 idx ++;
1188                                 break;
1189                                 }
1190
1191                         case CONSTANT_Integer: {
1192                                 constant_integer *ci = NEW (constant_integer);
1193
1194 #ifdef STATISTICS
1195         count_const_pool_len += sizeof(constant_integer);
1196 #endif
1197
1198                                 ci -> value = suck_s4 ();
1199                                 cptags [idx] = CONSTANT_Integer;
1200                                 cpinfos [idx] = ci;
1201                                 idx ++;
1202                                 
1203                                 break;
1204                                 }
1205                                 
1206                         case CONSTANT_Float: {
1207                                 constant_float *cf = NEW (constant_float);
1208
1209 #ifdef STATISTICS
1210         count_const_pool_len += sizeof(constant_float);
1211 #endif
1212
1213                                 cf -> value = suck_float ();
1214                                 cptags [idx] = CONSTANT_Float;
1215                                 cpinfos[idx] = cf;
1216                                 idx ++;
1217                                 break;
1218                                 }
1219                                 
1220                         case CONSTANT_Long: {
1221                                 constant_long *cl = NEW(constant_long);
1222                                         
1223 #ifdef STATISTICS
1224         count_const_pool_len += sizeof(constant_long);
1225 #endif
1226
1227                                 cl -> value = suck_s8 ();
1228                                 cptags [idx] = CONSTANT_Long;
1229                                 cpinfos [idx] = cl;
1230                                 idx += 2;
1231                                 break;
1232                                 }
1233                         
1234                         case CONSTANT_Double: {
1235                                 constant_double *cd = NEW(constant_double);
1236                                 
1237 #ifdef STATISTICS
1238         count_const_pool_len += sizeof(constant_double);
1239 #endif
1240
1241                                 cd -> value = suck_double ();
1242                                 cptags [idx] = CONSTANT_Double;
1243                                 cpinfos [idx] = cd;
1244                                 idx += 2;
1245                                 break;
1246                                 }
1247                                 
1248                         case CONSTANT_Utf8: { 
1249
1250                                 /* number of bytes in the bytes array (not string-length) */
1251                                 u4 length = suck_u2();
1252                                 cptags [idx]  = CONSTANT_Utf8;
1253                                 /* insert utf-string into the utf-symboltable */
1254                                 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1255                                 /* skip bytes of the string */
1256                                 skip_nbytes(length);
1257                                 idx++;
1258                                 break;
1259                                 }
1260                                                                                 
1261                         default:
1262                                 sprintf (logtext, "Unkown constant type: %d",(int) t);
1263                                 error ();
1264                 
1265                         }  /* end switch */
1266                         
1267                 } /* end while */
1268                 
1269
1270
1271            /* resolve entries in temporary structures */
1272
1273         while (forward_classes) {
1274                 utf *name =
1275                   class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1276                 
1277                 if ( (name->blength>0) && (name->text[0]=='[') ) {
1278                         /* check validity of descriptor */
1279                         checkfielddescriptor (name->text, utf_end(name)); 
1280
1281                         cptags  [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1282                         cpinfos [forward_classes -> thisindex] = 
1283                            buildarraydescriptor(name->text, name->blength);
1284
1285                         }
1286                 else {                                  
1287                         cptags  [forward_classes -> thisindex] = CONSTANT_Class;
1288                         /* retrieve class from class-table */
1289                         cpinfos [forward_classes -> thisindex] = class_new (name);
1290                         }
1291                 forward_classes = forward_classes -> next;
1292                 
1293                 }
1294
1295         while (forward_strings) {
1296                 utf *text = 
1297                   class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1298         
1299                 /* resolve utf-string */                
1300                 cptags   [forward_strings -> thisindex] = CONSTANT_String;
1301                 cpinfos  [forward_strings -> thisindex] = text;
1302                 
1303                 forward_strings = forward_strings -> next;
1304                 }       
1305
1306         while (forward_nameandtypes) {
1307                 constant_nameandtype *cn = NEW (constant_nameandtype);  
1308
1309 #ifdef STATISTICS
1310                 count_const_pool_len += sizeof(constant_nameandtype);
1311 #endif
1312
1313                 /* resolve simple name and descriptor */
1314                 cn -> name = class_getconstant 
1315                    (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1316                 cn -> descriptor = class_getconstant
1317                    (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1318                  
1319                 cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1320                 cpinfos  [forward_nameandtypes -> thisindex] = cn;
1321                 
1322                 forward_nameandtypes = forward_nameandtypes -> next;
1323                 }
1324
1325
1326         while (forward_fieldmethints)  {
1327                 constant_nameandtype *nat;
1328                 constant_FMIref *fmi = NEW (constant_FMIref);
1329
1330 #ifdef STATISTICS
1331                 count_const_pool_len += sizeof(constant_FMIref);
1332 #endif
1333                 /* resolve simple name and descriptor */
1334                 nat = class_getconstant
1335                         (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1336
1337                 fmi -> class = class_getconstant 
1338                         (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1339                 fmi -> name = nat -> name;
1340                 fmi -> descriptor = nat -> descriptor;
1341
1342                 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1343                 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1344         
1345                 switch (forward_fieldmethints -> tag) {
1346                 case CONSTANT_Fieldref:  /* check validity of descriptor */
1347                                          checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1348                                          break;
1349                 case CONSTANT_InterfaceMethodref: 
1350                 case CONSTANT_Methodref: /* check validity of descriptor */
1351                                          checkmethoddescriptor (fmi->descriptor);
1352                                          break;
1353                 }               
1354         
1355                 forward_fieldmethints = forward_fieldmethints -> next;
1356
1357                 }
1358
1359
1360         dump_release (dumpsize);
1361 }
1362
1363
1364 /********************** Funktion: class_load ***********************************
1365
1366         l"adt alle Infos f"ur eine ganze Klasse aus einem ClassFile. Die
1367         'classinfo'-Struktur mu"s bereits angelegt worden sein.
1368         
1369         Die Superklasse und die Interfaces, die diese Klasse implementiert,
1370         m"ussen zu diesem Zeitpunkt noch nicht geladen sein, die 
1371         Verbindung dazu wird sp"ater in der Funktion 'class_link' hergestellt.
1372         
1373         Die gelesene Klasse wird dann aus der Liste 'unloadedclasses' ausgetragen
1374         und in die Liste 'unlinkedclasses' eingh"angt.
1375         
1376 *******************************************************************************/
1377
1378 static int class_load (classinfo *c)
1379 {
1380         u4 i;
1381         u4 mi,ma;
1382
1383         /* output for debugging purposes */
1384         if (loadverbose) {              
1385                 sprintf (logtext, "Loading class: ");
1386                 utf_sprint (logtext+strlen(logtext), c->name );
1387                 dolog();
1388                 }
1389         
1390         /* load classdata, throw exception on error */
1391         if (!suck_start (c->name)) {
1392                 throw_classnotfoundexception();            
1393                 return false;
1394         }
1395         
1396         /* check signature */           
1397         if (suck_u4() != MAGIC) panic("Can not find class-file signature");     
1398         /* check version */
1399         mi = suck_u2(); 
1400         ma = suck_u2();
1401         if (ma != MAJOR_VERSION) {
1402                 sprintf (logtext, "Can only support major version %d, but not %d",
1403                                  MAJOR_VERSION, (int) ma);
1404                 error();
1405                 }
1406         if (mi > MINOR_VERSION)  {
1407                 sprintf (logtext, "Minor version %d is not yet supported.", (int) mi);
1408                 error();
1409                 }
1410
1411
1412         class_loadcpool (c);
1413         
1414         /* ACC flags */
1415         c -> flags = suck_u2 (); 
1416         /* this class */
1417         suck_u2 ();       
1418         
1419         /* retrieve superclass */
1420         if ( (i = suck_u2 () ) ) {
1421                 c -> super = class_getconstant (c, i, CONSTANT_Class);
1422                 }
1423         else {
1424                 c -> super = NULL;
1425                 }
1426                          
1427         /* retrieve interfaces */
1428         c -> interfacescount = suck_u2 ();
1429         c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1430         for (i=0; i < c -> interfacescount; i++) {
1431                 c -> interfaces [i] = 
1432                       class_getconstant (c, suck_u2(), CONSTANT_Class);
1433                 }
1434
1435         /* load fields */
1436         c -> fieldscount = suck_u2 ();
1437         c -> fields = MNEW (fieldinfo, c -> fieldscount);
1438         for (i=0; i < c -> fieldscount; i++) {
1439                 field_load (&(c->fields[i]), c);
1440                 }
1441
1442         /* load methods */
1443         c -> methodscount = suck_u2 ();
1444         c -> methods = MNEW (methodinfo, c -> methodscount);
1445         for (i=0; i < c -> methodscount; i++) {
1446                 method_load (&(c -> methods [i]), c);
1447                 }
1448
1449 #ifdef STATISTICS
1450         count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1451         count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1452         count_class_infos += sizeof(methodinfo) * c -> methodscount;
1453 #endif
1454
1455         /* load variable-length attribute structures */ 
1456         attribute_load (suck_u2(), c);
1457
1458         /* free memory */
1459         suck_stop ();
1460
1461         /* remove class from list of unloaded classes and 
1462            add to list of unlinked classes                */
1463         list_remove (&unloadedclasses, c);
1464         list_addlast (&unlinkedclasses, c);
1465
1466         return true;
1467 }
1468
1469
1470
1471 /************** interne Funktion: class_highestinterface ***********************
1472
1473         wird von der Funktion class_link ben"otigt, um festzustellen, wie gro"s
1474         die Interfacetable einer Klasse sein mu"s.
1475
1476 *******************************************************************************/
1477
1478 static s4 class_highestinterface (classinfo *c) 
1479 {
1480         s4 h;
1481         s4 i;
1482         
1483         if ( ! (c->flags & ACC_INTERFACE) ) {
1484                 sprintf (logtext, "Interface-methods count requested for non-interface:  ");
1485         utf_sprint (logtext+strlen(logtext), c->name);
1486         error();
1487         }
1488     
1489     h = c->index;
1490         for (i=0; i<c->interfacescount; i++) {
1491                 s4 h2 = class_highestinterface (c->interfaces[i]);
1492                 if (h2>h) h=h2;
1493                 }
1494         return h;
1495 }
1496
1497
1498 /* class_addinterface **********************************************************
1499
1500         wird von der Funktion class_link ben"otigt, um eine Virtual Function 
1501         Table f"ur ein Interface (und alle weiteren von diesem Interface
1502         implementierten Interfaces) in eine Klasse einzutragen.
1503
1504 *******************************************************************************/        
1505
1506 static void class_addinterface (classinfo *c, classinfo *ic)
1507 {
1508         s4     j, m;
1509         s4     i     = ic->index;
1510         vftbl *vftbl = c->vftbl;
1511         
1512         if (i >= vftbl->interfacetablelength)
1513                 panic ("Inernal error: interfacetable overflow");
1514         if (vftbl->interfacetable[-i])
1515                 return;
1516
1517         if (ic->methodscount == 0) {  /* fake entry needed for subtype test */
1518                 vftbl->interfacevftbllength[i] = 1;
1519                 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1520                 vftbl->interfacetable[-i][0] = NULL;
1521                 }
1522         else {
1523                 vftbl->interfacevftbllength[i] = ic->methodscount;
1524                 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount); 
1525
1526 #ifdef STATISTICS
1527         count_vftbl_len += sizeof(methodptr) *
1528                                  (ic->methodscount + (ic->methodscount == 0));
1529 #endif
1530
1531                 for (j=0; j<ic->methodscount; j++) {
1532                         classinfo *sc = c;
1533                         while (sc) {
1534                                 for (m = 0; m < sc->methodscount; m++) {
1535                                         methodinfo *mi = &(sc->methods[m]);
1536                                         if (method_canoverwrite(mi, &(ic->methods[j]))) {
1537                                                 vftbl->interfacetable[-i][j] = 
1538                                                                           vftbl->table[mi->vftblindex];
1539                                                 goto foundmethod;
1540                                                 }
1541                                         }
1542                                 sc = sc->super;
1543                                 }
1544                          foundmethod: ;
1545                         }
1546                 }
1547
1548         for (j = 0; j < ic->interfacescount; j++) 
1549                 class_addinterface(c, ic->interfaces[j]);
1550 }
1551
1552
1553 /********************** Funktion: class_link ***********************************
1554
1555         versucht, eine Klasse in das System voll zu integrieren (linken). Dazu 
1556         m"ussen sowol die Superklasse, als auch alle implementierten
1557         Interfaces schon gelinkt sein.
1558         Diese Funktion berechnet sowohl die L"ange (in Bytes) einer Instanz 
1559         dieser Klasse, als auch die Virtual Function Tables f"ur normale
1560         Methoden als auch Interface-Methoden.
1561         
1562         Wenn die Klasse erfolgreich gelinkt werden kann, dann wird sie aus
1563         der Liste 'unlinkedclasses' ausgeh"angt, und in die Klasse 'linkedclasses'
1564         eingetragen.
1565         Wenn nicht, dann wird sie ans Ende der Liste 'unlinkedclasses' gestellt.
1566
1567         Achtung: Bei zyklischen Klassendefinitionen ger"at das Programm hier in
1568                  eine Endlosschleife!!  (Da muss ich mir noch was einfallen lassen)
1569
1570 *******************************************************************************/
1571
1572 static void class_link (classinfo *c)
1573 {
1574         s4 supervftbllength;          /* vftbllegnth of super class               */
1575         s4 vftbllength;               /* vftbllength of current class             */
1576         s4 interfacetablelength;      /* interface table length                   */
1577         classinfo *super = c->super;  /* super class                              */
1578         classinfo *ic, *c2;           /* intermediate class variables             */
1579         vftbl *v;                     /* vftbl of current class                   */
1580         s4 i;                         /* interface/method/field counter           */                     
1581
1582
1583         /*  check if all superclasses are already linked, if not put c at end of
1584             unlinked list and return. Additionally initialize class fields.       */
1585
1586         /*  check interfaces */
1587
1588         for (i = 0; i < c->interfacescount; i++) {
1589                 ic = c->interfaces[i];
1590                 if (!ic->linked) {
1591                         list_remove(&unlinkedclasses, c);
1592                         list_addlast(&unlinkedclasses, c);
1593                         return; 
1594                         }
1595                 }
1596         
1597         /*  check super class */
1598
1599         if (super == NULL) {          /* class java.long.Object */
1600                 c->index = 0;
1601                 c->instancesize = sizeof(java_objectheader);
1602                 
1603                 vftbllength = supervftbllength = 0;
1604
1605                 c->finalizer = NULL;
1606                 }
1607         else {
1608                 if (!super->linked) {
1609                         list_remove(&unlinkedclasses, c);
1610                         list_addlast(&unlinkedclasses, c);
1611                         return; 
1612                         }
1613
1614                 if (c->flags & ACC_INTERFACE)
1615                         c->index = interfaceindex++;
1616                 else
1617                         c->index = super->index + 1;
1618                 
1619                 c->instancesize = super->instancesize;
1620                 
1621                 vftbllength = supervftbllength = super->vftbl->vftbllength;
1622                 
1623                 c->finalizer = super->finalizer;
1624                 }
1625
1626
1627         if (linkverbose) {
1628                 sprintf (logtext, "Linking Class: ");
1629                 utf_sprint (logtext+strlen(logtext), c->name );
1630                 dolog ();
1631                 }
1632
1633         /* compute vftbl length */
1634
1635         for (i = 0; i < c->methodscount; i++) {
1636                 methodinfo *m = &(c->methods[i]);
1637                         
1638                 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1639                         classinfo *sc = super;
1640                         while (sc) {
1641                                 int j;
1642                                 for (j = 0; j < sc->methodscount; j++) {
1643                                         if (method_canoverwrite(m, &(sc->methods[j]))) {
1644                                                 m->vftblindex = sc->methods[j].vftblindex;
1645                                                 goto foundvftblindex;
1646                                                 }
1647                                         }
1648                                 sc = sc->super;
1649                                 }
1650                         m->vftblindex = (vftbllength++);
1651 foundvftblindex: ;
1652                         }
1653                 }       
1654         
1655 #ifdef STATISTICS
1656         count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1657 #endif
1658
1659         /* compute interfacetable length */
1660
1661         interfacetablelength = 0;
1662         c2 = c;
1663         while (c2) {
1664                 for (i = 0; i < c2->interfacescount; i++) {
1665                         s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1666                         if (h > interfacetablelength)
1667                                 interfacetablelength = h;
1668                         }
1669                 c2 = c2->super;
1670                 }
1671
1672         /* allocate virtual function table */
1673
1674         v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1675                     (vftbllength - 1) + sizeof(methodptr*) *
1676                     (interfacetablelength - (interfacetablelength > 0)));
1677         v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1678                                          (interfacetablelength > 1));
1679         c->header.vftbl = c->vftbl = v;
1680         v->class = c;
1681         v->vftbllength = vftbllength;
1682         v->interfacetablelength = interfacetablelength;
1683
1684         /* copy virtual function table of super class */
1685
1686         for (i = 0; i < supervftbllength; i++) 
1687            v->table[i] = super->vftbl->table[i];
1688         
1689         /* add method stubs into virtual function table */
1690
1691         for (i = 0; i < c->methodscount; i++) {
1692                 methodinfo *m = &(c->methods[i]);
1693                 if (!(m->flags & ACC_STATIC)) {
1694                         v->table[m->vftblindex] = m->stubroutine;
1695                         }
1696                 }
1697
1698         /* compute instance size and offset of each field */
1699         
1700         for (i = 0; i < c->fieldscount; i++) {
1701                 s4 dsize;
1702                 fieldinfo *f = &(c->fields[i]);
1703                 
1704                 if (!(f->flags & ACC_STATIC) ) {
1705                         dsize = desc_typesize (f->descriptor);
1706                         c->instancesize = ALIGN (c->instancesize, dsize);
1707                         f->offset = c->instancesize;
1708                         c->instancesize += dsize;
1709                         }
1710                 }
1711
1712         /* initialize interfacetable and interfacevftbllength */
1713         
1714         v->interfacevftbllength = MNEW (s4, interfacetablelength);
1715
1716 #ifdef STATISTICS
1717         count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1718 #endif
1719
1720         for (i = 0; i < interfacetablelength; i++) {
1721                 v->interfacevftbllength[i] = 0;
1722                 v->interfacetable[-i] = NULL;
1723                 }
1724         
1725         /* add interfaces */
1726         
1727         for (c2 = c; c2 != NULL; c2 = c2->super)
1728                 for (i = 0; i < c2->interfacescount; i++) {
1729                         class_addinterface (c, c2->interfaces[i]);
1730                         }
1731
1732         /* add finalizer method (not for java.lang.Object) */
1733
1734         if (super != NULL) {
1735                 methodinfo *fi;
1736                 static utf *finame = NULL;
1737                 static utf *fidesc = NULL;
1738
1739                 if (finame == NULL)
1740                         finame = utf_finalize;
1741                 if (fidesc == NULL)
1742                         fidesc = utf_fidesc;
1743
1744                 fi = class_findmethod (c, finame, fidesc);
1745                 if (fi != NULL) {
1746                         if (!(fi->flags & ACC_STATIC)) {
1747                                 c->finalizer = fi;
1748                                 }
1749                         }
1750                 }
1751
1752         /* final tasks */
1753
1754         c->linked = true;       
1755
1756         list_remove (&unlinkedclasses, c);
1757         list_addlast (&linkedclasses, c);
1758 }
1759
1760
1761 /******************* Funktion: class_freepool **********************************
1762
1763         Gibt alle Resourcen, die der ConstantPool einer Klasse ben"otigt,
1764         wieder frei.
1765
1766 *******************************************************************************/
1767
1768 static void class_freecpool (classinfo *c)
1769 {
1770         u4 idx;
1771         u4 tag;
1772         voidptr info;
1773         
1774         for (idx=0; idx < c->cpcount; idx++) {
1775                 tag = c->cptags[idx];
1776                 info = c->cpinfos[idx];
1777                 
1778                 if (info != NULL) {
1779                         switch (tag) {
1780                         case CONSTANT_Fieldref:
1781                         case CONSTANT_Methodref:
1782                         case CONSTANT_InterfaceMethodref:
1783                                 FREE (info, constant_FMIref);
1784                                 break;
1785                         case CONSTANT_Integer:
1786                                 FREE (info, constant_integer);
1787                                 break;
1788                         case CONSTANT_Float:
1789                                 FREE (info, constant_float);
1790                                 break;
1791                         case CONSTANT_Long:
1792                                 FREE (info, constant_long);
1793                                 break;
1794                         case CONSTANT_Double:
1795                                 FREE (info, constant_double);
1796                                 break;
1797                         case CONSTANT_NameAndType:
1798                                 FREE (info, constant_nameandtype);
1799                                 break;
1800                         case CONSTANT_Arraydescriptor:
1801                                 freearraydescriptor (info);
1802                                 break;
1803                         }
1804                         }
1805                 }
1806
1807         MFREE (c -> cptags,  u1, c -> cpcount);
1808         MFREE (c -> cpinfos, voidptr, c -> cpcount);
1809 }
1810
1811
1812 /*********************** Funktion: class_free **********************************
1813
1814         Gibt alle Resourcen, die eine ganze Klasse ben"otigt, frei
1815
1816 *******************************************************************************/
1817
1818 static void class_free (classinfo *c)
1819 {
1820         s4 i;
1821         vftbl *v;
1822                 
1823         class_freecpool (c);
1824
1825         MFREE (c->interfaces, classinfo*, c->interfacescount);
1826
1827         for (i = 0; i < c->fieldscount; i++)
1828                 field_free(&(c->fields[i]));
1829         MFREE (c->fields, fieldinfo, c->fieldscount);
1830         
1831         for (i = 0; i < c->methodscount; i++)
1832                 method_free(&(c->methods[i]));
1833         MFREE (c->methods, methodinfo, c->methodscount);
1834
1835         if ((v = c->vftbl) != NULL) {
1836                 for (i = 0; i < v->interfacetablelength; i++) {
1837                         MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1838                         }
1839                 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1840
1841                 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1842                     sizeof(methodptr*) * (v->interfacetablelength -
1843                                          (v->interfacetablelength > 0));
1844                 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1845                                              (v->interfacetablelength > 1));
1846                 mem_free (v, i);
1847                 }
1848
1849         if (c->innerclasscount)
1850                 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1851
1852         FREE (c, classinfo);
1853 }
1854
1855 /************************* Funktion: class_findfield ***************************
1856         
1857         sucht in einer 'classinfo'-Struktur nach einem Feld mit gew"unschtem
1858         Namen und Typ.
1859
1860 *******************************************************************************/
1861
1862
1863 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1864 {
1865         s4 i;
1866
1867         for (i = 0; i < c->fieldscount; i++) { 
1868                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
1869                         return &(c->fields[i]);                                                         
1870     }
1871
1872         panic ("Can not find field given in CONSTANT_Fieldref");
1873         return NULL;
1874 }
1875
1876
1877 /************************* Funktion: class_findmethod **************************
1878         
1879         sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
1880         Namen und Typ.
1881         Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
1882
1883 *******************************************************************************/
1884
1885 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1886 {
1887         s4 i;
1888         for (i = 0; i < c->methodscount; i++) {
1889                 if ((c->methods[i].name == name) && ((desc == NULL) ||
1890                                                    (c->methods[i].descriptor == desc)))
1891                         return &(c->methods[i]);
1892                 }
1893         return NULL;
1894 }
1895
1896 /************************* Funktion: class_findmethod_approx ******************
1897         
1898         sucht in einer 'classinfo'-Struktur nach einer Methode mit gew"unschtem
1899         Namen und Typ.
1900         Wenn als Typ NULL angegeben wird, dann ist der Typ egal.
1901         beim Vergleichen des Descriptors wird der R"uckgabewert nicht betrachtet
1902
1903 *******************************************************************************/
1904
1905 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1906 {
1907         s4 i;
1908
1909         for (i = 0; i < c->methodscount; i++) 
1910                 if (c->methods[i].name == name) {
1911                         utf *meth_descr = c->methods[i].descriptor;
1912                         
1913                         if (desc == NULL) 
1914                                 /* ignore type */
1915                                 return &(c->methods[i]);
1916
1917                         if (desc->blength <= meth_descr->blength) {
1918                                            /* current position in utf text   */
1919                                            char *desc_utf_ptr = desc->text;      
1920                                            char *meth_utf_ptr = meth_descr->text;                                         
1921                                            /* points behind utf strings */
1922                                            char *desc_end = utf_end(desc);         
1923                                            char *meth_end = utf_end(meth_descr);   
1924                                            char ch;
1925
1926                                            /* compare argument types */
1927                                            while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1928
1929                                                    if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1930                                                            break; /* no match */
1931
1932                                                    if (ch==')')
1933                                                            return &(c->methods[i]);   /* all parameter types equal */
1934                                            }
1935                         }
1936                 }
1937
1938         return NULL;
1939 }
1940
1941 /***************** Funktion: class_resolvemethod_approx ***********************
1942         
1943         sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
1944         (ohne Beachtung des R"uckgabewertes)
1945
1946 *******************************************************************************/
1947
1948 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
1949 {
1950         while (c) {
1951                 /* search for method (ignore returntype) */
1952                 methodinfo *m = class_findmethod_approx (c, name, desc);
1953                 /* method found */
1954                 if (m) return m;
1955                 /* search superclass */
1956                 c = c->super;
1957                 }
1958         return NULL;
1959 }
1960
1961
1962 /************************* Funktion: class_resolvemethod ***********************
1963         
1964         sucht eine Klasse und alle Superklassen ab, um eine Methode zu finden.
1965
1966 *******************************************************************************/
1967
1968
1969 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
1970 {
1971         while (c) {
1972                 methodinfo *m = class_findmethod (c, name, desc);
1973                 if (m) return m;
1974                 /* search superclass */
1975                 c = c->super;
1976                 }
1977         return NULL;
1978 }
1979         
1980
1981
1982 /************************* Funktion: class_issubclass **************************
1983
1984         "uberpr"uft, ob eine Klasse von einer anderen Klasse abgeleitet ist.            
1985         
1986 *******************************************************************************/
1987
1988 bool class_issubclass (classinfo *sub, classinfo *super)
1989 {
1990         for (;;) {
1991                 if (!sub) return false;
1992                 if (sub==super) return true;
1993                 sub = sub -> super;
1994                 }
1995 }
1996
1997
1998
1999 /****************** Initialisierungsfunktion f"ur eine Klasse ******************
2000
2001         In Java kann jede Klasse ein statische Initialisierungsfunktion haben.
2002         Diese Funktion mu"s aufgerufen werden, BEVOR irgendwelche Methoden der
2003         Klasse aufgerufen werden, oder auf statische Variablen zugegriffen
2004         wird.
2005
2006 *******************************************************************************/
2007
2008 #ifdef USE_THREADS
2009 extern int blockInts;
2010 #endif
2011
2012 void class_init (classinfo *c)
2013 {
2014         methodinfo *m;
2015         java_objectheader *exceptionptr;
2016         s4 i;
2017         int b;
2018
2019         if (!makeinitializations) return;
2020         if (c->initialized) return;
2021         c -> initialized = true;
2022         
2023         if (c->super) class_init (c->super);
2024         for (i=0; i < c->interfacescount; i++) class_init(c->interfaces[i]);
2025
2026         m = class_findmethod (c, 
2027                               utf_clinit, 
2028                               utf_fidesc);
2029         if (!m) {
2030                 if (initverbose) {
2031                         sprintf (logtext, "Class ");
2032                         utf_sprint (logtext+strlen(logtext), c->name);
2033                         sprintf (logtext+strlen(logtext), " has no initializer");       
2034                         dolog ();
2035                         }
2036                 return;
2037                 }
2038                 
2039         if (! (m->flags & ACC_STATIC)) panic ("Class initializer is not static!");
2040         
2041         if (initverbose) {
2042                 sprintf (logtext, "Starting initializer for class: ");
2043                 utf_sprint (logtext+strlen(logtext), c->name);
2044                 dolog ();
2045         }
2046
2047 #ifdef USE_THREADS
2048         b = blockInts;
2049         blockInts = 0;
2050 #endif
2051
2052         exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2053
2054 #ifdef USE_THREADS
2055         assert(blockInts == 0);
2056         blockInts = b;
2057 #endif
2058
2059         if (exceptionptr) {     
2060                 printf ("#### Initializer of ");
2061                 utf_display (c->name);
2062                 printf (" has thrown: ");
2063                 utf_display (exceptionptr->vftbl->class->name);
2064                 printf ("\n");
2065                 fflush (stdout);
2066                 }
2067
2068         if (initverbose) {
2069                 sprintf (logtext, "Finished initializer for class: ");
2070                 utf_sprint (logtext+strlen(logtext), c->name);
2071                 dolog ();
2072         }
2073
2074         if (c->name == utf_systemclass) {
2075                 /* class java.lang.System requires explicit initialization */
2076                 
2077                 if (initverbose)
2078                         printf ("#### Initializing class System");
2079
2080                 /* find initializing method */     
2081                 m = class_findmethod (c, 
2082                                         utf_initsystemclass,
2083                                         utf_fidesc);
2084
2085                 if (!m) {
2086                         /* no method found */
2087                         log("initializeSystemClass failed");
2088                         return;
2089                 }
2090
2091                 #ifdef USE_THREADS
2092                         b = blockInts;
2093                         blockInts = 0;
2094                 #endif
2095
2096                 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2097
2098                 #ifdef USE_THREADS
2099                         assert(blockInts == 0);
2100                         blockInts = b;
2101                 #endif
2102
2103                 if (exceptionptr) {                     
2104                         printf ("#### initializeSystemClass has thrown: ");
2105                         utf_display (exceptionptr->vftbl->class->name);
2106                         printf ("\n");
2107                         fflush (stdout);                  
2108                 }
2109         }
2110 }
2111
2112
2113
2114
2115 /********* Funktion: class_showconstantpool   (nur f"ur Debug-Zwecke) *********/
2116
2117 void class_showconstantpool (classinfo *c) 
2118 {
2119         u4 i;
2120         voidptr e;
2121
2122         printf ("---- dump of constant pool ----\n");
2123
2124         for (i=0; i<c->cpcount; i++) {
2125                 printf ("#%d:  ", (int) i);
2126                 
2127                 e = c -> cpinfos [i];
2128                 if (e) {
2129                         
2130                         switch (c -> cptags [i]) {
2131                                 case CONSTANT_Class:
2132                                         printf ("Classreference -> ");
2133                                         utf_display ( ((classinfo*)e) -> name );
2134                                         break;
2135                                 
2136                                 case CONSTANT_Fieldref:
2137                                         printf ("Fieldref -> "); goto displayFMI;
2138                                 case CONSTANT_Methodref:
2139                                         printf ("Methodref -> "); goto displayFMI;
2140                                 case CONSTANT_InterfaceMethodref:
2141                                         printf ("InterfaceMethod -> "); goto displayFMI;
2142                                   displayFMI:
2143                                         {
2144                                         constant_FMIref *fmi = e;
2145                                         utf_display ( fmi->class->name );
2146                                         printf (".");
2147                                         utf_display ( fmi->name);
2148                                         printf (" ");
2149                                         utf_display ( fmi->descriptor );
2150                                     }
2151                                         break;
2152
2153                                 case CONSTANT_String:
2154                                         printf ("String -> ");
2155                                         utf_display (e);
2156                                         break;
2157                                 case CONSTANT_Integer:
2158                                         printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2159                                         break;
2160                                 case CONSTANT_Float:
2161                                         printf ("Float -> %f", ((constant_float*)e) -> value);
2162                                         break;
2163                                 case CONSTANT_Double:
2164                                         printf ("Double -> %f", ((constant_double*)e) -> value);
2165                                         break;
2166                                 case CONSTANT_Long:
2167                                         {
2168                                         u8 v = ((constant_long*)e) -> value;
2169 #if U8_AVAILABLE
2170                                         printf ("Long -> %ld", (long int) v);
2171 #else
2172                                         printf ("Long -> HI: %ld, LO: %ld\n", 
2173                                             (long int) v.high, (long int) v.low);
2174 #endif 
2175                                         }
2176                                         break;
2177                                 case CONSTANT_NameAndType:
2178                                         { constant_nameandtype *cnt = e;
2179                                           printf ("NameAndType: ");
2180                                           utf_display (cnt->name);
2181                                           printf (" ");
2182                                           utf_display (cnt->descriptor);
2183                                         }
2184                                         break;
2185                                 case CONSTANT_Utf8:
2186                                         printf ("Utf8 -> ");
2187                                         utf_display (e);
2188                                         break;
2189                                 case CONSTANT_Arraydescriptor:  {
2190                                         printf ("Arraydescriptor: ");
2191                                         displayarraydescriptor (e);
2192                                         }
2193                                         break;
2194                                 default: 
2195                                         panic ("Invalid type of ConstantPool-Entry");
2196                                 }
2197                                 
2198                         }
2199
2200                 printf ("\n");
2201                 }
2202         
2203 }
2204
2205
2206
2207 /********** Funktion: class_showmethods   (nur f"ur Debug-Zwecke) *************/
2208
2209 void class_showmethods (classinfo *c)
2210 {
2211         s4 i;
2212         
2213         printf ("--------- Fields and Methods ----------------\n");
2214         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
2215
2216         printf ("This: "); utf_display (c->name); printf ("\n");
2217         if (c->super) {
2218                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2219                 }
2220         printf ("Index: %d\n", c->index);
2221         
2222         printf ("interfaces:\n");       
2223         for (i=0; i < c-> interfacescount; i++) {
2224                 printf ("   ");
2225                 utf_display (c -> interfaces[i] -> name);
2226                 printf (" (%d)\n", c->interfaces[i] -> index);
2227                 }
2228
2229         printf ("fields:\n");           
2230         for (i=0; i < c -> fieldscount; i++) {
2231                 field_display (&(c -> fields[i]));
2232                 }
2233
2234         printf ("methods:\n");
2235         for (i=0; i < c -> methodscount; i++) {
2236                 methodinfo *m = &(c->methods[i]);
2237                 if ( !(m->flags & ACC_STATIC)) 
2238                         printf ("vftblindex: %d   ", m->vftblindex);
2239
2240                 method_display ( m );
2241
2242                 }
2243
2244         printf ("Virtual function table:\n");
2245         for (i=0; i<c->vftbl->vftbllength; i++) {
2246                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
2247                 }
2248
2249 }
2250
2251
2252
2253 /******************************************************************************/
2254 /******************* Funktionen fuer den Class-loader generell ****************/
2255 /******************************************************************************/
2256
2257
2258 /********************* Funktion: loader_load ***********************************
2259
2260         l"adt und linkt die ge"unschte Klasse und alle davon 
2261         referenzierten Klassen und Interfaces
2262         Return: Einen Zeiger auf diese Klasse
2263
2264 *******************************************************************************/
2265
2266 classinfo *loader_load (utf *topname)
2267 {
2268         classinfo *top;
2269         classinfo *c;
2270         long int starttime=0,stoptime=0;
2271         
2272         intsDisable();                           /* schani */
2273
2274         if (getloadingtime) starttime = getcputime();
2275
2276         top = class_new (topname);
2277
2278         /* load classes */
2279         while ( (c = list_first(&unloadedclasses)) ) {
2280                 if (!class_load (c)) {
2281                         list_remove (&unloadedclasses, c);
2282                         top=NULL;
2283                     }
2284         }
2285
2286         /* link classes */
2287         while ( (c = list_first(&unlinkedclasses)) ) {
2288                 class_link (c);
2289                 }
2290
2291         /* measure time */
2292         if (getloadingtime) {
2293                 stoptime = getcputime();
2294                 loadingtime += (stoptime-starttime);
2295                 }
2296
2297         intsRestore();                          /* schani */
2298
2299         return top; 
2300 }
2301
2302
2303 /**************** function: create_primitive_classes ***************************
2304
2305         create classes representing primitive types 
2306
2307 ********************************************************************************/
2308
2309
2310 void create_primitive_classes()
2311 {  
2312         int i;
2313
2314         for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2315                 /* create primitive class */
2316                 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2317                 
2318                 /* prevent loader from loading primitive class */
2319                 list_remove (&unloadedclasses, c);
2320                 /* add to unlinked classes */
2321                 list_addlast (&unlinkedclasses, c);             
2322                 c -> super = class_java_lang_Object;
2323                 class_link (c);
2324
2325                 primitivetype_table[i].class_primitive = c;
2326
2327                 /* create class for wrapping the primitive type */
2328                 primitivetype_table[i].class_wrap =
2329                         class_new( utf_new_char(primitivetype_table[i].wrapname) );
2330         }
2331 }
2332
2333 /***************** function: create_array_class ********************************
2334
2335         create class representing an array
2336
2337 ********************************************************************************/
2338
2339
2340 classinfo *create_array_class(utf *u)
2341 {  
2342         classinfo *c = class_new (u);
2343         /* prevent loader from loading the array class */
2344         list_remove (&unloadedclasses, c);
2345         /* add to unlinked classes */
2346         list_addlast (&unlinkedclasses, c);
2347         c -> super = class_java_lang_Object;
2348         class_link(c);
2349
2350         return c;
2351 }
2352
2353 /********************** Funktion: loader_init **********************************
2354
2355         Initialisiert alle Listen und l"adt alle Klassen, die vom System
2356         und vom Compiler direkt ben"otigt werden.
2357
2358 *******************************************************************************/
2359  
2360 void loader_init ()
2361 {
2362         utf *string_class;
2363         interfaceindex = 0;
2364         
2365         list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2366         list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2367         list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2368
2369         /* create utf-symbols for pointer comparison of frequently used strings */
2370         utf_innerclasses    = utf_new_char("InnerClasses");
2371         utf_constantvalue   = utf_new_char("ConstantValue");
2372         utf_code                = utf_new_char("Code");
2373         utf_finalize        = utf_new_char("finalize");
2374         utf_fidesc              = utf_new_char("()V");
2375         utf_clinit              = utf_new_char("<clinit>");
2376         utf_initsystemclass = utf_new_char("initializeSystemClass");
2377         utf_systemclass     = utf_new_char("java/lang/System");
2378
2379         /* create class for arrays */
2380         class_array = class_new ( utf_new_char ("The_Array_Class") );
2381         list_remove (&unloadedclasses, class_array);
2382
2383         /* create class for strings, load it after class Object was loaded */
2384         string_class = utf_new_char ("java/lang/String");
2385         class_java_lang_String = class_new(string_class);
2386         list_remove (&unloadedclasses, class_java_lang_String);
2387
2388         class_java_lang_Object = 
2389                 loader_load ( utf_new_char ("java/lang/Object") );
2390
2391         list_addlast(&unloadedclasses, class_java_lang_String);
2392
2393         class_java_lang_String = 
2394                 loader_load ( string_class );
2395         class_java_lang_ClassCastException = 
2396                 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2397         class_java_lang_NullPointerException = 
2398                 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2399         class_java_lang_ArrayIndexOutOfBoundsException = loader_load ( 
2400              utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2401         class_java_lang_NegativeArraySizeException = loader_load ( 
2402              utf_new_char ("java/lang/NegativeArraySizeException") );
2403         class_java_lang_OutOfMemoryError = loader_load ( 
2404              utf_new_char ("java/lang/OutOfMemoryError") );
2405         class_java_lang_ArrayStoreException =
2406                 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2407         class_java_lang_ArithmeticException = 
2408                 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2409         class_java_lang_ThreadDeath =                             /* schani */
2410                 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2411
2412         /* link class for arrays */
2413         list_addlast (&unlinkedclasses, class_array);
2414         class_array -> super = class_java_lang_Object;
2415         class_link (class_array);
2416
2417         /* correct vftbl-entries (retarded loading of class java/lang/String) */
2418         stringtable_update(); 
2419
2420         /* create classes representing primitive types */
2421         create_primitive_classes();
2422                 
2423         proto_java_lang_ClassCastException = 
2424                 builtin_new(class_java_lang_ClassCastException);
2425         heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2426
2427         proto_java_lang_NullPointerException = 
2428                 builtin_new(class_java_lang_NullPointerException);
2429         heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2430
2431         proto_java_lang_ArrayIndexOutOfBoundsException = 
2432                 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2433         heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2434
2435         proto_java_lang_NegativeArraySizeException = 
2436                 builtin_new(class_java_lang_NegativeArraySizeException);
2437         heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2438
2439         proto_java_lang_OutOfMemoryError = 
2440                 builtin_new(class_java_lang_OutOfMemoryError);
2441         heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2442
2443         proto_java_lang_ArithmeticException = 
2444                 builtin_new(class_java_lang_ArithmeticException);
2445         heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2446
2447         proto_java_lang_ArrayStoreException = 
2448                 builtin_new(class_java_lang_ArrayStoreException);
2449         heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2450
2451         proto_java_lang_ThreadDeath =                             /* schani */
2452                 builtin_new(class_java_lang_ThreadDeath);
2453         heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2454 }
2455
2456
2457
2458
2459 /********************* Funktion: loader_initclasses ****************************
2460
2461         initialisiert alle geladenen aber noch nicht initialisierten Klassen
2462
2463 *******************************************************************************/
2464
2465 void loader_initclasses ()
2466 {
2467         classinfo *c;
2468         
2469         intsDisable();                     /* schani */
2470
2471         if (makeinitializations) {
2472                 c = list_first (&linkedclasses);
2473                 while (c) {
2474                         class_init (c);
2475                         c = list_next (&linkedclasses, c);
2476                         }
2477                 }
2478
2479         intsRestore();                      /* schani */
2480 }
2481
2482 static s4 classvalue = 0;
2483
2484 static void loader_compute_class_values (classinfo *c)
2485 {
2486         classinfo *subs;
2487
2488         c->vftbl->baseval = ++classvalue;
2489         subs = c->sub;
2490         while (subs != NULL) {
2491                 loader_compute_class_values(subs);
2492                 subs = subs->nextsub;
2493                 }
2494         c->vftbl->diffval = classvalue - c->vftbl->baseval;
2495 /*
2496         {
2497         int i;
2498         for (i = 0; i < c->index; i++)
2499                 printf(" ");
2500         printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
2501         utf_display(c->name);
2502         printf("\n");
2503         }
2504 */
2505 }
2506
2507
2508 void loader_compute_subclasses ()
2509 {
2510         classinfo *c;
2511         
2512         intsDisable();                     /* schani */
2513
2514         c = list_first (&linkedclasses);
2515         while (c) {
2516                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2517                         c->nextsub = c->super->sub;
2518                         c->super->sub = c;
2519                         }
2520                 c = list_next (&linkedclasses, c);
2521                 }
2522
2523         loader_compute_class_values(class_java_lang_Object);
2524
2525         intsRestore();                      /* schani */
2526 }
2527
2528
2529
2530 /******************** function: classloader_buffer ***************************
2531  
2532     set buffer for reading classdata
2533
2534 ******************************************************************************/
2535
2536 void classload_buffer(u1 *buf,int len)
2537 {
2538         classbuffer        =  buf;
2539         classbuffer_size   =  len;
2540         classbuf_pos       =  buf-1;
2541 }
2542
2543 /******************** Funktion: loader_close ***********************************
2544
2545         gibt alle Resourcen wieder frei
2546         
2547 *******************************************************************************/
2548
2549 void loader_close ()
2550 {
2551         classinfo *c;
2552
2553         while ( (c=list_first(&unloadedclasses)) ) {
2554                 list_remove (&unloadedclasses,c);
2555                 class_free (c);
2556                 }
2557         while ( (c=list_first(&unlinkedclasses)) ) {
2558                 list_remove (&unlinkedclasses,c);
2559                 class_free (c);
2560                 }
2561         while ( (c=list_first(&linkedclasses)) ) {
2562                 list_remove (&linkedclasses,c);
2563                 class_free (c);
2564                 }
2565 }
2566
2567
2568 /*
2569  * These are local overrides for various environment variables in Emacs.
2570  * Please do not remove this and leave it at the end of the file, where
2571  * Emacs will automagically detect them.
2572  * ---------------------------------------------------------------------
2573  * Local variables:
2574  * mode: c
2575  * indent-tabs-mode: t
2576  * c-basic-offset: 4
2577  * tab-width: 4
2578  * End:
2579  */
2580