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