* src/vm/vm.c (vm_call_method_intern): Removed.
[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 4559 2006-03-05 23:24:50Z twisti $
36
37 */
38
39
40 #include "config.h"
41
42 #include <stdlib.h>
43 #include <string.h>
44 #include <assert.h>
45
46 #include "vm/types.h"
47
48 #include "mm/memory.h"
49 #include "native/native.h"
50 #include "native/include/java_lang_Throwable.h"
51
52 #if defined(USE_THREADS)
53 # if defined(NATIVE_THREADS)
54 #  include "threads/native/threads.h"
55 # else
56 #  include "threads/green/threads.h"
57 #  include "threads/green/locks.h"
58 # endif
59 #endif
60
61 #include "toolbox/logging.h"
62 #include "vm/builtin.h"
63 #include "vm/classcache.h"
64 #include "vm/exceptions.h"
65 #include "vm/global.h"
66 #include "vm/linker.h"
67 #include "vm/loader.h"
68 #include "vm/options.h"
69 #include "vm/statistics.h"
70 #include "vm/stringlocal.h"
71 #include "vm/suck.h"
72 #include "vm/vm.h"
73
74 #if defined(ENABLE_ZLIB)
75 # include "vm/zip.h"
76 #endif
77
78 #include "vm/jit/asmpart.h"
79 #include "vm/jit/codegen-common.h"
80
81
82 /******************************************************************************/
83 /* DEBUG HELPERS                                                              */
84 /******************************************************************************/
85
86 #ifndef NDEBUG
87 #define LOADER_DEBUG
88 #endif
89
90 #ifdef LOADER_DEBUG
91 #define LOADER_ASSERT(cond)  assert(cond)
92 #else
93 #define LOADER_ASSERT(cond)
94 #endif
95
96
97 /* loader_init *****************************************************************
98
99    Initializes all lists and loads all classes required for the system
100    or the compiler.
101
102 *******************************************************************************/
103  
104 bool loader_init(u1 *stackbottom)
105 {
106 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
107         list_classpath_entry *lce;
108
109         /* Initialize the monitor pointer for zip/jar file locking. */
110
111         for (lce = list_first(list_classpath_entries); lce != NULL;
112                  lce = list_next(list_classpath_entries, lce))
113                 if (lce->type == CLASSPATH_ARCHIVE)
114                         initObjectLock((java_objectheader *) lce);
115 #endif
116
117         /* load some important classes */
118
119         if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
120                 return false;
121
122         if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
123                 return false;
124
125         if (!(class_java_lang_Cloneable =
126                   load_class_bootstrap(utf_java_lang_Cloneable)))
127                 return false;
128
129         if (!(class_java_io_Serializable =
130                   load_class_bootstrap(utf_java_io_Serializable)))
131                 return false;
132
133
134         /* load classes for wrapping primitive types */
135
136         if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
137                 return false;
138
139         if (!(class_java_lang_Boolean =
140                   load_class_bootstrap(utf_java_lang_Boolean)))
141                 return false;
142
143         if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
144                 return false;
145
146         if (!(class_java_lang_Character =
147                   load_class_bootstrap(utf_java_lang_Character)))
148                 return false;
149
150         if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
151                 return false;
152
153         if (!(class_java_lang_Integer =
154                   load_class_bootstrap(utf_java_lang_Integer)))
155                 return false;
156
157         if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
158                 return false;
159
160         if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
161                 return false;
162
163         if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
164                 return false;
165
166
167         /* load some other important classes */
168
169         if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
170                 return false;
171
172         if (!(class_java_lang_ClassLoader =
173                   load_class_bootstrap(utf_java_lang_ClassLoader)))
174                 return false;
175
176         if (!(class_java_lang_SecurityManager =
177                   load_class_bootstrap(utf_java_lang_SecurityManager)))
178                 return false;
179
180         if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
181                 return false;
182
183         if (!(class_java_lang_Thread =
184                   load_class_bootstrap(utf_new_char("java/lang/Thread"))))
185                 return false;
186
187         if (!(class_java_lang_ThreadGroup =
188                   load_class_bootstrap(utf_java_lang_ThreadGroup)))
189                 return false;
190
191         if (!(class_java_lang_VMThread =
192                   load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
193                 return false;
194
195
196         /* some classes which may be used more often */
197
198         if (!(class_java_lang_StackTraceElement =
199                   load_class_bootstrap(utf_java_lang_StackTraceElement)))
200                 return false;
201
202         if (!(class_java_lang_reflect_Constructor =
203                   load_class_bootstrap(utf_java_lang_reflect_Constructor)))
204                 return false;
205
206         if (!(class_java_lang_reflect_Field =
207                   load_class_bootstrap(utf_java_lang_reflect_Field)))
208                 return false;
209
210         if (!(class_java_lang_reflect_Method =
211                   load_class_bootstrap(utf_java_lang_reflect_Method)))
212                 return false;
213
214         if (!(class_java_security_PrivilegedAction =
215                   load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
216                 return false;
217
218         if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
219                 return false;
220
221         if (!(arrayclass_java_lang_Object =
222                   load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
223                 return false;
224
225 #if defined(USE_THREADS)
226         if (stackbottom != 0)
227                 initLocks();
228 #endif
229
230         return true;
231 }
232
233
234 /* loader_load_all_classes *****************************************************
235
236    Loads all classes specified in the BOOTCLASSPATH.
237
238 *******************************************************************************/
239
240 void loader_load_all_classes(void)
241 {
242         list_classpath_entry    *lce;
243 #if defined(ENABLE_ZLIB)
244         hashtable               *ht;
245         s4                       slot;
246         hashtable_zipfile_entry *htzfe;
247         utf                     *u;
248 #endif
249
250         for (lce = list_first(list_classpath_entries); lce != NULL;
251                  lce = list_next(list_classpath_entries, lce)) {
252 #if defined(ENABLE_ZLIB)
253                 if (lce->type == CLASSPATH_ARCHIVE) {
254                         /* get the classes hashtable */
255
256                         ht = lce->htclasses;
257
258                         for (slot = 0; slot < ht->size; slot++) {
259                                 htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
260
261                                 for (; htzfe; htzfe = htzfe->hashlink) {
262                                         u = htzfe->filename;
263
264                                         /* skip all entries in META-INF and .properties,
265                        .png files */
266
267                                         if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
268                                                 strstr(u->text, ".properties") ||
269                                                 strstr(u->text, ".png"))
270                                                 continue;
271
272                                         /* load class from bootstrap classloader */
273
274                                         if (!load_class_bootstrap(u)) {
275                                                 fprintf(stderr, "Error loading: ");
276                                                 utf_fprint_classname(stderr, u);
277                                                 fprintf(stderr, "\n");
278
279                                                 /* 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->mcode            = NULL;
1122         m->entrypoint       = NULL;
1123
1124         if (!suck_check_classbuffer_size(cb, 2))
1125                 return false;
1126         
1127         attrnum = suck_u2(cb);
1128         for (i = 0; i < attrnum; i++) {
1129                 utf *aname;
1130
1131                 if (!suck_check_classbuffer_size(cb, 2))
1132                         return false;
1133
1134                 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1135                         return false;
1136
1137                 if (aname == utf_Code) {
1138                         if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
1139                                 exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
1140                                 return false;
1141                         }
1142                         
1143                         if (m->jcode) {
1144                                 exceptions_throw_classformaterror(c, "Multiple Code attributes");
1145                                 return false;
1146                         }
1147
1148                         if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1149                                 return false;
1150
1151                         suck_u4(cb);
1152                         m->maxstack = suck_u2(cb);
1153                         m->maxlocals = suck_u2(cb);
1154
1155                         if (m->maxlocals < argcount) {
1156                                 exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
1157                                 return false;
1158                         }
1159                         
1160                         if (!suck_check_classbuffer_size(cb, 4))
1161                                 return false;
1162
1163                         m->jcodelength = suck_u4(cb);
1164
1165                         if (m->jcodelength == 0) {
1166                                 exceptions_throw_classformaterror(c, "Code of a method has length 0");
1167                                 return false;
1168                         }
1169                         
1170                         if (m->jcodelength > 65535) {
1171                                 exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
1172                                 return false;
1173                         }
1174
1175                         if (!suck_check_classbuffer_size(cb, m->jcodelength))
1176                                 return false;
1177
1178                         m->jcode = MNEW(u1, m->jcodelength);
1179                         suck_nbytes(m->jcode, cb, m->jcodelength);
1180
1181                         if (!suck_check_classbuffer_size(cb, 2))
1182                                 return false;
1183
1184                         m->exceptiontablelength = suck_u2(cb);
1185                         if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
1186                                 return false;
1187
1188                         m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
1189
1190 #if defined(ENABLE_STATISTICS)
1191                         if (opt_stat) {
1192                                 count_vmcode_len += m->jcodelength + 18;
1193                                 count_extable_len +=
1194                                         m->exceptiontablelength * sizeof(exceptiontable);
1195                         }
1196 #endif
1197
1198                         for (j = 0; j < m->exceptiontablelength; j++) {
1199                                 u4 idx;
1200                                 m->exceptiontable[j].startpc = suck_u2(cb);
1201                                 m->exceptiontable[j].endpc = suck_u2(cb);
1202                                 m->exceptiontable[j].handlerpc = suck_u2(cb);
1203
1204                                 idx = suck_u2(cb);
1205                                 if (!idx) {
1206                                         m->exceptiontable[j].catchtype.any = NULL;
1207
1208                                 } else {
1209                                         /* the classref is created later */
1210                                         if (!(m->exceptiontable[j].catchtype.any =
1211                                                   (utf*)class_getconstant(c, idx, CONSTANT_Class)))
1212                                                 return false;
1213                                 }
1214                         }
1215
1216                         if (!suck_check_classbuffer_size(cb, 2))
1217                                 return false;
1218
1219                         codeattrnum = suck_u2(cb);
1220
1221                         for (; codeattrnum > 0; codeattrnum--) {
1222                                 utf *caname;
1223
1224                                 if (!suck_check_classbuffer_size(cb, 2))
1225                                         return false;
1226
1227                                 if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1228                                         return false;
1229
1230                                 if (caname == utf_LineNumberTable) {
1231                                         u2 lncid;
1232
1233                                         if (!suck_check_classbuffer_size(cb, 4 + 2))
1234                                                 return false;
1235
1236                                         suck_u4(cb);
1237                                         m->linenumbercount = suck_u2(cb);
1238
1239                                         if (!suck_check_classbuffer_size(cb,
1240                                                                                                 (2 + 2) * m->linenumbercount))
1241                                                 return false;
1242
1243                                         m->linenumbers = MNEW(lineinfo, m->linenumbercount);
1244                                         
1245                                         for (lncid = 0; lncid < m->linenumbercount; lncid++) {
1246                                                 m->linenumbers[lncid].start_pc = suck_u2(cb);
1247                                                 m->linenumbers[lncid].line_number = suck_u2(cb);
1248                                         }
1249                                         codeattrnum--;
1250
1251                                         if (!skipattributes(cb, codeattrnum))
1252                                                 return false;
1253                                         
1254                                         break;
1255
1256                                 } else {
1257                                         if (!skipattributebody(cb))
1258                                                 return false;
1259                                 }
1260                         }
1261
1262                 } else if (aname == utf_Exceptions) {
1263                         s4 j;
1264
1265                         if (m->thrownexceptions) {
1266                                 exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
1267                                 return false;
1268                         }
1269
1270                         if (!suck_check_classbuffer_size(cb, 4 + 2))
1271                                 return false;
1272
1273                         suck_u4(cb); /* length */
1274                         m->thrownexceptionscount = suck_u2(cb);
1275
1276                         if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
1277                                 return false;
1278
1279                         m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
1280
1281                         for (j = 0; j < m->thrownexceptionscount; j++) {
1282                                 /* the classref is created later */
1283                                 if (!((m->thrownexceptions)[j].any =
1284                                           (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1285                                         return false;
1286                         }
1287                                 
1288                 } else {
1289                         if (!skipattributebody(cb))
1290                                 return false;
1291                 }
1292         }
1293
1294         if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
1295                 exceptions_throw_classformaterror(c, "Missing Code attribute");
1296                 return false;
1297         }
1298
1299         /* everything was ok */
1300
1301         return true;
1302 }
1303
1304
1305 /* load_attribute **************************************************************
1306
1307    Read attributes from classfile.
1308         
1309 *******************************************************************************/
1310
1311 static bool load_attributes(classbuffer *cb, u4 num)
1312 {
1313         classinfo *c;
1314         utf       *aname;
1315         u4 i, j;
1316
1317         c = cb->class;
1318
1319         for (i = 0; i < num; i++) {
1320                 /* retrieve attribute name */
1321                 if (!suck_check_classbuffer_size(cb, 2))
1322                         return false;
1323
1324                 if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1325                         return false;
1326
1327                 if (aname == utf_InnerClasses) {
1328                         /* innerclasses attribute */
1329                         if (c->innerclass) {
1330                                 exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
1331                                 return false;
1332                         }
1333                                 
1334                         if (!suck_check_classbuffer_size(cb, 4 + 2))
1335                                 return false;
1336
1337                         /* skip attribute length */
1338                         suck_u4(cb);
1339
1340                         /* number of records */
1341                         c->innerclasscount = suck_u2(cb);
1342
1343                         if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
1344                                 return false;
1345
1346                         /* allocate memory for innerclass structure */
1347                         c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
1348
1349                         for (j = 0; j < c->innerclasscount; j++) {
1350                                 /* The innerclass structure contains a class with an encoded
1351                                    name, its defining scope, its simple name and a bitmask of
1352                                    the access flags. If an inner class is not a member, its
1353                                    outer_class is NULL, if a class is anonymous, its name is
1354                                    NULL. */
1355                                                                 
1356                                 innerclassinfo *info = c->innerclass + j;
1357
1358                                 info->inner_class.ref =
1359                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1360                                 info->outer_class.ref =
1361                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
1362                                 info->name =
1363                                         innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
1364                                 info->flags = suck_u2(cb);
1365                         }
1366
1367                 } else if (aname == utf_SourceFile) {
1368                         if (!suck_check_classbuffer_size(cb, 4 + 2))
1369                                 return false;
1370
1371                         if (suck_u4(cb) != 2) {
1372                                 exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
1373                                 return false;
1374                         }
1375
1376                         if (c->sourcefile) {
1377                                 exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
1378                                 return false;
1379                         }
1380
1381                         if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
1382                                 return false;
1383
1384                 } else {
1385                         /* unknown attribute */
1386                         if (!skipattributebody(cb))
1387                                 return false;
1388                 }
1389         }
1390
1391         return true;
1392 }
1393
1394
1395 /* load_class_from_sysloader ***************************************************
1396
1397    Load the class with the given name using the system class loader
1398
1399    IN:
1400        name.............the classname
1401
1402    RETURN VALUE:
1403        the loaded class, or
1404            NULL if an exception has been thrown
1405
1406 *******************************************************************************/
1407
1408 classinfo *load_class_from_sysloader(utf *name)
1409 {
1410         methodinfo        *m;
1411         java_objectheader *cl;
1412         classinfo         *c;
1413
1414         LOADER_ASSERT(class_java_lang_Object);
1415         LOADER_ASSERT(class_java_lang_ClassLoader);
1416         LOADER_ASSERT(class_java_lang_ClassLoader->state & CLASS_LINKED);
1417         
1418         m = class_resolveclassmethod(class_java_lang_ClassLoader,
1419                                                                  utf_getSystemClassLoader,
1420                                                                  utf_void__java_lang_ClassLoader,
1421                                                                  class_java_lang_Object,
1422                                                                  false);
1423
1424         if (!m)
1425                 return false;
1426
1427         cl = vm_call_method(m, NULL);
1428
1429         if (!cl)
1430                 return false;
1431
1432         c = load_class_from_classloader(name, cl);
1433
1434         return c;
1435 }
1436
1437
1438 /* load_class_from_classloader *************************************************
1439
1440    Load the class with the given name using the given user-defined class loader.
1441
1442    IN:
1443        name.............the classname
1444            cl...............user-defined class loader
1445            
1446    RETURN VALUE:
1447        the loaded class, or
1448            NULL if an exception has been thrown
1449
1450 *******************************************************************************/
1451
1452 classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
1453 {
1454         java_objectheader *o;
1455         classinfo         *c;
1456         classinfo         *tmpc;
1457         java_lang_String  *s;
1458
1459         LOADER_ASSERT(name);
1460
1461         /* lookup if this class has already been loaded */
1462
1463         c = classcache_lookup(cl, name);
1464
1465         if (c)
1466                 return c;
1467
1468         /* if other class loader than bootstrap, call it */
1469
1470         if (cl) {
1471                 methodinfo *lc;
1472                 char       *text;
1473                 s4          namelen;
1474
1475                 text = name->text;
1476                 namelen = name->blength;
1477
1478                 /* handle array classes */
1479                 if (text[0] == '[') {
1480                         classinfo *comp;
1481                         utf       *u;
1482
1483                         switch (text[1]) {
1484                         case 'L':
1485                                 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
1486                                 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
1487                                         *exceptionptr = new_noclassdeffounderror(name);
1488                                         return false;
1489                                 }
1490
1491                                 u = utf_new(text + 2, namelen - 3);
1492
1493                                 if (!(comp = load_class_from_classloader(u, cl)))
1494                                         return false;
1495
1496                                 /* create the array class */
1497
1498                                 c = class_array_of(comp, false);
1499
1500                                 tmpc = classcache_store(cl, c, true);
1501
1502                                 if (tmpc == NULL) {
1503                                         /* exception, free the loaded class */
1504                                         c->state &= ~CLASS_LOADING;
1505                                         class_free(c);
1506                                 }
1507
1508                                 return tmpc;
1509
1510                         case '[':
1511                                 /* load the component class */
1512
1513                                 u = utf_new(text + 1, namelen - 1);
1514
1515                                 if (!(comp = load_class_from_classloader(u, cl)))
1516                                         return false;
1517
1518                                 /* create the array class */
1519
1520                                 c = class_array_of(comp, false);
1521
1522                                 tmpc = classcache_store(cl, c, true);
1523
1524                                 if (tmpc == NULL) {
1525                                         /* exception, free the loaded class */
1526                                         c->state &= ~CLASS_LOADING;
1527                                         class_free(c);
1528                                 }
1529
1530                                 return tmpc;
1531
1532                         default:
1533                                 /* primitive array classes are loaded by the bootstrap loader */
1534
1535                                 c = load_class_bootstrap(name);
1536
1537                                 return c;
1538                         }
1539                 }
1540                 
1541                 LOADER_ASSERT(class_java_lang_Object);
1542
1543                 lc = class_resolveclassmethod(cl->vftbl->class,
1544                                                                           utf_loadClass,
1545                                                                           utf_java_lang_String__java_lang_Class,
1546                                                                           class_java_lang_Object,
1547                                                                           true);
1548
1549                 if (!lc)
1550                         return false; /* exception */
1551
1552                 /* move return value into `o' and cast it afterwards to a classinfo* */
1553
1554                 s = javastring_new_slash_to_dot(name);
1555
1556                 o = vm_call_method(lc, cl, s);
1557
1558                 c = (classinfo *) o;
1559
1560                 if (c) {
1561                         /* Store this class in the loaded class cache. If another
1562                            class with the same (initloader,name) pair has been
1563                            stored earlier it will be returned by classcache_store
1564                            In this case classcache_store may not free the class
1565                            because it has already been exposed to Java code which
1566                            may have kept references to that class. */
1567
1568                     tmpc = classcache_store(cl, c, false);
1569
1570                         if (tmpc == NULL) {
1571                                 /* exception, free the loaded class */
1572                                 c->state &= ~CLASS_LOADING;
1573                                 class_free(c);
1574                         }
1575
1576                         c = tmpc;
1577
1578                 } else {
1579                         /* loadClass has thrown an exception.  We must convert
1580                            ClassNotFoundException into
1581                            NoClassDefFoundException. */
1582
1583                         /* XXX Maybe we should have a flag that avoids this
1584                            conversion for calling load_class_from_classloader from
1585                            Class.forName.  Currently we do a double conversion in
1586                            these cases.  */
1587
1588                         classnotfoundexception_to_noclassdeffounderror();
1589                 }
1590
1591                 /* SUN compatible -verbose:class output */
1592
1593                 if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
1594                         printf("[Loaded ");
1595                         utf_display_classname(name);
1596                         printf("]\n");
1597                 }
1598
1599                 return c;
1600         } 
1601
1602         c = load_class_bootstrap(name);
1603
1604         return c;
1605 }
1606
1607
1608 /* load_class_bootstrap ********************************************************
1609         
1610    Load the class with the given name using the bootstrap class loader.
1611
1612    IN:
1613        name.............the classname
1614
1615    RETURN VALUE:
1616        loaded classinfo, or
1617            NULL if an exception has been thrown
1618
1619    SYNCHRONIZATION:
1620        load_class_bootstrap is synchronized. It can be treated as an
1621            atomic operation.
1622
1623 *******************************************************************************/
1624
1625 classinfo *load_class_bootstrap(utf *name)
1626 {
1627         classbuffer *cb;
1628         classinfo   *c;
1629         classinfo   *r;
1630
1631         /* for debugging */
1632
1633         LOADER_ASSERT(name);
1634
1635         /* lookup if this class has already been loaded */
1636
1637         if ((r = classcache_lookup(NULL, name)))
1638                 return r;
1639
1640         /* create the classinfo */
1641
1642         c = class_create_classinfo(name);
1643         
1644         /* handle array classes */
1645
1646         if (name->text[0] == '[') {
1647                 c = load_newly_created_array(c, NULL);
1648                 if (c == NULL)
1649                         return NULL;
1650                 LOADER_ASSERT(c->state & CLASS_LOADED);
1651                 return c;
1652         }
1653
1654 #if defined(ENABLE_STATISTICS)
1655         /* measure time */
1656
1657         if (getcompilingtime)
1658                 compilingtime_stop();
1659
1660         if (getloadingtime)
1661                 loadingtime_start();
1662 #endif
1663
1664         /* load classdata, throw exception on error */
1665
1666         if ((cb = suck_start(c)) == NULL) {
1667                 /* this normally means, the classpath was not set properly */
1668
1669                 if (name == utf_java_lang_Object)
1670                         throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
1671                                                                            "java/lang/Object");
1672
1673                 *exceptionptr = new_noclassdeffounderror(name);
1674
1675                 return NULL;
1676         }
1677         
1678         /* load the class from the buffer */
1679
1680         r = load_class_from_classbuffer(cb);
1681
1682         if (!r) {
1683                 /* the class could not be loaded, free the classinfo struct */
1684
1685                 class_free(c);
1686
1687         } else {
1688                 /* Store this class in the loaded class cache this step also
1689                 checks the loading constraints. If the class has been loaded
1690                 before, the earlier loaded class is returned. */
1691
1692                 classinfo *res = classcache_store(NULL, c, true);
1693
1694                 if (!res) {
1695                         /* exception */
1696                         class_free(c);
1697                 }
1698
1699                 r = res;
1700         }
1701
1702         /* SUN compatible -verbose:class output */
1703
1704         if (opt_verboseclass && r) {
1705                 printf("[Loaded ");
1706                 utf_display_classname(name);
1707                 printf(" from %s]\n", cb->path);
1708         }
1709
1710         /* free memory */
1711
1712         suck_stop(cb);
1713
1714 #if defined(ENABLE_STATISTICS)
1715         /* measure time */
1716
1717         if (getloadingtime)
1718                 loadingtime_stop();
1719
1720         if (getcompilingtime)
1721                 compilingtime_start();
1722 #endif
1723
1724         return r;
1725 }
1726
1727
1728 /* load_class_from_classbuffer *************************************************
1729         
1730    Loads everything interesting about a class from the class file. The
1731    'classinfo' structure must have been allocated previously.
1732
1733    The super class and the interfaces implemented by this class need
1734    not be loaded. The link is set later by the function 'class_link'.
1735
1736    The loaded class is removed from the list 'unloadedclasses' and
1737    added to the list 'unlinkedclasses'.
1738         
1739    SYNCHRONIZATION:
1740        This function is NOT synchronized!
1741    
1742 *******************************************************************************/
1743
1744 classinfo *load_class_from_classbuffer(classbuffer *cb)
1745 {
1746         classinfo *c;
1747         utf *name;
1748         utf *supername;
1749         u4 i,j;
1750         u4 ma, mi;
1751         s4 dumpsize;
1752         descriptor_pool *descpool;
1753 #if defined(ENABLE_STATISTICS)
1754         u4 classrefsize;
1755         u4 descsize;
1756 #endif
1757
1758         /* get the classbuffer's class */
1759
1760         c = cb->class;
1761
1762         /* the class is already loaded */
1763
1764         if (c->state & CLASS_LOADED)
1765                 return c;
1766
1767 #if defined(ENABLE_STATISTICS)
1768         if (opt_stat)
1769                 count_class_loads++;
1770 #endif
1771
1772 #if !defined(NDEBUG)
1773         /* output for debugging purposes */
1774
1775         if (loadverbose)
1776                 log_message_class("Loading class: ", c);
1777 #endif
1778         
1779         /* mark start of dump memory area */
1780
1781         dumpsize = dump_size();
1782
1783         /* class is currently loading */
1784
1785         c->state |= CLASS_LOADING;
1786
1787         if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
1788                 goto return_exception;
1789
1790         /* check signature */
1791
1792         if (suck_u4(cb) != MAGIC) {
1793                 exceptions_throw_classformaterror(c, "Bad magic number");
1794
1795                 goto return_exception;
1796         }
1797
1798         /* check version */
1799
1800         mi = suck_u2(cb);
1801         ma = suck_u2(cb);
1802
1803         if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
1804                 *exceptionptr =
1805                         new_unsupportedclassversionerror(c,
1806                                                                                          "Unsupported major.minor version %d.%d",
1807                                                                                          ma, mi);
1808
1809                 goto return_exception;
1810         }
1811
1812         /* create a new descriptor pool */
1813
1814         descpool = descriptor_pool_new(c);
1815
1816         /* load the constant pool */
1817
1818         if (!load_constantpool(cb, descpool))
1819                 goto return_exception;
1820
1821         /* ACC flags */
1822
1823         if (!suck_check_classbuffer_size(cb, 2))
1824                 goto return_exception;
1825
1826         c->flags = suck_u2(cb);
1827
1828         /* check ACC flags consistency */
1829
1830         if (c->flags & ACC_INTERFACE) {
1831                 if (!(c->flags & ACC_ABSTRACT)) {
1832                         /* We work around this because interfaces in JDK 1.1 are
1833                          * not declared abstract. */
1834
1835                         c->flags |= ACC_ABSTRACT;
1836                 }
1837
1838                 if (c->flags & ACC_FINAL) {
1839                         exceptions_throw_classformaterror(c,
1840                                                                                           "Illegal class modifiers: 0x%X",
1841                                                                                           c->flags);
1842                         goto return_exception;
1843                 }
1844
1845                 if (c->flags & ACC_SUPER) {
1846                         c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1847                 }
1848         }
1849
1850         if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
1851                 exceptions_throw_classformaterror(c,
1852                                                                                   "Illegal class modifiers: 0x%X",
1853                                                                                   c->flags);
1854                 goto return_exception;
1855         }
1856
1857         if (!suck_check_classbuffer_size(cb, 2 + 2))
1858                 goto return_exception;
1859
1860         /* this class */
1861
1862         i = suck_u2(cb);
1863         if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1864                 goto return_exception;
1865
1866         if (c->name == utf_not_named_yet) {
1867                 /* we finally have a name for this class */
1868                 c->name = name;
1869                 class_set_packagename(c);
1870
1871         } else if (name != c->name) {
1872                 char *msg;
1873                 s4    msglen;
1874
1875                 msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
1876                         utf_strlen(name) + strlen(")") + strlen("0");
1877
1878                 msg = MNEW(char, msglen);
1879
1880                 utf_sprint(msg, c->name);
1881                 strcat(msg, " (wrong name: ");
1882                 utf_strcat(msg, name);
1883                 strcat(msg, ")");
1884
1885                 *exceptionptr =
1886                         new_exception_message(string_java_lang_NoClassDefFoundError, msg);
1887
1888                 MFREE(msg, char, msglen);
1889
1890                 goto return_exception;
1891         }
1892         
1893         /* retrieve superclass */
1894
1895         c->super.any = NULL;
1896         if ((i = suck_u2(cb))) {
1897                 if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
1898                         goto return_exception;
1899
1900                 /* java.lang.Object may not have a super class. */
1901
1902                 if (c->name == utf_java_lang_Object) {
1903                         *exceptionptr =
1904                                 new_exception_message(string_java_lang_ClassFormatError,
1905                                                                           "java.lang.Object with superclass");
1906
1907                         goto return_exception;
1908                 }
1909
1910                 /* Interfaces must have java.lang.Object as super class. */
1911
1912                 if ((c->flags & ACC_INTERFACE) &&
1913                         supername != utf_java_lang_Object) {
1914                         *exceptionptr =
1915                                 new_exception_message(string_java_lang_ClassFormatError,
1916                                                                           "Interfaces must have java.lang.Object as superclass");
1917
1918                         goto return_exception;
1919                 }
1920
1921         } else {
1922                 supername = NULL;
1923
1924                 /* This is only allowed for java.lang.Object. */
1925
1926                 if (c->name != utf_java_lang_Object) {
1927                         exceptions_throw_classformaterror(c, "Bad superclass index");
1928                         goto return_exception;
1929                 }
1930         }
1931                          
1932         /* retrieve interfaces */
1933
1934         if (!suck_check_classbuffer_size(cb, 2))
1935                 goto return_exception;
1936
1937         c->interfacescount = suck_u2(cb);
1938
1939         if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
1940                 goto return_exception;
1941
1942         c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
1943         for (i = 0; i < c->interfacescount; i++) {
1944                 /* the classrefs are created later */
1945                 if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
1946                         goto return_exception;
1947         }
1948
1949         /* load fields */
1950         if (!suck_check_classbuffer_size(cb, 2))
1951                 goto return_exception;
1952
1953         c->fieldscount = suck_u2(cb);
1954         c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
1955 /*      c->fields = MNEW(fieldinfo, c->fieldscount); */
1956         for (i = 0; i < c->fieldscount; i++) {
1957                 if (!load_field(cb, &(c->fields[i]),descpool))
1958                         goto return_exception;
1959         }
1960
1961         /* load methods */
1962         if (!suck_check_classbuffer_size(cb, 2))
1963                 goto return_exception;
1964
1965         c->methodscount = suck_u2(cb);
1966 /*      c->methods = GCNEW(methodinfo, c->methodscount); */
1967         c->methods = MNEW(methodinfo, c->methodscount);
1968         for (i = 0; i < c->methodscount; i++) {
1969                 if (!load_method(cb, &(c->methods[i]),descpool))
1970                         goto return_exception;
1971         }
1972
1973         /* create the class reference table */
1974
1975         c->classrefs =
1976                 descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
1977
1978         /* allocate space for the parsed descriptors */
1979
1980         descriptor_pool_alloc_parsed_descriptors(descpool);
1981         c->parseddescs =
1982                 descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
1983
1984 #if defined(ENABLE_STATISTICS)
1985         if (opt_stat) {
1986                 descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
1987                 count_classref_len += classrefsize;
1988                 count_parsed_desc_len += descsize;
1989         }
1990 #endif
1991
1992         /* put the classrefs in the constant pool */
1993         for (i = 0; i < c->cpcount; i++) {
1994                 if (c->cptags[i] == CONSTANT_Class) {
1995                         utf *name = (utf *) c->cpinfos[i];
1996                         c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
1997                 }
1998         }
1999
2000         /* set the super class reference */
2001
2002         if (supername) {
2003                 c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
2004                 if (!c->super.ref)
2005                         goto return_exception;
2006         }
2007
2008         /* set the super interfaces references */
2009
2010         for (i = 0; i < c->interfacescount; i++) {
2011                 c->interfaces[i].ref =
2012                         descriptor_pool_lookup_classref(descpool,
2013                                                                                         (utf *) c->interfaces[i].any);
2014                 if (!c->interfaces[i].ref)
2015                         goto return_exception;
2016         }
2017
2018         /* parse field descriptors */
2019
2020         for (i = 0; i < c->fieldscount; i++) {
2021                 c->fields[i].parseddesc =
2022                         descriptor_pool_parse_field_descriptor(descpool,
2023                                                                                                    c->fields[i].descriptor);
2024                 if (!c->fields[i].parseddesc)
2025                         goto return_exception;
2026         }
2027
2028         /* parse method descriptors */
2029
2030         for (i = 0; i < c->methodscount; i++) {
2031                 methodinfo *m = &c->methods[i];
2032                 m->parseddesc =
2033                         descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
2034                                                                                                         m->flags, class_get_self_classref(m->class));
2035                 if (!m->parseddesc)
2036                         goto return_exception;
2037
2038                 for (j = 0; j < m->exceptiontablelength; j++) {
2039                         if (!m->exceptiontable[j].catchtype.any)
2040                                 continue;
2041                         if ((m->exceptiontable[j].catchtype.ref =
2042                                  descriptor_pool_lookup_classref(descpool,
2043                                                 (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
2044                                 goto return_exception;
2045                 }
2046
2047                 for (j = 0; j < m->thrownexceptionscount; j++) {
2048                         if (!m->thrownexceptions[j].any)
2049                                 continue;
2050                         if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
2051                                                 (utf *) m->thrownexceptions[j].any)) == NULL)
2052                                 goto return_exception;
2053                 }
2054         }
2055
2056         /* parse the loaded descriptors */
2057
2058         for (i = 0; i < c->cpcount; i++) {
2059                 constant_FMIref *fmi;
2060                 s4               index;
2061                 
2062                 switch (c->cptags[i]) {
2063                 case CONSTANT_Fieldref:
2064                         fmi = (constant_FMIref *) c->cpinfos[i];
2065                         fmi->parseddesc.fd =
2066                                 descriptor_pool_parse_field_descriptor(descpool,
2067                                                                                                            fmi->descriptor);
2068                         if (!fmi->parseddesc.fd)
2069                                 goto return_exception;
2070                         index = (int) (size_t) fmi->classref;
2071                         fmi->classref =
2072                                 (constant_classref *) class_getconstant(c, index,
2073                                                                                                                 CONSTANT_Class);
2074                         if (!fmi->classref)
2075                                 goto return_exception;
2076                         break;
2077                 case CONSTANT_Methodref:
2078                 case CONSTANT_InterfaceMethodref:
2079                         fmi = (constant_FMIref *) c->cpinfos[i];
2080                         index = (int) (size_t) fmi->classref;
2081                         fmi->classref =
2082                                 (constant_classref *) class_getconstant(c, index,
2083                                                                                                                 CONSTANT_Class);
2084                         if (!fmi->classref)
2085                                 goto return_exception;
2086                         fmi->parseddesc.md =
2087                                 descriptor_pool_parse_method_descriptor(descpool,
2088                                                                                                                 fmi->descriptor,
2089                                                                                                                 ACC_UNDEF,
2090                                                                                                                 fmi->classref);
2091                         if (!fmi->parseddesc.md)
2092                                 goto return_exception;
2093                         break;
2094                 }
2095         }
2096
2097 #ifdef ENABLE_VERIFIER
2098         /* Check if all fields and methods can be uniquely
2099          * identified by (name,descriptor). */
2100
2101         if (opt_verify) {
2102                 /* We use a hash table here to avoid making the
2103                  * average case quadratic in # of methods, fields.
2104                  */
2105                 static int shift = 0;
2106                 u2 *hashtab;
2107                 u2 *next; /* for chaining colliding hash entries */
2108                 size_t len;
2109                 size_t hashlen;
2110                 u2 index;
2111                 u2 old;
2112
2113                 /* Allocate hashtable */
2114                 len = c->methodscount;
2115                 if (len < c->fieldscount) len = c->fieldscount;
2116                 hashlen = 5 * len;
2117                 hashtab = MNEW(u2,(hashlen + len));
2118                 next = hashtab + hashlen;
2119
2120                 /* Determine bitshift (to get good hash values) */
2121                 if (!shift) {
2122                         len = sizeof(utf);
2123                         while (len) {
2124                                 len >>= 1;
2125                                 shift++;
2126                         }
2127                 }
2128
2129                 /* Check fields */
2130                 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
2131
2132                 for (i = 0; i < c->fieldscount; ++i) {
2133                         fieldinfo *fi = c->fields + i;
2134
2135                         /* It's ok if we lose bits here */
2136                         index = ((((size_t) fi->name) +
2137                                           ((size_t) fi->descriptor)) >> shift) % hashlen;
2138
2139                         if ((old = hashtab[index])) {
2140                                 old--;
2141                                 next[i] = old;
2142                                 do {
2143                                         if (c->fields[old].name == fi->name &&
2144                                                 c->fields[old].descriptor == fi->descriptor) {
2145                                                 exceptions_throw_classformaterror(c, "Repetitive field name/signature");
2146                                                 goto return_exception;
2147                                         }
2148                                 } while ((old = next[old]));
2149                         }
2150                         hashtab[index] = i + 1;
2151                 }
2152                 
2153                 /* Check methods */
2154                 memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
2155
2156                 for (i = 0; i < c->methodscount; ++i) {
2157                         methodinfo *mi = c->methods + i;
2158
2159                         /* It's ok if we lose bits here */
2160                         index = ((((size_t) mi->name) +
2161                                           ((size_t) mi->descriptor)) >> shift) % hashlen;
2162
2163                         /*{ JOWENN
2164                                 int dbg;
2165                                 for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
2166                                         printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
2167                                 }
2168                         }*/
2169
2170                         if ((old = hashtab[index])) {
2171                                 old--;
2172                                 next[i] = old;
2173                                 do {
2174                                         if (c->methods[old].name == mi->name &&
2175                                                 c->methods[old].descriptor == mi->descriptor) {
2176                                                 exceptions_throw_classformaterror(c, "Repetitive method name/signature");
2177                                                 goto return_exception;
2178                                         }
2179                                 } while ((old = next[old]));
2180                         }
2181                         hashtab[index] = i + 1;
2182                 }
2183                 
2184                 MFREE(hashtab, u2, (hashlen + len));
2185         }
2186 #endif /* ENABLE_VERIFIER */
2187
2188 #if defined(ENABLE_STATISTICS)
2189         if (opt_stat) {
2190                 count_class_infos += sizeof(classinfo*) * c->interfacescount;
2191                 count_class_infos += sizeof(fieldinfo)  * c->fieldscount;
2192                 count_class_infos += sizeof(methodinfo) * c->methodscount;
2193         }
2194 #endif
2195
2196         /* load attribute structures */
2197
2198         if (!suck_check_classbuffer_size(cb, 2))
2199                 goto return_exception;
2200
2201         if (!load_attributes(cb, suck_u2(cb)))
2202                 goto return_exception;
2203
2204 #if 0
2205         /* Pre java 1.5 version don't check this. This implementation is like
2206            java 1.5 do it: for class file version 45.3 we don't check it, older
2207            versions are checked.
2208          */
2209         if ((ma == 45 && mi > 3) || ma > 45) {
2210                 /* check if all data has been read */
2211                 s4 classdata_left = ((cb->data + cb->size) - cb->pos);
2212
2213                 if (classdata_left > 0) {
2214                         exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
2215                         goto return_exception;
2216                 }
2217         }
2218 #endif
2219
2220         /* release dump area */
2221
2222         dump_release(dumpsize);
2223
2224         /* revert loading state and class is loaded */
2225
2226         c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
2227
2228 #if !defined(NDEBUG)
2229         if (loadverbose)
2230                 log_message_class("Loading done class: ", c);
2231 #endif
2232
2233         return c;
2234
2235 return_exception:
2236         /* release dump area */
2237
2238         dump_release(dumpsize);
2239
2240         /* an exception has been thrown */
2241
2242         return NULL;
2243 }
2244
2245
2246 /* load_newly_created_array ****************************************************
2247
2248    Load a newly created array class.
2249
2250         RETURN VALUE:
2251             c....................the array class C has been loaded
2252                 other classinfo......the array class was found in the class cache, 
2253                                      C has been freed
2254             NULL.................an exception has been thrown
2255
2256         Note:
2257                 This is an internal function. Do not use it unless you know exactly
2258                 what you are doing!
2259
2260                 Use one of the load_class_... functions for general array class loading.
2261
2262 *******************************************************************************/
2263
2264 classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
2265 {
2266         classinfo         *comp = NULL;
2267         methodinfo        *clone;
2268         methoddesc        *clonedesc;
2269         constant_classref *classrefs;
2270         char              *text;
2271         s4                 namelen;
2272         utf               *u;
2273
2274         text = c->name->text;
2275         namelen = c->name->blength;
2276
2277         /* Check array class name */
2278
2279         if (namelen < 2 || text[0] != '[') {
2280                 *exceptionptr = new_noclassdeffounderror(c->name);
2281                 return NULL;
2282         }
2283
2284         /* Check the element type */
2285
2286         switch (text[1]) {
2287         case '[':
2288                 /* c is an array of arrays. We have to create the component class. */
2289
2290                 u = utf_new(text + 1, namelen - 1);
2291                 if (!(comp = load_class_from_classloader(u, loader)))
2292                         return NULL;
2293
2294                 LOADER_ASSERT(comp->state & CLASS_LOADED);
2295
2296                 if (opt_eager)
2297                         if (!link_class(c))
2298                                 return NULL;
2299
2300                 /* the array's flags are that of the component class */
2301                 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2302                 c->classloader = comp->classloader;
2303                 break;
2304
2305         case 'L':
2306                 /* c is an array of objects. */
2307
2308                 /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
2309                 if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
2310                         *exceptionptr = new_noclassdeffounderror(c->name);
2311                         return NULL;
2312                 }
2313
2314                 u = utf_new(text + 2, namelen - 3);
2315
2316                 if (!(comp = load_class_from_classloader(u, loader)))
2317                         return NULL;
2318
2319                 LOADER_ASSERT(comp->state & CLASS_LOADED);
2320
2321                 if (opt_eager)
2322                         if (!link_class(c))
2323                                 return NULL;
2324
2325                 /* the array's flags are that of the component class */
2326                 c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
2327                 c->classloader = comp->classloader;
2328                 break;
2329
2330         default:
2331                 /* c is an array of a primitive type */
2332
2333                 /* check for cases like `[II' */
2334                 if (namelen > 2) {
2335                         *exceptionptr = new_noclassdeffounderror(c->name);
2336                         return NULL;
2337                 }
2338
2339                 /* the accessibility of the array class is public (VM Spec 5.3.3) */
2340                 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2341                 c->classloader = NULL;
2342         }
2343
2344         LOADER_ASSERT(class_java_lang_Object);
2345         LOADER_ASSERT(class_java_lang_Cloneable);
2346         LOADER_ASSERT(class_java_io_Serializable);
2347
2348         /* setup the array class */
2349
2350         c->super.cls = class_java_lang_Object;
2351
2352     c->interfacescount = 2;
2353     c->interfaces = MNEW(classref_or_classinfo, 2);
2354
2355         if (opt_eager) {
2356                 classinfo *tc;
2357
2358                 tc = class_java_lang_Cloneable;
2359                 LOADER_ASSERT(tc->state & CLASS_LOADED);
2360                 list_addfirst(&unlinkedclasses, tc);
2361                 c->interfaces[0].cls = tc;
2362
2363                 tc = class_java_io_Serializable;
2364                 LOADER_ASSERT(tc->state & CLASS_LOADED);
2365                 list_addfirst(&unlinkedclasses, tc);
2366                 c->interfaces[1].cls = tc;
2367
2368         } else {
2369                 c->interfaces[0].cls = class_java_lang_Cloneable;
2370                 c->interfaces[1].cls = class_java_io_Serializable;
2371         }
2372
2373         c->methodscount = 1;
2374         c->methods = MNEW(methodinfo, c->methodscount);
2375
2376         classrefs = MNEW(constant_classref, 2);
2377         CLASSREF_INIT(classrefs[0], c, c->name);
2378         CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
2379
2380         /* create descriptor for clone method */
2381         /* we need one paramslot which is reserved for the 'this' parameter */
2382         clonedesc = NEW(methoddesc);
2383         clonedesc->returntype.type = TYPE_ADDRESS;
2384         clonedesc->returntype.classref = classrefs + 1;
2385         clonedesc->returntype.arraydim = 0;
2386         /* initialize params to "empty", add real params below in
2387            descriptor_params_from_paramtypes */
2388         clonedesc->paramcount = 0;
2389         clonedesc->paramslots = 0;
2390         clonedesc->paramtypes[0].classref = classrefs + 0;
2391
2392         /* create methodinfo */
2393
2394         clone = c->methods;
2395         MSET(clone, 0, methodinfo, 1);
2396
2397 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2398         initObjectLock(&clone->header);
2399 #endif
2400
2401         /* ATTENTION: if you delete the ACC_NATIVE below, set
2402            clone->maxlocals=1 (interpreter related) */
2403
2404         clone->flags      = ACC_PUBLIC | ACC_NATIVE;
2405         clone->name       = utf_clone;
2406         clone->descriptor = utf_void__java_lang_Object;
2407         clone->parseddesc = clonedesc;
2408         clone->class      = c;
2409
2410         /* parse the descriptor to get the register allocation */
2411
2412         if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
2413                 return false;
2414
2415         clone->entrypoint =
2416                 codegen_createnativestub((functionptr) &builtin_clone_array, clone);
2417
2418         /* XXX: field: length? */
2419
2420         /* array classes are not loaded from class files */
2421
2422         c->state          |= CLASS_LOADED;
2423         c->parseddescs    = (u1 *) clonedesc;
2424         c->parseddescsize = sizeof(methodinfo);
2425         c->classrefs      = classrefs;
2426         c->classrefcount  = 1;
2427
2428         /* insert class into the loaded class cache */
2429         /* XXX free classinfo if NULL returned? */
2430
2431         return classcache_store(loader, c, true);
2432 }
2433
2434
2435 /* loader_close ****************************************************************
2436
2437    Frees all resources.
2438         
2439 *******************************************************************************/
2440
2441 void loader_close(void)
2442 {
2443         /* empty */
2444 }
2445
2446
2447 /*
2448  * These are local overrides for various environment variables in Emacs.
2449  * Please do not remove this and leave it at the end of the file, where
2450  * Emacs will automagically detect them.
2451  * ---------------------------------------------------------------------
2452  * Local variables:
2453  * mode: c
2454  * indent-tabs-mode: t
2455  * c-basic-offset: 4
2456  * tab-width: 4
2457  * End:
2458  * vim:noexpandtab:sw=4:ts=4:
2459  */