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