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