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