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