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