aad9a25a9e4866fbd0e6d9ee1472ccdb915f8dc9
[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 2155 2005-03-30 20:04:42Z twisti $
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)
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
1231         /* resolve entries in temporary structures */
1232
1233         while (forward_classes) {
1234                 utf *name =
1235                         class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
1236
1237                 if (opt_verify && !is_valid_name_utf(name))
1238                         panic("Class reference with invalid name");
1239
1240                 cptags[forward_classes->thisindex] = CONSTANT_Class;
1241                 /* retrieve class from class-table */
1242                 if (opt_eager) {
1243                         classinfo *tc;
1244                         tc = class_new_intern(name);
1245
1246                         if (!load_class_from_classloader(tc, c->classloader))
1247                                 return false;
1248
1249                         /* link the class later, because we cannot link the class currently
1250                            loading */
1251                         list_addfirst(&unlinkedclasses, tc);
1252
1253                         cpinfos[forward_classes->thisindex] = tc;
1254
1255                 } else {
1256                         cpinfos[forward_classes->thisindex] = class_new(name);
1257                 }
1258
1259                 nfc = forward_classes;
1260                 forward_classes = forward_classes->next;
1261                 FREE(nfc, forward_class);
1262         }
1263
1264         while (forward_strings) {
1265                 utf *text =
1266                         class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
1267
1268                 /* resolve utf-string */
1269                 cptags[forward_strings->thisindex] = CONSTANT_String;
1270                 cpinfos[forward_strings->thisindex] = text;
1271                 
1272                 nfs = forward_strings;
1273                 forward_strings = forward_strings->next;
1274                 FREE(nfs, forward_string);
1275         }
1276
1277         while (forward_nameandtypes) {
1278                 constant_nameandtype *cn = NEW(constant_nameandtype);   
1279
1280 #if defined(STATISTICS)
1281                 if (opt_stat)
1282                         count_const_pool_len += sizeof(constant_nameandtype);
1283 #endif
1284
1285                 /* resolve simple name and descriptor */
1286                 cn->name = class_getconstant(c,
1287                                                                          forward_nameandtypes->name_index,
1288                                                                          CONSTANT_Utf8);
1289
1290                 cn->descriptor = class_getconstant(c,
1291                                                                                    forward_nameandtypes->sig_index,
1292                                                                                    CONSTANT_Utf8);
1293
1294                 if (opt_verify) {
1295                         /* check name */
1296                         if (!is_valid_name_utf(cn->name)) {
1297                                 *exceptionptr =
1298                                         new_classformaterror(c,
1299                                                                                  "Illegal Field name \"%s\"",
1300                                                                                  cn->name->text);
1301
1302                                 return false;
1303                         }
1304
1305                         /* disallow referencing <clinit> among others */
1306                         if (cn->name->text[0] == '<' && cn->name != utf_init) {
1307                                 *exceptionptr =
1308                                         new_exception_utfmessage(string_java_lang_InternalError,
1309                                                                                          cn->name);
1310                                 return false;
1311                         }
1312                 }
1313
1314                 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
1315                 cpinfos[forward_nameandtypes->thisindex] = cn;
1316
1317                 nfn = forward_nameandtypes;
1318                 forward_nameandtypes = forward_nameandtypes->next;
1319                 FREE(nfn, forward_nameandtype);
1320         }
1321
1322         while (forward_fieldmethints) {
1323                 constant_nameandtype *nat;
1324                 constant_FMIref *fmi = NEW(constant_FMIref);
1325
1326 #if defined(STATISTICS)
1327                 if (opt_stat)
1328                         count_const_pool_len += sizeof(constant_FMIref);
1329 #endif
1330                 /* resolve simple name and descriptor */
1331                 nat = class_getconstant(c,
1332                                                                 forward_fieldmethints->nameandtype_index,
1333                                                                 CONSTANT_NameAndType);
1334
1335                 fmi->class = class_getconstant(c,
1336                                                                            forward_fieldmethints->class_index,
1337                                                                            CONSTANT_Class);
1338                 fmi->name = nat->name;
1339                 fmi->descriptor = nat->descriptor;
1340
1341                 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
1342                 cpinfos[forward_fieldmethints->thisindex] = fmi;
1343         
1344                 switch (forward_fieldmethints->tag) {
1345                 case CONSTANT_Fieldref:  /* check validity of descriptor */
1346                         checkfielddescriptor(fmi->descriptor->text,
1347                                                                  utf_end(fmi->descriptor));
1348                         break;
1349                 case CONSTANT_InterfaceMethodref:
1350                 case CONSTANT_Methodref: /* check validity of descriptor */
1351                         checkmethoddescriptor(c, fmi->descriptor);
1352                         break;
1353                 }
1354         
1355                 nff = forward_fieldmethints;
1356                 forward_fieldmethints = forward_fieldmethints->next;
1357                 FREE(nff, forward_fieldmethint);
1358         }
1359
1360         /* everything was ok */
1361
1362         return true;
1363 }
1364
1365
1366 /* load_field ******************************************************************
1367
1368    Load everything about a class field from the class file and fill a
1369    'fieldinfo' structure. For static fields, space in the data segment
1370    is allocated.
1371
1372 *******************************************************************************/
1373
1374 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
1375
1376 static bool load_field(classbuffer *cb, fieldinfo *f)
1377 {
1378         classinfo *c;
1379         u4 attrnum, i;
1380         u4 jtype;
1381         u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
1382         utf *u;
1383
1384         c = cb->class;
1385
1386         if (!check_classbuffer_size(cb, 2 + 2 + 2))
1387                 return false;
1388
1389         f->flags = suck_u2(cb);
1390
1391         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1392                 return false;
1393         f->name = u;
1394
1395         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1396                 return false;
1397         f->descriptor = u;
1398
1399         if (opt_verify) {
1400                 /* check name */
1401                 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
1402                         *exceptionptr = new_classformaterror(c,
1403                                                                                                  "Illegal Field name \"%s\"",
1404                                                                                                  f->name->text);
1405                         return false;
1406                 }
1407
1408                 /* check flag consistency */
1409                 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
1410
1411                 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
1412                         ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
1413                         *exceptionptr =
1414                                 new_classformaterror(c,
1415                                                                          "Illegal field modifiers: 0x%X",
1416                                                                          f->flags);
1417                         return false;
1418                 }
1419
1420                 if (c->flags & ACC_INTERFACE) {
1421                         if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
1422                                 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
1423                                 f->flags & ACC_TRANSIENT) {
1424                                 *exceptionptr =
1425                                         new_classformaterror(c,
1426                                                                                  "Illegal field modifiers: 0x%X",
1427                                                                                  f->flags);
1428                                 return false;
1429                         }
1430                 }
1431
1432                 /* check descriptor */
1433                 checkfielddescriptor(f->descriptor->text, utf_end(f->descriptor));
1434         }
1435                 
1436         f->type = jtype = desc_to_type(f->descriptor);    /* data type            */
1437         f->offset = 0;                             /* offset from start of object */
1438         f->class = c;
1439         f->xta = NULL;
1440         
1441         switch (f->type) {
1442         case TYPE_INT:     f->value.i = 0; break;
1443         case TYPE_FLOAT:   f->value.f = 0.0; break;
1444         case TYPE_DOUBLE:  f->value.d = 0.0; break;
1445         case TYPE_ADDRESS: f->value.a = NULL; break;
1446         case TYPE_LONG:
1447 #if U8_AVAILABLE
1448                 f->value.l = 0; break;
1449 #else
1450                 f->value.l.low = 0; f->value.l.high = 0; break;
1451 #endif
1452         }
1453
1454         /* read attributes */
1455         if (!check_classbuffer_size(cb, 2))
1456                 return false;
1457
1458         attrnum = suck_u2(cb);
1459         for (i = 0; i < attrnum; i++) {
1460                 if (!check_classbuffer_size(cb, 2))
1461                         return false;
1462
1463                 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1464                         return false;
1465
1466                 if (u == utf_ConstantValue) {
1467                         if (!check_classbuffer_size(cb, 4 + 2))
1468                                 return false;
1469
1470                         /* check attribute length */
1471                         if (suck_u4(cb) != 2) {
1472                                 *exceptionptr =
1473                                         new_classformaterror(c, "Wrong size for VALUE attribute");
1474                                 return false;
1475                         }
1476                         
1477                         /* constant value attribute */
1478                         if (pindex != field_load_NOVALUE) {
1479                                 *exceptionptr =
1480                                         new_classformaterror(c,
1481                                                                                  "Multiple ConstantValue attributes");
1482                                 return false;
1483                         }
1484                         
1485                         /* index of value in constantpool */            
1486                         pindex = suck_u2(cb);
1487                 
1488                         /* initialize field with value from constantpool */             
1489                         switch (jtype) {
1490                         case TYPE_INT: {
1491                                 constant_integer *ci; 
1492
1493                                 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
1494                                         return false;
1495
1496                                 f->value.i = ci->value;
1497                         }
1498                         break;
1499                                         
1500                         case TYPE_LONG: {
1501                                 constant_long *cl; 
1502
1503                                 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
1504                                         return false;
1505
1506                                 f->value.l = cl->value;
1507                         }
1508                         break;
1509
1510                         case TYPE_FLOAT: {
1511                                 constant_float *cf;
1512
1513                                 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
1514                                         return false;
1515
1516                                 f->value.f = cf->value;
1517                         }
1518                         break;
1519                                                                                         
1520                         case TYPE_DOUBLE: {
1521                                 constant_double *cd;
1522
1523                                 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
1524                                         return false;
1525
1526                                 f->value.d = cd->value;
1527                         }
1528                         break;
1529                                                 
1530                         case TYPE_ADDRESS:
1531                                 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
1532                                         return false;
1533
1534                                 /* create javastring from compressed utf8-string */
1535                                 f->value.a = literalstring_new(u);
1536                                 break;
1537         
1538                         default: 
1539                                 log_text("Invalid Constant - Type");
1540                         }
1541
1542                 } else {
1543                         /* unknown attribute */
1544                         if (!skipattributebody(cb))
1545                                 return false;
1546                 }
1547         }
1548
1549         /* everything was ok */
1550
1551         return true;
1552 }
1553
1554
1555 /* load_method *****************************************************************
1556
1557    Loads a method from the class file and fills an existing
1558    'methodinfo' structure. For native methods, the function pointer
1559    field is set to the real function pointer, for JavaVM methods a
1560    pointer to the compiler is used preliminarily.
1561         
1562 *******************************************************************************/
1563
1564 static bool load_method(classbuffer *cb, methodinfo *m)
1565 {
1566         classinfo *c;
1567         s4 argcount;
1568         s4 i, j;
1569         u4 attrnum;
1570         u4 codeattrnum;
1571         utf *u;
1572
1573         c = cb->class;
1574
1575 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1576         initObjectLock(&m->header);
1577 #endif
1578
1579 #ifdef STATISTICS
1580         if (opt_stat)
1581                 count_all_methods++;
1582 #endif
1583
1584         m->thrownexceptionscount = 0;
1585         m->linenumbercount = 0;
1586         m->linenumbers = 0;
1587         m->class = c;
1588         m->nativelyoverloaded = false;
1589         
1590         if (!check_classbuffer_size(cb, 2 + 2 + 2))
1591                 return false;
1592
1593         m->flags = suck_u2(cb);
1594
1595         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1596                 return false;
1597         m->name = u;
1598
1599         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1600                 return false;
1601         m->descriptor = u;
1602
1603         if (opt_verify) {
1604                 if (!is_valid_name_utf(m->name))
1605                         panic("Method with invalid name");
1606
1607                 if (m->name->text[0] == '<'
1608                         && m->name != utf_init && m->name != utf_clinit)
1609                         panic("Method with invalid special name");
1610         }
1611         
1612         argcount = checkmethoddescriptor(c, m->descriptor);
1613
1614         if (!(m->flags & ACC_STATIC))
1615                 argcount++; /* count the 'this' argument */
1616
1617         if (opt_verify) {
1618                 if (argcount > 255) {
1619                         *exceptionptr =
1620                                 new_classformaterror(c, "Too many arguments in signature");
1621                         return false;
1622                 }
1623
1624                 /* check flag consistency */
1625                 if (m->name != utf_clinit) {
1626                         i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1627
1628                         if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1629                                 *exceptionptr =
1630                                         new_classformaterror(c,
1631                                                                                  "Illegal method modifiers: 0x%X",
1632                                                                                  m->flags);
1633                                 return false;
1634                         }
1635
1636                         if (m->flags & ACC_ABSTRACT) {
1637                                 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1638                                                                  ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1639                                         *exceptionptr =
1640                                                 new_classformaterror(c,
1641                                                                                          "Illegal method modifiers: 0x%X",
1642                                                                                          m->flags);
1643                                         return false;
1644                                 }
1645                         }
1646
1647                         if (c->flags & ACC_INTERFACE) {
1648                                 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1649                                         *exceptionptr =
1650                                                 new_classformaterror(c,
1651                                                                                          "Illegal method modifiers: 0x%X",
1652                                                                                          m->flags);
1653                                         return false;
1654                                 }
1655                         }
1656
1657                         if (m->name == utf_init) {
1658                                 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1659                                                                 ACC_NATIVE | ACC_ABSTRACT))
1660                                         panic("Instance initialization method has invalid flags set");
1661                         }
1662                 }
1663         }
1664                 
1665         m->jcode = NULL;
1666         m->basicblockcount = 0;
1667         m->basicblocks = NULL;
1668         m->basicblockindex = NULL;
1669         m->instructioncount = 0;
1670         m->instructions = NULL;
1671         m->stackcount = 0;
1672         m->stack = NULL;
1673         m->exceptiontable = NULL;
1674         m->stubroutine = NULL;
1675         m->mcode = NULL;
1676         m->entrypoint = NULL;
1677         m->methodUsed = NOTUSED;    
1678         m->monoPoly = MONO;    
1679         m->subRedefs = 0;
1680         m->subRedefsUsed = 0;
1681
1682         m->xta = NULL;
1683
1684         if (!check_classbuffer_size(cb, 2))
1685                 return false;
1686         
1687         attrnum = suck_u2(cb);
1688         for (i = 0; i < attrnum; i++) {
1689                 utf *aname;
1690
1691                 if (!check_classbuffer_size(cb, 2))
1692                         return false;
1693
1694                 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1695                         return false;
1696
1697                 if (aname == utf_Code) {
1698                         if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1699                                         *exceptionptr =
1700                                                 new_classformaterror(c,
1701                                                                                          "Code attribute in native or abstract methods");
1702
1703                                         return false;
1704                         }
1705                         
1706                         if (m->jcode) {
1707                                 *exceptionptr =
1708                                         new_classformaterror(c, "Multiple Code attributes");
1709
1710                                 return false;
1711                         }
1712
1713                         if (!check_classbuffer_size(cb, 4 + 2 + 2))
1714                                 return false;
1715
1716                         suck_u4(cb);
1717                         m->maxstack = suck_u2(cb);
1718                         m->maxlocals = suck_u2(cb);
1719
1720                         if (m->maxlocals < argcount) {
1721                                 *exceptionptr =
1722                                         new_classformaterror(c, "Arguments can't fit into locals");
1723
1724                                 return false;
1725                         }
1726                         
1727                         if (!check_classbuffer_size(cb, 4))
1728                                 return false;
1729
1730                         m->jcodelength = suck_u4(cb);
1731
1732                         if (m->jcodelength == 0) {
1733                                 *exceptionptr =
1734                                         new_classformaterror(c, "Code of a method has length 0");
1735
1736                                 return false;
1737                         }
1738                         
1739                         if (m->jcodelength > 65535) {
1740                                 *exceptionptr =
1741                                         new_classformaterror(c,
1742                                                                                  "Code of a method longer than 65535 bytes");
1743
1744                                 return false;
1745                         }
1746
1747                         if (!check_classbuffer_size(cb, m->jcodelength))
1748                                 return false;
1749
1750                         m->jcode = MNEW(u1, m->jcodelength);
1751                         suck_nbytes(m->jcode, cb, m->jcodelength);
1752
1753                         if (!check_classbuffer_size(cb, 2))
1754                                 return false;
1755
1756                         m->exceptiontablelength = suck_u2(cb);
1757                         if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1758                                 return false;
1759
1760                         m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1761
1762 #if defined(STATISTICS)
1763                         if (opt_stat) {
1764                                 count_vmcode_len += m->jcodelength + 18;
1765                                 count_extable_len += 8 * m->exceptiontablelength;
1766                         }
1767 #endif
1768
1769                         for (j = 0; j < m->exceptiontablelength; j++) {
1770                                 u4 idx;
1771                                 m->exceptiontable[j].startpc = suck_u2(cb);
1772                                 m->exceptiontable[j].endpc = suck_u2(cb);
1773                                 m->exceptiontable[j].handlerpc = suck_u2(cb);
1774
1775                                 idx = suck_u2(cb);
1776                                 if (!idx) {
1777                                         m->exceptiontable[j].catchtype = NULL;
1778
1779                                 } else {
1780                                         if (!(m->exceptiontable[j].catchtype =
1781                                                   class_getconstant(c, idx, CONSTANT_Class)))
1782                                                 return false;
1783                                 }
1784                         }
1785
1786                         if (!check_classbuffer_size(cb, 2))
1787                                 return false;
1788
1789                         codeattrnum = suck_u2(cb);
1790
1791                         for (; codeattrnum > 0; codeattrnum--) {
1792                                 utf *caname;
1793
1794                                 if (!check_classbuffer_size(cb, 2))
1795                                         return false;
1796
1797                                 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1798                                         return false;
1799
1800                                 if (caname == utf_LineNumberTable) {
1801                                         u2 lncid;
1802
1803                                         if (!check_classbuffer_size(cb, 4 + 2))
1804                                                 return false;
1805
1806                                         suck_u4(cb);
1807                                         m->linenumbercount = suck_u2(cb);
1808
1809                                         if (!check_classbuffer_size(cb,
1810                                                                                                 (2 + 2) * m->linenumbercount))
1811                                                 return false;
1812
1813                                         m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1814                                         
1815                                         for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1816                                                 m->linenumbers[lncid].start_pc = suck_u2(cb);
1817                                                 m->linenumbers[lncid].line_number = suck_u2(cb);
1818                                         }
1819                                         codeattrnum--;
1820
1821                                         if (!skipattributes(cb, codeattrnum))
1822                                                 return false;
1823                                         
1824                                         break;
1825
1826                                 } else {
1827                                         if (!skipattributebody(cb))
1828                                                 return false;
1829                                 }
1830                         }
1831
1832                 } else if (aname == utf_Exceptions) {
1833                         s4 j;
1834
1835                         if (m->thrownexceptions) {
1836                                 *exceptionptr =
1837                                         new_classformaterror(c, "Multiple Exceptions attributes");
1838                                 return false;
1839                         }
1840
1841                         if (!check_classbuffer_size(cb, 4 + 2))
1842                                 return false;
1843
1844                         suck_u4(cb); /* length */
1845                         m->thrownexceptionscount = suck_u2(cb);
1846
1847                         if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1848                                 return false;
1849
1850                         m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount);
1851
1852                         for (j = 0; j < m->thrownexceptionscount; j++) {
1853                                 if (!((m->thrownexceptions)[j] =
1854                                           class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1855                                         return false;
1856                         }
1857                                 
1858                 } else {
1859                         if (!skipattributebody(cb))
1860                                 return false;
1861                 }
1862         }
1863
1864         if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1865                 *exceptionptr = new_classformaterror(c, "Missing Code attribute");
1866
1867                 return false;
1868         }
1869
1870         /* everything was ok */
1871
1872         return true;
1873 }
1874
1875
1876 /* load_attribute **************************************************************
1877
1878    Read attributes from classfile.
1879         
1880 *******************************************************************************/
1881
1882 static bool load_attributes(classbuffer *cb, u4 num)
1883 {
1884         classinfo *c;
1885         utf       *aname;
1886         u4 i, j;
1887
1888         c = cb->class;
1889
1890         for (i = 0; i < num; i++) {
1891                 /* retrieve attribute name */
1892                 if (!check_classbuffer_size(cb, 2))
1893                         return false;
1894
1895                 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1896                         return false;
1897
1898                 if (aname == utf_InnerClasses) {
1899                         /* innerclasses attribute */
1900                         if (c->innerclass) {
1901                                 *exceptionptr =
1902                                         new_classformaterror(c, "Multiple InnerClasses attributes");
1903                                 return false;
1904                         }
1905                                 
1906                         if (!check_classbuffer_size(cb, 4 + 2))
1907                                 return false;
1908
1909                         /* skip attribute length */
1910                         suck_u4(cb);
1911
1912                         /* number of records */
1913                         c->innerclasscount = suck_u2(cb);
1914
1915                         if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1916                                 return false;
1917
1918                         /* allocate memory for innerclass structure */
1919                         c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1920
1921                         for (j = 0; j < c->innerclasscount; j++) {
1922                                 /* The innerclass structure contains a class with an encoded
1923                                    name, its defining scope, its simple name and a bitmask of
1924                                    the access flags. If an inner class is not a member, its
1925                                    outer_class is NULL, if a class is anonymous, its name is
1926                                    NULL. */
1927                                                                 
1928                                 innerclassinfo *info = c->innerclass + j;
1929
1930                                 info->inner_class =
1931                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1932                                 info->outer_class =
1933                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1934                                 info->name =
1935                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1936                                 info->flags = suck_u2(cb);
1937                         }
1938
1939                 } else if (aname == utf_SourceFile) {
1940                         if (!check_classbuffer_size(cb, 4 + 2))
1941                                 return false;
1942
1943                         if (suck_u4(cb) != 2) {
1944                                 *exceptionptr =
1945                                         new_classformaterror(c, "Wrong size for VALUE attribute");
1946                                 return false;
1947                         }
1948
1949                         if (c->sourcefile) {
1950                                 *exceptionptr =
1951                                         new_classformaterror(c, "Multiple SourceFile attributes");
1952                                 return false;
1953                         }
1954
1955                         if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1956                                 return false;
1957
1958                 } else {
1959                         /* unknown attribute */
1960                         if (!skipattributebody(cb))
1961                                 return false;
1962                 }
1963         }
1964
1965         return true;
1966 }
1967
1968
1969 /***************** Function: print_arraydescriptor ****************************
1970
1971         Debugging helper for displaying an arraydescriptor
1972         
1973 *******************************************************************************/
1974
1975 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
1976 {
1977         if (!desc) {
1978                 fprintf(file, "<NULL>");
1979                 return;
1980         }
1981
1982         fprintf(file, "{");
1983         if (desc->componentvftbl) {
1984                 if (desc->componentvftbl->class)
1985                         utf_fprint(file, desc->componentvftbl->class->name);
1986                 else
1987                         fprintf(file, "<no classinfo>");
1988         }
1989         else
1990                 fprintf(file, "0");
1991                 
1992         fprintf(file, ",");
1993         if (desc->elementvftbl) {
1994                 if (desc->elementvftbl->class)
1995                         utf_fprint(file, desc->elementvftbl->class->name);
1996                 else
1997                         fprintf(file, "<no classinfo>");
1998         }
1999         else
2000                 fprintf(file, "0");
2001         fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
2002                         desc->dataoffset, desc->componentsize);
2003 }
2004
2005
2006 /* load_class_from_classloader *************************************************
2007
2008    XXX
2009         
2010 *******************************************************************************/
2011
2012 classinfo *load_class_from_classloader(classinfo *c, java_objectheader *cl)
2013 {
2014         classinfo *r;
2015
2016         /* if other class loader than bootstrap, call it */
2017
2018         if (cl) {
2019                 methodinfo *lc;
2020
2021                 lc = class_resolveclassmethod(cl->vftbl->class,
2022                                                                           utf_loadClass,
2023                                                                           utf_java_lang_String__java_lang_Class,
2024                                                                           class_java_lang_Object,
2025                                                                           true);
2026
2027                 if (!lc)
2028                         return NULL;
2029
2030                 r = (classinfo *) asm_calljavafunction(lc,
2031                                                                                            cl,
2032                                                                                            javastring_new(c->name),
2033                                                                                            NULL, NULL);
2034
2035                 return r;
2036
2037         } else {
2038                 return load_class_bootstrap(c);
2039         }
2040 }
2041
2042
2043 /* load_class_bootstrap ********************************************************
2044         
2045    XXX
2046
2047 *******************************************************************************/
2048
2049 classinfo *load_class_bootstrap(classinfo *c)
2050 {
2051         classbuffer *cb;
2052         classinfo *r;
2053
2054 #if defined(USE_THREADS)
2055         /* enter a monitor on the class */
2056
2057         builtin_monitorenter((java_objectheader *) c);
2058 #endif
2059
2060         /* maybe the class is already loaded */
2061
2062         if (c->loaded) {
2063 #if defined(USE_THREADS)
2064                 builtin_monitorexit((java_objectheader *) c);
2065 #endif
2066
2067                 return c;
2068         }
2069
2070 #if defined(STATISTICS)
2071         /* measure time */
2072
2073         if (getcompilingtime)
2074                 compilingtime_stop();
2075
2076         if (getloadingtime)
2077                 loadingtime_start();
2078 #endif
2079
2080         /* load classdata, throw exception on error */
2081
2082         if ((cb = suck_start(c)) == NULL) {
2083                 /* this means, the classpath was not set properly */
2084                 if (c->name == utf_java_lang_Object)
2085                         throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
2086                                                                            "java/lang/Object");
2087
2088                 *exceptionptr =
2089                         new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
2090                                                                          c->name);
2091
2092 #if defined(USE_THREADS)
2093                 builtin_monitorexit((java_objectheader *) c);
2094 #endif
2095
2096                 return NULL;
2097         }
2098         
2099         /* load the class from the buffer */
2100
2101         r = load_class_from_classbuffer(cb);
2102
2103         /* if return value is NULL, we had a problem and the class is not loaded */
2104         if (!r) {
2105                 c->loaded = false;
2106
2107                 /* now free the allocated memory, otherwise we could ran into a DOS */
2108                 class_remove(c);
2109         }
2110
2111         /* free memory */
2112         suck_stop(cb);
2113
2114 #if defined(STATISTICS)
2115         /* measure time */
2116
2117         if (getloadingtime)
2118                 loadingtime_stop();
2119
2120         if (getcompilingtime)
2121                 compilingtime_start();
2122 #endif
2123
2124 #if defined(USE_THREADS)
2125         /* leave the monitor */
2126
2127         builtin_monitorexit((java_objectheader *) c);
2128 #endif
2129
2130         return r;
2131 }
2132
2133
2134 /* load_class_from_classbuffer *************************************************
2135         
2136    Loads everything interesting about a class from the class file. The
2137    'classinfo' structure must have been allocated previously.
2138
2139    The super class and the interfaces implemented by this class need
2140    not be loaded. The link is set later by the function 'class_link'.
2141
2142    The loaded class is removed from the list 'unloadedclasses' and
2143    added to the list 'unlinkedclasses'.
2144         
2145 *******************************************************************************/
2146
2147 classinfo *load_class_from_classbuffer(classbuffer *cb)
2148 {
2149         classinfo *c;
2150         classinfo *tc;
2151         u4 i;
2152         u4 ma, mi;
2153         char msg[MAXLOGTEXT];               /* maybe we get an exception */
2154
2155         /* get the classbuffer's class */
2156         c = cb->class;
2157
2158         /* maybe the class is already loaded */
2159         if (c->loaded)
2160                 return c;
2161
2162 #if defined(STATISTICS)
2163         if (opt_stat)
2164                 count_class_loads++;
2165 #endif
2166
2167         /* output for debugging purposes */
2168         if (loadverbose)
2169                 log_message_class("Loading class: ", c);
2170         
2171         /* class is somewhat loaded */
2172         c->loaded = true;
2173
2174         if (!check_classbuffer_size(cb, 4 + 2 + 2))
2175                 return NULL;
2176
2177         /* check signature */
2178         if (suck_u4(cb) != MAGIC) {
2179                 *exceptionptr = new_classformaterror(c, "Bad magic number");
2180
2181                 return NULL;
2182         }
2183
2184         /* check version */
2185         mi = suck_u2(cb);
2186         ma = suck_u2(cb);
2187
2188         if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
2189                 *exceptionptr =
2190                         new_unsupportedclassversionerror(c,
2191                                                                                          "Unsupported major.minor version %d.%d",
2192                                                                                          ma, mi);
2193
2194                 return NULL;
2195         }
2196
2197         /* load the constant pool */
2198         if (!load_constantpool(cb))
2199                 return NULL;
2200
2201         /*JOWENN*/
2202         c->erroneous_state = 0;
2203         c->initializing_thread = 0;     
2204         /*JOWENN*/
2205         c->classUsed = NOTUSED; /* not used initially CO-RT */
2206         c->impldBy = NULL;
2207
2208         /* ACC flags */
2209         if (!check_classbuffer_size(cb, 2))
2210                 return NULL;
2211
2212         c->flags = suck_u2(cb);
2213         /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
2214
2215         /* check ACC flags consistency */
2216         if (c->flags & ACC_INTERFACE) {
2217                 if (!(c->flags & ACC_ABSTRACT)) {
2218                         /* We work around this because interfaces in JDK 1.1 are
2219                          * not declared abstract. */
2220
2221                         c->flags |= ACC_ABSTRACT;
2222                         /* panic("Interface class not declared abstract"); */
2223                 }
2224
2225                 if (c->flags & ACC_FINAL) {
2226                         *exceptionptr =
2227                                 new_classformaterror(c,
2228                                                                          "Illegal class modifiers: 0x%X", c->flags);
2229
2230                         return NULL;
2231                 }
2232
2233                 if (c->flags & ACC_SUPER) {
2234                         c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
2235                 }
2236         }
2237
2238         if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
2239                 *exceptionptr =
2240                         new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
2241
2242                 return NULL;
2243         }
2244
2245         if (!check_classbuffer_size(cb, 2 + 2))
2246                 return NULL;
2247
2248         /* this class */
2249         i = suck_u2(cb);
2250         if (!(tc = class_getconstant(c, i, CONSTANT_Class)))
2251                 return NULL;
2252
2253         if (tc != c) {
2254                 utf_sprint(msg, c->name);
2255                 sprintf(msg + strlen(msg), " (wrong name: ");
2256                 utf_sprint(msg + strlen(msg), tc->name);
2257                 sprintf(msg + strlen(msg), ")");
2258
2259                 *exceptionptr =
2260                         new_exception_message(string_java_lang_NoClassDefFoundError, msg);
2261
2262                 return NULL;
2263         }
2264         
2265         /* retrieve superclass */
2266         if ((i = suck_u2(cb))) {
2267                 if (!(c->super = class_getconstant(c, i, CONSTANT_Class)))
2268                         return NULL;
2269
2270                 /* java.lang.Object may not have a super class. */
2271                 if (c->name == utf_java_lang_Object) {
2272                         *exceptionptr =
2273                                 new_exception_message(string_java_lang_ClassFormatError,
2274                                                                           "java.lang.Object with superclass");
2275
2276                         return NULL;
2277                 }
2278
2279                 /* Interfaces must have java.lang.Object as super class. */
2280                 if ((c->flags & ACC_INTERFACE) &&
2281                         c->super->name != utf_java_lang_Object) {
2282                         *exceptionptr =
2283                                 new_exception_message(string_java_lang_ClassFormatError,
2284                                                                           "Interfaces must have java.lang.Object as superclass");
2285
2286                         return NULL;
2287                 }
2288
2289         } else {
2290                 c->super = NULL;
2291
2292                 /* This is only allowed for java.lang.Object. */
2293                 if (c->name != utf_java_lang_Object) {
2294                         *exceptionptr = new_classformaterror(c, "Bad superclass index");
2295
2296                         return NULL;
2297                 }
2298         }
2299                          
2300         /* retrieve interfaces */
2301         if (!check_classbuffer_size(cb, 2))
2302                 return NULL;
2303
2304         c->interfacescount = suck_u2(cb);
2305
2306         if (!check_classbuffer_size(cb, 2 * c->interfacescount))
2307                 return NULL;
2308
2309         c->interfaces = MNEW(classinfo*, c->interfacescount);
2310         for (i = 0; i < c->interfacescount; i++) {
2311                 if (!(c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
2312                         return NULL;
2313         }
2314
2315         /* load fields */
2316         if (!check_classbuffer_size(cb, 2))
2317                 return NULL;
2318
2319         c->fieldscount = suck_u2(cb);
2320         c->fields = GCNEW(fieldinfo, c->fieldscount);
2321 /*      c->fields = MNEW(fieldinfo, c->fieldscount); */
2322         for (i = 0; i < c->fieldscount; i++) {
2323                 if (!load_field(cb, &(c->fields[i])))
2324                         return NULL;
2325         }
2326
2327         /* load methods */
2328         if (!check_classbuffer_size(cb, 2))
2329                 return NULL;
2330
2331         c->methodscount = suck_u2(cb);
2332 /*      c->methods = GCNEW(methodinfo, c->methodscount); */
2333         c->methods = MNEW(methodinfo, c->methodscount);
2334         for (i = 0; i < c->methodscount; i++) {
2335                 if (!load_method(cb, &(c->methods[i])))
2336                         return NULL;
2337         }
2338
2339         /* Check if all fields and methods can be uniquely
2340          * identified by (name,descriptor). */
2341         if (opt_verify) {
2342                 /* We use a hash table here to avoid making the
2343                  * average case quadratic in # of methods, fields.
2344                  */
2345                 static int shift = 0;
2346                 u2 *hashtab;
2347                 u2 *next; /* for chaining colliding hash entries */
2348                 size_t len;
2349                 size_t hashlen;
2350                 u2 index;
2351                 u2 old;
2352
2353                 /* Allocate hashtable */
2354                 len = c->methodscount;
2355                 if (len < c->fieldscount) len = c->fieldscount;
2356                 hashlen = 5 * len;
2357                 hashtab = MNEW(u2,(hashlen + len));
2358                 next = hashtab + hashlen;
2359
2360                 /* Determine bitshift (to get good hash values) */
2361                 if (!shift) {
2362                         len = sizeof(utf);
2363                         while (len) {
2364                                 len >>= 1;
2365                                 shift++;
2366                         }
2367                 }
2368
2369                 /* Check fields */
2370                 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2371
2372                 for (i = 0; i < c->fieldscount; ++i) {
2373                         fieldinfo *fi = c->fields + i;
2374
2375                         /* It's ok if we lose bits here */
2376                         index = ((((size_t) fi->name) +
2377                                           ((size_t) fi->descriptor)) >> shift) % hashlen;
2378
2379                         if ((old = hashtab[index])) {
2380                                 old--;
2381                                 next[i] = old;
2382                                 do {
2383                                         if (c->fields[old].name == fi->name &&
2384                                                 c->fields[old].descriptor == fi->descriptor) {
2385                                                 *exceptionptr =
2386                                                         new_classformaterror(c,
2387                                                                                                  "Repetitive field name/signature");
2388
2389                                                 return NULL;
2390                                         }
2391                                 } while ((old = next[old]));
2392                         }
2393                         hashtab[index] = i + 1;
2394                 }
2395                 
2396                 /* Check methods */
2397                 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2398
2399                 for (i = 0; i < c->methodscount; ++i) {
2400                         methodinfo *mi = c->methods + i;
2401
2402                         /* It's ok if we lose bits here */
2403                         index = ((((size_t) mi->name) +
2404                                           ((size_t) mi->descriptor)) >> shift) % hashlen;
2405
2406                         /*{ JOWENN
2407                                 int dbg;
2408                                 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2409                                         printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2410                                 }
2411                         }*/
2412
2413                         if ((old = hashtab[index])) {
2414                                 old--;
2415                                 next[i] = old;
2416                                 do {
2417                                         if (c->methods[old].name == mi->name &&
2418                                                 c->methods[old].descriptor == mi->descriptor) {
2419                                                 *exceptionptr =
2420                                                         new_classformaterror(c,
2421                                                                                                  "Repetitive method name/signature");
2422
2423                                                 return NULL;
2424                                         }
2425                                 } while ((old = next[old]));
2426                         }
2427                         hashtab[index] = i + 1;
2428                 }
2429                 
2430                 MFREE(hashtab, u2, (hashlen + len));
2431         }
2432
2433 #if defined(STATISTICS)
2434         if (opt_stat) {
2435                 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2436                 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
2437                 count_class_infos += sizeof(methodinfo) * c->methodscount;
2438         }
2439 #endif
2440
2441         /* load attribute structures */
2442         if (!check_classbuffer_size(cb, 2))
2443                 return NULL;
2444
2445         if (!load_attributes(cb, suck_u2(cb)))
2446                 return NULL;
2447
2448 #if 0
2449         /* Pre java 1.5 version don't check this. This implementation is like
2450            java 1.5 do it: for class file version 45.3 we don't check it, older
2451            versions are checked.
2452          */
2453         if ((ma == 45 && mi > 3) || ma > 45) {
2454                 /* check if all data has been read */
2455                 s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
2456
2457                 if (classdata_left > 0) {
2458                         *exceptionptr =
2459                                 new_classformaterror(c, "Extra bytes at the end of class file");
2460                         return NULL;
2461                 }
2462         }
2463 #endif
2464
2465         if (loadverbose)
2466                 log_message_class("Loading done class: ", c);
2467
2468         return c;
2469 }
2470
2471
2472
2473 /******************* Function: class_new_array *********************************
2474
2475     This function is called by class_new to setup an array class.
2476
2477 *******************************************************************************/
2478
2479 void class_new_array(classinfo *c)
2480 {
2481         classinfo *comp = NULL;
2482         methodinfo *clone;
2483         int namelen;
2484
2485         /* Check array class name */
2486         namelen = c->name->blength;
2487         if (namelen < 2 || c->name->text[0] != '[')
2488                 panic("Invalid array class name");
2489
2490         /* Check the component type */
2491         switch (c->name->text[1]) {
2492         case '[':
2493                 /* c is an array of arrays. We have to create the component class. */
2494                 if (opt_eager) {
2495                         comp = class_new_intern(utf_new_intern(c->name->text + 1,
2496                                                                                                    namelen - 1));
2497                         load_class_from_classloader(comp, c->classloader);
2498                         list_addfirst(&unlinkedclasses, comp);
2499
2500                 } else {
2501                         comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
2502                 }
2503                 break;
2504
2505         case 'L':
2506                 /* c is an array of objects. */
2507                 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2508                         panic("Invalid array class name");
2509
2510                 if (opt_eager) {
2511                         comp = class_new_intern(utf_new_intern(c->name->text + 2,
2512                                                                                                    namelen - 3));
2513                         load_class_from_classloader(comp, c->classloader);
2514                         list_addfirst(&unlinkedclasses, comp);
2515
2516                 } else {
2517                         comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
2518                 }
2519                 break;
2520         }
2521
2522         /* Setup the array class */
2523         c->super = class_java_lang_Object;
2524         c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2525
2526     c->interfacescount = 2;
2527     c->interfaces = MNEW(classinfo*, 2);
2528
2529         if (opt_eager) {
2530                 classinfo *tc;
2531
2532                 tc = class_java_lang_Cloneable;
2533                 load_class_bootstrap(tc);
2534                 list_addfirst(&unlinkedclasses, tc);
2535                 c->interfaces[0] = tc;
2536
2537                 tc = class_java_io_Serializable;
2538                 load_class_bootstrap(tc);
2539                 list_addfirst(&unlinkedclasses, tc);
2540                 c->interfaces[1] = tc;
2541
2542         } else {
2543                 c->interfaces[0] = class_java_lang_Cloneable;
2544                 c->interfaces[1] = class_java_io_Serializable;
2545         }
2546
2547         c->methodscount = 1;
2548         c->methods = MNEW(methodinfo, c->methodscount);
2549
2550         clone = c->methods;
2551         MSET(clone, 0, methodinfo, 1);
2552         clone->flags = ACC_PUBLIC;
2553         clone->name = utf_new_char("clone");
2554         clone->descriptor = utf_void__java_lang_Object;
2555         clone->class = c;
2556         clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2557         clone->monoPoly = MONO;
2558
2559         /* XXX: field: length? */
2560
2561         /* array classes are not loaded from class files */
2562         c->loaded = true;
2563 }
2564
2565
2566 /************************* Function: class_findfield ***************************
2567         
2568         Searches a 'classinfo' structure for a field having the given name and
2569         type.
2570
2571 *******************************************************************************/
2572
2573 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2574 {
2575         s4 i;
2576
2577         for (i = 0; i < c->fieldscount; i++) { 
2578                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
2579                         return &(c->fields[i]);                                                         
2580     }
2581
2582         panic("Can not find field given in CONSTANT_Fieldref");
2583
2584         /* keep compiler happy */
2585         return NULL;
2586 }
2587
2588
2589 /****************** Function: class_resolvefield_int ***************************
2590
2591     This is an internally used helper function. Do not use this directly.
2592
2593         Tries to resolve a field having the given name and type.
2594     If the field cannot be resolved, NULL is returned.
2595
2596 *******************************************************************************/
2597
2598 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2599 {
2600         fieldinfo *fi;
2601         s4         i;
2602
2603         /* search for field in class c */
2604
2605         for (i = 0; i < c->fieldscount; i++) { 
2606                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
2607                         return &(c->fields[i]);
2608                 }
2609     }
2610
2611         /* try superinterfaces recursively */
2612
2613         for (i = 0; i < c->interfacescount; i++) {
2614                 fi = class_resolvefield_int(c->interfaces[i], name, desc);
2615                 if (fi)
2616                         return fi;
2617         }
2618
2619         /* try superclass */
2620
2621         if (c->super)
2622                 return class_resolvefield_int(c->super, name, desc);
2623
2624         /* not found */
2625
2626         return NULL;
2627 }
2628
2629
2630 /********************* Function: class_resolvefield ***************************
2631         
2632         Resolves a reference from REFERER to a field with NAME and DESC in class C.
2633
2634     If the field cannot be resolved the return value is NULL. If EXCEPT is
2635     true *exceptionptr is set, too.
2636
2637 *******************************************************************************/
2638
2639 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2640                                                           classinfo *referer, bool except)
2641 {
2642         fieldinfo *fi;
2643
2644         /* XXX resolve class c */
2645         /* XXX check access from REFERER to C */
2646         
2647         fi = class_resolvefield_int(c, name, desc);
2648
2649         if (!fi) {
2650                 if (except)
2651                         *exceptionptr =
2652                                 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
2653                                                                                  name);
2654
2655                 return NULL;
2656         }
2657
2658         /* XXX check access rights */
2659
2660         return fi;
2661 }
2662
2663
2664 /* class_findmethod ************************************************************
2665         
2666    Searches a 'classinfo' structure for a method having the given name
2667    and descriptor. If descriptor is NULL, it is ignored.
2668
2669 *******************************************************************************/
2670
2671 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2672 {
2673         methodinfo *m;
2674         s4 i;
2675
2676         for (i = 0; i < c->methodscount; i++) {
2677                 m = &(c->methods[i]);
2678
2679                 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
2680                         return m;
2681         }
2682
2683         return NULL;
2684 }
2685
2686
2687 /*********************** Function: class_fetchmethod **************************
2688         
2689     like class_findmethod, but aborts with an error if the method is not found
2690
2691 *******************************************************************************/
2692
2693 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2694 {
2695         methodinfo *mi;
2696
2697         mi = class_findmethod(c, name, desc);
2698
2699         if (!mi) {
2700                 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2701                 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2702                 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2703                 panic("Method not found");
2704         }
2705
2706         return mi;
2707 }
2708
2709
2710 /************************* Function: class_findmethod_approx ******************
2711         
2712         like class_findmethod but ignores the return value when comparing the
2713         descriptor.
2714
2715 *******************************************************************************/
2716
2717 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2718 {
2719         s4 i;
2720
2721         for (i = 0; i < c->methodscount; i++) {
2722                 if (c->methods[i].name == name) {
2723                         utf *meth_descr = c->methods[i].descriptor;
2724                         
2725                         if (desc == NULL) 
2726                                 /* ignore type */
2727                                 return &(c->methods[i]);
2728
2729                         if (desc->blength <= meth_descr->blength) {
2730                                 /* current position in utf text   */
2731                                 char *desc_utf_ptr = desc->text;      
2732                                 char *meth_utf_ptr = meth_descr->text;                                    
2733                                 /* points behind utf strings */
2734                                 char *desc_end = utf_end(desc);         
2735                                 char *meth_end = utf_end(meth_descr);   
2736                                 char ch;
2737
2738                                 /* compare argument types */
2739                                 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2740
2741                                         if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2742                                                 break; /* no match */
2743
2744                                         if (ch == ')')
2745                                                 return &(c->methods[i]);   /* all parameter types equal */
2746                                 }
2747                         }
2748                 }
2749         }
2750
2751         return NULL;
2752 }
2753
2754
2755 /***************** Function: class_resolvemethod_approx ***********************
2756         
2757         Searches a class and every super class for a method (without paying
2758         attention to the return value)
2759
2760 *******************************************************************************/
2761
2762 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2763 {
2764         while (c) {
2765                 /* search for method (ignore returntype) */
2766                 methodinfo *m = class_findmethod_approx(c, name, desc);
2767                 /* method found */
2768                 if (m) return m;
2769                 /* search superclass */
2770                 c = c->super;
2771         }
2772
2773         return NULL;
2774 }
2775
2776
2777 /* class_resolvemethod *********************************************************
2778         
2779    Searches a class and it's super classes for a method.
2780
2781 *******************************************************************************/
2782
2783 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2784 {
2785         methodinfo *m;
2786
2787         while (c) {
2788                 m = class_findmethod(c, name, desc);
2789
2790                 if (m)
2791                         return m;
2792
2793                 c = c->super;
2794         }
2795
2796         return NULL;
2797 }
2798
2799
2800 /* class_resolveinterfacemethod_intern *****************************************
2801
2802    Internally used helper function. Do not use this directly.
2803
2804 *******************************************************************************/
2805
2806 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
2807                                                                                                            utf *name, utf *desc)
2808 {
2809         methodinfo *m;
2810         s4 i;
2811         
2812         m = class_findmethod(c, name, desc);
2813
2814         if (m)
2815                 return m;
2816
2817         /* try the superinterfaces */
2818
2819         for (i = 0; i < c->interfacescount; i++) {
2820                 m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
2821
2822                 if (m)
2823                         return m;
2824         }
2825         
2826         return NULL;
2827 }
2828
2829 /* class_resolveinterfacemethod ************************************************
2830
2831    Resolves a reference from REFERER to a method with NAME and DESC in
2832    interface C.
2833
2834    If the method cannot be resolved the return value is NULL. If
2835    EXCEPT is true *exceptionptr is set, too.
2836
2837 *******************************************************************************/
2838
2839 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2840                                                                                  classinfo *referer, bool except)
2841 {
2842         methodinfo *mi;
2843
2844         /* XXX resolve class c */
2845         /* XXX check access from REFERER to C */
2846         
2847         if (!(c->flags & ACC_INTERFACE)) {
2848                 if (except)
2849                         *exceptionptr =
2850                                 new_exception(string_java_lang_IncompatibleClassChangeError);
2851
2852                 return NULL;
2853         }
2854
2855         mi = class_resolveinterfacemethod_intern(c, name, desc);
2856
2857         if (mi)
2858                 return mi;
2859
2860         /* try class java.lang.Object */
2861         mi = class_findmethod(class_java_lang_Object, name, desc);
2862
2863         if (mi)
2864                 return mi;
2865
2866         if (except)
2867                 *exceptionptr =
2868                         new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
2869
2870         return NULL;
2871 }
2872
2873
2874 /* class_resolveclassmethod ****************************************************
2875         
2876     Resolves a reference from REFERER to a method with NAME and DESC in
2877     class C.
2878
2879     If the method cannot be resolved the return value is NULL. If EXCEPT is
2880     true *exceptionptr is set, too.
2881
2882 *******************************************************************************/
2883
2884 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
2885                                                                          classinfo *referer, bool except)
2886 {
2887         classinfo  *cls;
2888         methodinfo *mi;
2889         s4          i;
2890         char       *msg;
2891         s4          msglen;
2892
2893         /* XXX resolve class c */
2894         /* XXX check access from REFERER to C */
2895         
2896 /*      if (c->flags & ACC_INTERFACE) { */
2897 /*              if (except) */
2898 /*                      *exceptionptr = */
2899 /*                              new_exception(string_java_lang_IncompatibleClassChangeError); */
2900 /*              return NULL; */
2901 /*      } */
2902
2903         /* try class c and its superclasses */
2904
2905         cls = c;
2906
2907         while (cls) {
2908                 mi = class_findmethod(cls, name, desc);
2909
2910                 if (mi)
2911                         goto found;
2912
2913                 cls = cls->super;
2914         }
2915
2916         /* try the superinterfaces */
2917
2918         for (i = 0; i < c->interfacescount; i++) {
2919                 mi = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
2920
2921                 if (mi)
2922                         goto found;
2923         }
2924         
2925         if (except) {
2926                 msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
2927                         utf_strlen(desc) + strlen("0");
2928
2929                 msg = MNEW(char, msglen);
2930
2931                 utf_sprint(msg, c->name);
2932                 strcat(msg, ".");
2933                 utf_sprint(msg + strlen(msg), name);
2934                 utf_sprint(msg + strlen(msg), desc);
2935
2936                 *exceptionptr =
2937                         new_exception_message(string_java_lang_NoSuchMethodError, msg);
2938
2939                 MFREE(msg, char, msglen);
2940         }
2941
2942         return NULL;
2943
2944  found:
2945         if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
2946                 if (except)
2947                         *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
2948
2949                 return NULL;
2950         }
2951
2952         /* XXX check access rights */
2953
2954         return mi;
2955 }
2956
2957
2958 /************************* Function: class_issubclass **************************
2959
2960         Checks if sub is a descendant of super.
2961         
2962 *******************************************************************************/
2963
2964 bool class_issubclass(classinfo *sub, classinfo *super)
2965 {
2966         for (;;) {
2967                 if (!sub) return false;
2968                 if (sub == super) return true;
2969                 sub = sub->super;
2970         }
2971 }
2972
2973
2974 /****************** Initialization function for classes ******************
2975
2976         In Java, every class can have a static initialization function. This
2977         function has to be called BEFORE calling other methods or accessing static
2978         variables.
2979
2980 *******************************************************************************/
2981
2982 static classinfo *class_init_intern(classinfo *c);
2983
2984 classinfo *class_init(classinfo *c)
2985 {
2986         classinfo *r;
2987
2988         if (!makeinitializations)
2989                 return c;
2990
2991 #if defined(USE_THREADS)
2992         /* enter a monitor on the class */
2993
2994         builtin_monitorenter((java_objectheader *) c);
2995 #endif
2996
2997         /* maybe the class is already initalized or the current thread, which can
2998            pass the monitor, is currently initalizing this class */
2999
3000         /* JOWENN: In future we need an additinal flag: initializationfailed,
3001                 since further access to the class should cause a NoClassDefFound,
3002                 if the static initializer failed once
3003         */
3004
3005         if (c->initialized || c->initializing) {
3006 #if defined(USE_THREADS)
3007                 builtin_monitorexit((java_objectheader *) c);
3008 #endif
3009
3010                 return c;
3011         }
3012
3013         /* this initalizing run begins NOW */
3014         c->initializing = true;
3015
3016         /* call the internal function */
3017         r = class_init_intern(c);
3018
3019         /* if return value is not NULL everything was ok and the class is
3020            initialized */
3021         if (r)
3022                 c->initialized = true;
3023
3024         /* this initalizing run is done */
3025         c->initializing = false;
3026
3027 #if defined(USE_THREADS)
3028         /* leave the monitor */
3029
3030         builtin_monitorexit((java_objectheader *) c);
3031 #endif
3032
3033         return r;
3034 }
3035
3036
3037 /* this function MUST NOT be called directly, because of thread <clinit>
3038    race conditions */
3039
3040 static classinfo *class_init_intern(classinfo *c)
3041 {
3042         methodinfo *m;
3043         s4 i;
3044 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3045         int b;
3046 #endif
3047
3048         /* maybe the class is not already loaded */
3049         if (!c->loaded)
3050                 if (!load_class_bootstrap(c))
3051                         return NULL;
3052
3053         /* maybe the class is not already linked */
3054         if (!c->linked)
3055                 if (!link_class(c))
3056                         return NULL;
3057
3058 #if defined(STATISTICS)
3059         if (opt_stat)
3060                 count_class_inits++;
3061 #endif
3062
3063         /* initialize super class */
3064
3065         if (c->super) {
3066                 if (!c->super->initialized) {
3067                         if (initverbose) {
3068                                 char logtext[MAXLOGTEXT];
3069                                 sprintf(logtext, "Initialize super class ");
3070                                 utf_sprint_classname(logtext + strlen(logtext), c->super->name);
3071                                 sprintf(logtext + strlen(logtext), " from ");
3072                                 utf_sprint_classname(logtext + strlen(logtext), c->name);
3073                                 log_text(logtext);
3074                         }
3075
3076                         if (!class_init(c->super))
3077                                 return NULL;
3078                 }
3079         }
3080
3081         /* initialize interface classes */
3082
3083         for (i = 0; i < c->interfacescount; i++) {
3084                 if (!c->interfaces[i]->initialized) {
3085                         if (initverbose) {
3086                                 char logtext[MAXLOGTEXT];
3087                                 sprintf(logtext, "Initialize interface class ");
3088                                 utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i]->name);
3089                                 sprintf(logtext + strlen(logtext), " from ");
3090                                 utf_sprint_classname(logtext + strlen(logtext), c->name);
3091                                 log_text(logtext);
3092                         }
3093                         
3094                         if (!class_init(c->interfaces[i]))
3095                                 return NULL;
3096                 }
3097         }
3098
3099         m = class_findmethod(c, utf_clinit, utf_void__void);
3100
3101         if (!m) {
3102                 if (initverbose) {
3103                         char logtext[MAXLOGTEXT];
3104                         sprintf(logtext, "Class ");
3105                         utf_sprint_classname(logtext + strlen(logtext), c->name);
3106                         sprintf(logtext + strlen(logtext), " has no static class initializer");
3107                         log_text(logtext);
3108                 }
3109
3110                 return c;
3111         }
3112
3113         /* Sun's and IBM's JVM don't care about the static flag */
3114 /*      if (!(m->flags & ACC_STATIC)) { */
3115 /*              panic("Class initializer is not static!"); */
3116
3117         if (initverbose)
3118                 log_message_class("Starting static class initializer for class: ", c);
3119
3120 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3121         b = blockInts;
3122         blockInts = 0;
3123 #endif
3124
3125         /* now call the initializer */
3126         asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3127
3128 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3129         assert(blockInts == 0);
3130         blockInts = b;
3131 #endif
3132
3133         /* we have an exception or error */
3134         if (*exceptionptr) {
3135                 /* class is NOT initialized */
3136                 c->initialized = false;
3137
3138                 /* is this an exception, than wrap it */
3139                 if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
3140                         java_objectheader *xptr;
3141                         java_objectheader *cause;
3142
3143                         /* get the cause */
3144                         cause = *exceptionptr;
3145
3146                         /* clear exception, because we are calling jit code again */
3147                         *exceptionptr = NULL;
3148
3149                         /* wrap the exception */
3150                         xptr =
3151                                 new_exception_throwable(string_java_lang_ExceptionInInitializerError,
3152                                                                                 (java_lang_Throwable *) cause);
3153
3154                         /* XXX should we exit here? */
3155                         if (*exceptionptr)
3156                                 throw_exception();
3157
3158                         /* set new exception */
3159                         *exceptionptr = xptr;
3160                 }
3161
3162                 return NULL;
3163         }
3164
3165         if (initverbose)
3166                 log_message_class("Finished static class initializer for class: ", c);
3167
3168         return c;
3169 }
3170
3171
3172 void class_showconstanti(classinfo *c, int ii) 
3173 {
3174         u4 i = ii;
3175         voidptr e;
3176                 
3177         e = c->cpinfos [i];
3178         printf ("#%d:  ", (int) i);
3179         if (e) {
3180                 switch (c->cptags [i]) {
3181                 case CONSTANT_Class:
3182                         printf("Classreference -> ");
3183                         utf_display(((classinfo*)e)->name);
3184                         break;
3185                                 
3186                 case CONSTANT_Fieldref:
3187                         printf("Fieldref -> "); goto displayFMIi;
3188                 case CONSTANT_Methodref:
3189                         printf("Methodref -> "); goto displayFMIi;
3190                 case CONSTANT_InterfaceMethodref:
3191                         printf("InterfaceMethod -> "); goto displayFMIi;
3192                 displayFMIi:
3193                         {
3194                                 constant_FMIref *fmi = e;
3195                                 utf_display(fmi->class->name);
3196                                 printf(".");
3197                                 utf_display(fmi->name);
3198                                 printf(" ");
3199                                 utf_display(fmi->descriptor);
3200                         }
3201                         break;
3202
3203                 case CONSTANT_String:
3204                         printf("String -> ");
3205                         utf_display(e);
3206                         break;
3207                 case CONSTANT_Integer:
3208                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3209                         break;
3210                 case CONSTANT_Float:
3211                         printf("Float -> %f", ((constant_float*)e)->value);
3212                         break;
3213                 case CONSTANT_Double:
3214                         printf("Double -> %f", ((constant_double*)e)->value);
3215                         break;
3216                 case CONSTANT_Long:
3217                         {
3218                                 u8 v = ((constant_long*)e)->value;
3219 #if U8_AVAILABLE
3220                                 printf("Long -> %ld", (long int) v);
3221 #else
3222                                 printf("Long -> HI: %ld, LO: %ld\n", 
3223                                             (long int) v.high, (long int) v.low);
3224 #endif 
3225                         }
3226                         break;
3227                 case CONSTANT_NameAndType:
3228                         { 
3229                                 constant_nameandtype *cnt = e;
3230                                 printf("NameAndType: ");
3231                                 utf_display(cnt->name);
3232                                 printf(" ");
3233                                 utf_display(cnt->descriptor);
3234                         }
3235                         break;
3236                 case CONSTANT_Utf8:
3237                         printf("Utf8 -> ");
3238                         utf_display(e);
3239                         break;
3240                 default: 
3241                         panic("Invalid type of ConstantPool-Entry");
3242                 }
3243         }
3244         printf("\n");
3245 }
3246
3247
3248 void class_showconstantpool (classinfo *c) 
3249 {
3250         u4 i;
3251         voidptr e;
3252
3253         printf ("---- dump of constant pool ----\n");
3254
3255         for (i=0; i<c->cpcount; i++) {
3256                 printf ("#%d:  ", (int) i);
3257                 
3258                 e = c -> cpinfos [i];
3259                 if (e) {
3260                         
3261                         switch (c -> cptags [i]) {
3262                         case CONSTANT_Class:
3263                                 printf ("Classreference -> ");
3264                                 utf_display ( ((classinfo*)e) -> name );
3265                                 break;
3266                                 
3267                         case CONSTANT_Fieldref:
3268                                 printf ("Fieldref -> "); goto displayFMI;
3269                         case CONSTANT_Methodref:
3270                                 printf ("Methodref -> "); goto displayFMI;
3271                         case CONSTANT_InterfaceMethodref:
3272                                 printf ("InterfaceMethod -> "); goto displayFMI;
3273                         displayFMI:
3274                                 {
3275                                         constant_FMIref *fmi = e;
3276                                         utf_display ( fmi->class->name );
3277                                         printf (".");
3278                                         utf_display ( fmi->name);
3279                                         printf (" ");
3280                                         utf_display ( fmi->descriptor );
3281                                 }
3282                                 break;
3283
3284                         case CONSTANT_String:
3285                                 printf ("String -> ");
3286                                 utf_display (e);
3287                                 break;
3288                         case CONSTANT_Integer:
3289                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3290                                 break;
3291                         case CONSTANT_Float:
3292                                 printf ("Float -> %f", ((constant_float*)e) -> value);
3293                                 break;
3294                         case CONSTANT_Double:
3295                                 printf ("Double -> %f", ((constant_double*)e) -> value);
3296                                 break;
3297                         case CONSTANT_Long:
3298                                 {
3299                                         u8 v = ((constant_long*)e) -> value;
3300 #if U8_AVAILABLE
3301                                         printf ("Long -> %ld", (long int) v);
3302 #else
3303                                         printf ("Long -> HI: %ld, LO: %ld\n", 
3304                                                         (long int) v.high, (long int) v.low);
3305 #endif 
3306                                 }
3307                                 break;
3308                         case CONSTANT_NameAndType:
3309                                 {
3310                                         constant_nameandtype *cnt = e;
3311                                         printf ("NameAndType: ");
3312                                         utf_display (cnt->name);
3313                                         printf (" ");
3314                                         utf_display (cnt->descriptor);
3315                                 }
3316                                 break;
3317                         case CONSTANT_Utf8:
3318                                 printf ("Utf8 -> ");
3319                                 utf_display (e);
3320                                 break;
3321                         default: 
3322                                 panic ("Invalid type of ConstantPool-Entry");
3323                         }
3324                 }
3325
3326                 printf ("\n");
3327         }
3328 }
3329
3330
3331
3332 /********** Function: class_showmethods   (debugging only) *************/
3333
3334 void class_showmethods (classinfo *c)
3335 {
3336         s4 i;
3337         
3338         printf ("--------- Fields and Methods ----------------\n");
3339         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
3340
3341         printf ("This: "); utf_display (c->name); printf ("\n");
3342         if (c->super) {
3343                 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3344                 }
3345         printf ("Index: %d\n", c->index);
3346         
3347         printf ("interfaces:\n");       
3348         for (i=0; i < c-> interfacescount; i++) {
3349                 printf ("   ");
3350                 utf_display (c -> interfaces[i] -> name);
3351                 printf (" (%d)\n", c->interfaces[i] -> index);
3352                 }
3353
3354         printf ("fields:\n");           
3355         for (i=0; i < c -> fieldscount; i++) {
3356                 field_display (&(c -> fields[i]));
3357                 }
3358
3359         printf ("methods:\n");
3360         for (i=0; i < c -> methodscount; i++) {
3361                 methodinfo *m = &(c->methods[i]);
3362                 if ( !(m->flags & ACC_STATIC)) 
3363                         printf ("vftblindex: %d   ", m->vftblindex);
3364
3365                 method_display ( m );
3366
3367                 }
3368
3369         printf ("Virtual function table:\n");
3370         for (i=0; i<c->vftbl->vftbllength; i++) {
3371                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
3372                 }
3373
3374 }
3375
3376
3377 /******************************************************************************/
3378 /******************* General functions for the class loader *******************/
3379 /******************************************************************************/
3380
3381 /**************** function: class_primitive_from_sig ***************************
3382
3383         return the primitive class indicated by the given signature character
3384
3385     If the descriptor does not indicate a valid primitive type the
3386     return value is NULL.
3387
3388 ********************************************************************************/
3389
3390 classinfo *class_primitive_from_sig(char sig)
3391 {
3392         switch (sig) {
3393           case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3394           case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3395           case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3396           case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3397           case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3398           case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3399           case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3400           case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3401           case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3402         }
3403         return NULL;
3404 }
3405
3406 /****************** function: class_from_descriptor ****************************
3407
3408     return the class indicated by the given descriptor
3409
3410     utf_ptr....first character of descriptor
3411     end_ptr....first character after the end of the string
3412     next.......if non-NULL, *next is set to the first character after
3413                the descriptor. (Undefined if an error occurs.)
3414
3415     mode.......a combination (binary or) of the following flags:
3416
3417                (Flags marked with * are the default settings.)
3418
3419                What to do if a reference type descriptor is parsed successfully:
3420
3421                    CLASSLOAD_SKIP...skip it and return something != NULL
3422                                  * CLASSLOAD_NEW....get classinfo * via class_new
3423                    CLASSLOAD_LOAD...get classinfo * via loader_load
3424
3425                How to handle primitive types:
3426
3427                              * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3428                    CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3429
3430                How to handle "V" descriptors:
3431
3432                              * CLASSLOAD_VOID.....handle it like other primitive types
3433                    CLASSLOAD_NOVOID...treat it as an error
3434
3435                How to deal with extra characters after the end of the
3436                descriptor:
3437
3438                              * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3439                    CLASSLOAD_CHECKEND.....treat them as an error
3440
3441                How to deal with errors:
3442
3443                              * CLASSLOAD_PANIC....abort execution with an error message
3444                    CLASSLOAD_NOPANIC..return NULL on error
3445
3446 *******************************************************************************/
3447
3448 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3449                                                                  char **next, int mode)
3450 {
3451         char *start = utf_ptr;
3452         bool error = false;
3453         utf *name;
3454
3455         SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3456
3457         if (mode & CLASSLOAD_CHECKEND)
3458                 error |= (utf_ptr != end_ptr);
3459         
3460         if (!error) {
3461                 if (next) *next = utf_ptr;
3462                 
3463                 switch (*start) {
3464                   case 'V':
3465                           if (mode & CLASSLOAD_NOVOID)
3466                                   break;
3467                           /* FALLTHROUGH! */
3468                   case 'I':
3469                   case 'J':
3470                   case 'F':
3471                   case 'D':
3472                   case 'B':
3473                   case 'C':
3474                   case 'S':
3475                   case 'Z':
3476                           return (mode & CLASSLOAD_NULLPRIMITIVE)
3477                                   ? NULL
3478                                   : class_primitive_from_sig(*start);
3479                           
3480                   case 'L':
3481                           start++;
3482                           utf_ptr--;
3483                           /* FALLTHROUGH! */
3484                   case '[':
3485                           if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3486                           name = utf_new(start, utf_ptr - start);
3487                           if (opt_eager) {
3488                                   classinfo *tc;
3489
3490                                   tc = class_new_intern(name);
3491                                   load_class_from_classloader(tc, NULL);
3492                                   list_addfirst(&unlinkedclasses, tc);
3493
3494                                   return tc;
3495
3496                           } else {
3497                                   return (mode & CLASSLOAD_LOAD)
3498                                           ? load_class_from_classloader(class_new(name), NULL) : class_new(name); /* XXX handle errors */
3499                           }
3500                 }
3501         }
3502
3503         /* An error occurred */
3504         if (mode & CLASSLOAD_NOPANIC)
3505                 return NULL;
3506
3507         log_plain("Invalid descriptor at beginning of '");
3508         log_plain_utf(utf_new(start, end_ptr - start));
3509         log_plain("'");
3510         log_nl();
3511                                                   
3512         panic("Invalid descriptor");
3513
3514         /* keep compiler happy */
3515         return NULL;
3516 }
3517
3518
3519 /******************* function: type_from_descriptor ****************************
3520
3521     return the basic type indicated by the given descriptor
3522
3523     This function parses a descriptor and returns its basic type as
3524     TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3525
3526     cls...if non-NULL the referenced variable is set to the classinfo *
3527           returned by class_from_descriptor.
3528
3529     For documentation of the arguments utf_ptr, end_ptr, next and mode
3530     see class_from_descriptor. The only difference is that
3531     type_from_descriptor always uses CLASSLOAD_PANIC.
3532
3533 ********************************************************************************/
3534
3535 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3536                                                  char **next, int mode)
3537 {
3538         classinfo *mycls;
3539         if (!cls) cls = &mycls;
3540         *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3541         switch (*utf_ptr) {
3542           case 'B': 
3543           case 'C':
3544           case 'I':
3545           case 'S':  
3546           case 'Z':
3547                   return TYPE_INT;
3548           case 'D':
3549                   return TYPE_DOUBLE;
3550           case 'F':
3551                   return TYPE_FLOAT;
3552           case 'J':
3553                   return TYPE_LONG;
3554           case 'V':
3555                   return TYPE_VOID;
3556         }
3557         return TYPE_ADDRESS;
3558 }
3559
3560
3561 /******************** Function: loader_close ***********************************
3562
3563         Frees all resources
3564         
3565 *******************************************************************************/
3566
3567 void loader_close()
3568 {
3569         classinfo *c;
3570         s4 slot;
3571
3572         for (slot = 0; slot < class_hash.size; slot++) {
3573                 c = class_hash.ptr[slot];
3574
3575                 while (c) {
3576                         class_free(c);
3577                         c = c->hashlink;
3578                 }
3579         }
3580 }
3581
3582
3583 /*
3584  * These are local overrides for various environment variables in Emacs.
3585  * Please do not remove this and leave it at the end of the file, where
3586  * Emacs will automagically detect them.
3587  * ---------------------------------------------------------------------
3588  * Local variables:
3589  * mode: c
3590  * indent-tabs-mode: t
3591  * c-basic-offset: 4
3592  * tab-width: 4
3593  * End:
3594  */