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