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