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