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