3bc2793df9dc98099887978043595dc82a55717d
[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                 
2193                 e = c -> cpinfos [i];
2194                 if (e) {
2195                         
2196                         switch (c -> cptags [i]) {
2197                                 case CONSTANT_Methodref:
2198                                         {
2199                                         constant_FMIref *fmi = e;
2200                                         if (       (fmi->class->name == c1)  
2201                                                 && (fmi->name == m1)
2202                                                 && (fmi->descriptor == d1)) {
2203                                         
2204                                                 return i;
2205                                                 }
2206                                         }
2207                                         break;
2208                                 case CONSTANT_InterfaceMethodref:
2209                                         {
2210                                         constant_FMIref *fmi = e;
2211                                         if (       (fmi->class->name == c1)  
2212                                                 && (fmi->name == m1)
2213                                                 && (fmi->descriptor == d1)) {
2214
2215                                                 return i;
2216                                                 }
2217                                     }
2218                                         break;
2219                                 
2220                                 default: 
2221                                 }
2222                                 
2223                         }
2224
2225                 }
2226 return -1;
2227 }
2228
2229 void class_showconstanti(classinfo *c, int ii) 
2230 {
2231         u4 i = ii;
2232         voidptr e;
2233
2234 printf ("#%d:  ", (int) i);
2235                 
2236 e = c -> cpinfos [i];
2237 if (e) {
2238                         switch (c -> cptags [i]) {
2239                                 case CONSTANT_Class:
2240                                         printf ("Classreference -> ");
2241                                         utf_display ( ((classinfo*)e) -> name );
2242                                         break;
2243                                 
2244                                 case CONSTANT_Fieldref:
2245                                         printf ("Fieldref -> "); goto displayFMIi;
2246                                 case CONSTANT_Methodref:
2247                                         printf ("Methodref -> "); goto displayFMIi;
2248                                 case CONSTANT_InterfaceMethodref:
2249                                         printf ("InterfaceMethod -> "); goto displayFMIi;
2250                                   displayFMIi:
2251                                         {
2252                                         constant_FMIref *fmi = e;
2253                                         utf_display ( fmi->class->name );
2254                                         printf (".");
2255                                         utf_display ( fmi->name);
2256                                         printf (" ");
2257                                         utf_display ( fmi->descriptor );
2258                                     }
2259                                         break;
2260
2261                                 case CONSTANT_String:
2262                                         printf ("String -> ");
2263                                         utf_display (e);
2264                                         break;
2265                                 case CONSTANT_Integer:
2266                                         printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2267                                         break;
2268                                 case CONSTANT_Float:
2269                                         printf ("Float -> %f", ((constant_float*)e) -> value);
2270                                         break;
2271                                 case CONSTANT_Double:
2272                                         printf ("Double -> %f", ((constant_double*)e) -> value);
2273                                         break;
2274                                 case CONSTANT_Long:
2275                                         {
2276                                         u8 v = ((constant_long*)e) -> value;
2277 #if U8_AVAILABLE
2278                                         printf ("Long -> %ld", (long int) v);
2279 #else
2280                                         printf ("Long -> HI: %ld, LO: %ld\n", 
2281                                             (long int) v.high, (long int) v.low);
2282 #endif 
2283                                         }
2284                                         break;
2285                                 case CONSTANT_NameAndType:
2286                                         { constant_nameandtype *cnt = e;
2287                                           printf ("NameAndType: ");
2288                                           utf_display (cnt->name);
2289                                           printf (" ");
2290                                           utf_display (cnt->descriptor);
2291                                         }
2292                                         break;
2293                                 case CONSTANT_Utf8:
2294                                         printf ("Utf8 -> ");
2295                                         utf_display (e);
2296                                         break;
2297                                 case CONSTANT_Arraydescriptor:  {
2298                                         printf ("Arraydescriptor: ");
2299                                         displayarraydescriptor (e);
2300                                         }
2301                                         break;
2302                                 default: 
2303                                         panic ("Invalid type of ConstantPool-Entry");
2304                                 }  }
2305 printf("\n");
2306
2307 }
2308
2309 void class_showconstantpool (classinfo *c) 
2310 {
2311         u4 i;
2312         voidptr e;
2313
2314         printf ("---- dump of constant pool ----\n");
2315
2316         for (i=0; i<c->cpcount; i++) {
2317                 printf ("#%d:  ", (int) i);
2318                 
2319                 e = c -> cpinfos [i];
2320                 if (e) {
2321                         
2322                         switch (c -> cptags [i]) {
2323                                 case CONSTANT_Class:
2324                                         printf ("Classreference -> ");
2325                                         utf_display ( ((classinfo*)e) -> name );
2326                                         break;
2327                                 
2328                                 case CONSTANT_Fieldref:
2329                                         printf ("Fieldref -> "); goto displayFMI;
2330                                 case CONSTANT_Methodref:
2331                                         printf ("Methodref -> "); goto displayFMI;
2332                                 case CONSTANT_InterfaceMethodref:
2333                                         printf ("InterfaceMethod -> "); goto displayFMI;
2334                                   displayFMI:
2335                                         {
2336                                         constant_FMIref *fmi = e;
2337                                         utf_display ( fmi->class->name );
2338                                         printf (".");
2339                                         utf_display ( fmi->name);
2340                                         printf (" ");
2341                                         utf_display ( fmi->descriptor );
2342                                     }
2343                                         break;
2344
2345                                 case CONSTANT_String:
2346                                         printf ("String -> ");
2347                                         utf_display (e);
2348                                         break;
2349                                 case CONSTANT_Integer:
2350                                         printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2351                                         break;
2352                                 case CONSTANT_Float:
2353                                         printf ("Float -> %f", ((constant_float*)e) -> value);
2354                                         break;
2355                                 case CONSTANT_Double:
2356                                         printf ("Double -> %f", ((constant_double*)e) -> value);
2357                                         break;
2358                                 case CONSTANT_Long:
2359                                         {
2360                                         u8 v = ((constant_long*)e) -> value;
2361 #if U8_AVAILABLE
2362                                         printf ("Long -> %ld", (long int) v);
2363 #else
2364                                         printf ("Long -> HI: %ld, LO: %ld\n", 
2365                                             (long int) v.high, (long int) v.low);
2366 #endif 
2367                                         }
2368                                         break;
2369                                 case CONSTANT_NameAndType:
2370                                         { constant_nameandtype *cnt = e;
2371                                           printf ("NameAndType: ");
2372                                           utf_display (cnt->name);
2373                                           printf (" ");
2374                                           utf_display (cnt->descriptor);
2375                                         }
2376                                         break;
2377                                 case CONSTANT_Utf8:
2378                                         printf ("Utf8 -> ");
2379                                         utf_display (e);
2380                                         break;
2381                                 case CONSTANT_Arraydescriptor:  {
2382                                         printf ("Arraydescriptor: ");
2383                                         displayarraydescriptor (e);
2384                                         }
2385                                         break;
2386                                 default: 
2387                                         panic ("Invalid type of ConstantPool-Entry");
2388                                 }
2389                                 
2390                         }
2391
2392                 printf ("\n");
2393                 }
2394         
2395 }
2396
2397
2398
2399 /********** Function: class_showmethods   (debugging only) *************/
2400
2401 void class_showmethods (classinfo *c)
2402 {
2403         s4 i;
2404         
2405         printf ("--------- Fields and Methods ----------------\n");
2406         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
2407
2408         printf ("This: "); utf_display (c->name); printf ("\n");
2409         if (c->super) {
2410                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2411                 }
2412         printf ("Index: %d\n", c->index);
2413         
2414         printf ("interfaces:\n");       
2415         for (i=0; i < c-> interfacescount; i++) {
2416                 printf ("   ");
2417                 utf_display (c -> interfaces[i] -> name);
2418                 printf (" (%d)\n", c->interfaces[i] -> index);
2419                 }
2420
2421         printf ("fields:\n");           
2422         for (i=0; i < c -> fieldscount; i++) {
2423                 field_display (&(c -> fields[i]));
2424                 }
2425
2426         printf ("methods:\n");
2427         for (i=0; i < c -> methodscount; i++) {
2428                 methodinfo *m = &(c->methods[i]);
2429                 if ( !(m->flags & ACC_STATIC)) 
2430                         printf ("vftblindex: %d   ", m->vftblindex);
2431
2432                 method_display ( m );
2433
2434                 }
2435
2436         printf ("Virtual function table:\n");
2437         for (i=0; i<c->vftbl->vftbllength; i++) {
2438                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
2439                 }
2440
2441 }
2442
2443
2444
2445 /******************************************************************************/
2446 /******************* General functions for the class loader *******************/
2447 /******************************************************************************/
2448
2449 static int loader_inited = 0;
2450
2451 /********************* Function: loader_load ***********************************
2452
2453         Loads and links the class desired class and each class and interface
2454         referenced by it.
2455         Returns: a pointer to this class
2456
2457 *******************************************************************************/
2458
2459 classinfo *loader_load (utf *topname)
2460 {
2461         classinfo *top;
2462         classinfo *c;
2463         long int starttime=0,stoptime=0;
2464         
2465         intsDisable();                           /* schani */
2466
2467         if (getloadingtime)
2468                 starttime = getcputime();
2469
2470         top = class_new (topname);
2471
2472         /* load classes */
2473         while ( (c = list_first(&unloadedclasses)) ) {
2474                 if (!class_load (c)) {
2475                         list_remove (&unloadedclasses, c);
2476                         top=NULL;
2477                     }
2478         }
2479
2480         /* link classes */
2481         while ( (c = list_first(&unlinkedclasses)) ) {
2482                 class_link (c);
2483                 }
2484
2485         if (loader_inited)
2486                 loader_compute_subclasses();
2487
2488         /* measure time */
2489         if (getloadingtime) {
2490                 stoptime = getcputime();
2491                 loadingtime += (stoptime-starttime);
2492                 }
2493
2494         intsRestore();                          /* schani */
2495
2496         return top; 
2497 }
2498
2499
2500 /**************** function: create_primitive_classes ***************************
2501
2502         create classes representing primitive types 
2503
2504 ********************************************************************************/
2505
2506
2507 void create_primitive_classes()
2508 {  
2509         int i;
2510
2511         for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2512                 /* create primitive class */
2513                 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2514                 c -> classUsed = 0; /* not used initially CO-RT */              
2515                 c -> impldBy = NULL;
2516                 c -> nextimpldBy = NULL;
2517
2518                 /* prevent loader from loading primitive class */
2519                 list_remove (&unloadedclasses, c);
2520                 /* add to unlinked classes */
2521                 list_addlast (&unlinkedclasses, c);             
2522                 c -> super = class_java_lang_Object;
2523                 class_link (c);
2524
2525                 primitivetype_table[i].class_primitive = c;
2526
2527                 /* create class for wrapping the primitive type */
2528                 primitivetype_table[i].class_wrap =
2529                         class_new( utf_new_char(primitivetype_table[i].wrapname) );
2530                 primitivetype_table[i].class_wrap -> classUsed = 0; /* not used initially CO-RT */
2531                 primitivetype_table[i].class_wrap  -> impldBy = NULL;
2532                 primitivetype_table[i].class_wrap  -> nextimpldBy = NULL;
2533         }
2534 }
2535
2536 /***************** function: create_array_class ********************************
2537
2538         create class representing an array
2539
2540 ********************************************************************************/
2541
2542
2543 classinfo *create_array_class(utf *u)
2544 {  
2545         classinfo *c = class_new (u);
2546         /* prevent loader from loading the array class */
2547         list_remove (&unloadedclasses, c);
2548         /* add to unlinked classes */
2549         list_addlast (&unlinkedclasses, c);
2550         c -> super = class_java_lang_Object;
2551         class_link(c);
2552
2553         return c;
2554 }
2555
2556 /********************** Function: loader_init **********************************
2557
2558         Initializes all lists and loads all classes required for the system or the
2559         compiler.
2560
2561 *******************************************************************************/
2562  
2563 void loader_init ()
2564 {
2565         utf *string_class;
2566         interfaceindex = 0;
2567         
2568         list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2569         list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2570         list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2571
2572         /* create utf-symbols for pointer comparison of frequently used strings */
2573         utf_innerclasses    = utf_new_char("InnerClasses");
2574         utf_constantvalue   = utf_new_char("ConstantValue");
2575         utf_code                = utf_new_char("Code");
2576         utf_finalize        = utf_new_char("finalize");
2577         utf_fidesc              = utf_new_char("()V");
2578         utf_clinit              = utf_new_char("<clinit>");
2579         utf_initsystemclass = utf_new_char("initializeSystemClass");
2580         utf_systemclass     = utf_new_char("java/lang/System");
2581
2582         /* create class for arrays */
2583         class_array = class_new ( utf_new_char ("The_Array_Class") );
2584         class_array -> classUsed = 0; /* not used initially CO-RT */
2585         class_array -> impldBy = NULL;
2586         class_array -> nextimpldBy = NULL;
2587
2588         list_remove (&unloadedclasses, class_array);
2589
2590         /* create class for strings, load it after class Object was loaded */
2591         string_class = utf_new_char ("java/lang/String");
2592         class_java_lang_String = class_new(string_class);
2593         class_java_lang_String -> classUsed = 0; /* not used initially CO-RT */
2594         class_java_lang_String -> impldBy = NULL;
2595         class_java_lang_String -> nextimpldBy = NULL;
2596
2597         list_remove (&unloadedclasses, class_java_lang_String);
2598
2599         class_java_lang_Object = 
2600                 loader_load ( utf_new_char ("java/lang/Object") );
2601
2602         list_addlast(&unloadedclasses, class_java_lang_String);
2603
2604         class_java_lang_String = 
2605                 loader_load ( string_class );
2606         class_java_lang_ClassCastException = 
2607                 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2608         class_java_lang_NullPointerException = 
2609                 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2610         class_java_lang_ArrayIndexOutOfBoundsException = loader_load ( 
2611              utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2612         class_java_lang_NegativeArraySizeException = loader_load ( 
2613              utf_new_char ("java/lang/NegativeArraySizeException") );
2614         class_java_lang_OutOfMemoryError = loader_load ( 
2615              utf_new_char ("java/lang/OutOfMemoryError") );
2616         class_java_lang_ArrayStoreException =
2617                 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2618         class_java_lang_ArithmeticException = 
2619                 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2620         class_java_lang_ThreadDeath =                             /* schani */
2621                 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2622
2623         /* link class for arrays */
2624         list_addlast (&unlinkedclasses, class_array);
2625         class_array -> super = class_java_lang_Object;
2626         class_link (class_array);
2627
2628         /* correct vftbl-entries (retarded loading of class java/lang/String) */
2629         stringtable_update(); 
2630
2631         /* create classes representing primitive types */
2632         create_primitive_classes();
2633                 
2634         proto_java_lang_ClassCastException = 
2635                 builtin_new(class_java_lang_ClassCastException);
2636         heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2637
2638         proto_java_lang_NullPointerException = 
2639                 builtin_new(class_java_lang_NullPointerException);
2640         heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2641
2642         proto_java_lang_ArrayIndexOutOfBoundsException = 
2643                 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2644         heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2645
2646         proto_java_lang_NegativeArraySizeException = 
2647                 builtin_new(class_java_lang_NegativeArraySizeException);
2648         heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2649
2650         proto_java_lang_OutOfMemoryError = 
2651                 builtin_new(class_java_lang_OutOfMemoryError);
2652         heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2653
2654         proto_java_lang_ArithmeticException = 
2655                 builtin_new(class_java_lang_ArithmeticException);
2656         heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2657
2658         proto_java_lang_ArrayStoreException = 
2659                 builtin_new(class_java_lang_ArrayStoreException);
2660         heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2661
2662         proto_java_lang_ThreadDeath =                             /* schani */
2663                 builtin_new(class_java_lang_ThreadDeath);
2664         heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2665
2666         loader_inited = 1;
2667 }
2668
2669
2670
2671
2672 /********************* Function: loader_initclasses ****************************
2673
2674         Initializes all loaded but uninitialized classes
2675
2676 *******************************************************************************/
2677
2678 void loader_initclasses ()
2679 {
2680         classinfo *c;
2681         
2682         intsDisable();                     /* schani */
2683
2684         if (makeinitializations) {
2685                 c = list_first (&linkedclasses);
2686                 while (c) {
2687                         class_init (c);
2688                         c = list_next (&linkedclasses, c);
2689                         }
2690                 }
2691
2692         intsRestore();                      /* schani */
2693 }
2694
2695 static s4 classvalue;
2696
2697 static void loader_compute_class_values (classinfo *c)
2698 {
2699         classinfo *subs;
2700
2701         c->vftbl->baseval = ++classvalue;
2702         subs = c->sub;
2703         while (subs != NULL) {
2704                 loader_compute_class_values(subs);
2705                 subs = subs->nextsub;
2706                 }
2707         c->vftbl->diffval = classvalue - c->vftbl->baseval;
2708 /*
2709         {
2710         int i;
2711         for (i = 0; i < c->index; i++)
2712                 printf(" ");
2713         printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
2714         utf_display(c->name);
2715         printf("\n");
2716         }
2717 */
2718 }
2719
2720
2721 void loader_compute_subclasses ()
2722 {
2723         classinfo *c;
2724         
2725         intsDisable();                     /* schani */
2726
2727         c = list_first (&linkedclasses);
2728         while (c) {
2729                 if (!(c->flags & ACC_INTERFACE)) {
2730                         c->nextsub = 0;
2731                         c->sub = 0;
2732                         }
2733                 c = list_next (&linkedclasses, c);
2734                 }
2735
2736         c = list_first (&linkedclasses);
2737         while (c) {
2738                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2739                         c->nextsub = c->super->sub;
2740                         c->super->sub = c;
2741                         }
2742                 c = list_next (&linkedclasses, c);
2743                 }
2744         classvalue = 0;
2745         loader_compute_class_values(class_java_lang_Object);
2746
2747         intsRestore();                      /* schani */
2748 }
2749
2750
2751
2752 /******************** function classloader_buffer ******************************
2753  
2754     sets buffer for reading classdata
2755
2756 *******************************************************************************/
2757
2758 void classload_buffer(u1 *buf, int len)
2759 {
2760         classbuffer        =  buf;
2761         classbuffer_size   =  len;
2762         classbuf_pos       =  buf - 1;
2763 }
2764
2765
2766 /******************** Function: loader_close ***********************************
2767
2768         Frees all resources
2769         
2770 *******************************************************************************/
2771
2772 void loader_close ()
2773 {
2774         classinfo *c;
2775
2776         while ( (c=list_first(&unloadedclasses)) ) {
2777                 list_remove (&unloadedclasses,c);
2778                 class_free (c);
2779                 }
2780         while ( (c=list_first(&unlinkedclasses)) ) {
2781                 list_remove (&unlinkedclasses,c);
2782                 class_free (c);
2783                 }
2784         while ( (c=list_first(&linkedclasses)) ) {
2785                 list_remove (&linkedclasses,c);
2786                 class_free (c);
2787                 }
2788 }
2789
2790
2791 /*
2792  * These are local overrides for various environment variables in Emacs.
2793  * Please do not remove this and leave it at the end of the file, where
2794  * Emacs will automagically detect them.
2795  * ---------------------------------------------------------------------
2796  * Local variables:
2797  * mode: c
2798  * indent-tabs-mode: t
2799  * c-basic-offset: 4
2800  * tab-width: 4
2801  * End:
2802  */
2803