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