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