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