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