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