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