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