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