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