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