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