* SUPPORT_FMOD: Removed.
[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 4127 2006-01-10 20:56:16Z twisti $
36
37 */
38
39
40 #include "config.h"
41
42 #include <stdlib.h>
43 #include <string.h>
44 #include <assert.h>
45
46 #include "vm/types.h"
47
48 #include "mm/memory.h"
49 #include "native/native.h"
50 #include "native/include/java_lang_Throwable.h"
51
52 #if defined(USE_THREADS)
53 # if defined(NATIVE_THREADS)
54 #  include "threads/native/threads.h"
55 # else
56 #  include "threads/green/threads.h"
57 #  include "threads/green/locks.h"
58 # endif
59 #endif
60
61 #include "toolbox/logging.h"
62 #include "vm/builtin.h"
63 #include "vm/classcache.h"
64 #include "vm/exceptions.h"
65 #include "vm/global.h"
66 #include "vm/linker.h"
67 #include "vm/loader.h"
68 #include "vm/options.h"
69 #include "vm/statistics.h"
70 #include "vm/stringlocal.h"
71 #include "vm/suck.h"
72
73 #if defined(ENABLE_ZLIB)
74 # include "vm/zip.h"
75 #endif
76
77 #include "vm/jit/asmpart.h"
78 #include "vm/jit/codegen-common.h"
79
80
81 /******************************************************************************/
82 /* DEBUG HELPERS                                                              */
83 /******************************************************************************/
84
85 #ifndef NDEBUG
86 #define LOADER_DEBUG
87 #endif
88
89 #ifdef LOADER_DEBUG
90 #define LOADER_ASSERT(cond)  assert(cond)
91 #else
92 #define LOADER_ASSERT(cond)
93 #endif
94
95
96 /* loader_init *****************************************************************
97
98    Initializes all lists and loads all classes required for the system
99    or the compiler.
100
101 *******************************************************************************/
102  
103 bool loader_init(u1 *stackbottom)
104 {
105 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
106         list_classpath_entry *lce;
107
108         /* Initialize the monitor pointer for zip/jar file locking. */
109
110         for (lce = list_first(list_classpath_entries); lce != NULL;
111                  lce = list_next(list_classpath_entries, lce))
112                 if (lce->type == CLASSPATH_ARCHIVE)
113                         initObjectLock((java_objectheader *) lce);
114 #endif
115
116         /* load some important classes */
117
118         if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
119                 return false;
120
121         if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
122                 return false;
123
124         if (!(class_java_lang_Cloneable =
125                   load_class_bootstrap(utf_java_lang_Cloneable)))
126                 return false;
127
128         if (!(class_java_io_Serializable =
129                   load_class_bootstrap(utf_java_io_Serializable)))
130                 return false;
131
132
133         /* load classes for wrapping primitive types */
134
135         if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
136                 return false;
137
138         if (!(class_java_lang_Boolean =
139                   load_class_bootstrap(utf_java_lang_Boolean)))
140                 return false;
141
142         if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
143                 return false;
144
145         if (!(class_java_lang_Character =
146                   load_class_bootstrap(utf_java_lang_Character)))
147                 return false;
148
149         if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
150                 return false;
151
152         if (!(class_java_lang_Integer =
153                   load_class_bootstrap(utf_java_lang_Integer)))
154                 return false;
155
156         if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
157                 return false;
158
159         if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
160                 return false;
161
162         if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
163                 return false;
164
165
166         /* load some other important classes */
167
168         if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
169                 return false;
170
171         if (!(class_java_lang_ClassLoader =
172                   load_class_bootstrap(utf_java_lang_ClassLoader)))
173                 return false;
174
175         if (!(class_java_lang_SecurityManager =
176                   load_class_bootstrap(utf_java_lang_SecurityManager)))
177                 return false;
178
179         if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
180                 return false;
181
182         if (!(class_java_lang_Thread =
183                   load_class_bootstrap(utf_new_char("java/lang/Thread"))))
184                 return false;
185
186         if (!(class_java_lang_ThreadGroup =
187                   load_class_bootstrap(utf_java_lang_ThreadGroup)))
188                 return false;
189
190         if (!(class_java_lang_VMThread =
191                   load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
192                 return false;
193
194
195         /* some classes which may be used more often */
196
197         if (!(class_java_lang_StackTraceElement =
198                   load_class_bootstrap(utf_java_lang_StackTraceElement)))
199                 return false;
200
201         if (!(class_java_lang_reflect_Constructor =
202                   load_class_bootstrap(utf_java_lang_reflect_Constructor)))
203                 return false;
204
205         if (!(class_java_lang_reflect_Field =
206                   load_class_bootstrap(utf_java_lang_reflect_Field)))
207                 return false;
208
209         if (!(class_java_lang_reflect_Method =
210                   load_class_bootstrap(utf_java_lang_reflect_Method)))
211                 return false;
212
213         if (!(class_java_security_PrivilegedAction =
214                   load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
215                 return false;
216
217         if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
218                 return false;
219
220         if (!(arrayclass_java_lang_Object =
221                   load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
222                 return false;
223
224 #if defined(USE_THREADS)
225         if (stackbottom != 0)
226                 initLocks();
227 #endif
228
229         return true;
230 }
231
232
233 /* loader_load_all_classes *****************************************************
234
235    Loads all classes specified in the BOOTCLASSPATH.
236
237 *******************************************************************************/
238
239 void loader_load_all_classes(void)
240 {
241         list_classpath_entry    *lce;
242         hashtable               *ht;
243         s4                       slot;
244         hashtable_zipfile_entry *htzfe;
245         utf                     *u;
246
247         for (lce = list_first(list_classpath_entries); lce != NULL;
248                  lce = list_next(list_classpath_entries, lce)) {
249 #if defined(ENABLE_ZLIB)
250                 if (lce->type == CLASSPATH_ARCHIVE) {
251                         /* get the classes hashtable */
252
253                         ht = lce->htclasses;
254
255                         for (slot = 0; slot < ht->size; slot++) {
256                                 htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
257
258                                 for (; htzfe; htzfe = htzfe->hashlink) {
259                                         u = htzfe->filename;
260
261                                         /* skip all entries in META-INF and .properties,
262                        .png files */
263
264                                         if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
265                                                 strstr(u->text, ".properties") ||
266                                                 strstr(u->text, ".png"))
267                                                 continue;
268
269                                         /* load class from bootstrap classloader */
270
271                                         if (!load_class_bootstrap(u)) {
272                                                 fprintf(stderr, "Error loading: ");
273                                                 utf_fprint_classname(stderr, u);
274                                                 fprintf(stderr, "\n");
275
276                                                 /* print out exception and cause */
277
278                                                 exceptions_print_exception(*exceptionptr);
279                                         }
280                                 }
281                         }
282
283                 } else {
284 #endif
285 #if defined(ENABLE_ZLIB)
286                 }
287 #endif
288         }
289 }
290
291
292 /******************************************************************************/
293 /******************* Some support functions ***********************************/
294 /******************************************************************************/
295
296 void fprintflags (FILE *fp, u2 f)
297 {
298    if ( f & ACC_PUBLIC )       fprintf (fp," PUBLIC");
299    if ( f & ACC_PRIVATE )      fprintf (fp," PRIVATE");
300    if ( f & ACC_PROTECTED )    fprintf (fp," PROTECTED");
301    if ( f & ACC_STATIC )       fprintf (fp," STATIC");
302    if ( f & ACC_FINAL )        fprintf (fp," FINAL");
303    if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
304    if ( f & ACC_VOLATILE )     fprintf (fp," VOLATILE");
305    if ( f & ACC_TRANSIENT )    fprintf (fp," TRANSIENT");
306    if ( f & ACC_NATIVE )       fprintf (fp," NATIVE");
307    if ( f & ACC_INTERFACE )    fprintf (fp," INTERFACE");
308    if ( f & ACC_ABSTRACT )     fprintf (fp," ABSTRACT");
309 }
310
311
312 /********** internal function: printflags  (only for debugging) ***************/
313
314 void printflags(u2 f)
315 {
316         fprintflags(stdout,f);
317 }
318
319
320 /********************** Function: skipattributebody ****************************
321
322         skips an attribute after the 16 bit reference to attribute_name has already
323         been read
324         
325 *******************************************************************************/
326
327 static bool skipattributebody(classbuffer *cb)
328 {
329         u4 len;
330
331         if (!suck_check_classbuffer_size(cb, 4))
332                 return false;
333
334         len = suck_u4(cb);
335
336         if (!suck_check_classbuffer_size(cb, len))
337                 return false;
338
339         suck_skip_nbytes(cb, len);
340
341         return true;
342 }
343
344
345 /************************* Function: skipattributes ****************************
346
347         skips num attribute structures
348         
349 *******************************************************************************/
350
351 static bool skipattributes(classbuffer *cb, u4 num)
352 {
353         u4 i;
354         u4 len;
355
356         for (i = 0; i < num; i++) {
357                 if (!suck_check_classbuffer_size(cb, 2 + 4))
358                         return false;
359
360                 suck_u2(cb);
361                 len = suck_u4(cb);
362
363                 if (!suck_check_classbuffer_size(cb, len))
364                         return false;
365
366                 suck_skip_nbytes(cb, len);
367         }
368
369         return true;
370 }
371
372
373 /* load_constantpool ***********************************************************
374
375    Loads the constantpool of a class, the entries are transformed into
376    a simpler format by resolving references (a detailed overview of
377    the compact structures can be found in global.h).
378
379 *******************************************************************************/
380
381 static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
382 {
383
384         /* The following structures are used to save information which cannot be 
385            processed during the first pass. After the complete constantpool has 
386            been traversed the references can be resolved. 
387            (only in specific order)                                                */
388         
389         /* CONSTANT_Class entries */
390         typedef struct forward_class {
391                 struct forward_class *next;
392                 u2 thisindex;
393                 u2 name_index;
394         } forward_class;
395
396         /* CONSTANT_String */
397         typedef struct forward_string {
398                 struct forward_string *next;
399                 u2 thisindex;
400                 u2 string_index;
401         } forward_string;
402
403         /* CONSTANT_NameAndType */
404         typedef struct forward_nameandtype {
405                 struct forward_nameandtype *next;
406                 u2 thisindex;
407                 u2 name_index;
408                 u2 sig_index;
409         } forward_nameandtype;
410
411         /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
412         typedef struct forward_fieldmethint {
413                 struct forward_fieldmethint *next;
414                 u2 thisindex;
415                 u1 tag;
416                 u2 class_index;
417                 u2 nameandtype_index;
418         } forward_fieldmethint;
419
420
421         classinfo *c;
422         u4 idx;
423
424         forward_class *forward_classes = NULL;
425         forward_string *forward_strings = NULL;
426         forward_nameandtype *forward_nameandtypes = NULL;
427         forward_fieldmethint *forward_fieldmethints = NULL;
428
429         forward_class *nfc;
430         forward_string *nfs;
431         forward_nameandtype *nfn;
432         forward_fieldmethint *nff;
433
434         u4 cpcount;
435         u1 *cptags;
436         voidptr *cpinfos;
437
438         c = cb->class;
439
440         /* number of entries in the constant_pool table plus one */
441         if (!suck_check_classbuffer_size(cb, 2))
442                 return false;
443
444         cpcount = c->cpcount = suck_u2(cb);
445
446         /* allocate memory */
447         cptags  = c->cptags  = MNEW(u1, cpcount);
448         cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
449
450         if (cpcount < 1) {
451                 exceptions_throw_classformaterror(c, "Illegal constant pool size");
452                 return false;
453         }
454         
455 #if defined(ENABLE_STATISTICS)
456         if (opt_stat)
457                 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
458 #endif
459         
460         /* initialize constantpool */
461         for (idx = 0; idx < cpcount; idx++) {
462                 cptags[idx] = CONSTANT_UNUSED;
463                 cpinfos[idx] = NULL;
464         }
465
466                         
467         /******* first pass *******/
468         /* entries which cannot be resolved now are written into 
469            temporary structures and traversed again later        */
470                    
471         idx = 1;
472         while (idx < cpcount) {
473                 u4 t;
474
475                 /* get constant type */
476                 if (!suck_check_classbuffer_size(cb, 1))
477                         return false;
478
479                 t = suck_u1(cb);
480
481                 switch (t) {
482                 case CONSTANT_Class:
483                         nfc = DNEW(forward_class);
484
485                         nfc->next = forward_classes;
486                         forward_classes = nfc;
487
488                         nfc->thisindex = idx;
489                         /* reference to CONSTANT_NameAndType */
490                         if (!suck_check_classbuffer_size(cb, 2))
491                                 return false;
492
493                         nfc->name_index = suck_u2(cb);
494
495                         idx++;
496                         break;
497                         
498                 case CONSTANT_String:
499                         nfs = DNEW(forward_string);
500                                 
501                         nfs->next = forward_strings;
502                         forward_strings = nfs;
503                                 
504                         nfs->thisindex = idx;
505
506                         /* reference to CONSTANT_Utf8_info with string characters */
507                         if (!suck_check_classbuffer_size(cb, 2))
508                                 return false;
509
510                         nfs->string_index = suck_u2(cb);
511                                 
512                         idx++;
513                         break;
514
515                 case CONSTANT_NameAndType:
516                         nfn = DNEW(forward_nameandtype);
517                                 
518                         nfn->next = forward_nameandtypes;
519                         forward_nameandtypes = nfn;
520                                 
521                         nfn->thisindex = idx;
522
523                         if (!suck_check_classbuffer_size(cb, 2 + 2))
524                                 return false;
525
526                         /* reference to CONSTANT_Utf8_info containing simple name */
527                         nfn->name_index = suck_u2(cb);
528
529                         /* reference to CONSTANT_Utf8_info containing field or method
530                            descriptor */
531                         nfn->sig_index = suck_u2(cb);
532                                 
533                         idx++;
534                         break;
535
536                 case CONSTANT_Fieldref:
537                 case CONSTANT_Methodref:
538                 case CONSTANT_InterfaceMethodref:
539                         nff = DNEW(forward_fieldmethint);
540                         
541                         nff->next = forward_fieldmethints;
542                         forward_fieldmethints = nff;
543
544                         nff->thisindex = idx;
545                         /* constant type */
546                         nff->tag = t;
547
548                         if (!suck_check_classbuffer_size(cb, 2 + 2))
549                                 return false;
550
551                         /* class or interface type that contains the declaration of the
552                            field or method */
553                         nff->class_index = suck_u2(cb);
554
555                         /* name and descriptor of the field or method */
556                         nff->nameandtype_index = suck_u2(cb);
557
558                         idx++;
559                         break;
560                                 
561                 case CONSTANT_Integer: {
562                         constant_integer *ci = NEW(constant_integer);
563
564 #if defined(ENABLE_STATISTICS)
565                         if (opt_stat)
566                                 count_const_pool_len += sizeof(constant_integer);
567 #endif
568
569                         if (!suck_check_classbuffer_size(cb, 4))
570                                 return false;
571
572                         ci->value = suck_s4(cb);
573                         cptags[idx] = CONSTANT_Integer;
574                         cpinfos[idx] = ci;
575
576                         idx++;
577                         break;
578                 }
579                                 
580                 case CONSTANT_Float: {
581                         constant_float *cf = NEW(constant_float);
582
583 #if defined(ENABLE_STATISTICS)
584                         if (opt_stat)
585                                 count_const_pool_len += sizeof(constant_float);
586 #endif
587
588                         if (!suck_check_classbuffer_size(cb, 4))
589                                 return false;
590
591                         cf->value = suck_float(cb);
592                         cptags[idx] = CONSTANT_Float;
593                         cpinfos[idx] = cf;
594
595                         idx++;
596                         break;
597                 }
598                                 
599                 case CONSTANT_Long: {
600                         constant_long *cl = NEW(constant_long);
601                                         
602 #if defined(ENABLE_STATISTICS)
603                         if (opt_stat)
604                                 count_const_pool_len += sizeof(constant_long);
605 #endif
606
607                         if (!suck_check_classbuffer_size(cb, 8))
608                                 return false;
609
610                         cl->value = suck_s8(cb);
611                         cptags[idx] = CONSTANT_Long;
612                         cpinfos[idx] = cl;
613                         idx += 2;
614                         if (idx > cpcount) {
615                                 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
616                                 return false;
617                         }
618                         break;
619                 }
620                         
621                 case CONSTANT_Double: {
622                         constant_double *cd = NEW(constant_double);
623                                 
624 #if defined(ENABLE_STATISTICS)
625                         if (opt_stat)
626                                 count_const_pool_len += sizeof(constant_double);
627 #endif
628
629                         if (!suck_check_classbuffer_size(cb, 8))
630                                 return false;
631
632                         cd->value = suck_double(cb);
633                         cptags[idx] = CONSTANT_Double;
634                         cpinfos[idx] = cd;
635                         idx += 2;
636                         if (idx > cpcount) {
637                                 exceptions_throw_classformaterror(c, "Invalid constant pool entry");
638                                 return false;
639                         }
640                         break;
641                 }
642                                 
643                 case CONSTANT_Utf8: { 
644                         u4 length;
645
646                         /* number of bytes in the bytes array (not string-length) */
647                         if (!suck_check_classbuffer_size(cb, 2))
648                                 return false;
649
650                         length = suck_u2(cb);
651                         cptags[idx] = CONSTANT_Utf8;
652
653                         /* validate the string */
654                         if (!suck_check_classbuffer_size(cb, length))
655                                 return false;
656
657 #ifdef ENABLE_VERIFIER
658                         if (opt_verify &&
659                                 !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length))) 
660                         {
661                                 exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
662                                 return false;
663                         }
664 #endif /* ENABLE_VERIFIER */
665                         /* insert utf-string into the utf-symboltable */
666                         cpinfos[idx] = utf_new((char *) cb->pos, length);
667
668                         /* skip bytes of the string (buffer size check above) */
669                         suck_skip_nbytes(cb, length);
670                         idx++;
671                         break;
672                 }
673                                                                                 
674                 default:
675                         exceptions_throw_classformaterror(c, "Illegal constant pool type");
676                         return false;
677                 }  /* end switch */
678         } /* end while */
679
680
681         /* resolve entries in temporary structures */
682
683         while (forward_classes) {
684                 utf *name =
685                         class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
686                 if (!name)
687                         return false;
688
689 #ifdef ENABLE_VERIFIER
690                 if (opt_verify && !is_valid_name_utf(name)) {
691                         exceptions_throw_classformaterror(c, "Class reference with invalid name");
692                         return false;
693                 }
694 #endif /* ENABLE_VERIFIER */
695
696                 /* add all class references to the descriptor_pool */
697
698                 if (!descriptor_pool_add_class(descpool, name))
699                         return false;
700
701                 cptags[forward_classes->thisindex] = CONSTANT_Class;
702
703                 if (opt_eager) {
704                         classinfo *tc;
705
706                         if (!(tc = load_class_bootstrap(name)))
707                                 return false;
708
709                         /* link the class later, because we cannot link the class currently
710                            loading */
711                         list_addfirst(&unlinkedclasses, tc);
712                 }
713
714                 /* the classref is created later */
715                 cpinfos[forward_classes->thisindex] = name;
716
717                 nfc = forward_classes;
718                 forward_classes = forward_classes->next;
719         }
720
721         while (forward_strings) {
722                 utf *text =
723                         class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
724                 if (!text)
725                         return false;
726
727                 /* resolve utf-string */
728                 cptags[forward_strings->thisindex] = CONSTANT_String;
729                 cpinfos[forward_strings->thisindex] = text;
730                 
731                 nfs = forward_strings;
732                 forward_strings = forward_strings->next;
733         }
734
735         while (forward_nameandtypes) {
736                 constant_nameandtype *cn = NEW(constant_nameandtype);   
737
738 #if defined(ENABLE_STATISTICS)
739                 if (opt_stat)
740                         count_const_pool_len += sizeof(constant_nameandtype);
741 #endif
742
743                 /* resolve simple name and descriptor */
744                 cn->name = class_getconstant(c,
745                                                                          forward_nameandtypes->name_index,
746                                                                          CONSTANT_Utf8);
747                 if (!cn->name)
748                         return false;
749
750                 cn->descriptor = class_getconstant(c,
751                                                                                    forward_nameandtypes->sig_index,
752                                                                                    CONSTANT_Utf8);
753                 if (!cn->descriptor)
754                         return false;
755
756 #ifdef ENABLE_VERIFIER
757                 if (opt_verify) {
758                         /* check name */
759                         if (!is_valid_name_utf(cn->name)) {
760                                 exceptions_throw_classformaterror(c,
761                                                                                                   "Illegal Field name \"%s\"",
762                                                                                                   cn->name->text);
763
764                                 return false;
765                         }
766
767                         /* disallow referencing <clinit> among others */
768                         if (cn->name->text[0] == '<' && cn->name != utf_init) {
769                                 exceptions_throw_classformaterror(c, "Illegal reference to special method");
770                                 return false;
771                         }
772                 }
773 #endif /* ENABLE_VERIFIER */
774
775                 cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
776                 cpinfos[forward_nameandtypes->thisindex] = cn;
777
778                 nfn = forward_nameandtypes;
779                 forward_nameandtypes = forward_nameandtypes->next;
780         }
781
782         while (forward_fieldmethints) {
783                 constant_nameandtype *nat;
784                 constant_FMIref *fmi = NEW(constant_FMIref);
785
786 #if defined(ENABLE_STATISTICS)
787                 if (opt_stat)
788                         count_const_pool_len += sizeof(constant_FMIref);
789 #endif
790                 /* resolve simple name and descriptor */
791
792                 nat = class_getconstant(c,
793                                                                 forward_fieldmethints->nameandtype_index,
794                                                                 CONSTANT_NameAndType);
795                 if (!nat)
796                         return false;
797
798                 /* add all descriptors in {Field,Method}ref to the descriptor_pool */
799
800                 if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
801                         return false;
802
803                 /* the classref is created later */
804
805                 fmi->classref = (constant_classref *) (size_t) forward_fieldmethints->class_index;
806                 fmi->name = nat->name;
807                 fmi->descriptor = nat->descriptor;
808
809                 cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
810                 cpinfos[forward_fieldmethints->thisindex] = fmi;
811         
812                 nff = forward_fieldmethints;
813                 forward_fieldmethints = forward_fieldmethints->next;
814         }
815
816         /* everything was ok */
817
818         return true;
819 }
820
821
822 /* load_field ******************************************************************
823
824    Load everything about a class field from the class file and fill a
825    'fieldinfo' structure. For static fields, space in the data segment
826    is allocated.
827
828 *******************************************************************************/
829
830 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
831
832 static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
833 {
834         classinfo *c;
835         u4 attrnum, i;
836         u4 jtype;
837         u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
838         utf *u;
839
840         c = cb->class;
841
842         if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
843                 return false;
844
845         f->flags = suck_u2(cb);
846
847         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
848                 return false;
849
850         f->name = u;
851
852         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
853                 return false;
854
855         f->descriptor = u;
856         f->parseddesc = NULL;
857
858         if (!descriptor_pool_add(descpool, u, NULL))
859                 return false;
860
861         /* descriptor_pool_add accepts method descriptors, so we have to check  */
862         /* against them here before the call of descriptor_to_basic_type below. */
863         if (u->text[0] == '(') {
864                 exceptions_throw_classformaterror(c, "Method descriptor used for field");
865                 return false;
866         }
867
868 #ifdef ENABLE_VERIFIER
869         if (opt_verify) {
870                 /* check name */
871                 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
872                         exceptions_throw_classformaterror(c,
873                                                                                           "Illegal Field name \"%s\"",
874                                                                                           f->name->text);
875                         return false;
876                 }
877
878                 /* check flag consistency */
879                 i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
880
881                 if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
882                         ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
883                         exceptions_throw_classformaterror(c,
884                                                                                           "Illegal field modifiers: 0x%X",
885                                                                                           f->flags);
886                         return false;
887                 }
888
889                 if (c->flags & ACC_INTERFACE) {
890                         if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
891                                 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
892                                 f->flags & ACC_TRANSIENT) {
893                                 exceptions_throw_classformaterror(c,
894                                                                                                   "Illegal field modifiers: 0x%X",
895                                                                                                   f->flags);
896                                 return false;
897                         }
898                 }
899         }
900 #endif /* ENABLE_VERIFIER */
901                 
902         f->type = jtype = descriptor_to_basic_type(f->descriptor); /* data type */
903         f->offset = 0;                           /* offset from start of object */
904         f->class = c;
905         f->xta = NULL;
906         
907         switch (f->type) {
908         case TYPE_INT:     f->value.i = 0; break;
909         case TYPE_FLOAT:   f->value.f = 0.0; break;
910         case TYPE_DOUBLE:  f->value.d = 0.0; break;
911         case TYPE_ADDRESS: f->value.a = NULL; break;
912         case TYPE_LONG:
913 #if U8_AVAILABLE
914                 f->value.l = 0; break;
915 #else
916                 f->value.l.low = 0; f->value.l.high = 0; break;
917 #endif
918         }
919
920         /* read attributes */
921         if (!suck_check_classbuffer_size(cb, 2))
922                 return false;
923
924         attrnum = suck_u2(cb);
925         for (i = 0; i < attrnum; i++) {
926                 if (!suck_check_classbuffer_size(cb, 2))
927                         return false;
928
929                 if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
930                         return false;
931
932                 if (u == utf_ConstantValue) {
933                         if (!suck_check_classbuffer_size(cb, 4 + 2))
934                                 return false;
935
936                         /* check attribute length */
937                         if (suck_u4(cb) != 2) {
938                                 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
939                                 return false;
940                         }
941                         
942                         /* constant value attribute */
943                         if (pindex != field_load_NOVALUE) {
944                                 exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
945                                 return false;
946                         }
947                         
948                         /* index of value in constantpool */            
949                         pindex = suck_u2(cb);
950                 
951                         /* initialize field with value from constantpool */             
952                         switch (jtype) {
953                         case TYPE_INT: {
954                                 constant_integer *ci; 
955
956                                 if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
957                                         return false;
958
959                                 f->value.i = ci->value;
960                         }
961                         break;
962                                         
963                         case TYPE_LONG: {
964                                 constant_long *cl; 
965
966                                 if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
967                                         return false;
968
969                                 f->value.l = cl->value;
970                         }
971                         break;
972
973                         case TYPE_FLOAT: {
974                                 constant_float *cf;
975
976                                 if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
977                                         return false;
978
979                                 f->value.f = cf->value;
980                         }
981                         break;
982                                                                                         
983                         case TYPE_DOUBLE: {
984                                 constant_double *cd;
985
986                                 if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
987                                         return false;
988
989                                 f->value.d = cd->value;
990                         }
991                         break;
992                                                 
993                         case TYPE_ADDRESS:
994                                 if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
995                                         return false;
996
997                                 /* create javastring from compressed utf8-string */
998                                 f->value.a = literalstring_new(u);
999                                 break;
1000         
1001                         default: 
1002                                 log_text("Invalid Constant - Type");
1003                         }
1004
1005                 } else {
1006                         /* unknown attribute */
1007                         if (!skipattributebody(cb))
1008                                 return false;
1009                 }
1010         }
1011
1012         /* everything was ok */
1013
1014         return true;
1015 }
1016
1017
1018 /* load_method *****************************************************************
1019
1020    Loads a method from the class file and fills an existing
1021    'methodinfo' structure. For native methods, the function pointer
1022    field is set to the real function pointer, for JavaVM methods a
1023    pointer to the compiler is used preliminarily.
1024         
1025 *******************************************************************************/
1026
1027 static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
1028 {
1029         classinfo *c;
1030         int argcount;
1031         s4 i, j;
1032         u4 attrnum;
1033         u4 codeattrnum;
1034         utf *u;
1035
1036         c = cb->class;
1037
1038 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1039         initObjectLock(&m->header);
1040 #endif
1041
1042 #if defined(ENABLE_STATISTICS)
1043         if (opt_stat)
1044                 count_all_methods++;
1045 #endif
1046
1047         m->thrownexceptionscount = 0;
1048         m->linenumbercount = 0;
1049         m->linenumbers = 0;
1050         m->class = c;
1051         m->nativelyoverloaded = false;
1052         
1053         if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
1054                 return false;
1055
1056         m->flags = suck_u2(cb);
1057
1058         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1059                 return false;
1060
1061         m->name = u;
1062
1063         if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1064                 return false;
1065
1066         m->descriptor = u;
1067         m->parseddesc = NULL;
1068
1069         if (!descriptor_pool_add(descpool, u, &argcount))
1070                 return false;
1071
1072 #ifdef ENABLE_VERIFIER
1073         if (opt_verify) {
1074                 if (!is_valid_name_utf(m->name)) {
1075                         exceptions_throw_classformaterror(c, "Method with invalid name");
1076                         return false;
1077                 }
1078
1079                 if (m->name->text[0] == '<' &&
1080                         m->name != utf_init && m->name != utf_clinit) {
1081                         exceptions_throw_classformaterror(c, "Method with invalid special name");
1082                         return false;
1083                 }
1084         }
1085 #endif /* ENABLE_VERIFIER */
1086         
1087         if (!(m->flags & ACC_STATIC))
1088                 argcount++; /* count the 'this' argument */
1089
1090 #ifdef ENABLE_VERIFIER
1091         if (opt_verify) {
1092                 if (argcount > 255) {
1093                         exceptions_throw_classformaterror(c, "Too many arguments in signature");
1094                         return false;
1095                 }
1096
1097                 /* check flag consistency */
1098                 if (m->name != utf_clinit) {
1099                         i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1100
1101                         if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
1102                                 exceptions_throw_classformaterror(c,
1103                                                                                                   "Illegal method modifiers: 0x%X",
1104                                                                                                   m->flags);
1105                                 return false;
1106                         }
1107
1108                         if (m->flags & ACC_ABSTRACT) {
1109                                 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
1110                                                                  ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
1111                                         exceptions_throw_classformaterror(c,
1112                                                                                                           "Illegal method modifiers: 0x%X",
1113                                                                                                           m->flags);
1114                                         return false;
1115                                 }
1116                         }
1117
1118                         if (c->flags & ACC_INTERFACE) {
1119                                 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
1120                                         exceptions_throw_classformaterror(c,
1121                                                                                                           "Illegal method modifiers: 0x%X",
1122                                                                                                           m->flags);
1123                                         return false;
1124                                 }
1125                         }
1126
1127                         if (m->name == utf_init) {
1128                                 if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
1129                                                                 ACC_NATIVE | ACC_ABSTRACT)) {
1130                                         exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
1131                                         return false;
1132                                 }
1133                         }
1134                 }
1135         }
1136 #endif /* ENABLE_VERIFIER */
1137                 
1138         m->jcode = NULL;
1139         m->basicblockcount = 0;
1140         m->basicblocks = NULL;
1141         m->basicblockindex = NULL;
1142         m->instructioncount = 0;
1143         m->instructions = NULL;
1144         m->stackcount = 0;
1145         m->stack = NULL;
1146         m->exceptiontable = NULL;
1147         m->stubroutine = NULL;
1148         m->mcode = NULL;
1149         m->entrypoint = NULL;
1150         m->methodUsed = NOTUSED;    
1151         m->monoPoly = MONO;    
1152         m->subRedefs = 0;
1153         m->subRedefsUsed = 0;
1154
1155         m->xta = NULL;
1156
1157         if (!suck_check_classbuffer_size(cb, 2))
1158                 return false;
1159         
1160         attrnum = suck_u2(cb);
1161         for (i = 0; i < attrnum; i++) {
1162                 utf *aname;
1163
1164                 if (!suck_check_classbuffer_size(cb, 2))
1165                         return false;
1166
1167                 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1168                         return false;
1169
1170                 if (aname == utf_Code) {
1171                         if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1172                                 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
1173                                 return false;
1174                         }
1175                         
1176                         if (m->jcode) {
1177                                 exceptions_throw_classformaterror(c, "Multiple Code attributes");
1178                                 return false;
1179                         }
1180
1181                         if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1182                                 return false;
1183
1184                         suck_u4(cb);
1185                         m->maxstack = suck_u2(cb);
1186                         m->maxlocals = suck_u2(cb);
1187
1188                         if (m->maxlocals < argcount) {
1189                                 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
1190                                 return false;
1191                         }
1192                         
1193                         if (!suck_check_classbuffer_size(cb, 4))
1194                                 return false;
1195
1196                         m->jcodelength = suck_u4(cb);
1197
1198                         if (m->jcodelength == 0) {
1199                                 exceptions_throw_classformaterror(c, "Code of a method has length 0");
1200                                 return false;
1201                         }
1202                         
1203                         if (m->jcodelength > 65535) {
1204                                 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
1205                                 return false;
1206                         }
1207
1208                         if (!suck_check_classbuffer_size(cb, m->jcodelength))
1209                                 return false;
1210
1211                         m->jcode = MNEW(u1, m->jcodelength);
1212                         suck_nbytes(m->jcode, cb, m->jcodelength);
1213
1214                         if (!suck_check_classbuffer_size(cb, 2))
1215                                 return false;
1216
1217                         m->exceptiontablelength = suck_u2(cb);
1218                         if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1219                                 return false;
1220
1221                         m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1222
1223 #if defined(ENABLE_STATISTICS)
1224                         if (opt_stat) {
1225                                 count_vmcode_len += m->jcodelength + 18;
1226                                 count_extable_len +=
1227                                         m->exceptiontablelength * sizeof(exceptiontable);
1228                         }
1229 #endif
1230
1231                         for (j = 0; j < m->exceptiontablelength; j++) {
1232                                 u4 idx;
1233                                 m->exceptiontable[j].startpc = suck_u2(cb);
1234                                 m->exceptiontable[j].endpc = suck_u2(cb);
1235                                 m->exceptiontable[j].handlerpc = suck_u2(cb);
1236
1237                                 idx = suck_u2(cb);
1238                                 if (!idx) {
1239                                         m->exceptiontable[j].catchtype.any = NULL;
1240
1241                                 } else {
1242                                         /* the classref is created later */
1243                                         if (!(m->exceptiontable[j].catchtype.any =
1244                                                   (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1245                                                 return false;
1246                                 }
1247                         }
1248
1249                         if (!suck_check_classbuffer_size(cb, 2))
1250                                 return false;
1251
1252                         codeattrnum = suck_u2(cb);
1253
1254                         for (; codeattrnum > 0; codeattrnum--) {
1255                                 utf *caname;
1256
1257                                 if (!suck_check_classbuffer_size(cb, 2))
1258                                         return false;
1259
1260                                 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1261                                         return false;
1262
1263                                 if (caname == utf_LineNumberTable) {
1264                                         u2 lncid;
1265
1266                                         if (!suck_check_classbuffer_size(cb, 4 + 2))
1267                                                 return false;
1268
1269                                         suck_u4(cb);
1270                                         m->linenumbercount = suck_u2(cb);
1271
1272                                         if (!suck_check_classbuffer_size(cb,
1273                                                                                                 (2 + 2) * m->linenumbercount))
1274                                                 return false;
1275
1276                                         m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1277                                         
1278                                         for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1279                                                 m->linenumbers[lncid].start_pc = suck_u2(cb);
1280                                                 m->linenumbers[lncid].line_number = suck_u2(cb);
1281                                         }
1282                                         codeattrnum--;
1283
1284                                         if (!skipattributes(cb, codeattrnum))
1285                                                 return false;
1286                                         
1287                                         break;
1288
1289                                 } else {
1290                                         if (!skipattributebody(cb))
1291                                                 return false;
1292                                 }
1293                         }
1294
1295                 } else if (aname == utf_Exceptions) {
1296                         s4 j;
1297
1298                         if (m->thrownexceptions) {
1299                                 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
1300                                 return false;
1301                         }
1302
1303                         if (!suck_check_classbuffer_size(cb, 4 + 2))
1304                                 return false;
1305
1306                         suck_u4(cb); /* length */
1307                         m->thrownexceptionscount = suck_u2(cb);
1308
1309                         if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1310                                 return false;
1311
1312                         m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1313
1314                         for (j = 0; j < m->thrownexceptionscount; j++) {
1315                                 /* the classref is created later */
1316                                 if (!((m->thrownexceptions)[j].any =
1317                                           (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1318                                         return false;
1319                         }
1320                                 
1321                 } else {
1322                         if (!skipattributebody(cb))
1323                                 return false;
1324                 }
1325         }
1326
1327         if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1328                 exceptions_throw_classformaterror(c, "Missing Code attribute");
1329                 return false;
1330         }
1331
1332         /* everything was ok */
1333
1334         return true;
1335 }
1336
1337
1338 /* load_attribute **************************************************************
1339
1340    Read attributes from classfile.
1341         
1342 *******************************************************************************/
1343
1344 static bool load_attributes(classbuffer *cb, u4 num)
1345 {
1346         classinfo *c;
1347         utf       *aname;
1348         u4 i, j;
1349
1350         c = cb->class;
1351
1352         for (i = 0; i < num; i++) {
1353                 /* retrieve attribute name */
1354                 if (!suck_check_classbuffer_size(cb, 2))
1355                         return false;
1356
1357                 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1358                         return false;
1359
1360                 if (aname == utf_InnerClasses) {
1361                         /* innerclasses attribute */
1362                         if (c->innerclass) {
1363                                 exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
1364                                 return false;
1365                         }
1366                                 
1367                         if (!suck_check_classbuffer_size(cb, 4 + 2))
1368                                 return false;
1369
1370                         /* skip attribute length */
1371                         suck_u4(cb);
1372
1373                         /* number of records */
1374                         c->innerclasscount = suck_u2(cb);
1375
1376                         if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1377                                 return false;
1378
1379                         /* allocate memory for innerclass structure */
1380                         c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1381
1382                         for (j = 0; j < c->innerclasscount; j++) {
1383                                 /* The innerclass structure contains a class with an encoded
1384                                    name, its defining scope, its simple name and a bitmask of
1385                                    the access flags. If an inner class is not a member, its
1386                                    outer_class is NULL, if a class is anonymous, its name is
1387                                    NULL. */
1388                                                                 
1389                                 innerclassinfo *info = c->innerclass + j;
1390
1391                                 info->inner_class.ref =
1392                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1393                                 info->outer_class.ref =
1394                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1395                                 info->name =
1396                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1397                                 info->flags = suck_u2(cb);
1398                         }
1399
1400                 } else if (aname == utf_SourceFile) {
1401                         if (!suck_check_classbuffer_size(cb, 4 + 2))
1402                                 return false;
1403
1404                         if (suck_u4(cb) != 2) {
1405                                 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
1406                                 return false;
1407                         }
1408
1409                         if (c->sourcefile) {
1410                                 exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
1411                                 return false;
1412                         }
1413
1414                         if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1415                                 return false;
1416
1417                 } else {
1418                         /* unknown attribute */
1419                         if (!skipattributebody(cb))
1420                                 return false;
1421                 }
1422         }
1423
1424         return true;
1425 }
1426
1427
1428 /* load_class_from_sysloader ***************************************************
1429
1430    Load the class with the given name using the system class loader
1431
1432    IN:
1433        name.............the classname
1434
1435    RETURN VALUE:
1436        the loaded class, or
1437            NULL if an exception has been thrown
1438
1439 *******************************************************************************/
1440
1441 classinfo *load_class_from_sysloader(utf *name)
1442 {
1443         methodinfo        *m;
1444         java_objectheader *cl;
1445         classinfo         *c;
1446
1447         LOADER_ASSERT(class_java_lang_Object);
1448         LOADER_ASSERT(class_java_lang_ClassLoader);
1449         LOADER_ASSERT(class_java_lang_ClassLoader->state & CLASS_LINKED);
1450         
1451         m = class_resolveclassmethod(class_java_lang_ClassLoader,
1452                                                                  utf_getSystemClassLoader,
1453                                                                  utf_void__java_lang_ClassLoader,
1454                                                                  class_java_lang_Object,
1455                                                                  false);
1456
1457         if (!m)
1458                 return false;
1459
1460         cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
1461
1462         if (!cl)
1463                 return false;
1464
1465         c = load_class_from_classloader(name, cl);
1466
1467         return c;
1468 }
1469
1470
1471 /* load_class_from_classloader *************************************************
1472
1473    Load the class with the given name using the given user-defined class loader.
1474
1475    IN:
1476        name.............the classname
1477            cl...............user-defined class loader
1478            
1479    RETURN VALUE:
1480        the loaded class, or
1481            NULL if an exception has been thrown
1482
1483 *******************************************************************************/
1484
1485 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1486 {
1487         classinfo *c;
1488         classinfo *tmpc;
1489
1490         LOADER_ASSERT(name);
1491
1492         /* lookup if this class has already been loaded */
1493
1494         c = classcache_lookup(cl, name);
1495
1496         if (c)
1497                 return c;
1498
1499         /* if other class loader than bootstrap, call it */
1500
1501         if (cl) {
1502                 methodinfo *lc;
1503                 char       *text;
1504                 s4          namelen;
1505
1506                 text = name->text;
1507                 namelen = name->blength;
1508
1509                 /* handle array classes */
1510                 if (text[0] == '[') {
1511                         classinfo *comp;
1512                         utf       *u;
1513
1514                         switch (text[1]) {
1515                         case 'L':
1516                                 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
1517                                 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
1518                                         *exceptionptr = new_noclassdeffounderror(name);
1519                                         return false;
1520                                 }
1521
1522                                 u = utf_new(text + 2, namelen - 3);
1523
1524                                 if (!(comp = load_class_from_classloader(u, cl)))
1525                                         return false;
1526
1527                                 /* create the array class */
1528
1529                                 c = class_array_of(comp, false);
1530
1531                                 tmpc = classcache_store(cl, c, true);
1532
1533                                 if (tmpc == NULL) {
1534                                         /* exception, free the loaded class */
1535                                         c->state &= ~CLASS_LOADING;
1536                                         class_free(c);
1537                                 }
1538
1539                                 return tmpc;
1540
1541                         case '[':
1542                                 /* load the component class */
1543
1544                                 u = utf_new(text + 1, namelen - 1);
1545
1546                                 if (!(comp = load_class_from_classloader(u, cl)))
1547                                         return false;
1548
1549                                 /* create the array class */
1550
1551                                 c = class_array_of(comp, false);
1552
1553                                 tmpc = classcache_store(cl, c, true);
1554
1555                                 if (tmpc == NULL) {
1556                                         /* exception, free the loaded class */
1557                                         c->state &= ~CLASS_LOADING;
1558                                         class_free(c);
1559                                 }
1560
1561                                 return tmpc;
1562
1563                         default:
1564                                 /* primitive array classes are loaded by the bootstrap loader */
1565
1566                                 c = load_class_bootstrap(name);
1567
1568                                 return c;
1569                         }
1570                 }
1571                 
1572                 LOADER_ASSERT(class_java_lang_Object);
1573
1574                 lc = class_resolveclassmethod(cl->vftbl->class,
1575                                                                           utf_loadClass,
1576                                                                           utf_java_lang_String__java_lang_Class,
1577                                                                           class_java_lang_Object,
1578                                                                           true);
1579
1580                 if (!lc)
1581                         return false; /* exception */
1582
1583                 c = (classinfo *) asm_calljavafunction(lc,
1584                                                                                            cl,
1585                                                                                            javastring_new_slash_to_dot(name),
1586                                                                                            NULL, NULL);
1587
1588                 if (c) {
1589                         /* Store this class in the loaded class cache. If another
1590                            class with the same (initloader,name) pair has been
1591                            stored earlier it will be returned by classcache_store
1592                            In this case classcache_store may not free the class
1593                            because it has already been exposed to Java code which
1594                            may have kept references to that class. */
1595
1596                     tmpc = classcache_store(cl, c, false);
1597
1598                         if (tmpc == NULL) {
1599                                 /* exception, free the loaded class */
1600                                 c->state &= ~CLASS_LOADING;
1601                                 class_free(c);
1602                         }
1603
1604                         c = tmpc;
1605
1606                 } else {
1607                         /* loadClass has thrown an exception */
1608                         /* we must convert ClassNotFoundException into NoClassDefFoundException */
1609                         /* XXX maybe we should have a flag that avoids this conversion */
1610                         /* for calling load_class_from_classloader from Class.forName  */
1611                         /* Currently we do a double conversion in these cases          */
1612                         classnotfoundexception_to_noclassdeffounderror();
1613                 }
1614
1615                 /* SUN compatible -verbose:class output */
1616
1617                 if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
1618                         printf("[Loaded ");
1619                         utf_display_classname(name);
1620                         printf("]\n");
1621                 }
1622
1623                 return c;
1624         } 
1625
1626         c = load_class_bootstrap(name);
1627
1628         return c;
1629 }
1630
1631
1632 /* load_class_bootstrap ********************************************************
1633         
1634    Load the class with the given name using the bootstrap class loader.
1635
1636    IN:
1637        name.............the classname
1638
1639    RETURN VALUE:
1640        loaded classinfo, or
1641            NULL if an exception has been thrown
1642
1643    SYNCHRONIZATION:
1644        load_class_bootstrap is synchronized. It can be treated as an
1645            atomic operation.
1646
1647 *******************************************************************************/
1648
1649 classinfo *load_class_bootstrap(utf *name)
1650 {
1651         classbuffer *cb;
1652         classinfo   *c;
1653         classinfo   *r;
1654
1655         /* for debugging */
1656
1657         LOADER_ASSERT(name);
1658
1659         /* lookup if this class has already been loaded */
1660
1661         if ((r = classcache_lookup(NULL, name)))
1662                 return r;
1663
1664         /* create the classinfo */
1665
1666         c = class_create_classinfo(name);
1667         
1668         /* handle array classes */
1669
1670         if (name->text[0] == '[') {
1671                 c = load_newly_created_array(c, NULL);
1672                 if (c == NULL)
1673                         return NULL;
1674                 LOADER_ASSERT(c->state & CLASS_LOADED);
1675                 return c;
1676         }
1677
1678 #if defined(ENABLE_STATISTICS)
1679         /* measure time */
1680
1681         if (getcompilingtime)
1682                 compilingtime_stop();
1683
1684         if (getloadingtime)
1685                 loadingtime_start();
1686 #endif
1687
1688         /* load classdata, throw exception on error */
1689
1690         if ((cb = suck_start(c)) == NULL) {
1691                 /* this normally means, the classpath was not set properly */
1692
1693                 if (name == utf_java_lang_Object)
1694                         throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1695                                                                            "java/lang/Object");
1696
1697                 *exceptionptr = new_noclassdeffounderror(name);
1698
1699                 return NULL;
1700         }
1701         
1702         /* load the class from the buffer */
1703
1704         r = load_class_from_classbuffer(cb);
1705
1706         if (!r) {
1707                 /* the class could not be loaded, free the classinfo struct */
1708
1709                 class_free(c);
1710
1711         } else {
1712                 /* Store this class in the loaded class cache this step also
1713                 checks the loading constraints. If the class has been loaded
1714                 before, the earlier loaded class is returned. */
1715
1716                 classinfo *res = classcache_store(NULL, c, true);
1717
1718                 if (!res) {
1719                         /* exception */
1720                         class_free(c);
1721                 }
1722
1723                 r = res;
1724         }
1725
1726         /* SUN compatible -verbose:class output */
1727
1728         if (opt_verboseclass && r) {
1729                 printf("[Loaded ");
1730                 utf_display_classname(name);
1731                 printf(" from %s]\n", cb->path);
1732         }
1733
1734         /* free memory */
1735
1736         suck_stop(cb);
1737
1738 #if defined(ENABLE_STATISTICS)
1739         /* measure time */
1740
1741         if (getloadingtime)
1742                 loadingtime_stop();
1743
1744         if (getcompilingtime)
1745                 compilingtime_start();
1746 #endif
1747
1748         return r;
1749 }
1750
1751
1752 /* load_class_from_classbuffer *************************************************
1753         
1754    Loads everything interesting about a class from the class file. The
1755    'classinfo' structure must have been allocated previously.
1756
1757    The super class and the interfaces implemented by this class need
1758    not be loaded. The link is set later by the function 'class_link'.
1759
1760    The loaded class is removed from the list 'unloadedclasses' and
1761    added to the list 'unlinkedclasses'.
1762         
1763    SYNCHRONIZATION:
1764        This function is NOT synchronized!
1765    
1766 *******************************************************************************/
1767
1768 classinfo *load_class_from_classbuffer(classbuffer *cb)
1769 {
1770         classinfo *c;
1771         utf *name;
1772         utf *supername;
1773         u4 i,j;
1774         u4 ma, mi;
1775         s4 dumpsize;
1776         descriptor_pool *descpool;
1777 #if defined(ENABLE_STATISTICS)
1778         u4 classrefsize;
1779         u4 descsize;
1780 #endif
1781
1782         /* get the classbuffer's class */
1783
1784         c = cb->class;
1785
1786         /* the class is already loaded */
1787
1788         if (c->state & CLASS_LOADED)
1789                 return c;
1790
1791 #if defined(ENABLE_STATISTICS)
1792         if (opt_stat)
1793                 count_class_loads++;
1794 #endif
1795
1796 #if !defined(NDEBUG)
1797         /* output for debugging purposes */
1798
1799         if (loadverbose)
1800                 log_message_class("Loading class: ", c);
1801 #endif
1802         
1803         /* mark start of dump memory area */
1804
1805         dumpsize = dump_size();
1806
1807         /* class is currently loading */
1808
1809         c->state |= CLASS_LOADING;
1810
1811         if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1812                 goto return_exception;
1813
1814         /* check signature */
1815
1816         if (suck_u4(cb) != MAGIC) {
1817                 exceptions_throw_classformaterror(c, "Bad magic number");
1818
1819                 goto return_exception;
1820         }
1821
1822         /* check version */
1823
1824         mi = suck_u2(cb);
1825         ma = suck_u2(cb);
1826
1827         if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
1828                 *exceptionptr =
1829                         new_unsupportedclassversionerror(c,
1830                                                                                          "Unsupported major.minor version %d.%d",
1831                                                                                          ma, mi);
1832
1833                 goto return_exception;
1834         }
1835
1836         /* create a new descriptor pool */
1837
1838         descpool = descriptor_pool_new(c);
1839
1840         /* load the constant pool */
1841
1842         if (!load_constantpool(cb, descpool))
1843                 goto return_exception;
1844
1845         c->classUsed = NOTUSED; /* not used initially CO-RT */
1846         c->impldBy = NULL;
1847
1848         /* ACC flags */
1849
1850         if (!suck_check_classbuffer_size(cb, 2))
1851                 goto return_exception;
1852
1853         c->flags = suck_u2(cb);
1854
1855         /* check ACC flags consistency */
1856
1857         if (c->flags & ACC_INTERFACE) {
1858                 if (!(c->flags & ACC_ABSTRACT)) {
1859                         /* We work around this because interfaces in JDK 1.1 are
1860                          * not declared abstract. */
1861
1862                         c->flags |= ACC_ABSTRACT;
1863                 }
1864
1865                 if (c->flags & ACC_FINAL) {
1866                         exceptions_throw_classformaterror(c,
1867                                                                                           "Illegal class modifiers: 0x%X",
1868                                                                                           c->flags);
1869                         goto return_exception;
1870                 }
1871
1872                 if (c->flags & ACC_SUPER) {
1873                         c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1874                 }
1875         }
1876
1877         if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1878                 exceptions_throw_classformaterror(c,
1879                                                                                   "Illegal class modifiers: 0x%X",
1880                                                                                   c->flags);
1881                 goto return_exception;
1882         }
1883
1884         if (!suck_check_classbuffer_size(cb, 2 + 2))
1885                 goto return_exception;
1886
1887         /* this class */
1888
1889         i = suck_u2(cb);
1890         if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1891                 goto return_exception;
1892
1893         if (c->name == utf_not_named_yet) {
1894                 /* we finally have a name for this class */
1895                 c->name = name;
1896                 class_set_packagename(c);
1897
1898         } else if (name != c->name) {
1899                 char *msg;
1900                 s4    msglen;
1901
1902                 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
1903                         utf_strlen(name) + strlen(")") + strlen("0");
1904
1905                 msg = MNEW(char, msglen);
1906
1907                 utf_sprint(msg, c->name);
1908                 strcat(msg, " (wrong name: ");
1909                 utf_strcat(msg, name);
1910                 strcat(msg, ")");
1911
1912                 *exceptionptr =
1913                         new_exception_message(string_java_lang_NoClassDefFoundError, msg);
1914
1915                 MFREE(msg, char, msglen);
1916
1917                 goto return_exception;
1918         }
1919         
1920         /* retrieve superclass */
1921
1922         c->super.any = NULL;
1923         if ((i = suck_u2(cb))) {
1924                 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1925                         goto return_exception;
1926
1927                 /* java.lang.Object may not have a super class. */
1928
1929                 if (c->name == utf_java_lang_Object) {
1930                         *exceptionptr =
1931                                 new_exception_message(string_java_lang_ClassFormatError,
1932                                                                           "java.lang.Object with superclass");
1933
1934                         goto return_exception;
1935                 }
1936
1937                 /* Interfaces must have java.lang.Object as super class. */
1938
1939                 if ((c->flags & ACC_INTERFACE) &&
1940                         supername != utf_java_lang_Object) {
1941                         *exceptionptr =
1942                                 new_exception_message(string_java_lang_ClassFormatError,
1943                                                                           "Interfaces must have java.lang.Object as superclass");
1944
1945                         goto return_exception;
1946                 }
1947
1948         } else {
1949                 supername = NULL;
1950
1951                 /* This is only allowed for java.lang.Object. */
1952
1953                 if (c->name != utf_java_lang_Object) {
1954                         exceptions_throw_classformaterror(c, "Bad superclass index");
1955                         goto return_exception;
1956                 }
1957         }
1958                          
1959         /* retrieve interfaces */
1960
1961         if (!suck_check_classbuffer_size(cb, 2))
1962                 goto return_exception;
1963
1964         c->interfacescount = suck_u2(cb);
1965
1966         if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
1967                 goto return_exception;
1968
1969         c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
1970         for (i = 0; i < c->interfacescount; i++) {
1971                 /* the classrefs are created later */
1972                 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1973                         goto return_exception;
1974         }
1975
1976         /* load fields */
1977         if (!suck_check_classbuffer_size(cb, 2))
1978                 goto return_exception;
1979
1980         c->fieldscount = suck_u2(cb);
1981         c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
1982 /*      c->fields = MNEW(fieldinfo, c->fieldscount); */
1983         for (i = 0; i < c->fieldscount; i++) {
1984                 if (!load_field(cb, &(c->fields[i]),descpool))
1985                         goto return_exception;
1986         }
1987
1988         /* load methods */
1989         if (!suck_check_classbuffer_size(cb, 2))
1990                 goto return_exception;
1991
1992         c->methodscount = suck_u2(cb);
1993 /*      c->methods = GCNEW(methodinfo, c->methodscount); */
1994         c->methods = MNEW(methodinfo, c->methodscount);
1995         for (i = 0; i < c->methodscount; i++) {
1996                 if (!load_method(cb, &(c->methods[i]),descpool))
1997                         goto return_exception;
1998         }
1999
2000         /* create the class reference table */
2001
2002         c->classrefs =
2003                 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
2004
2005         /* allocate space for the parsed descriptors */
2006
2007         descriptor_pool_alloc_parsed_descriptors(descpool);
2008         c->parseddescs =
2009                 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
2010
2011 #if defined(ENABLE_STATISTICS)
2012         if (opt_stat) {
2013                 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
2014                 count_classref_len += classrefsize;
2015                 count_parsed_desc_len += descsize;
2016         }
2017 #endif
2018
2019         /* put the classrefs in the constant pool */
2020         for (i = 0; i < c->cpcount; i++) {
2021                 if (c->cptags[i] == CONSTANT_Class) {
2022                         utf *name = (utf *) c->cpinfos[i];
2023                         c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
2024                 }
2025         }
2026
2027         /* set the super class reference */
2028
2029         if (supername) {
2030                 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2031                 if (!c->super.ref)
2032                         goto return_exception;
2033         }
2034
2035         /* set the super interfaces references */
2036
2037         for (i = 0; i < c->interfacescount; i++) {
2038                 c->interfaces[i].ref =
2039                         descriptor_pool_lookup_classref(descpool,
2040                                                                                         (utf *) c->interfaces[i].any);
2041                 if (!c->interfaces[i].ref)
2042                         goto return_exception;
2043         }
2044
2045         /* parse field descriptors */
2046
2047         for (i = 0; i < c->fieldscount; i++) {
2048                 c->fields[i].parseddesc =
2049                         descriptor_pool_parse_field_descriptor(descpool,
2050                                                                                                    c->fields[i].descriptor);
2051                 if (!c->fields[i].parseddesc)
2052                         goto return_exception;
2053         }
2054
2055         /* parse method descriptors */
2056
2057         for (i = 0; i < c->methodscount; i++) {
2058                 methodinfo *m = &c->methods[i];
2059                 m->parseddesc =
2060                         descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2061                                                                                                         m->flags, class_get_self_classref(m->class));
2062                 if (!m->parseddesc)
2063                         goto return_exception;
2064
2065                 for (j = 0; j < m->exceptiontablelength; j++) {
2066                         if (!m->exceptiontable[j].catchtype.any)
2067                                 continue;
2068                         if ((m->exceptiontable[j].catchtype.ref =
2069                                  descriptor_pool_lookup_classref(descpool,
2070                                                 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2071                                 goto return_exception;
2072                 }
2073
2074                 for (j = 0; j < m->thrownexceptionscount; j++) {
2075                         if (!m->thrownexceptions[j].any)
2076                                 continue;
2077                         if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2078                                                 (utf *) m->thrownexceptions[j].any)) == NULL)
2079                                 goto return_exception;
2080                 }
2081         }
2082
2083         /* parse the loaded descriptors */
2084
2085         for (i = 0; i < c->cpcount; i++) {
2086                 constant_FMIref *fmi;
2087                 s4               index;
2088                 
2089                 switch (c->cptags[i]) {
2090                 case CONSTANT_Fieldref:
2091                         fmi = (constant_FMIref *) c->cpinfos[i];
2092                         fmi->parseddesc.fd =
2093                                 descriptor_pool_parse_field_descriptor(descpool,
2094                                                                                                            fmi->descriptor);
2095                         if (!fmi->parseddesc.fd)
2096                                 goto return_exception;
2097                         index = (int) (size_t) fmi->classref;
2098                         fmi->classref =
2099                                 (constant_classref *) class_getconstant(c, index,
2100                                                                                                                 CONSTANT_Class);
2101                         if (!fmi->classref)
2102                                 goto return_exception;
2103                         break;
2104                 case CONSTANT_Methodref:
2105                 case CONSTANT_InterfaceMethodref:
2106                         fmi = (constant_FMIref *) c->cpinfos[i];
2107                         index = (int) (size_t) fmi->classref;
2108                         fmi->classref =
2109                                 (constant_classref *) class_getconstant(c, index,
2110                                                                                                                 CONSTANT_Class);
2111                         if (!fmi->classref)
2112                                 goto return_exception;
2113                         fmi->parseddesc.md =
2114                                 descriptor_pool_parse_method_descriptor(descpool,
2115                                                                                                                 fmi->descriptor,
2116                                                                                                                 ACC_UNDEF,
2117                                                                                                                 fmi->classref);
2118                         if (!fmi->parseddesc.md)
2119                                 goto return_exception;
2120                         break;
2121                 }
2122         }
2123
2124 #ifdef ENABLE_VERIFIER
2125         /* Check if all fields and methods can be uniquely
2126          * identified by (name,descriptor). */
2127
2128         if (opt_verify) {
2129                 /* We use a hash table here to avoid making the
2130                  * average case quadratic in # of methods, fields.
2131                  */
2132                 static int shift = 0;
2133                 u2 *hashtab;
2134                 u2 *next; /* for chaining colliding hash entries */
2135                 size_t len;
2136                 size_t hashlen;
2137                 u2 index;
2138                 u2 old;
2139
2140                 /* Allocate hashtable */
2141                 len = c->methodscount;
2142                 if (len < c->fieldscount) len = c->fieldscount;
2143                 hashlen = 5 * len;
2144                 hashtab = MNEW(u2,(hashlen + len));
2145                 next = hashtab + hashlen;
2146
2147                 /* Determine bitshift (to get good hash values) */
2148                 if (!shift) {
2149                         len = sizeof(utf);
2150                         while (len) {
2151                                 len >>= 1;
2152                                 shift++;
2153                         }
2154                 }
2155
2156                 /* Check fields */
2157                 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2158
2159                 for (i = 0; i < c->fieldscount; ++i) {
2160                         fieldinfo *fi = c->fields + i;
2161
2162                         /* It's ok if we lose bits here */
2163                         index = ((((size_t) fi->name) +
2164                                           ((size_t) fi->descriptor)) >> shift) % hashlen;
2165
2166                         if ((old = hashtab[index])) {
2167                                 old--;
2168                                 next[i] = old;
2169                                 do {
2170                                         if (c->fields[old].name == fi->name &&
2171                                                 c->fields[old].descriptor == fi->descriptor) {
2172                                                 exceptions_throw_classformaterror(c, "Repetitive field name/signature");
2173                                                 goto return_exception;
2174                                         }
2175                                 } while ((old = next[old]));
2176                         }
2177                         hashtab[index] = i + 1;
2178                 }
2179                 
2180                 /* Check methods */
2181                 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2182
2183                 for (i = 0; i < c->methodscount; ++i) {
2184                         methodinfo *mi = c->methods + i;
2185
2186                         /* It's ok if we lose bits here */
2187                         index = ((((size_t) mi->name) +
2188                                           ((size_t) mi->descriptor)) >> shift) % hashlen;
2189
2190                         /*{ JOWENN
2191                                 int dbg;
2192                                 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2193                                         printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2194                                 }
2195                         }*/
2196
2197                         if ((old = hashtab[index])) {
2198                                 old--;
2199                                 next[i] = old;
2200                                 do {
2201                                         if (c->methods[old].name == mi->name &&
2202                                                 c->methods[old].descriptor == mi->descriptor) {
2203                                                 exceptions_throw_classformaterror(c, "Repetitive method name/signature");
2204                                                 goto return_exception;
2205                                         }
2206                                 } while ((old = next[old]));
2207                         }
2208                         hashtab[index] = i + 1;
2209                 }
2210                 
2211                 MFREE(hashtab, u2, (hashlen + len));
2212         }
2213 #endif /* ENABLE_VERIFIER */
2214
2215 #if defined(ENABLE_STATISTICS)
2216         if (opt_stat) {
2217                 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2218                 count_class_infos += sizeof(fieldinfo)  * c->fieldscount;
2219                 count_class_infos += sizeof(methodinfo) * c->methodscount;
2220         }
2221 #endif
2222
2223         /* load attribute structures */
2224
2225         if (!suck_check_classbuffer_size(cb, 2))
2226                 goto return_exception;
2227
2228         if (!load_attributes(cb, suck_u2(cb)))
2229                 goto return_exception;
2230
2231 #if 0
2232         /* Pre java 1.5 version don't check this. This implementation is like
2233            java 1.5 do it: for class file version 45.3 we don't check it, older
2234            versions are checked.
2235          */
2236         if ((ma == 45 && mi > 3) || ma > 45) {
2237                 /* check if all data has been read */
2238                 s4 classdata_left = ((cb->data + cb->size) - cb->pos);
2239
2240                 if (classdata_left > 0) {
2241                         exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
2242                         goto return_exception;
2243                 }
2244         }
2245 #endif
2246
2247         /* release dump area */
2248
2249         dump_release(dumpsize);
2250
2251         /* revert loading state and class is loaded */
2252
2253         c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
2254
2255 #if !defined(NDEBUG)
2256         if (loadverbose)
2257                 log_message_class("Loading done class: ", c);
2258 #endif
2259
2260         return c;
2261
2262 return_exception:
2263         /* release dump area */
2264
2265         dump_release(dumpsize);
2266
2267         /* an exception has been thrown */
2268
2269         return NULL;
2270 }
2271
2272
2273 /* load_newly_created_array ****************************************************
2274
2275    Load a newly created array class.
2276
2277         RETURN VALUE:
2278             c....................the array class C has been loaded
2279                 other classinfo......the array class was found in the class cache, 
2280                                      C has been freed
2281             NULL.................an exception has been thrown
2282
2283         Note:
2284                 This is an internal function. Do not use it unless you know exactly
2285                 what you are doing!
2286
2287                 Use one of the load_class_... functions for general array class loading.
2288
2289 *******************************************************************************/
2290
2291 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2292 {
2293         classinfo         *comp = NULL;
2294         methodinfo        *clone;
2295         methoddesc        *clonedesc;
2296         constant_classref *classrefs;
2297         char              *text;
2298         s4                 namelen;
2299         utf               *u;
2300
2301         text = c->name->text;
2302         namelen = c->name->blength;
2303
2304         /* Check array class name */
2305
2306         if (namelen < 2 || text[0] != '[') {
2307                 *exceptionptr = new_noclassdeffounderror(c->name);
2308                 return NULL;
2309         }
2310
2311         /* Check the element type */
2312
2313         switch (text[1]) {
2314         case '[':
2315                 /* c is an array of arrays. We have to create the component class. */
2316
2317                 u = utf_new(text + 1, namelen - 1);
2318                 if (!(comp = load_class_from_classloader(u, loader)))
2319                         return NULL;
2320
2321                 LOADER_ASSERT(comp->state & CLASS_LOADED);
2322
2323                 if (opt_eager)
2324                         if (!link_class(c))
2325                                 return NULL;
2326
2327                 /* the array's flags are that of the component class */
2328                 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2329                 c->classloader = comp->classloader;
2330                 break;
2331
2332         case 'L':
2333                 /* c is an array of objects. */
2334
2335                 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2336                 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2337                         *exceptionptr = new_noclassdeffounderror(c->name);
2338                         return NULL;
2339                 }
2340
2341                 u = utf_new(text + 2, namelen - 3);
2342
2343                 if (!(comp = load_class_from_classloader(u, loader)))
2344                         return NULL;
2345
2346                 LOADER_ASSERT(comp->state & CLASS_LOADED);
2347
2348                 if (opt_eager)
2349                         if (!link_class(c))
2350                                 return NULL;
2351
2352                 /* the array's flags are that of the component class */
2353                 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2354                 c->classloader = comp->classloader;
2355                 break;
2356
2357         default:
2358                 /* c is an array of a primitive type */
2359
2360                 /* check for cases like `[II' */
2361                 if (namelen > 2) {
2362                         *exceptionptr = new_noclassdeffounderror(c->name);
2363                         return NULL;
2364                 }
2365
2366                 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2367                 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2368                 c->classloader = NULL;
2369         }
2370
2371         LOADER_ASSERT(class_java_lang_Object);
2372         LOADER_ASSERT(class_java_lang_Cloneable);
2373         LOADER_ASSERT(class_java_io_Serializable);
2374
2375         /* setup the array class */
2376
2377         c->super.cls = class_java_lang_Object;
2378
2379     c->interfacescount = 2;
2380     c->interfaces = MNEW(classref_or_classinfo, 2);
2381
2382         if (opt_eager) {
2383                 classinfo *tc;
2384
2385                 tc = class_java_lang_Cloneable;
2386                 LOADER_ASSERT(tc->state & CLASS_LOADED);
2387                 list_addfirst(&unlinkedclasses, tc);
2388                 c->interfaces[0].cls = tc;
2389
2390                 tc = class_java_io_Serializable;
2391                 LOADER_ASSERT(tc->state & CLASS_LOADED);
2392                 list_addfirst(&unlinkedclasses, tc);
2393                 c->interfaces[1].cls = tc;
2394
2395         } else {
2396                 c->interfaces[0].cls = class_java_lang_Cloneable;
2397                 c->interfaces[1].cls = class_java_io_Serializable;
2398         }
2399
2400         c->methodscount = 1;
2401         c->methods = MNEW(methodinfo, c->methodscount);
2402
2403         classrefs = MNEW(constant_classref, 2);
2404         CLASSREF_INIT(classrefs[0], c, c->name);
2405         CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2406
2407         /* create descriptor for clone method */
2408         /* we need one paramslot which is reserved for the 'this' parameter */
2409         clonedesc = NEW(methoddesc);
2410         clonedesc->returntype.type = TYPE_ADDRESS;
2411         clonedesc->returntype.classref = classrefs + 1;
2412         clonedesc->returntype.arraydim = 0;
2413         /* initialize params to "empty", add real params below in
2414            descriptor_params_from_paramtypes */
2415         clonedesc->paramcount = 0;
2416         clonedesc->paramslots = 0;
2417         clonedesc->paramtypes[0].classref = classrefs + 0;
2418
2419         /* create methodinfo */
2420
2421         clone = c->methods;
2422         MSET(clone, 0, methodinfo, 1);
2423
2424 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2425         initObjectLock(&clone->header);
2426 #endif
2427
2428         /* if you delete the ACC_NATIVE below, set clone->maxlocals=1 (interpreter 
2429            related) */
2430         clone->flags = ACC_PUBLIC | ACC_NATIVE;
2431         clone->name = utf_clone;
2432         clone->descriptor = utf_void__java_lang_Object;
2433         clone->parseddesc = clonedesc;
2434         clone->class = c;
2435         clone->monoPoly = MONO;
2436
2437         /* parse the descriptor to get the register allocation */
2438
2439         if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2440                 return false;
2441
2442         clone->entrypoint =
2443                 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2444
2445         /* XXX: field: length? */
2446
2447         /* array classes are not loaded from class files */
2448
2449         c->state |= CLASS_LOADED;
2450         c->parseddescs = (u1 *) clonedesc;
2451         c->parseddescsize = sizeof(methodinfo);
2452         c->classrefs = classrefs;
2453         c->classrefcount = 1;
2454
2455         /* insert class into the loaded class cache */
2456         /* XXX free classinfo if NULL returned? */
2457
2458         return classcache_store(loader, c, true);
2459 }
2460
2461
2462 /* loader_close ****************************************************************
2463
2464    Frees all resources.
2465         
2466 *******************************************************************************/
2467
2468 void loader_close(void)
2469 {
2470         /* empty */
2471 }
2472
2473
2474 /*
2475  * These are local overrides for various environment variables in Emacs.
2476  * Please do not remove this and leave it at the end of the file, where
2477  * Emacs will automagically detect them.
2478  * ---------------------------------------------------------------------
2479  * Local variables:
2480  * mode: c
2481  * indent-tabs-mode: t
2482  * c-basic-offset: 4
2483  * tab-width: 4
2484  * End:
2485  */