merge from gnuclasspath branch. I hope I didn't miss or revert any modifications...
[cacao.git] / src / vm / loader.c
1 /* loader.c - class loader functions
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28    Changes: Andreas Krall
29             Roman Obermaiser
30             Mark Probst
31
32    $Id: loader.c 664 2003-11-21 18:24:01Z jowenn $
33
34 */
35
36
37 #include <string.h>
38 #include <assert.h>
39 #include <sys/stat.h>
40 #include "global.h"
41 #include "loader.h"
42 #include "native.h"
43 #include "tables.h"
44 #include "builtin.h"
45 #include "jit.h"
46 #include "asmpart.h"
47 #include "toolbox/memory.h"
48 #include "toolbox/loging.h"
49 #include "threads/thread.h"
50 #include <sys/stat.h>
51
52 #ifdef USE_ZLIB
53 #include "unzip.h"
54 #endif
55
56 #undef JOWENN_DEBUG
57 #undef JOWENN_DEBUG1
58 #undef JOWENN_DEBUG2
59
60 /* global variables ***********************************************************/
61
62 bool opt_rt = false;            /* true if RTA parse should be used     RT-CO */
63 bool opt_xta = false;           /* true if XTA parse should be used    XTA-CO */
64 bool opt_vta = false;           /* true if VTA parse should be used    VTA-CO */
65
66 int count_class_infos = 0;      /* variables for measurements                 */
67 int count_const_pool_len = 0;
68 int count_vftbl_len = 0;
69 int count_all_methods = 0;
70 int count_vmcode_len = 0;
71 int count_extable_len = 0;
72 int count_class_loads = 0;
73 int count_class_inits = 0;
74
75 bool loadverbose = false;       /* switches for debug messages                */
76 bool linkverbose = false;
77 bool initverbose = false;
78
79 bool makeinitializations = true;
80
81 bool getloadingtime  = false;   /* to measure the runtime                     */
82 long int loadingtime = 0;
83
84 static s4 interfaceindex;       /* sequential numbering of interfaces         */ 
85
86 list unloadedclasses;       /* list of all referenced but not loaded classes  */
87 list unlinkedclasses;       /* list of all loaded but not linked classes      */
88 list linkedclasses;         /* list of all completely linked classes          */
89
90
91 /* utf-symbols for pointer comparison of frequently used strings */
92
93 static utf *utf_innerclasses;           /* InnerClasses                    */
94 static utf *utf_constantvalue;          /* ConstantValue                   */
95 static utf *utf_code;                       /* Code                            */
96 static utf *utf_finalize;                   /* finalize                            */
97 static utf *utf_fidesc;                     /* ()V changed                                   */
98 static utf *utf_clinit;                     /* <clinit>                            */
99 static utf *utf_initsystemclass;        /* initializeSystemClass */
100 static utf *utf_systemclass;            /* java/lang/System        */
101 static utf *utf_vmclassloader; /*java/lang/VMClassLoader*/
102 static utf *utf_vmclass; /*java/lang/VMClassLoader*/
103 static utf *utf_initialize;
104 static utf *utf_initializedesc;
105
106 utf* clinit_desc(){
107         return utf_fidesc;
108 }
109 utf* clinit_name(){
110         return utf_clinit;
111 }
112 /* important system classes ***************************************************/
113
114 classinfo *class_java_lang_Object;
115 classinfo *class_java_lang_String;
116
117 classinfo *class_java_lang_Throwable;
118 classinfo *class_java_lang_Cloneable;
119 classinfo *class_java_io_Serializable;
120
121 /* Pseudo classes for the typechecker */
122 classinfo *pseudo_class_Arraystub = NULL;
123 classinfo *pseudo_class_Null = NULL;
124 vftbl *pseudo_class_Arraystub_vftbl = NULL;
125
126 /* stefan */
127 /* These are made static so they cannot be used for throwing in native */
128 /* functions.                                                          */
129 static classinfo *class_java_lang_ClassCastException;
130 static classinfo *class_java_lang_NullPointerException;
131 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
132 static classinfo *class_java_lang_NegativeArraySizeException;
133 static classinfo *class_java_lang_OutOfMemoryError;
134 static classinfo *class_java_lang_ArithmeticException;
135 static classinfo *class_java_lang_ArrayStoreException;
136 static classinfo *class_java_lang_ThreadDeath;
137
138 static methodinfo method_clone_array;
139
140 static int loader_inited = 0;
141
142 /******************************************************************************
143
144    structure for primitive classes: contains the class for wrapping the 
145    primitive type, the primitive class, the name of the class for wrapping, 
146    the one character type signature and the name of the primitive class
147  
148  ******************************************************************************/
149
150 /* CAUTION: Don't change the order of the types. This table is indexed
151  * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
152  */
153 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = { 
154                 { NULL, NULL, "java/lang/Integer",   'I', "int"     , "[I", NULL, NULL },
155                 { NULL, NULL, "java/lang/Long",      'J', "long"    , "[J", NULL, NULL },
156                 { NULL, NULL, "java/lang/Float",     'F', "float"   , "[F", NULL, NULL },
157                 { NULL, NULL, "java/lang/Double",    'D', "double"  , "[D", NULL, NULL },
158                 { NULL, NULL, "java/lang/Byte",      'B', "byte"    , "[B", NULL, NULL },
159                 { NULL, NULL, "java/lang/Character", 'C', "char"    , "[C", NULL, NULL },
160                 { NULL, NULL, "java/lang/Short",     'S', "short"   , "[S", NULL, NULL },
161                 { NULL, NULL, "java/lang/Boolean",   'Z', "boolean" , "[Z", NULL, NULL },
162                 { NULL, NULL, "java/lang/Void",      'V', "void"    , NULL, NULL, NULL }};
163
164 /* instances of important system classes **************************************/
165
166 java_objectheader *proto_java_lang_ClassCastException;
167 java_objectheader *proto_java_lang_NullPointerException;
168 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
169 java_objectheader *proto_java_lang_NegativeArraySizeException;
170 java_objectheader *proto_java_lang_OutOfMemoryError;
171 java_objectheader *proto_java_lang_ArithmeticException;
172 java_objectheader *proto_java_lang_ArrayStoreException;
173 java_objectheader *proto_java_lang_ThreadDeath;
174
175 /* XXX delete */
176 #if 0
177 void override_array_class(classinfo *c) {
178         int i;
179         classinfo *sup;
180         utf *u=utf_new_char("clone");
181         sup=c->super;
182         class_showmethods(c);
183
184         for (i=0;i<sup->methodscount;i++) {
185                 if (sup->methods[i].name==u) {
186                         method_clone_array.class = c;
187                         method_clone_array. flags = ACC_PUBLIC;
188                         method_clone_array.name =  utf_new_char("clone");
189                         method_clone_array.descriptor = utf_new_char("()Ljava/lang/Object;");
190
191                         method_clone_array.jcode = NULL;
192                         method_clone_array.exceptiontable = NULL;
193                         method_clone_array.entrypoint = NULL;
194                         method_clone_array.mcode = NULL;
195                         method_clone_array.stubroutine = NULL;
196                         method_clone_array.methodUsed = NOTUSED;
197                         method_clone_array.monoPoly = MONO;
198                         method_clone_array.subRedefs = 0;
199                         method_clone_array.subRedefsUsed = 0;
200                         method_clone_array.flags=0;
201                         method_clone_array.xta = NULL;
202                         method_clone_array.stubroutine = createnativestub (&builtin_clone_array, &method_clone_array);
203                         c->vftbl->table[sup->methods[i].vftblindex]=method_clone_array.stubroutine;
204                         log_text("Found !!!! :)))))))))))))))))))))))))))))))))))))))))))))))))");
205                 }
206         
207
208         }
209 }
210 #endif
211
212
213
214
215
216
217
218
219
220 /************* functions for reading classdata *********************************
221
222     getting classdata in blocks of variable size
223     (8,16,32,64-bit integer or float)
224
225 *******************************************************************************/
226
227 static char *classpath    = "";     /* searchpath for classfiles              */
228 static u1 *classbuffer    = NULL;   /* pointer to buffer with classfile-data  */
229 static u1 *classbuf_pos;            /* current position in classfile buffer   */
230 static int classbuffer_size;        /* size of classfile-data                 */
231
232 /* transfer block of classfile data into a buffer */
233
234 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
235                                 classbuf_pos+=len;
236
237 /* skip block of classfile data */
238
239 #define skip_nbytes(len) classbuf_pos+=len;
240
241 inline u1 suck_u1()
242 {
243         return *++classbuf_pos;
244 }
245 inline u2 suck_u2()
246 {
247         u1 a=suck_u1(), b=suck_u1();
248         return ((u2)a<<8)+(u2)b;
249 }
250 inline u4 suck_u4()
251 {
252         u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
253         return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
254 }
255 #define suck_s8() (s8) suck_u8()
256 #define suck_s2() (s2) suck_u2()
257 #define suck_s4() (s4) suck_u4()
258 #define suck_s1() (s1) suck_u1()
259
260
261 /* get u8 from classfile data */
262
263 static u8 suck_u8 ()
264 {
265 #if U8_AVAILABLE
266         u8 lo,hi;
267         hi = suck_u4();
268         lo = suck_u4();
269         return (hi<<32) + lo;
270 #else
271         u8 v;
272         v.high = suck_u4();
273         v.low = suck_u4();
274         return v;
275 #endif
276 }
277
278 /* get float from classfile data */
279
280 static float suck_float ()
281 {
282         float f;
283
284 #if !WORDS_BIGENDIAN 
285                 u1 buffer[4];
286                 u2 i;
287                 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
288                 memcpy ( (u1*) (&f), buffer, 4);
289 #else 
290                 suck_nbytes ( (u1*) (&f), 4 );
291 #endif
292
293         PANICIF (sizeof(float) != 4, "Incompatible float-format");
294         
295         return f;
296 }
297
298 /* get double from classfile data */
299 static double suck_double ()
300 {
301         double d;
302
303 #if !WORDS_BIGENDIAN 
304                 u1 buffer[8];
305                 u2 i;   
306                 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
307                 memcpy ( (u1*) (&d), buffer, 8);
308 #else 
309                 suck_nbytes ( (u1*) (&d), 8 );
310 #endif
311
312         PANICIF (sizeof(double) != 8, "Incompatible double-format" );
313         
314         return d;
315 }
316
317 /************************** function suck_init *********************************
318
319         called once at startup, sets the searchpath for the classfiles
320
321 *******************************************************************************/
322
323 void suck_init (char *cpath)
324 {
325         classpath   = cpath;
326         classbuffer = NULL;
327 }
328
329
330 /************************** function suck_start ********************************
331
332         returns true if classbuffer is already loaded or a file for the
333         specified class has succussfully been read in. All directories of
334         the searchpath are used to find the classfile (<classname>.class).
335         Returns false if no classfile is found and writes an error message. 
336         
337 *******************************************************************************/
338
339
340 bool suck_start (utf *classname) {
341
342 #define MAXFILENAME 1000                /* maximum length of a filename           */
343         
344         char filename[MAXFILENAME+10];  /* room for '.class'                      */    
345         char *pathpos;                  /* position in searchpath                 */
346         char c, *utf_ptr;               /* pointer to the next utf8-character     */
347         FILE *classfile;
348         int  filenamelen, err;
349         struct stat buffer;
350         int isZip;
351
352         if (classbuffer)                /* classbuffer is already valid */
353                 return true;
354
355         pathpos = classpath;
356         
357         while (*pathpos) {
358
359                 /* skip path separator */
360
361                 while (*pathpos == ':')
362                         pathpos++;
363  
364                 /* extract directory from searchpath */
365
366                 filenamelen = 0;
367                 while ((*pathpos) && (*pathpos!=':')) {
368                     PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
369                         filename[filenamelen++] = *(pathpos++);
370                         }
371
372                 isZip=0;
373                 if (filenamelen>4) {
374                         if ( ((filename[filenamelen-1]=='p') || (filename[filenamelen-1]=='P')) &
375                              ((filename[filenamelen-2]=='i') || (filename[filenamelen-1]=='I')) &
376                              ((filename[filenamelen-3]=='z') || (filename[filenamelen-1]=='Z')) ) {
377                                 isZip=1;
378                         }
379                 }
380
381                 if (isZip) {
382 #ifdef USE_ZLIB
383
384                         unzFile uf;
385
386                         filename[filenamelen++]='\0';
387                         uf=unzOpen(filename);
388                         if (uf!=0) {
389                                 utf_ptr = classname->text;
390                                 filenamelen=0;
391                                 while (utf_ptr < utf_end(classname)) {
392                                         PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
393                                         c = *utf_ptr++;
394                                         if ((c <= ' ' || c > 'z') && (c != '/'))     /* invalid character */ 
395                                                 c = '?'; 
396                                         filename[filenamelen++] = c;    
397                                 }
398                                 strcpy (filename+filenamelen, ".class");
399                                 /*log_text(filename);*/
400                                 if (unzLocateFile(uf,filename,1 /*case sensitive*/)==UNZ_OK) {
401                                         unz_file_info file_info;
402                                         log_text("Class found in zip file");
403                                         if (unzGetCurrentFileInfo(uf,&file_info,filename,
404                                                 sizeof(filename),NULL,0,NULL,0) ==UNZ_OK) {
405                                                 if (unzOpenCurrentFile(uf)==UNZ_OK) {
406                                                         classbuffer_size = file_info.uncompressed_size;                         
407                                                         classbuffer      = MNEW(u1, classbuffer_size);
408                                                         classbuf_pos     = classbuffer-1;
409                                                         /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
410                                                         if (unzReadCurrentFile(uf,classbuffer,classbuffer_size)==classbuffer_size) {
411                                                                 unzCloseCurrentFile(uf);
412                                                                 return true;
413                                                         } else {
414                                                                 MFREE(classbuffer,u1,classbuffer_size);
415                                                                 log_text("Error while unzipping");
416                                                         }
417                                                 } else log_text("Error while opening file in archive");
418                                         } else log_text("Error while retrieving fileinfo");
419                                 }; 
420                                 unzCloseCurrentFile(uf);
421
422                         }
423 #endif                  
424                 } else {
425                         filename[filenamelen++] = '/';  
426    
427                         /* add classname to filename */
428
429                         utf_ptr = classname->text;
430                         while (utf_ptr < utf_end(classname)) {
431                                 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
432                                 c = *utf_ptr++;
433                                 if ((c <= ' ' || c > 'z') && (c != '/'))     /* invalid character */ 
434                                         c = '?'; 
435                                 filename[filenamelen++] = c;    
436                         }
437         
438                         /* add suffix */
439
440                         strcpy (filename+filenamelen, ".class");
441
442                         classfile = fopen(filename, "r");
443                         if (classfile) {                                       /* file exists */
444
445                                 /* XXX remove */
446                                 /*
447                                   sprintf(logtext,"Opening file: %s",filename);
448                                   dolog();
449                                 */
450                         
451                                 /* determine size of classfile */
452
453                                 err = stat (filename, &buffer);
454
455                                 if (!err) {                                /* read classfile data */                            
456                                         classbuffer_size = buffer.st_size;                              
457                                         classbuffer      = MNEW(u1, classbuffer_size);
458                                         classbuf_pos     = classbuffer-1;
459                                         fread(classbuffer, 1, classbuffer_size, classfile);
460                                         fclose(classfile);
461                                         return true;
462                                 }
463                         }
464                 }
465         }
466         if (verbose) {
467                 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
468                 dolog();
469         }
470
471         return false;
472 }
473
474
475 /************************** function suck_stop *********************************
476
477         frees memory for buffer with classfile data.
478         Caution: this function may only be called if buffer has been allocated
479                  by suck_start with reading a file
480         
481 *******************************************************************************/
482
483 void suck_stop () {
484
485         /* determine amount of classdata not retrieved by suck-operations         */
486
487         int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
488
489         if (classdata_left > 0) {               
490                 /* surplus */           
491                 sprintf (logtext,"There are %d access bytes at end of classfile",
492                          classdata_left);
493                 dolog();
494         }
495
496         /* free memory */
497
498         MFREE(classbuffer, u1, classbuffer_size);
499         classbuffer = NULL;
500 }
501
502 /******************************************************************************/
503 /******************* Some support functions ***********************************/
504 /******************************************************************************/
505
506
507
508 void fprintflags (FILE *fp, u2 f)
509 {
510    if ( f & ACC_PUBLIC )       fprintf (fp," PUBLIC");
511    if ( f & ACC_PRIVATE )      fprintf (fp," PRIVATE");
512    if ( f & ACC_PROTECTED )    fprintf (fp," PROTECTED");
513    if ( f & ACC_STATIC )       fprintf (fp," STATIC");
514    if ( f & ACC_FINAL )        fprintf (fp," FINAL");
515    if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
516    if ( f & ACC_VOLATILE )     fprintf (fp," VOLATILE");
517    if ( f & ACC_TRANSIENT )    fprintf (fp," TRANSIENT");
518    if ( f & ACC_NATIVE )       fprintf (fp," NATIVE");
519    if ( f & ACC_INTERFACE )    fprintf (fp," INTERFACE");
520    if ( f & ACC_ABSTRACT )     fprintf (fp," ABSTRACT");
521 }
522
523 /********** internal function: printflags  (only for debugging) ***************/
524 void printflags (u2 f)
525 {
526    if ( f & ACC_PUBLIC )       printf (" PUBLIC");
527    if ( f & ACC_PRIVATE )      printf (" PRIVATE");
528    if ( f & ACC_PROTECTED )    printf (" PROTECTED");
529    if ( f & ACC_STATIC )       printf (" STATIC");
530    if ( f & ACC_FINAL )        printf (" FINAL");
531    if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
532    if ( f & ACC_VOLATILE )     printf (" VOLATILE");
533    if ( f & ACC_TRANSIENT )    printf (" TRANSIENT");
534    if ( f & ACC_NATIVE )       printf (" NATIVE");
535    if ( f & ACC_INTERFACE )    printf (" INTERFACE");
536    if ( f & ACC_ABSTRACT )     printf (" ABSTRACT");
537 }
538
539
540 /************************* Function: skipattribute *****************************
541
542         skips a (1) 'attribute' structure in the class file
543
544 *******************************************************************************/
545
546 static void skipattribute ()
547 {
548         suck_u2 ();
549         skip_nbytes(suck_u4()); 
550 }
551
552 /********************** Function: skipattributebody ****************************
553
554         skips an attribute after the 16 bit reference to attribute_name has already
555         been read
556         
557 *******************************************************************************/
558
559 static void skipattributebody ()
560 {
561         skip_nbytes(suck_u4());
562 }
563
564 /************************* Function: skipattributes ****************************
565
566         skips num attribute structures
567         
568 *******************************************************************************/
569
570 static void skipattributes (u4 num)
571 {
572         u4 i;
573         for (i = 0; i < num; i++)
574                 skipattribute();
575 }
576
577 /******************** function: innerclass_getconstant ************************
578
579     like class_getconstant, but if cptags is ZERO null is returned                                       
580         
581 *******************************************************************************/
582
583 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype) 
584 {
585         /* invalid position in constantpool */
586         if (pos >= c->cpcount) 
587                 panic ("Attempt to access constant outside range");
588
589         /* constantpool entry of type 0 */      
590         if (!c->cptags[pos])
591                 return NULL;
592
593         /* check type of constantpool entry */
594         if (c->cptags[pos] != ctype) {
595                 sprintf (logtext, "Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
596                  (int) ctype, (int) c->cptags[pos] );
597                 error();
598                 }
599                 
600         return c->cpinfos[pos];
601 }
602
603 /************************ function: attribute_load ****************************
604
605     read attributes from classfile
606         
607 *******************************************************************************/
608
609 static void attribute_load (u4 num, classinfo *c)
610 {
611         u4 i,j;
612
613         for (i = 0; i < num; i++) {
614                 /* retrieve attribute name */   
615                 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
616
617                 if ( aname == utf_innerclasses)  {                      
618                         /* innerclasses attribute */
619                                 
620                         /* skip attribute length */                                             
621                         suck_u4(); 
622                         /* number of records */
623                         c->innerclasscount = suck_u2();
624                         /* allocate memory for innerclass structure */
625                         c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
626
627                         for (j=0;j<c->innerclasscount;j++) {
628                                 
629                                 /*  The innerclass structure contains a class with an encoded name, 
630                                     its defining scope, its simple name  and a bitmask of the access flags. 
631                                     If an inner class is not a member, its outer_class is NULL, 
632                                     if a class is anonymous, its name is NULL.                              */
633                                                                 
634                                 innerclassinfo *info = c->innerclass + j;
635
636                                 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
637                                 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
638                                 info->name  = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8);        /* CONSTANT_Utf8_info index  */
639                                 info->flags = suck_u2 ();                                                 /* access_flags bitmask      */
640                         }
641                 } else {
642                         /* unknown attribute */
643                         skipattributebody ();
644                 }
645         }
646 }
647
648 /******************* function: checkfielddescriptor ****************************
649
650         checks whether a field-descriptor is valid and aborts otherwise
651         all referenced classes are inserted into the list of unloaded classes
652         
653 *******************************************************************************/
654
655 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
656 {
657         char *tstart;  /* pointer to start of classname */
658         char ch;
659         char *start = utf_ptr; /* XXX remove */
660
661         switch (*utf_ptr++) {
662           case 'B':
663           case 'C':
664           case 'I':
665           case 'S':
666           case 'Z':  
667           case 'J':  
668           case 'F':  
669           case 'D':
670                   /* primitive type */  
671                   break;
672                   
673           case '[':
674           case 'L':
675                   if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
676                           panic ("Ill formed descriptor");
677                   break;
678                   
679           default:   
680                   panic ("Ill formed descriptor");
681         }                       
682         
683         /* exceeding characters */              
684         if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
685 }
686
687
688 /******************* function checkmethoddescriptor ****************************
689
690     checks whether a method-descriptor is valid and aborts otherwise.
691     All referenced classes are inserted into the list of unloaded classes.
692         
693 *******************************************************************************/
694
695 static void checkmethoddescriptor (utf *d)
696 {
697         char *utf_ptr = d->text;     /* current position in utf text   */
698         char *end_pos = utf_end(d);  /* points behind utf string       */
699         char *tstart;                /* pointer to start of classname  */
700         char c,ch;
701         char *start; /* XXX remove */
702
703         /* method descriptor must start with parenthesis */
704         /* XXX check length */
705         if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
706
707         /* XXX check length */
708         /* check arguments */
709         while ((c = *utf_ptr++) != ')') {
710                 start = utf_ptr-1; /* XXX remove */
711                 
712                 switch (c) {
713                 case 'B':
714                 case 'C':
715                 case 'I':
716                 case 'S':
717                 case 'Z':  
718                 case 'J':  
719                 case 'F':  
720                 case 'D':
721                         /* primitive type */  
722                         break;
723
724                 case '[':
725                 case 'L':
726                         if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
727                                 panic ("Ill formed method descriptor");
728                         break;
729                         
730                 default:   
731                         panic ("Ill formed methodtype-descriptor");
732                 }
733         }
734
735         /* check returntype */
736         if (*utf_ptr=='V') {
737                 /* returntype void */
738                 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
739         }
740         else
741                 /* treat as field-descriptor */
742                 checkfielddescriptor (utf_ptr,end_pos);
743 }
744
745
746 /******************** Function: buildarraydescriptor ***************************
747
748         creates a constant_arraydescriptor structure for the array type named by an
749         utf string
750         
751 *******************************************************************************/
752
753 /* XXX delete */
754 #if 0
755 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
756 {
757         constant_arraydescriptor *d;
758
759         /* class_new( utf_new(utf_ptr,namelen) ); */ /* XXX remove */
760         
761         if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
762
763         d = NEW (constant_arraydescriptor);
764         d -> objectclass = NULL;
765         d -> elementdescriptor = NULL;
766
767 #ifdef STATISTICS
768         count_const_pool_len += sizeof(constant_arraydescriptor);
769 #endif
770
771         switch (*utf_ptr) {
772         case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
773         case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
774         case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
775         case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
776         case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
777         case 'I': d -> arraytype = ARRAYTYPE_INT; break;
778         case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
779         case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
780
781         case '[':
782                 d -> arraytype = ARRAYTYPE_ARRAY; 
783                 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
784                 break;
785                 
786         case 'L':
787                 d -> arraytype = ARRAYTYPE_OBJECT;
788
789                 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
790                 d -> objectclass  -> classUsed = NOTUSED; /* not used initially CO-RT */
791                 d -> objectclass  -> impldBy = NULL;
792                 break;
793         }
794         return d;
795 }
796 #endif
797
798
799 /******************* Function: freearraydescriptor *****************************
800
801         removes a structure created by buildarraydescriptor from memory
802         
803 *******************************************************************************/
804
805 /* XXX delete */
806 #if 0
807 static void freearraydescriptor (constant_arraydescriptor *d)
808 {
809         while (d) {
810                 constant_arraydescriptor *n = d->elementdescriptor;
811                 FREE (d, constant_arraydescriptor);
812                 d = n;
813                 }
814 }
815 #endif
816
817 /*********************** Function: displayarraydescriptor *********************/
818
819 /* XXX delete */
820 #if 0
821 static void displayarraydescriptor (constant_arraydescriptor *d)
822 {
823         switch (d->arraytype) {
824         case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
825         case ARRAYTYPE_BYTE: printf ("byte[]"); break;
826         case ARRAYTYPE_CHAR: printf ("char[]"); break;
827         case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
828         case ARRAYTYPE_FLOAT: printf ("float[]"); break;
829         case ARRAYTYPE_INT: printf ("int[]"); break;
830         case ARRAYTYPE_LONG: printf ("long[]"); break;
831         case ARRAYTYPE_SHORT: printf ("short[]"); break;
832         case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
833         case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
834         }
835 }
836 #endif
837
838 /***************** Function: print_arraydescriptor ****************************
839
840         Debugging helper for displaying an arraydescriptor
841         
842 *******************************************************************************/
843
844 void
845 print_arraydescriptor(FILE *file,arraydescriptor *desc)
846 {
847         if (!desc) {
848                 fprintf(file,"<NULL>");
849                 return;
850         }
851
852         fprintf(file,"{");
853         if (desc->componentvftbl) {
854                 if (desc->componentvftbl->class)
855                         utf_fprint(file,desc->componentvftbl->class->name);
856                 else
857                         fprintf(file,"<no classinfo>");
858         }
859         else
860                 fprintf(file,"0");
861                 
862         fprintf(file,",");
863         if (desc->elementvftbl) {
864                 if (desc->elementvftbl->class)
865                         utf_fprint(file,desc->elementvftbl->class->name);
866                 else
867                         fprintf(file,"<no classinfo>");
868         }
869         else
870                 fprintf(file,"0");
871         fprintf(file,",%d,%d,%d,%d}",desc->arraytype,desc->dimension,
872                         desc->dataoffset,desc->componentsize);
873 }
874
875 /******************************************************************************/
876 /**************************  Functions for fields  ****************************/
877 /******************************************************************************/
878
879
880 /************************ Function: field_load *********************************
881
882         Load everything about a class field from the class file and fill a
883         'fieldinfo' structure. For static fields, space in the data segment is
884         allocated.
885
886 *******************************************************************************/
887
888 static void field_load (fieldinfo *f, classinfo *c)
889 {
890         u4 attrnum,i;
891         u4 jtype;
892
893         f -> flags = suck_u2 ();                                           /* ACC flags                   */
894         f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);       /* name of field               */
895         f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor           */
896         f -> type = jtype = desc_to_type (f->descriptor);                  /* data type                   */
897         f -> offset = 0;                                                   /* offset from start of object */
898         f->xta = NULL;
899         
900         switch (f->type) {
901         case TYPE_INT:        f->value.i = 0; break;
902         case TYPE_FLOAT:      f->value.f = 0.0; break;
903         case TYPE_DOUBLE:     f->value.d = 0.0; break;
904         case TYPE_ADDRESS:    f->value.a = NULL;                              
905                               heap_addreference (&(f->value.a));           /* make global reference (GC)  */    
906                               break;
907         case TYPE_LONG:
908 #if U8_AVAILABLE
909                 f->value.l = 0; break;
910 #else
911                 f->value.l.low = 0; f->value.l.high = 0; break;
912 #endif 
913         }
914
915         /* read attributes */
916         attrnum = suck_u2();
917         for (i=0; i<attrnum; i++) {
918                 u4 pindex;
919                 utf *aname;
920
921                 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
922                 
923                 if ( aname != utf_constantvalue ) {
924                         /* unknown attribute */
925                         skipattributebody ();
926                         }
927                 else {
928                         /* constant value attribute */
929                         
930                         /* skip attribute length */
931                         suck_u4();
932                         /* index of value in constantpool */            
933                         pindex = suck_u2();
934                 
935                         /* initialize field with value from constantpool */             
936                         switch (jtype) {
937                                 case TYPE_INT: {
938                                         constant_integer *ci = 
939                                                 class_getconstant(c, pindex, CONSTANT_Integer);
940                                         f->value.i = ci -> value;
941                                         }
942                                         break;
943                                         
944                                 case TYPE_LONG: {
945                                         constant_long *cl = 
946                                            class_getconstant(c, pindex, CONSTANT_Long);
947         
948                                         f->value.l = cl -> value;
949                                         }
950                                         break;
951
952                                 case TYPE_FLOAT: {
953                                         constant_float *cf = 
954                                             class_getconstant(c, pindex, CONSTANT_Float);
955         
956                                         f->value.f = cf->value;
957                                         }
958                                         break;
959                                                                                         
960                                 case TYPE_DOUBLE: {
961                                         constant_double *cd = 
962                                             class_getconstant(c, pindex, CONSTANT_Double);
963         
964                                         f->value.d = cd->value;
965                                         }
966                                         break;
967                                                 
968                                 case TYPE_ADDRESS: { 
969                                         utf *u = class_getconstant(c, pindex, CONSTANT_String);
970                                         /* create javastring from compressed utf8-string */                                     
971                                         f->value.a = literalstring_new(u);
972                                         }
973                                         break;
974         
975                                 default: 
976                                         log_text ("Invalid Constant - Type");
977
978                                 }
979
980                         }
981                 }
982 }
983
984
985 /********************** function: field_free **********************************/
986
987 static void field_free (fieldinfo *f)
988 {
989         /* empty */
990 }
991
992
993 /**************** Function: field_display (debugging only) ********************/
994
995 void field_display (fieldinfo *f)
996 {
997         printf ("   ");
998         printflags (f -> flags);
999         printf (" ");
1000         utf_display (f -> name);
1001         printf (" ");
1002         utf_display (f -> descriptor);  
1003         printf (" offset: %ld\n", (long int) (f -> offset) );
1004 }
1005
1006
1007 /******************************************************************************/
1008 /************************* Functions for methods ******************************/ 
1009 /******************************************************************************/
1010
1011
1012 /*********************** Function: method_load *********************************
1013
1014         Loads a method from the class file and fills an existing 'methodinfo'
1015         structure. For native methods, the function pointer field is set to the
1016         real function pointer, for JavaVM methods a pointer to the compiler is used
1017         preliminarily.
1018         
1019 *******************************************************************************/
1020
1021 static void method_load (methodinfo *m, classinfo *c)
1022 {
1023         u4 attrnum,i,e;
1024         
1025 #ifdef STATISTICS
1026         count_all_methods++;
1027 #endif
1028
1029         m -> class = c;
1030         
1031         m -> flags = suck_u2 ();
1032         m -> name =  class_getconstant (c, suck_u2(), CONSTANT_Utf8);
1033         m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
1034         
1035         m -> jcode = NULL;
1036         m -> exceptiontable = NULL;
1037         m -> entrypoint = NULL;
1038         m -> mcode = NULL;
1039         m -> stubroutine = NULL;
1040         m -> methodUsed = NOTUSED;    
1041         m -> monoPoly = MONO;    
1042         m -> subRedefs = 0;
1043         m -> subRedefsUsed = 0;
1044
1045         m->xta = NULL;
1046         
1047         if (! (m->flags & ACC_NATIVE) ) {
1048                 m -> stubroutine = createcompilerstub (m);
1049                 }
1050         else {
1051
1052                 functionptr f = native_findfunction 
1053                        (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
1054                 if (f) {
1055                         m -> stubroutine = createnativestub (f, m);
1056                         }
1057                 }
1058         
1059         
1060         attrnum = suck_u2();
1061         for (i=0; i<attrnum; i++) {
1062                 utf *aname;
1063
1064                 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
1065
1066                 if ( aname != utf_code)  {
1067                         skipattributebody ();
1068                         }
1069                 else {
1070                         if (m -> jcode) panic ("Two code-attributes for one method!");
1071                         
1072                         suck_u4();
1073                         m -> maxstack = suck_u2();
1074                         m -> maxlocals = suck_u2();
1075                         m -> jcodelength = suck_u4();
1076                         m -> jcode = MNEW (u1, m->jcodelength);
1077                         suck_nbytes (m->jcode, m->jcodelength);
1078                         m -> exceptiontablelength = suck_u2 ();
1079                         m -> exceptiontable = 
1080                            MNEW (exceptiontable, m->exceptiontablelength);
1081
1082 #ifdef STATISTICS
1083         count_vmcode_len += m->jcodelength + 18;
1084         count_extable_len += 8 * m->exceptiontablelength;
1085 #endif
1086
1087                         for (e=0; e < m->exceptiontablelength; e++) {
1088                                 u4 idx;
1089                                 m -> exceptiontable[e].startpc = suck_u2();
1090                                 m -> exceptiontable[e].endpc = suck_u2();
1091                                 m -> exceptiontable[e].handlerpc = suck_u2();
1092
1093                                 idx = suck_u2();
1094                                 if (!idx) m -> exceptiontable[e].catchtype = NULL;
1095                                 else {
1096                                         m -> exceptiontable[e].catchtype = 
1097                                       class_getconstant (c, idx, CONSTANT_Class);
1098                                         }
1099                                 }                       
1100
1101                         skipattributes ( suck_u2() );
1102                         }
1103                         
1104                 }
1105
1106 }
1107
1108 /********************* Function: method_free ***********************************
1109
1110         frees all memory that was allocated for this method
1111
1112 *******************************************************************************/
1113
1114 static void method_free (methodinfo *m)
1115 {
1116         if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
1117         if (m->exceptiontable) 
1118                 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
1119         if (m->mcode) CFREE (m->mcode, m->mcodelength);
1120         if (m->stubroutine) {
1121                 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
1122                 else                       removecompilerstub (m->stubroutine);
1123                 }
1124 }
1125
1126
1127 /************** Function: method_display  (debugging only) **************/
1128
1129 void method_display (methodinfo *m)
1130 {
1131         printf ("   ");
1132         printflags (m -> flags);
1133         printf (" ");
1134         utf_display (m -> name);
1135         printf (" "); 
1136         utf_display (m -> descriptor);
1137         printf ("\n");
1138 }
1139
1140
1141 /******************** Function: method_canoverwrite ****************************
1142
1143         Check if m and old are identical with respect to type and name. This means
1144         that old can be overwritten with m.
1145         
1146 *******************************************************************************/  
1147
1148 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1149 {
1150         if (m->name != old->name) return false;
1151         if (m->descriptor != old->descriptor) return false;
1152         if (m->flags & ACC_STATIC) return false;
1153         return true;
1154 }
1155
1156
1157
1158
1159 /******************************************************************************/
1160 /************************ Functions for class *********************************/
1161 /******************************************************************************/
1162
1163
1164 /******************** function:: class_getconstant ******************************
1165
1166         retrieves the value at position 'pos' of the constantpool of a class
1167         if the type of the value is other than 'ctype' the system is stopped
1168
1169 *******************************************************************************/
1170
1171 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype) 
1172 {
1173         /* invalid position in constantpool */  
1174         if (pos >= c->cpcount) 
1175                 panic ("Attempt to access constant outside range");
1176
1177         /* check type of constantpool entry */
1178
1179         if (c->cptags[pos] != ctype) {
1180                 class_showconstantpool(c);
1181                 sprintf (logtext, "Type mismatch on constant: %d requested, %d here (class_getconstant)",
1182                  (int) ctype, (int) c->cptags[pos] );
1183                 error();
1184                 }
1185                 
1186         return c->cpinfos[pos];
1187 }
1188
1189
1190 /********************* Function: class_constanttype ****************************
1191
1192         Determines the type of a class entry in the ConstantPool
1193         
1194 *******************************************************************************/
1195
1196 u4 class_constanttype (classinfo *c, u4 pos)
1197 {
1198         if (pos >= c->cpcount) 
1199                 panic ("Attempt to access constant outside range");
1200         return c->cptags[pos];
1201 }
1202
1203
1204 /******************** function: class_loadcpool ********************************
1205
1206         loads the constantpool of a class, 
1207         the entries are transformed into a simpler format 
1208         by resolving references
1209         (a detailed overview of the compact structures can be found in global.h)        
1210
1211 *******************************************************************************/
1212
1213 static void class_loadcpool (classinfo *c)
1214 {
1215
1216         /* The following structures are used to save information which cannot be 
1217            processed during the first pass. After the complete constantpool has 
1218            been traversed the references can be resolved. 
1219            (only in specific order)                                                */
1220         
1221         /* CONSTANT_Class_info entries */
1222         typedef struct forward_class {      
1223                 struct forward_class *next; 
1224                 u2 thisindex;               
1225                 u2 name_index;              
1226         } forward_class;                    
1227                                         
1228         /* CONSTANT_String */                                      
1229         typedef struct forward_string { 
1230                 struct forward_string *next; 
1231                 u2 thisindex;                
1232                 u2 string_index;
1233         } forward_string;
1234
1235         /* CONSTANT_NameAndType */
1236         typedef struct forward_nameandtype {
1237                 struct forward_nameandtype *next;
1238                 u2 thisindex;
1239                 u2 name_index;
1240                 u2 sig_index;
1241         } forward_nameandtype;
1242
1243         /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1244         typedef struct forward_fieldmethint {   
1245                 struct forward_fieldmethint *next;
1246                 u2 thisindex;
1247                 u1 tag;
1248                 u2 class_index;
1249                 u2 nameandtype_index;
1250         } forward_fieldmethint;
1251
1252
1253         u4 idx;
1254         long int dumpsize = dump_size ();
1255
1256         forward_class *forward_classes = NULL;
1257         forward_string *forward_strings = NULL;
1258         forward_nameandtype *forward_nameandtypes = NULL;
1259         forward_fieldmethint *forward_fieldmethints = NULL;
1260
1261         /* number of entries in the constant_pool table  */
1262         u4 cpcount       = c -> cpcount = suck_u2();
1263         /* allocate memory */
1264         u1 *cptags       = c -> cptags  = MNEW (u1, cpcount);
1265         voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1266
1267 #ifdef STATISTICS
1268         count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1269 #endif
1270         
1271         /* initialize constantpool */
1272         for (idx=0; idx<cpcount; idx++) {
1273                 cptags[idx] = CONSTANT_UNUSED;
1274                 cpinfos[idx] = NULL;
1275                 }
1276
1277                         
1278                 /******* first pass *******/
1279                 /* entries which cannot be resolved now are written into 
1280                    temporary structures and traversed again later        */
1281                    
1282         idx = 1;
1283         while (idx < cpcount) {
1284                 /* get constant type */
1285                 u4 t = suck_u1 (); 
1286                 switch ( t ) {
1287
1288                         case CONSTANT_Class: { 
1289                                 forward_class *nfc = DNEW(forward_class);
1290
1291                                 nfc -> next = forward_classes;                                                                                  
1292                                 forward_classes = nfc;
1293
1294                                 nfc -> thisindex = idx;
1295                                 /* reference to CONSTANT_NameAndType */
1296                                 nfc -> name_index = suck_u2 (); 
1297
1298                                 idx++;
1299                                 break;
1300                                 }
1301                         
1302                         case CONSTANT_Fieldref:
1303                         case CONSTANT_Methodref:
1304                         case CONSTANT_InterfaceMethodref: { 
1305                                 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1306                                 
1307                                 nff -> next = forward_fieldmethints;
1308                                 forward_fieldmethints = nff;
1309
1310                                 nff -> thisindex = idx;
1311                                 /* constant type */
1312                                 nff -> tag = t;
1313                                 /* class or interface type that contains the declaration of the field or method */
1314                                 nff -> class_index = suck_u2 (); 
1315                                 /* name and descriptor of the field or method */
1316                                 nff -> nameandtype_index = suck_u2 ();
1317
1318                                 idx ++;
1319                                 break;
1320                                 }
1321                                 
1322                         case CONSTANT_String: {
1323                                 forward_string *nfs = DNEW (forward_string);
1324                                 
1325                                 nfs -> next = forward_strings;
1326                                 forward_strings = nfs;
1327                                 
1328                                 nfs -> thisindex = idx;
1329                                 /* reference to CONSTANT_Utf8_info with string characters */
1330                                 nfs -> string_index = suck_u2 ();
1331                                 
1332                                 idx ++;
1333                                 break;
1334                                 }
1335
1336                         case CONSTANT_NameAndType: {
1337                                 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1338                                 
1339                                 nfn -> next = forward_nameandtypes;
1340                                 forward_nameandtypes = nfn;
1341                                 
1342                                 nfn -> thisindex = idx;
1343                                 /* reference to CONSTANT_Utf8_info containing simple name */
1344                                 nfn -> name_index = suck_u2 ();
1345                                 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1346                                 nfn -> sig_index = suck_u2 ();
1347                                 
1348                                 idx ++;
1349                                 break;
1350                                 }
1351
1352                         case CONSTANT_Integer: {
1353                                 constant_integer *ci = NEW (constant_integer);
1354
1355 #ifdef STATISTICS
1356         count_const_pool_len += sizeof(constant_integer);
1357 #endif
1358
1359                                 ci -> value = suck_s4 ();
1360                                 cptags [idx] = CONSTANT_Integer;
1361                                 cpinfos [idx] = ci;
1362                                 idx ++;
1363                                 
1364                                 break;
1365                                 }
1366                                 
1367                         case CONSTANT_Float: {
1368                                 constant_float *cf = NEW (constant_float);
1369
1370 #ifdef STATISTICS
1371         count_const_pool_len += sizeof(constant_float);
1372 #endif
1373
1374                                 cf -> value = suck_float ();
1375                                 cptags [idx] = CONSTANT_Float;
1376                                 cpinfos[idx] = cf;
1377                                 idx ++;
1378                                 break;
1379                                 }
1380                                 
1381                         case CONSTANT_Long: {
1382                                 constant_long *cl = NEW(constant_long);
1383                                         
1384 #ifdef STATISTICS
1385         count_const_pool_len += sizeof(constant_long);
1386 #endif
1387
1388                                 cl -> value = suck_s8 ();
1389                                 cptags [idx] = CONSTANT_Long;
1390                                 cpinfos [idx] = cl;
1391                                 idx += 2;
1392                                 break;
1393                                 }
1394                         
1395                         case CONSTANT_Double: {
1396                                 constant_double *cd = NEW(constant_double);
1397                                 
1398 #ifdef STATISTICS
1399         count_const_pool_len += sizeof(constant_double);
1400 #endif
1401
1402                                 cd -> value = suck_double ();
1403                                 cptags [idx] = CONSTANT_Double;
1404                                 cpinfos [idx] = cd;
1405                                 idx += 2;
1406                                 break;
1407                                 }
1408                                 
1409                         case CONSTANT_Utf8: { 
1410
1411                                 /* number of bytes in the bytes array (not string-length) */
1412                                 u4 length = suck_u2();
1413                                 cptags [idx]  = CONSTANT_Utf8;
1414                                 /* insert utf-string into the utf-symboltable */
1415                                 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1416                                 /* skip bytes of the string */
1417                                 skip_nbytes(length);
1418                                 idx++;
1419                                 break;
1420                                 }
1421                                                                                 
1422                         default:
1423                                 sprintf (logtext, "Unkown constant type: %d",(int) t);
1424                                 error ();
1425                 
1426                         }  /* end switch */
1427                         
1428                 } /* end while */
1429                 
1430
1431
1432            /* resolve entries in temporary structures */
1433
1434         while (forward_classes) {
1435                 utf *name =
1436                   class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1437
1438                 cptags  [forward_classes -> thisindex] = CONSTANT_Class;
1439                 /* retrieve class from class-table */
1440                 cpinfos [forward_classes -> thisindex] = class_new (name);
1441
1442                 forward_classes = forward_classes -> next;
1443                 
1444                 }
1445
1446         while (forward_strings) {
1447                 utf *text = 
1448                   class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1449 /*
1450                 log_text("forward_string:");
1451                 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1452                 utf_display(text);
1453                 log_text("\n------------------"); */
1454                 /* resolve utf-string */                
1455                 cptags   [forward_strings -> thisindex] = CONSTANT_String;
1456                 cpinfos  [forward_strings -> thisindex] = text;
1457                 
1458                 forward_strings = forward_strings -> next;
1459                 }       
1460
1461         while (forward_nameandtypes) {
1462                 constant_nameandtype *cn = NEW (constant_nameandtype);  
1463
1464 #ifdef STATISTICS
1465                 count_const_pool_len += sizeof(constant_nameandtype);
1466 #endif
1467
1468                 /* resolve simple name and descriptor */
1469                 cn -> name = class_getconstant 
1470                    (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1471                 cn -> descriptor = class_getconstant
1472                    (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1473                  
1474                 cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1475                 cpinfos  [forward_nameandtypes -> thisindex] = cn;
1476                 
1477                 forward_nameandtypes = forward_nameandtypes -> next;
1478                 }
1479
1480
1481         while (forward_fieldmethints)  {
1482                 constant_nameandtype *nat;
1483                 constant_FMIref *fmi = NEW (constant_FMIref);
1484
1485 #ifdef STATISTICS
1486                 count_const_pool_len += sizeof(constant_FMIref);
1487 #endif
1488                 /* resolve simple name and descriptor */
1489                 nat = class_getconstant
1490                         (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1491
1492 #ifdef JOWENN_DEBUG
1493                 log_text("trying to resolve:");
1494                 log_text(nat->name->text);
1495                 switch(forward_fieldmethints ->tag) {
1496                 case CONSTANT_Fieldref: 
1497                                 log_text("CONSTANT_Fieldref");
1498                                 break;
1499                 case CONSTANT_InterfaceMethodref: 
1500                                 log_text("CONSTANT_InterfaceMethodref");
1501                                 break;
1502                 case CONSTANT_Methodref: 
1503                                 log_text("CONSTANT_Methodref");
1504                                 break;
1505                 }
1506 #endif
1507                 fmi -> class = class_getconstant 
1508                         (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1509                 fmi -> name = nat -> name;
1510                 fmi -> descriptor = nat -> descriptor;
1511
1512                 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1513                 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1514         
1515                 switch (forward_fieldmethints -> tag) {
1516                 case CONSTANT_Fieldref:  /* check validity of descriptor */
1517                                          checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1518                                          break;
1519                 case CONSTANT_InterfaceMethodref: 
1520                 case CONSTANT_Methodref: /* check validity of descriptor */
1521                                          checkmethoddescriptor (fmi->descriptor);
1522                                          break;
1523                 }               
1524         
1525                 forward_fieldmethints = forward_fieldmethints -> next;
1526
1527                 }
1528
1529 /*      class_showconstantpool(c); */
1530
1531         dump_release (dumpsize);
1532 }
1533
1534
1535 /********************** Function: class_load ***********************************
1536         
1537         Loads everything interesting about a class from the class file. The
1538         'classinfo' structure must have been allocated previously.
1539
1540         The super class and the interfaces implemented by this class need not be
1541         loaded. The link is set later by the function 'class_link'.
1542
1543         The loaded class is removed from the list 'unloadedclasses' and added to
1544         the list 'unlinkedclasses'.
1545         
1546 *******************************************************************************/
1547
1548 static int class_load (classinfo *c)
1549 {
1550         u4 i;
1551         u4 mi,ma;
1552
1553 #ifdef STATISTICS
1554         count_class_loads++;
1555 #endif
1556
1557         /* XXX remove */
1558         /*      loadverbose = 1; */
1559         
1560         /* output for debugging purposes */
1561         if (loadverbose) {              
1562
1563                 sprintf (logtext, "Loading class: ");
1564                 utf_sprint (logtext+strlen(logtext), c->name );
1565                 dolog();
1566                 }
1567         
1568         /* load classdata, throw exception on error */
1569
1570         if (!suck_start (c->name)) {
1571                 throw_classnotfoundexception2(c->name);            
1572                 return false;
1573         }
1574         
1575         /* check signature */           
1576         if (suck_u4() != MAGIC) panic("Can not find class-file signature");     
1577         /* check version */
1578         mi = suck_u2(); 
1579         ma = suck_u2();
1580         if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1581                 sprintf (logtext, "File version %d.%d is not supported",
1582                                  (int) ma, (int) mi);
1583                 error();
1584                 }
1585
1586         class_loadcpool (c);
1587         /*JOWENN*/
1588         c->erroneous_state=0;
1589         c->initializing_thread=0;       
1590         /*JOWENN*/
1591         c -> classUsed = NOTUSED; /* not used initially CO-RT */
1592         c -> impldBy = NULL;
1593
1594         /* ACC flags */
1595         c -> flags = suck_u2 (); 
1596         /* this class */
1597         suck_u2 ();       
1598         
1599         /* retrieve superclass */
1600         if ( (i = suck_u2 () ) ) {
1601                 c -> super = class_getconstant (c, i, CONSTANT_Class);
1602                 }
1603         else {
1604                 c -> super = NULL;
1605                 }
1606                          
1607         /* retrieve interfaces */
1608         c -> interfacescount = suck_u2 ();
1609         c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1610         for (i=0; i < c -> interfacescount; i++) {
1611                 c -> interfaces [i] = 
1612                       class_getconstant (c, suck_u2(), CONSTANT_Class);
1613                 }
1614
1615         /* load fields */
1616         c -> fieldscount = suck_u2 ();
1617 /*      utf_display(c->name);
1618         printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1619
1620         c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1621         for (i=0; i < c -> fieldscount; i++) {
1622                 field_load (&(c->fields[i]), c);
1623                 }
1624
1625         /* load methods */
1626         c -> methodscount = suck_u2 ();
1627         c -> methods = MNEW (methodinfo, c -> methodscount);
1628         for (i=0; i < c -> methodscount; i++) {
1629                 method_load (&(c -> methods [i]), c);
1630                 }
1631
1632 #ifdef STATISTICS
1633         count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1634         count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1635         count_class_infos += sizeof(methodinfo) * c -> methodscount;
1636 #endif
1637
1638         /* load variable-length attribute structures */ 
1639         attribute_load (suck_u2(), c);
1640
1641         /* free memory */
1642         suck_stop ();
1643
1644         /* remove class from list of unloaded classes and 
1645            add to list of unlinked classes                */
1646         list_remove (&unloadedclasses, c);
1647         list_addlast (&unlinkedclasses, c);
1648
1649         return true;
1650 }
1651
1652
1653
1654 /************** internal Function: class_highestinterface ***********************
1655
1656         Used by the function class_link to determine the amount of memory needed
1657         for the interface table.
1658
1659 *******************************************************************************/
1660
1661 static s4 class_highestinterface (classinfo *c) 
1662 {
1663         s4 h;
1664         s4 i;
1665         
1666         if ( ! (c->flags & ACC_INTERFACE) ) {
1667                 sprintf (logtext, "Interface-methods count requested for non-interface:  ");
1668         utf_sprint (logtext+strlen(logtext), c->name);
1669         error();
1670         }
1671     
1672     h = c->index;
1673         for (i=0; i<c->interfacescount; i++) {
1674                 s4 h2 = class_highestinterface (c->interfaces[i]);
1675                 if (h2>h) h=h2;
1676                 }
1677         return h;
1678 }
1679
1680
1681 /* class_addinterface **********************************************************
1682
1683         Is needed by class_link for adding a VTBL to a class. All interfaces
1684         implemented by ic are added as well.
1685
1686 *******************************************************************************/        
1687
1688 static void class_addinterface (classinfo *c, classinfo *ic)
1689 {
1690         s4     j, m;
1691         s4     i     = ic->index;
1692         vftbl *vftbl = c->vftbl;
1693         
1694         if (i >= vftbl->interfacetablelength)
1695                 panic ("Inernal error: interfacetable overflow");
1696         if (vftbl->interfacetable[-i])
1697                 return;
1698
1699         if (ic->methodscount == 0) {  /* fake entry needed for subtype test */
1700                 vftbl->interfacevftbllength[i] = 1;
1701                 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1702                 vftbl->interfacetable[-i][0] = NULL;
1703                 }
1704         else {
1705                 vftbl->interfacevftbllength[i] = ic->methodscount;
1706                 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount); 
1707
1708 #ifdef STATISTICS
1709         count_vftbl_len += sizeof(methodptr) *
1710                                  (ic->methodscount + (ic->methodscount == 0));
1711 #endif
1712
1713                 for (j=0; j<ic->methodscount; j++) {
1714                         classinfo *sc = c;
1715                         while (sc) {
1716                                 for (m = 0; m < sc->methodscount; m++) {
1717                                         methodinfo *mi = &(sc->methods[m]);
1718                                         if (method_canoverwrite(mi, &(ic->methods[j]))) {
1719                                                 vftbl->interfacetable[-i][j] = 
1720                                                                           vftbl->table[mi->vftblindex];
1721                                                 goto foundmethod;
1722                                                 }
1723                                         }
1724                                 sc = sc->super;
1725                                 }
1726                          foundmethod: ;
1727                         }
1728                 }
1729
1730         for (j = 0; j < ic->interfacescount; j++) 
1731                 class_addinterface(c, ic->interfaces[j]);
1732 }
1733
1734
1735 /******************* Function: class_new_array *********************************
1736
1737     This function is called by class_new to setup an array class.
1738
1739 *******************************************************************************/
1740
1741 void
1742 class_new_array(classinfo *c)
1743 {
1744         classinfo *comp = NULL;
1745         methodinfo *clone;
1746         int namelen;
1747
1748         /* XXX remove logging */
1749         /*
1750         sprintf(logtext,"new array class: ");
1751         utf_sprint(logtext+strlen(logtext),c->name);
1752         dolog();
1753         */
1754         
1755         /* Array classes are not loaded from classfiles. */
1756         list_remove (&unloadedclasses, c);
1757
1758         /* Check array class name */
1759         namelen = c->name->blength;
1760         if (namelen < 2 || c->name->text[0] != '[')
1761                 panic("Invalid array class name.");
1762
1763         /* Check the component type */
1764         switch (c->name->text[1]) {
1765           case '[':
1766                   /* c is an array of arrays. We have to create the component class. */
1767                   comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1768                   break;
1769
1770           case 'L':
1771                   /* XXX remove logging */
1772                   /*
1773                   sprintf(logtext,"Component class: ");
1774                   utf_sprint(logtext+strlen(logtext),utf_new(c->name->text + 2,namelen - 3));
1775                   dolog();
1776                   if (class_get(utf_new(c->name->text + 2,namelen - 3)))
1777                           log_text("Already created.");
1778                   */
1779                   
1780                   /* c is an array of objects. */
1781                   if (namelen < 4 || c->name->text[namelen-1] != ';')
1782                           panic("Invalid array class name.");
1783                   comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1784                   break;
1785         }
1786
1787         /* Setup the array class */
1788         c->super = class_java_lang_Object;
1789
1790     c->interfacescount = 2;
1791     c->interfaces = MNEW(classinfo*,2);
1792     c->interfaces[0] = class_java_lang_Cloneable;
1793     c->interfaces[1] = class_java_io_Serializable;
1794
1795         c->methodscount = 1;
1796         c->methods = MNEW (methodinfo, c->methodscount);
1797
1798         clone = c->methods;
1799         memset(clone,0,sizeof(methodinfo));
1800         clone->flags = ACC_PUBLIC; /* XXX protected? */
1801         clone->name = utf_new_char("clone");
1802         clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1803         clone->class = c;
1804         clone->stubroutine = createnativestub(&builtin_clone_array,clone);
1805         clone->monoPoly = MONO; /* XXX should be poly? */
1806
1807         /* XXX: field: length? */
1808
1809         /* The array class has to be linked */
1810         list_addlast(&unlinkedclasses,c);
1811         
1812         /*
1813      * Array classes which are created after the other classes have been
1814      * loaded and linked are linked explicitely.
1815      */
1816         if (loader_inited)
1817                 loader_load(c->name);
1818 }
1819
1820 /****************** Function: class_link_array *********************************
1821
1822     This function is called by class_link to create the
1823     arraydescriptor for an array class.
1824
1825     This function returns NULL if the array cannot be linked because
1826     the component type has not been linked yet.
1827
1828 *******************************************************************************/
1829
1830 static
1831 arraydescriptor *
1832 class_link_array(classinfo *c)
1833 {
1834         classinfo *comp = NULL;
1835         int namelen = c->name->blength;
1836         arraydescriptor *desc;
1837         vftbl *compvftbl;
1838
1839         /* XXX remove logging */
1840
1841         /*
1842           sprintf(logtext,"linking array class: ");
1843           utf_sprint(logtext+strlen(logtext),c->name);
1844           dolog();
1845         */
1846         
1847         
1848         /* Check the component type */
1849         switch (c->name->text[1]) {
1850           case '[':
1851                   /* c is an array of arrays. */
1852                   comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1853                   if (!comp) panic("Could not find component array class.");
1854                   break;
1855
1856           case 'L':
1857                   /* c is an array of objects. */
1858                   comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1859                   if (!comp) panic("Could not find component class.");
1860                   break;
1861         }
1862
1863         /* If the component type has not been linked return NULL */
1864         if (comp && !comp->linked)
1865                 return NULL;
1866
1867         /* Allocate the arraydescriptor */
1868         desc = NEW(arraydescriptor);
1869
1870         if (comp) {
1871                 /* c is an array of references */
1872                 desc->arraytype = ARRAYTYPE_OBJECT;
1873                 desc->componentsize = sizeof(void*);
1874                 desc->dataoffset = OFFSET(java_objectarray,data);
1875                 
1876                 compvftbl = comp->vftbl;
1877                 if (!compvftbl)
1878                         panic("Component class has no vftbl.");
1879                 desc->componentvftbl = compvftbl;
1880                 
1881                 if (compvftbl->arraydesc) {
1882                         desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1883                         desc->dimension = compvftbl->arraydesc->dimension + 1;
1884                 }
1885                 else {
1886                         desc->elementvftbl = compvftbl;
1887                         desc->dimension = 1;
1888                 }
1889         }
1890         else {
1891                 /* c is an array of a primitive type */
1892                 switch (c->name->text[1]) {
1893                   case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1894                             desc->dataoffset = OFFSET(java_booleanarray,data);
1895                                 desc->componentsize = sizeof(u1); break;
1896                   case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1897                             desc->dataoffset = OFFSET(java_bytearray,data);
1898                                 desc->componentsize = sizeof(u1); break;
1899                   case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1900                             desc->dataoffset = OFFSET(java_chararray,data);
1901                                 desc->componentsize = sizeof(u2); break;
1902                   case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1903                             desc->dataoffset = OFFSET(java_doublearray,data);
1904                                 desc->componentsize = sizeof(double); break;
1905                   case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1906                             desc->dataoffset = OFFSET(java_floatarray,data);
1907                                 desc->componentsize = sizeof(float); break;
1908                   case 'I': desc->arraytype = ARRAYTYPE_INT;
1909                             desc->dataoffset = OFFSET(java_intarray,data);
1910                                 desc->componentsize = sizeof(s4); break;
1911                   case 'J': desc->arraytype = ARRAYTYPE_LONG;
1912                             desc->dataoffset = OFFSET(java_longarray,data);
1913                                 desc->componentsize = sizeof(s8); break;
1914                   case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1915                             desc->dataoffset = OFFSET(java_shortarray,data);
1916                                 desc->componentsize = sizeof(s2); break;
1917                   default:
1918                           panic("Invalid array class name");
1919                 }
1920                 
1921                 desc->componentvftbl = NULL;
1922                 desc->elementvftbl = NULL;
1923                 desc->dimension = 1;
1924         }
1925
1926         /* XXX remove logging */
1927         /*
1928           print_arraydescriptor(stdout,desc); 
1929           printf("\n");
1930         */
1931
1932         return desc;
1933 }
1934
1935 /********************** Function: class_link ***********************************
1936
1937         Tries to link a class. The super class and every implemented interface must
1938         already have been linked. The function calculates the length in bytes that
1939         an instance of this class requires as well as the VTBL for methods and
1940         interface methods.
1941         
1942         If the class can be linked, it is removed from the list 'unlinkedclasses'
1943         and added to 'linkedclasses'. Otherwise, it is moved to the end of
1944         'unlinkedclasses'.
1945
1946         Attention: If cyclical class definitions are encountered, the program gets
1947         into an infinite loop (we'll have to work that out)
1948
1949 *******************************************************************************/
1950
1951 void class_link(classinfo *c)
1952 {
1953         s4 supervftbllength;          /* vftbllegnth of super class               */
1954         s4 vftbllength;               /* vftbllength of current class             */
1955         s4 interfacetablelength;      /* interface table length                   */
1956         classinfo *super = c->super;  /* super class                              */
1957         classinfo *ic, *c2;           /* intermediate class variables             */
1958         vftbl *v;                     /* vftbl of current class                   */
1959         s4 i;                         /* interface/method/field counter           */
1960         arraydescriptor *arraydesc = NULL;  /* descriptor for array classes       */
1961
1962
1963         /* XXX remove log */
1964         /*
1965           sprintf(logtext,"trying to link: ");
1966           utf_sprint(logtext+strlen(logtext),c->name);
1967           dolog();
1968         */
1969         
1970         /*  check if all superclasses are already linked, if not put c at end of
1971             unlinked list and return. Additionally initialize class fields.       */
1972
1973         /*  check interfaces */
1974
1975         for (i = 0; i < c->interfacescount; i++) {
1976                 ic = c->interfaces[i];
1977                 if (!ic->linked) {
1978                         list_remove(&unlinkedclasses, c);
1979                         list_addlast(&unlinkedclasses, c);
1980                         return; 
1981                 }
1982         }
1983         
1984         /*  check super class */
1985
1986         if (super == NULL) {          /* class java.long.Object */
1987                 c->index = 0;
1988         c->classUsed = USED;     /* Object class is always used CO-RT*/
1989                 c -> impldBy = NULL;
1990                 c->instancesize = sizeof(java_objectheader);
1991                 
1992                 vftbllength = supervftbllength = 0;
1993
1994                 c->finalizer = NULL;
1995         }
1996         else {
1997                 if (!super->linked) {
1998                         list_remove(&unlinkedclasses, c);
1999                         list_addlast(&unlinkedclasses, c);
2000                         return; 
2001                 }
2002
2003                 /* handle array classes */
2004                 if (c->name->text[0] == '[')
2005                         if ((arraydesc = class_link_array(c)) == NULL) {
2006                                 list_remove(&unlinkedclasses, c);
2007                                 list_addlast(&unlinkedclasses, c);
2008                                 return; 
2009                         }
2010                 
2011                 if (c->flags & ACC_INTERFACE)
2012                         c->index = interfaceindex++;
2013                 else
2014                         c->index = super->index + 1;
2015                 
2016                 c->instancesize = super->instancesize;
2017                 
2018                 vftbllength = supervftbllength = super->vftbl->vftbllength;
2019                 
2020                 c->finalizer = super->finalizer;
2021         }
2022
2023
2024         if (linkverbose) {
2025                 sprintf (logtext, "Linking Class: ");
2026                 utf_sprint (logtext+strlen(logtext), c->name );
2027                 dolog ();
2028         }
2029
2030         /* compute vftbl length */
2031
2032         for (i = 0; i < c->methodscount; i++) {
2033                 methodinfo *m = &(c->methods[i]);
2034                         
2035                 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2036                         classinfo *sc = super;
2037                         while (sc) {
2038                                 int j;
2039                                 for (j = 0; j < sc->methodscount; j++) {
2040                                         if (method_canoverwrite(m, &(sc->methods[j]))) {
2041                                                 m->vftblindex = sc->methods[j].vftblindex;
2042                                                 goto foundvftblindex;
2043                                         }
2044                                 }
2045                                 sc = sc->super;
2046                         }
2047                         m->vftblindex = (vftbllength++);
2048                 foundvftblindex: ;
2049                 }
2050         }       
2051         
2052 #ifdef STATISTICS
2053         count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
2054 #endif
2055
2056         /* compute interfacetable length */
2057
2058         interfacetablelength = 0;
2059         c2 = c;
2060         while (c2) {
2061                 for (i = 0; i < c2->interfacescount; i++) {
2062                         s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2063                         if (h > interfacetablelength)
2064                                 interfacetablelength = h;
2065                 }
2066                 c2 = c2->super;
2067         }
2068
2069         /* allocate virtual function table */
2070
2071         v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2072                                                    (vftbllength - 1) + sizeof(methodptr*) *
2073                                                    (interfacetablelength - (interfacetablelength > 0)));
2074         v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2075                                   (interfacetablelength > 1));
2076         c->header.vftbl = c->vftbl = v;
2077         v->class = c;
2078         v->vftbllength = vftbllength;
2079         v->interfacetablelength = interfacetablelength;
2080         v->arraydesc = arraydesc;
2081
2082         /* store interface index in vftbl */
2083         if (c->flags & ACC_INTERFACE)
2084                 v->baseval = -(c->index);
2085
2086         /* copy virtual function table of super class */
2087
2088         for (i = 0; i < supervftbllength; i++) 
2089                 v->table[i] = super->vftbl->table[i];
2090         
2091         /* add method stubs into virtual function table */
2092
2093         for (i = 0; i < c->methodscount; i++) {
2094                 methodinfo *m = &(c->methods[i]);
2095                 if (!(m->flags & ACC_STATIC)) {
2096                         v->table[m->vftblindex] = m->stubroutine;
2097                 }
2098         }
2099
2100         /* compute instance size and offset of each field */
2101         
2102         for (i = 0; i < c->fieldscount; i++) {
2103                 s4 dsize;
2104                 fieldinfo *f = &(c->fields[i]);
2105                 
2106                 if (!(f->flags & ACC_STATIC) ) {
2107                         dsize = desc_typesize (f->descriptor);
2108                         c->instancesize = ALIGN (c->instancesize, dsize);
2109                         f->offset = c->instancesize;
2110                         c->instancesize += dsize;
2111                 }
2112         }
2113
2114         /* initialize interfacetable and interfacevftbllength */
2115         
2116         v->interfacevftbllength = MNEW (s4, interfacetablelength);
2117
2118 #ifdef STATISTICS
2119         count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2120 #endif
2121
2122         for (i = 0; i < interfacetablelength; i++) {
2123                 v->interfacevftbllength[i] = 0;
2124                 v->interfacetable[-i] = NULL;
2125         }
2126         
2127         /* add interfaces */
2128         
2129         for (c2 = c; c2 != NULL; c2 = c2->super)
2130                 for (i = 0; i < c2->interfacescount; i++) {
2131                         class_addinterface (c, c2->interfaces[i]);
2132                 }
2133
2134         /* add finalizer method (not for java.lang.Object) */
2135
2136         if (super != NULL) {
2137                 methodinfo *fi;
2138                 static utf *finame = NULL;
2139                 static utf *fidesc = NULL;
2140
2141                 if (finame == NULL)
2142                         finame = utf_finalize;
2143                 if (fidesc == NULL)
2144                         fidesc = utf_fidesc;
2145
2146                 fi = class_findmethod (c, finame, fidesc);
2147                 if (fi != NULL) {
2148                         if (!(fi->flags & ACC_STATIC)) {
2149                                 c->finalizer = fi;
2150                         }
2151                 }
2152         }
2153
2154         /* final tasks */
2155
2156         c->linked = true;       
2157
2158         list_remove (&unlinkedclasses, c);
2159         list_addlast (&linkedclasses, c);
2160
2161 }
2162
2163
2164 /******************* Function: class_freepool **********************************
2165
2166         Frees all resources used by this classes Constant Pool.
2167
2168 *******************************************************************************/
2169
2170 static void class_freecpool (classinfo *c)
2171 {
2172         u4 idx;
2173         u4 tag;
2174         voidptr info;
2175         
2176         for (idx=0; idx < c->cpcount; idx++) {
2177                 tag = c->cptags[idx];
2178                 info = c->cpinfos[idx];
2179                 
2180                 if (info != NULL) {
2181                         switch (tag) {
2182                         case CONSTANT_Fieldref:
2183                         case CONSTANT_Methodref:
2184                         case CONSTANT_InterfaceMethodref:
2185                                 FREE (info, constant_FMIref);
2186                                 break;
2187                         case CONSTANT_Integer:
2188                                 FREE (info, constant_integer);
2189                                 break;
2190                         case CONSTANT_Float:
2191                                 FREE (info, constant_float);
2192                                 break;
2193                         case CONSTANT_Long:
2194                                 FREE (info, constant_long);
2195                                 break;
2196                         case CONSTANT_Double:
2197                                 FREE (info, constant_double);
2198                                 break;
2199                         case CONSTANT_NameAndType:
2200                                 FREE (info, constant_nameandtype);
2201                                 break;
2202                         }
2203                         }
2204                 }
2205
2206         MFREE (c -> cptags,  u1, c -> cpcount);
2207         MFREE (c -> cpinfos, voidptr, c -> cpcount);
2208 }
2209
2210
2211 /*********************** Function: class_free **********************************
2212
2213         Frees all resources used by the class.
2214
2215 *******************************************************************************/
2216
2217 static void class_free (classinfo *c)
2218 {
2219         s4 i;
2220         vftbl *v;
2221                 
2222         class_freecpool (c);
2223
2224         MFREE (c->interfaces, classinfo*, c->interfacescount);
2225
2226         for (i = 0; i < c->fieldscount; i++)
2227                 field_free(&(c->fields[i]));
2228         
2229         for (i = 0; i < c->methodscount; i++)
2230                 method_free(&(c->methods[i]));
2231         MFREE (c->methods, methodinfo, c->methodscount);
2232
2233         if ((v = c->vftbl) != NULL) {
2234                 if (v->arraydesc)
2235                         mem_free(v->arraydesc,sizeof(arraydescriptor));
2236                 
2237                 for (i = 0; i < v->interfacetablelength; i++) {
2238                         MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2239                         }
2240                 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
2241
2242                 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2243                     sizeof(methodptr*) * (v->interfacetablelength -
2244                                          (v->interfacetablelength > 0));
2245                 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2246                                              (v->interfacetablelength > 1));
2247                 mem_free (v, i);
2248                 }
2249
2250         if (c->innerclasscount)
2251                 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
2252
2253         /*      if (c->classvftbl)
2254                 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2255         
2256         FREE (c, classinfo);
2257 }
2258
2259 /************************* Function: class_findfield ***************************
2260         
2261         Searches a 'classinfo' structure for a field having the given name and
2262         type.
2263
2264 *******************************************************************************/
2265
2266
2267 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
2268 {
2269         s4 i;
2270
2271         
2272         for (i = 0; i < c->fieldscount; i++) { 
2273                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
2274                         return &(c->fields[i]);                                                         
2275     }
2276
2277         panic ("Can not find field given in CONSTANT_Fieldref");
2278         return NULL;
2279 }
2280
2281
2282 /************************* Function: class_findmethod **************************
2283         
2284         Searches a 'classinfo' structure for a method having the given name and
2285         type and returns the index in the class info structure.
2286         If type is NULL, it is ignored.
2287
2288 *******************************************************************************/
2289
2290 s4 class_findmethodIndex (classinfo *c, utf *name, utf *desc)
2291 {
2292         s4 i;
2293 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2294         char *buffer;                   
2295         int buffer_len, pos;
2296 #endif
2297 #ifdef JOWENN_DEBUG1
2298
2299         buffer_len = 
2300           utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2301         
2302         buffer = MNEW(char, buffer_len);
2303
2304         strcpy(buffer, "class_findmethod: method:");
2305         utf_sprint(buffer+strlen(buffer), name);
2306         strcpy(buffer+strlen(buffer), ", desc: ");
2307         utf_sprint(buffer+strlen(buffer), desc);
2308         strcpy(buffer+strlen(buffer), ", classname: ");
2309         utf_sprint(buffer+strlen(buffer), c->name);
2310         
2311         log_text(buffer);       
2312
2313         MFREE(buffer, char, buffer_len);
2314 #endif  
2315         for (i = 0; i < c->methodscount; i++) {
2316 #ifdef JOWENN_DEBUG2
2317                 buffer_len = 
2318                   utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2319         
2320                 buffer = MNEW(char, buffer_len);
2321
2322                 strcpy(buffer, "class_findmethod: comparing to method:");
2323                 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2324                 strcpy(buffer+strlen(buffer), ", desc: ");
2325                 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2326         
2327                 log_text(buffer);       
2328
2329                 MFREE(buffer, char, buffer_len);
2330                 #endif  
2331                 
2332                 
2333                 if ((c->methods[i].name == name) && ((desc == NULL) ||
2334                                                    (c->methods[i].descriptor == desc)))
2335                         return i;
2336                 }
2337 #ifdef JOWENN_DEBUG2    
2338         class_showconstantpool(c);
2339         log_text("class_findmethod: returning NULL");
2340 #endif
2341         return -1;
2342 }
2343
2344
2345
2346 /************************* Function: class_findmethod **************************
2347         
2348         Searches a 'classinfo' structure for a method having the given name and
2349         type.
2350         If type is NULL, it is ignored.
2351
2352 *******************************************************************************/
2353
2354 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
2355 {
2356 #if 0
2357         s4 i;
2358 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2359         char *buffer;                   
2360         int buffer_len, pos;
2361 #endif
2362 #ifdef JOWENN_DEBUG1
2363
2364         buffer_len = 
2365           utf_strlen(name) + utf_strlen(desc) +utf_strlen(c->name)+ 64;
2366         
2367         buffer = MNEW(char, buffer_len);
2368
2369         strcpy(buffer, "class_findmethod: method:");
2370         utf_sprint(buffer+strlen(buffer), name);
2371         strcpy(buffer+strlen(buffer), ", desc: ");
2372         utf_sprint(buffer+strlen(buffer), desc);
2373         strcpy(buffer+strlen(buffer), ", classname: ");
2374         utf_sprint(buffer+strlen(buffer), c->name);
2375         
2376         log_text(buffer);       
2377
2378         MFREE(buffer, char, buffer_len);
2379 #endif  
2380         for (i = 0; i < c->methodscount; i++) {
2381 #ifdef JOWENN_DEBUG2
2382                 buffer_len = 
2383                   utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2384         
2385                 buffer = MNEW(char, buffer_len);
2386
2387                 strcpy(buffer, "class_findmethod: comparing to method:");
2388                 utf_sprint(buffer+strlen(buffer), c->methods[i].name);
2389                 strcpy(buffer+strlen(buffer), ", desc: ");
2390                 utf_sprint(buffer+strlen(buffer), c->methods[i].descriptor);
2391         
2392                 log_text(buffer);       
2393
2394                 MFREE(buffer, char, buffer_len);
2395                 #endif  
2396                 
2397                 
2398                 if ((c->methods[i].name == name) && ((desc == NULL) ||
2399                                                    (c->methods[i].descriptor == desc)))
2400                         return &(c->methods[i]);
2401                 }
2402 #ifdef JOWENN_DEBUG2    
2403         class_showconstantpool(c);
2404         log_text("class_findmethod: returning NULL");
2405 #endif
2406         return NULL;
2407 #endif
2408         s4 idx=class_findmethodIndex(c,name,desc);
2409 /*      if (idx==-1) log_text("class_findmethod: method not found");*/
2410         if (idx==-1) return NULL;
2411         return &(c->methods[idx]);
2412 }
2413
2414
2415
2416
2417
2418
2419 /************************* Function: class_findmethod_approx ******************
2420         
2421         like class_findmethod but ignores the return value when comparing the
2422         descriptor.
2423
2424 *******************************************************************************/
2425
2426 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
2427 {
2428         s4 i;
2429
2430         for (i = 0; i < c->methodscount; i++) 
2431                 if (c->methods[i].name == name) {
2432                         utf *meth_descr = c->methods[i].descriptor;
2433                         
2434                         if (desc == NULL) 
2435                                 /* ignore type */
2436                                 return &(c->methods[i]);
2437
2438                         if (desc->blength <= meth_descr->blength) {
2439                                            /* current position in utf text   */
2440                                            char *desc_utf_ptr = desc->text;      
2441                                            char *meth_utf_ptr = meth_descr->text;                                         
2442                                            /* points behind utf strings */
2443                                            char *desc_end = utf_end(desc);         
2444                                            char *meth_end = utf_end(meth_descr);   
2445                                            char ch;
2446
2447                                            /* compare argument types */
2448                                            while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2449
2450                                                    if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2451                                                            break; /* no match */
2452
2453                                                    if (ch==')')
2454                                                            return &(c->methods[i]);   /* all parameter types equal */
2455                                            }
2456                         }
2457                 }
2458
2459         return NULL;
2460 }
2461
2462 /***************** Function: class_resolvemethod_approx ***********************
2463         
2464         Searches a class and every super class for a method (without paying
2465         attention to the return value)
2466
2467 *******************************************************************************/
2468
2469 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2470 {
2471         while (c) {
2472                 /* search for method (ignore returntype) */
2473                 methodinfo *m = class_findmethod_approx (c, name, desc);
2474                 /* method found */
2475                 if (m) return m;
2476                 /* search superclass */
2477                 c = c->super;
2478                 }
2479         return NULL;
2480 }
2481
2482
2483 /************************* Function: class_resolvemethod ***********************
2484         
2485         Searches a class and every super class for a method.
2486
2487 *******************************************************************************/
2488
2489 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2490 {
2491         while (c) {
2492                 methodinfo *m = class_findmethod(c, name, desc);
2493                 if (m) return m;
2494                 /* search superclass */
2495                 c = c->super;
2496         }
2497         return NULL;
2498 }
2499
2500
2501
2502 /************************* Function: class_issubclass **************************
2503
2504         Checks if sub is a descendant of super.
2505         
2506 *******************************************************************************/
2507
2508 bool class_issubclass(classinfo *sub, classinfo *super)
2509 {
2510         for (;;) {
2511                 if (!sub) return false;
2512                 if (sub==super) return true;
2513                 sub = sub -> super;
2514         }
2515 }
2516
2517
2518
2519 /****************** Initialization function for classes ******************
2520
2521         In Java, every class can have a static initialization function. This
2522         function has to be called BEFORE calling other methods or accessing static
2523         variables.
2524
2525 *******************************************************************************/
2526
2527 #ifdef USE_THREADS
2528 extern int blockInts;
2529 #endif
2530
2531 void class_init(classinfo *c)
2532 {
2533         methodinfo *m;
2534         java_objectheader *exceptionptr;
2535         s4 i;
2536         int b;
2537
2538
2539         if (!makeinitializations)
2540                 return;
2541         if (c->initialized)
2542                 return;
2543         c -> initialized = true;
2544
2545
2546
2547 #ifdef STATISTICS
2548         count_class_inits++;
2549 #endif
2550
2551         if (c->super)
2552                 class_init (c->super);
2553         for (i=0; i < c->interfacescount; i++)
2554                 class_init(c->interfaces[i]);  /* real */
2555
2556         m = class_findmethod (c, utf_clinit, utf_fidesc);
2557         if (!m) {
2558                 if (initverbose) {
2559                         sprintf (logtext, "Class ");
2560                         utf_sprint (logtext+strlen(logtext), c->name);
2561                         sprintf (logtext+strlen(logtext), " has no initializer");
2562                         dolog ();
2563                         }
2564 /*              goto callinitialize;*/
2565                 return;
2566                 }
2567
2568         if (! (m->flags & ACC_STATIC))
2569                 panic ("Class initializer is not static!");
2570
2571         if (initverbose) {
2572                 sprintf (logtext, "Starting initializer for class: ");
2573                 utf_sprint (logtext+strlen(logtext), c->name);
2574                 dolog ();
2575         }
2576
2577 #ifdef USE_THREADS
2578         b = blockInts;
2579         blockInts = 0;
2580 #endif
2581
2582         exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2583
2584 #ifdef USE_THREADS
2585         assert(blockInts == 0);
2586         blockInts = b;
2587 #endif
2588
2589         if (exceptionptr) {
2590                 printf ("#### Initializer of ");
2591                 utf_display (c->name);
2592                 printf (" has thrown: ");
2593                 utf_display (exceptionptr->vftbl->class->name);
2594                 printf ("\n");
2595                 fflush (stdout);
2596                 }
2597
2598         if (initverbose) {
2599                 sprintf (logtext, "Finished initializer for class: ");
2600                 utf_sprint (logtext+strlen(logtext), c->name);
2601                 dolog ();
2602         }
2603         if (c->name == utf_systemclass) {
2604                 /* class java.lang.System requires explicit initialization */
2605
2606                 if (initverbose)
2607                         printf ("#### Initializing class System");
2608
2609                 /* find initializing method */
2610                 m = class_findmethod (c,
2611                                         utf_initsystemclass,
2612                                         utf_fidesc);
2613
2614                 if (!m) {
2615                         /* no method found */
2616                         /* printf("initializeSystemClass failed"); */
2617                         return;
2618                 }
2619                 #ifdef USE_THREADS
2620                         b = blockInts;
2621                         blockInts = 0;
2622                 #endif
2623
2624                 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2625
2626                 #ifdef USE_THREADS
2627                         assert(blockInts == 0);
2628                         blockInts = b;
2629                 #endif
2630
2631                 if (exceptionptr) {
2632                         printf ("#### initializeSystemClass has thrown: ");
2633                         utf_display (exceptionptr->vftbl->class->name);
2634                         printf ("\n");
2635                         fflush (stdout);
2636                 }
2637         }
2638
2639 }
2640
2641
2642
2643
2644 /********* Function: find_class_method_constant *********/
2645 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)  
2646 {
2647         u4 i;
2648         voidptr e;
2649
2650         for (i=0; i<c->cpcount; i++) {
2651                 
2652                 e = c -> cpinfos [i];
2653                 if (e) {
2654                         
2655                         switch (c -> cptags [i]) {
2656                         case CONSTANT_Methodref:
2657                                 {
2658                                         constant_FMIref *fmi = e;
2659                                         if (       (fmi->class->name == c1)  
2660                                                            && (fmi->name == m1)
2661                                                            && (fmi->descriptor == d1)) {
2662                                         
2663                                                 return i;
2664                                         }
2665                                 }
2666                                 break;
2667
2668                         case CONSTANT_InterfaceMethodref:
2669                                 {
2670                                         constant_FMIref *fmi = e;
2671                                         if (       (fmi->class->name == c1)  
2672                                                            && (fmi->name == m1)
2673                                                            && (fmi->descriptor == d1)) {
2674
2675                                                 return i;
2676                                         }
2677                                 }
2678                                 break;
2679                         }
2680                 }
2681         }
2682
2683         return -1;
2684 }
2685
2686
2687 void class_showconstanti(classinfo *c, int ii) 
2688 {
2689         u4 i = ii;
2690         voidptr e;
2691                 
2692         e = c->cpinfos [i];
2693         printf ("#%d:  ", (int) i);
2694         if (e) {
2695                 switch (c->cptags [i]) {
2696                 case CONSTANT_Class:
2697                         printf("Classreference -> ");
2698                         utf_display(((classinfo*)e)->name);
2699                         break;
2700                                 
2701                 case CONSTANT_Fieldref:
2702                         printf("Fieldref -> "); goto displayFMIi;
2703                 case CONSTANT_Methodref:
2704                         printf("Methodref -> "); goto displayFMIi;
2705                 case CONSTANT_InterfaceMethodref:
2706                         printf("InterfaceMethod -> "); goto displayFMIi;
2707                 displayFMIi:
2708                         {
2709                                 constant_FMIref *fmi = e;
2710                                 utf_display(fmi->class->name);
2711                                 printf(".");
2712                                 utf_display(fmi->name);
2713                                 printf(" ");
2714                                 utf_display(fmi->descriptor);
2715                         }
2716                         break;
2717
2718                 case CONSTANT_String:
2719                         printf("String -> ");
2720                         utf_display(e);
2721                         break;
2722                 case CONSTANT_Integer:
2723                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2724                         break;
2725                 case CONSTANT_Float:
2726                         printf("Float -> %f", ((constant_float*)e)->value);
2727                         break;
2728                 case CONSTANT_Double:
2729                         printf("Double -> %f", ((constant_double*)e)->value);
2730                         break;
2731                 case CONSTANT_Long:
2732                         {
2733                                 u8 v = ((constant_long*)e)->value;
2734 #if U8_AVAILABLE
2735                                 printf("Long -> %ld", (long int) v);
2736 #else
2737                                 printf("Long -> HI: %ld, LO: %ld\n", 
2738                                             (long int) v.high, (long int) v.low);
2739 #endif 
2740                         }
2741                         break;
2742                 case CONSTANT_NameAndType:
2743                         { 
2744                                 constant_nameandtype *cnt = e;
2745                                 printf("NameAndType: ");
2746                                 utf_display(cnt->name);
2747                                 printf(" ");
2748                                 utf_display(cnt->descriptor);
2749                         }
2750                         break;
2751                 case CONSTANT_Utf8:
2752                         printf("Utf8 -> ");
2753                         utf_display(e);
2754                         break;
2755                 default: 
2756                         panic("Invalid type of ConstantPool-Entry");
2757                 }
2758         }
2759         printf("\n");
2760 }
2761
2762
2763 void class_showconstantpool (classinfo *c) 
2764 {
2765         u4 i;
2766         voidptr e;
2767
2768         printf ("---- dump of constant pool ----\n");
2769
2770         for (i=0; i<c->cpcount; i++) {
2771                 printf ("#%d:  ", (int) i);
2772                 
2773                 e = c -> cpinfos [i];
2774                 if (e) {
2775                         
2776                         switch (c -> cptags [i]) {
2777                         case CONSTANT_Class:
2778                                 printf ("Classreference -> ");
2779                                 utf_display ( ((classinfo*)e) -> name );
2780                                 break;
2781                                 
2782                         case CONSTANT_Fieldref:
2783                                 printf ("Fieldref -> "); goto displayFMI;
2784                         case CONSTANT_Methodref:
2785                                 printf ("Methodref -> "); goto displayFMI;
2786                         case CONSTANT_InterfaceMethodref:
2787                                 printf ("InterfaceMethod -> "); goto displayFMI;
2788                         displayFMI:
2789                                 {
2790                                         constant_FMIref *fmi = e;
2791                                         utf_display ( fmi->class->name );
2792                                         printf (".");
2793                                         utf_display ( fmi->name);
2794                                         printf (" ");
2795                                         utf_display ( fmi->descriptor );
2796                                 }
2797                                 break;
2798
2799                         case CONSTANT_String:
2800                                 printf ("String -> ");
2801                                 utf_display (e);
2802                                 break;
2803                         case CONSTANT_Integer:
2804                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2805                                 break;
2806                         case CONSTANT_Float:
2807                                 printf ("Float -> %f", ((constant_float*)e) -> value);
2808                                 break;
2809                         case CONSTANT_Double:
2810                                 printf ("Double -> %f", ((constant_double*)e) -> value);
2811                                 break;
2812                         case CONSTANT_Long:
2813                                 {
2814                                         u8 v = ((constant_long*)e) -> value;
2815 #if U8_AVAILABLE
2816                                         printf ("Long -> %ld", (long int) v);
2817 #else
2818                                         printf ("Long -> HI: %ld, LO: %ld\n", 
2819                                                         (long int) v.high, (long int) v.low);
2820 #endif 
2821                                 }
2822                                 break;
2823                         case CONSTANT_NameAndType:
2824                                 {
2825                                         constant_nameandtype *cnt = e;
2826                                         printf ("NameAndType: ");
2827                                         utf_display (cnt->name);
2828                                         printf (" ");
2829                                         utf_display (cnt->descriptor);
2830                                 }
2831                                 break;
2832                         case CONSTANT_Utf8:
2833                                 printf ("Utf8 -> ");
2834                                 utf_display (e);
2835                                 break;
2836                         default: 
2837                                 panic ("Invalid type of ConstantPool-Entry");
2838                         }
2839                 }
2840
2841                 printf ("\n");
2842         }
2843 }
2844
2845
2846
2847 /********** Function: class_showmethods   (debugging only) *************/
2848
2849 void class_showmethods (classinfo *c)
2850 {
2851         s4 i;
2852         
2853         printf ("--------- Fields and Methods ----------------\n");
2854         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
2855
2856         printf ("This: "); utf_display (c->name); printf ("\n");
2857         if (c->super) {
2858                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2859                 }
2860         printf ("Index: %d\n", c->index);
2861         
2862         printf ("interfaces:\n");       
2863         for (i=0; i < c-> interfacescount; i++) {
2864                 printf ("   ");
2865                 utf_display (c -> interfaces[i] -> name);
2866                 printf (" (%d)\n", c->interfaces[i] -> index);
2867                 }
2868
2869         printf ("fields:\n");           
2870         for (i=0; i < c -> fieldscount; i++) {
2871                 field_display (&(c -> fields[i]));
2872                 }
2873
2874         printf ("methods:\n");
2875         for (i=0; i < c -> methodscount; i++) {
2876                 methodinfo *m = &(c->methods[i]);
2877                 if ( !(m->flags & ACC_STATIC)) 
2878                         printf ("vftblindex: %d   ", m->vftblindex);
2879
2880                 method_display ( m );
2881
2882                 }
2883
2884         printf ("Virtual function table:\n");
2885         for (i=0; i<c->vftbl->vftbllength; i++) {
2886                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
2887                 }
2888
2889 }
2890
2891
2892
2893 /******************************************************************************/
2894 /******************* General functions for the class loader *******************/
2895 /******************************************************************************/
2896
2897 /********************* Function: loader_load ***********************************
2898
2899         Loads and links the class desired class and each class and interface
2900         referenced by it.
2901         Returns: a pointer to this class
2902
2903 *******************************************************************************/
2904
2905 static int loader_load_running = 0;
2906
2907 classinfo *loader_load (utf *topname)
2908 {
2909         classinfo *top;
2910         classinfo *c;
2911         long int starttime=0,stoptime=0;
2912
2913         /* avoid recursive calls */
2914         if (loader_load_running)
2915                 return class_new(topname);
2916         loader_load_running++;
2917         
2918         intsDisable();                           /* schani */
2919
2920         if (getloadingtime)
2921                 starttime = getcputime();
2922
2923         top = class_new (topname);
2924
2925         /* load classes */
2926         while ( (c = list_first(&unloadedclasses)) ) {
2927                 if (!class_load (c)) {
2928                         list_remove (&unloadedclasses, c);
2929                         top=NULL;
2930                     }
2931         }
2932
2933         /* link classes */
2934         while ( (c = list_first(&unlinkedclasses)) ) {
2935                 class_link (c);
2936                 }
2937
2938         if (loader_inited)
2939                 loader_compute_subclasses();
2940
2941         /* measure time */
2942         if (getloadingtime) {
2943                 stoptime = getcputime();
2944                 loadingtime += (stoptime-starttime);
2945                 }
2946
2947         intsRestore();                          /* schani */
2948
2949         loader_load_running--;
2950         
2951         return top; 
2952 }
2953
2954
2955 /**************** function: create_primitive_classes ***************************
2956
2957         create classes representing primitive types 
2958
2959 ********************************************************************************/
2960
2961
2962 void create_primitive_classes()
2963 {  
2964         int i;
2965
2966         for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2967                 /* create primitive class */
2968                 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2969                 c -> classUsed = NOTUSED; /* not used initially CO-RT */                
2970                 c -> impldBy = NULL;
2971
2972                 /* prevent loader from loading primitive class */
2973                 list_remove (&unloadedclasses, c);
2974                 /* add to unlinked classes */
2975                 list_addlast (&unlinkedclasses, c);             
2976                 c -> super = class_java_lang_Object;
2977                 class_link (c);
2978
2979                 primitivetype_table[i].class_primitive = c;
2980
2981                 /* create class for wrapping the primitive type */
2982                 primitivetype_table[i].class_wrap =
2983                         class_new( utf_new_char(primitivetype_table[i].wrapname) );
2984                 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2985                 primitivetype_table[i].class_wrap  -> impldBy = NULL;
2986
2987                 /* create the primitive array class */
2988                 if (primitivetype_table[i].arrayname) {
2989                         c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
2990                         primitivetype_table[i].arrayclass = c;
2991                         if (!c->linked) class_link(c);
2992                         primitivetype_table[i].arrayvftbl = c->vftbl;
2993                 }
2994         }
2995 }
2996
2997 /**************** function: class_primitive_from_sig ***************************
2998
2999         return the primitive class indicated by the given signature character
3000
3001     If the descriptor does not indicate a valid primitive type the
3002     return value is NULL.
3003
3004 ********************************************************************************/
3005
3006 classinfo *class_primitive_from_sig(char sig)
3007 {
3008         switch (sig) {
3009           case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3010           case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3011           case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3012           case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3013           case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3014           case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3015           case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3016           case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3017           case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3018         }
3019         return NULL;
3020 }
3021
3022 /****************** function: class_from_descriptor ****************************
3023
3024     return the class indicated by the given descriptor
3025
3026     utf_ptr....first character of descriptor
3027     end_ptr....first character after the end of the string
3028     next.......if non-NULL, *next is set to the first character after
3029                the descriptor
3030     mode.......what to do if a class descriptor is parsed successfully:
3031                    CLASSLOAD_SKIP...skip it and return something != NULL
3032                    CLASSLOAD_NEW....get classinfo * via class_new
3033                    CLASSLOAD_LOAD...get classinfo * via loader_load
3034
3035     If the descriptor is invalid the return value is NULL
3036
3037 ********************************************************************************/
3038
3039 classinfo *class_from_descriptor(char *utf_ptr,char *end_ptr,char **next,int mode)
3040 {
3041         char *start = utf_ptr;
3042         bool error = false;
3043         utf *name;
3044         
3045         SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3046         if (error) return NULL;
3047         if (next) *next = utf_ptr;
3048
3049         switch (*start) {
3050           case 'L':
3051                   start++;
3052                   utf_ptr--;
3053                   /* fallthrough */
3054           case '[':
3055                   if (mode == CLASSLOAD_SKIP) return class_java_lang_Object;
3056                   name = utf_new(start,utf_ptr-start);
3057                   return (mode == CLASSLOAD_LOAD) ? loader_load(name) : class_new(name);
3058           default:
3059                   return class_primitive_from_sig(*start);
3060         }
3061 }
3062
3063 /***************** function: create_array_class ********************************
3064
3065         create class representing an array
3066
3067 ********************************************************************************/
3068
3069 /* XXX delete */
3070 #if 0
3071 classinfo *create_array_class(utf *u)
3072 {  
3073         classinfo *c = class_new (u);
3074         /* prevent loader from loading the array class */
3075         list_remove (&unloadedclasses, c);
3076         /* add to unlinked classes */
3077         list_addlast (&unlinkedclasses, c);
3078         c -> super = class_java_lang_Object;
3079         class_link(c);
3080         return c;
3081 }
3082 #endif
3083
3084 /*************** function: create_pseudo_classes *******************************
3085
3086         create pseudo classes used by the typechecker
3087
3088 ********************************************************************************/
3089
3090 static void
3091 create_pseudo_classes()
3092 {
3093     /* pseudo class for Arraystubs (extends java.lang.Object) */
3094     
3095     pseudo_class_Arraystub = class_new( utf_new_char(";Arraystub;") );
3096     list_remove(&unloadedclasses,pseudo_class_Arraystub);
3097
3098     pseudo_class_Arraystub->super = class_java_lang_Object;
3099     pseudo_class_Arraystub->interfacescount = 2;
3100     pseudo_class_Arraystub->interfaces = MNEW(classinfo*,2);
3101     pseudo_class_Arraystub->interfaces[0] =
3102         class_java_lang_Cloneable;
3103     pseudo_class_Arraystub->interfaces[1] =
3104         class_java_io_Serializable;
3105
3106     list_addlast(&unlinkedclasses,pseudo_class_Arraystub);
3107     class_link(pseudo_class_Arraystub);
3108
3109         pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3110
3111     /* pseudo class representing the null type */
3112     
3113     pseudo_class_Null = class_new( utf_new_char(";Null;") );
3114     list_remove(&unloadedclasses,pseudo_class_Null);
3115
3116     pseudo_class_Null->super = class_java_lang_Object;
3117
3118     list_addlast(&unlinkedclasses,pseudo_class_Null);
3119     class_link(pseudo_class_Null);      
3120 }
3121
3122 /********************** Function: loader_init **********************************
3123
3124         Initializes all lists and loads all classes required for the system or the
3125         compiler.
3126
3127 *******************************************************************************/
3128  
3129 void loader_init (u1 * stackbottom)
3130 {
3131         interfaceindex = 0;
3132         
3133         
3134         log_text("Entering loader_init");
3135                                 
3136         
3137         list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
3138         list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
3139         list_init (&linkedclasses, OFFSET(classinfo, listnode) );
3140
3141         /* create utf-symbols for pointer comparison of frequently used strings */
3142         utf_innerclasses    = utf_new_char("InnerClasses");
3143         utf_constantvalue   = utf_new_char("ConstantValue");
3144         utf_code                = utf_new_char("Code");
3145         utf_finalize        = utf_new_char("finalize");
3146         utf_fidesc              = utf_new_char("()V");
3147         utf_clinit              = utf_new_char("<clinit>");
3148         utf_initsystemclass = utf_new_char("initializeSystemClass");
3149         utf_systemclass     = utf_new_char("java/lang/System");
3150         utf_vmclassloader =utf_new_char("java/lang/VMClassLoader");
3151         utf_initialize =utf_new_char("initialize");
3152         utf_initializedesc =utf_new_char("(I)V");
3153
3154         utf_vmclass =utf_new_char("java/lang/VMClass");
3155
3156         /* create some important classes */
3157         /* These classes have to be created now because the classinfo
3158          * pointers are used in the loading code.
3159          */
3160         class_java_lang_Object = class_new( utf_new_char ("java/lang/Object") );
3161         class_java_lang_String = class_new( utf_new_char("java/lang/String") );
3162         class_java_lang_Cloneable = class_new( utf_new_char ("java/lang/Cloneable") );
3163         class_java_io_Serializable = class_new( utf_new_char ("java/io/Serializable") );
3164
3165         log_text("loader_init: java/lang/Object");
3166         /* load the classes which were created above */
3167         loader_load (class_java_lang_Object->name);
3168
3169         loader_inited=1; /*JOWENN*/
3170
3171         class_java_lang_Throwable =
3172                 loader_load( utf_new_char("java/lang/Throwable") );
3173
3174         log_text("loader_init:  loader_load: java/lang/ClassCastException");
3175         class_java_lang_ClassCastException =
3176                 loader_load ( utf_new_char ("java/lang/ClassCastException") );
3177         class_java_lang_NullPointerException =
3178                 loader_load ( utf_new_char ("java/lang/NullPointerException") );
3179         class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
3180              utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
3181         class_java_lang_NegativeArraySizeException = loader_load (
3182              utf_new_char ("java/lang/NegativeArraySizeException") );
3183         class_java_lang_OutOfMemoryError = loader_load (
3184              utf_new_char ("java/lang/OutOfMemoryError") );
3185         class_java_lang_ArrayStoreException =
3186                 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
3187         class_java_lang_ArithmeticException =
3188                 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
3189         class_java_lang_ThreadDeath =                             /* schani */
3190                 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
3191         /* create classes representing primitive types */
3192         create_primitive_classes();
3193
3194         /* create classes used by the typechecker */
3195         create_pseudo_classes();
3196
3197         /* correct vftbl-entries (retarded loading of class java/lang/String) */
3198         stringtable_update();
3199 #ifdef USE_THREADS
3200         if (stackbottom!=0)
3201                 initLocks();
3202 #endif
3203
3204
3205
3206         log_text("loader_init: creating global proto_java_lang_ClassCastException");
3207         proto_java_lang_ClassCastException =
3208                 builtin_new(class_java_lang_ClassCastException);
3209         heap_addreference ( (void**) &proto_java_lang_ClassCastException);
3210
3211         log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3212
3213         proto_java_lang_NullPointerException =
3214                builtin_new(class_java_lang_NullPointerException);
3215         heap_addreference ( (void**) &proto_java_lang_NullPointerException);
3216         log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3217
3218         proto_java_lang_ArrayIndexOutOfBoundsException =
3219                 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3220         heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
3221
3222         proto_java_lang_NegativeArraySizeException =
3223                 builtin_new(class_java_lang_NegativeArraySizeException);
3224         heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
3225
3226         proto_java_lang_OutOfMemoryError =
3227                 builtin_new(class_java_lang_OutOfMemoryError);
3228         heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
3229
3230         proto_java_lang_ArithmeticException =
3231                builtin_new(class_java_lang_ArithmeticException);
3232         heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
3233
3234         proto_java_lang_ArrayStoreException =
3235                 builtin_new(class_java_lang_ArrayStoreException);
3236         heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
3237
3238         proto_java_lang_ThreadDeath =                             /* schani */
3239                 builtin_new(class_java_lang_ThreadDeath);
3240         heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
3241
3242         loader_inited = 1;
3243
3244 }
3245
3246
3247
3248
3249 /********************* Function: loader_initclasses ****************************
3250
3251         Initializes all loaded but uninitialized classes
3252
3253 *******************************************************************************/
3254
3255 void loader_initclasses ()
3256 {
3257         classinfo *c;
3258         
3259         intsDisable();                     /* schani */
3260
3261         if (makeinitializations) {
3262                 c = list_first (&linkedclasses);
3263                 while (c) {
3264                         class_init (c);
3265                         c = list_next (&linkedclasses, c);
3266                         }
3267                 }
3268
3269         intsRestore();                      /* schani */
3270 }
3271
3272 static s4 classvalue;
3273
3274 static void loader_compute_class_values (classinfo *c)
3275 {
3276         classinfo *subs;
3277
3278         c->vftbl->baseval = ++classvalue;
3279
3280         subs = c->sub;
3281         while (subs != NULL) {
3282                 loader_compute_class_values(subs);
3283                 subs = subs->nextsub;
3284                 }
3285         c->vftbl->diffval = classvalue - c->vftbl->baseval;
3286         
3287         /*
3288         {
3289         int i;
3290         for (i = 0; i < c->index; i++)
3291                 printf(" ");
3292         printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
3293         utf_display(c->name);
3294         printf("\n");
3295         }
3296         */
3297         
3298 }
3299
3300
3301 void loader_compute_subclasses ()
3302 {
3303         classinfo *c;
3304         
3305         intsDisable();                     /* schani */
3306
3307         c = list_first (&linkedclasses);
3308         while (c) {
3309                 if (!(c->flags & ACC_INTERFACE)) {
3310                         c->nextsub = 0;
3311                         c->sub = 0;
3312                         }
3313                 c = list_next (&linkedclasses, c);
3314                 }
3315
3316         c = list_first (&linkedclasses);
3317         while (c) {
3318                 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3319                         c->nextsub = c->super->sub;
3320                         c->super->sub = c;
3321                         }
3322                 c = list_next (&linkedclasses, c);
3323                 }
3324         classvalue = 0;
3325         loader_compute_class_values(class_java_lang_Object);
3326
3327         intsRestore();                      /* schani */
3328 }
3329
3330
3331
3332 /******************** function classloader_buffer ******************************
3333  
3334     sets buffer for reading classdata
3335
3336 *******************************************************************************/
3337
3338 void classload_buffer(u1 *buf, int len)
3339 {
3340         classbuffer        =  buf;
3341         classbuffer_size   =  len;
3342         classbuf_pos       =  buf - 1;
3343 }
3344
3345
3346 /******************** Function: loader_close ***********************************
3347
3348         Frees all resources
3349         
3350 *******************************************************************************/
3351
3352 void loader_close ()
3353 {
3354         classinfo *c;
3355
3356         while ( (c=list_first(&unloadedclasses)) ) {
3357                 list_remove (&unloadedclasses,c);
3358                 class_free (c);
3359                 }
3360         while ( (c=list_first(&unlinkedclasses)) ) {
3361                 list_remove (&unlinkedclasses,c);
3362                 class_free (c);
3363                 }
3364         while ( (c=list_first(&linkedclasses)) ) {
3365                 list_remove (&linkedclasses,c);
3366                 class_free (c);
3367                 }
3368 }
3369
3370
3371 /*
3372  * These are local overrides for various environment variables in Emacs.
3373  * Please do not remove this and leave it at the end of the file, where
3374  * Emacs will automagically detect them.
3375  * ---------------------------------------------------------------------
3376  * Local variables:
3377  * mode: c
3378  * indent-tabs-mode: t
3379  * c-basic-offset: 4
3380  * tab-width: 4
3381  * End:
3382  */