1 /* loader.c - class loader functions
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
28 Changes: Andreas Krall
33 $Id: loader.c 945 2004-03-06 21:33:21Z twisti $
50 #include "toolbox/memory.h"
51 #include "toolbox/loging.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
64 /* global variables ***********************************************************/
66 int count_class_infos = 0; /* variables for measurements */
67 int count_const_pool_len = 0;
68 int count_vftbl_len = 0;
69 int count_all_methods = 0;
70 int count_vmcode_len = 0;
71 int count_extable_len = 0;
72 int count_class_loads = 0;
73 int count_class_inits = 0;
75 static s4 interfaceindex; /* sequential numbering of interfaces */
78 list unloadedclasses; /* list of all referenced but not loaded classes */
79 list unlinkedclasses; /* list of all loaded but not linked classes */
80 list linkedclasses; /* list of all completely linked classes */
83 /* utf-symbols for pointer comparison of frequently used strings */
85 static utf *utf_innerclasses; /* InnerClasses */
86 static utf *utf_constantvalue; /* ConstantValue */
87 static utf *utf_code; /* Code */
88 static utf *utf_exceptions; /* Exceptions */
89 static utf *utf_linenumbertable; /* LineNumberTable */
90 static utf *utf_finalize; /* finalize */
91 static utf *utf_fidesc; /* ()V changed */
92 static utf *utf_init; /* <init> */
93 static utf *utf_clinit; /* <clinit> */
94 static utf *utf_initsystemclass; /* initializeSystemClass */
95 static utf *utf_systemclass; /* java/lang/System */
96 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
97 static utf *utf_vmclass; /* java/lang/VMClassLoader */
98 static utf *utf_initialize;
99 static utf *utf_initializedesc;
100 static utf *utf_java_lang_Object; /* java/lang/Object */
113 /* important system classes ***************************************************/
115 classinfo *class_java_lang_Object;
116 classinfo *class_java_lang_String;
118 classinfo *class_java_lang_Throwable;
119 classinfo *class_java_lang_Cloneable;
120 classinfo *class_java_io_Serializable;
122 /* Pseudo classes for the typechecker */
123 classinfo *pseudo_class_Arraystub = NULL;
124 classinfo *pseudo_class_Null = NULL;
125 classinfo *pseudo_class_New = NULL;
126 vftbl *pseudo_class_Arraystub_vftbl = NULL;
129 /* These are made static so they cannot be used for throwing in native */
131 static classinfo *class_java_lang_ClassCastException;
132 static classinfo *class_java_lang_NullPointerException;
133 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
134 static classinfo *class_java_lang_NegativeArraySizeException;
135 static classinfo *class_java_lang_OutOfMemoryError;
136 static classinfo *class_java_lang_ArithmeticException;
137 static classinfo *class_java_lang_ArrayStoreException;
138 static classinfo *class_java_lang_ThreadDeath;
140 utf *array_packagename = NULL;
142 static int loader_inited = 0;
145 /********************************************************************
146 list of classpath entries (either filesystem directories or
148 ********************************************************************/
149 static classpath_info *classpath_entries=0;
152 /******************************************************************************
154 structure for primitive classes: contains the class for wrapping the
155 primitive type, the primitive class, the name of the class for wrapping,
156 the one character type signature and the name of the primitive class
158 ******************************************************************************/
160 /* CAUTION: Don't change the order of the types. This table is indexed
161 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
163 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
164 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
165 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
166 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
167 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
168 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
169 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
170 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
171 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
172 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
176 /* instances of important system classes **************************************/
178 java_objectheader *proto_java_lang_ClassCastException;
179 java_objectheader *proto_java_lang_NullPointerException;
180 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
181 java_objectheader *proto_java_lang_NegativeArraySizeException;
182 java_objectheader *proto_java_lang_OutOfMemoryError;
183 java_objectheader *proto_java_lang_ArithmeticException;
184 java_objectheader *proto_java_lang_ArrayStoreException;
185 java_objectheader *proto_java_lang_ThreadDeath;
187 /************* functions for reading classdata *********************************
189 getting classdata in blocks of variable size
190 (8,16,32,64-bit integer or float)
192 *******************************************************************************/
194 static char *classpath = ""; /* searchpath for classfiles */
195 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
196 static u1 *classbuf_pos; /* current position in classfile buffer */
197 static int classbuffer_size; /* size of classfile-data */
199 /* assert that at least <len> bytes are left to read */
200 /* <len> is limited to the range of non-negative s4 values */
201 #define ASSERT_LEFT(len) \
202 do {if ( ((s4)(len)) < 0 \
203 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
204 panic("Unexpected end of classfile"); } while(0)
206 /* transfer block of classfile data into a buffer */
208 #define suck_nbytes(buffer,len) \
209 do {ASSERT_LEFT(len); \
210 memcpy(buffer,classbuf_pos+1,len); \
211 classbuf_pos+=len;} while (0)
213 /* skip block of classfile data */
215 #define skip_nbytes(len) \
216 do {ASSERT_LEFT(len); \
217 classbuf_pos+=len;} while(0)
222 return *++classbuf_pos;
226 u1 a=suck_u1(), b=suck_u1();
227 return ((u2)a<<8)+(u2)b;
231 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
232 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
234 #define suck_s8() (s8) suck_u8()
235 #define suck_s2() (s2) suck_u2()
236 #define suck_s4() (s4) suck_u4()
237 #define suck_s1() (s1) suck_u1()
240 /* get u8 from classfile data */
247 return (hi << 32) + lo;
257 /* get float from classfile data */
258 static float suck_float()
265 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
266 memcpy((u1*) (&f), buffer, 4);
268 suck_nbytes((u1*) (&f), 4);
271 PANICIF (sizeof(float) != 4, "Incompatible float-format");
277 /* get double from classfile data */
278 static double suck_double()
285 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
286 memcpy((u1*) (&d), buffer, 8);
288 suck_nbytes((u1*) (&d), 8);
291 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
297 /************************** function suck_init *********************************
299 called once at startup, sets the searchpath for the classfiles
301 *******************************************************************************/
303 void suck_init(char *cpath)
310 union classpath_info *tmp;
311 union classpath_info *insertAfter=0;
316 if (classpath_entries) panic("suck_init should be called only once");
317 for(start=classpath;(*start)!='\0';) {
318 for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
321 filenamelen=(end-start);
355 ( ( (*(end - 1)) == 'p') || ( (*(end - 1)) == 'P')) &&
356 (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
357 (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z')))
360 } else if ( (( (*(end - 1)) == 'r') || ( (*(end - 1)) == 'R')) &&
361 ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
362 (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
367 if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init");
369 filename=(char*)malloc(CLASSPATH_MAXFILENAME);
370 strncpy(filename,start,filenamelen);
371 filename[filenamelen+1]='\0';
376 unzFile uf=unzOpen(filename);
378 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
379 tmp->archive.type=CLASSPATH_ARCHIVE;
385 panic("Zip/JAR not supported");
389 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
390 tmp->filepath.type=CLASSPATH_PATH;
391 tmp->filepath.next=0;
392 if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
393 filename[filenamelen]='/';
394 filename[filenamelen+1]='\0';
398 tmp->filepath.filename=filename;
399 tmp->filepath.pathlen=filenamelen;
405 insertAfter->filepath.next=tmp;
407 classpath_entries=tmp;
412 if ((*end)==':') start=end+1; else start=end;
415 if (filename!=0) free(filename);
420 /************************** function suck_start ********************************
422 returns true if classbuffer is already loaded or a file for the
423 specified class has succussfully been read in. All directories of
424 the searchpath are used to find the classfile (<classname>.class).
425 Returns false if no classfile is found and writes an error message.
427 *******************************************************************************/
429 bool suck_start(utf *classname)
431 classpath_info *currPos;
434 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
440 if (classbuffer) return true; /* classbuffer is already valid */
442 utf_ptr = classname->text;
443 while (utf_ptr < utf_end(classname)) {
444 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
446 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
448 filename[filenamelen++] = c;
450 strcpy(filename + filenamelen, ".class");
452 for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
454 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
455 if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
456 unz_file_info file_info;
457 /*log_text("Class found in zip file");*/
458 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
459 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
460 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
461 classbuffer_size = file_info.uncompressed_size;
462 classbuffer = MNEW(u1, classbuffer_size);
463 classbuf_pos = classbuffer - 1;
464 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
465 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
466 unzCloseCurrentFile(currPos->archive.uf);
469 MFREE(classbuffer, u1, classbuffer_size);
470 log_text("Error while unzipping");
472 } else log_text("Error while opening file in archive");
473 } else log_text("Error while retrieving fileinfo");
475 unzCloseCurrentFile(currPos->archive.uf);
479 if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
480 strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
481 classfile = fopen(currPos->filepath.filename, "r");
482 if (classfile) { /* file exists */
484 /* determine size of classfile */
486 /* dolog("File: %s",filename); */
488 err = stat(currPos->filepath.filename, &buffer);
490 if (!err) { /* read classfile data */
491 classbuffer_size = buffer.st_size;
492 classbuffer = MNEW(u1, classbuffer_size);
493 classbuf_pos = classbuffer - 1;
494 fread(classbuffer, 1, classbuffer_size, classfile);
505 dolog("Warning: Can not open class file '%s'", filename);
512 /************************** function suck_stop *********************************
514 frees memory for buffer with classfile data.
515 Caution: this function may only be called if buffer has been allocated
516 by suck_start with reading a file
518 *******************************************************************************/
522 /* determine amount of classdata not retrieved by suck-operations */
524 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
526 if (classdata_left > 0) {
528 dolog("There are %d extra bytes at end of classfile",
530 /* The JVM spec disallows extra bytes. */
531 panic("Extra bytes at end of classfile");
536 MFREE(classbuffer, u1, classbuffer_size);
541 /******************************************************************************/
542 /******************* Some support functions ***********************************/
543 /******************************************************************************/
545 void fprintflags (FILE *fp, u2 f)
547 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
548 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
549 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
550 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
551 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
552 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
553 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
554 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
555 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
556 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
557 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
561 /********** internal function: printflags (only for debugging) ***************/
563 void printflags(u2 f)
565 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
566 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
567 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
568 if ( f & ACC_STATIC ) printf (" STATIC");
569 if ( f & ACC_FINAL ) printf (" FINAL");
570 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
571 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
572 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
573 if ( f & ACC_NATIVE ) printf (" NATIVE");
574 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
575 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
579 /************************* Function: skipattribute *****************************
581 skips a (1) 'attribute' structure in the class file
583 *******************************************************************************/
585 static void skipattribute()
594 /********************** Function: skipattributebody ****************************
596 skips an attribute after the 16 bit reference to attribute_name has already
599 *******************************************************************************/
601 static void skipattributebody()
609 /************************* Function: skipattributes ****************************
611 skips num attribute structures
613 *******************************************************************************/
615 static void skipattributes(u4 num)
618 for (i = 0; i < num; i++)
623 /******************** function: innerclass_getconstant ************************
625 like class_getconstant, but if cptags is ZERO null is returned
627 *******************************************************************************/
629 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
631 /* invalid position in constantpool */
632 if (pos >= c->cpcount)
633 panic("Attempt to access constant outside range");
635 /* constantpool entry of type 0 */
639 /* check type of constantpool entry */
640 if (c->cptags[pos] != ctype) {
641 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
642 (int) ctype, (int) c->cptags[pos] );
645 return c->cpinfos[pos];
649 /************************ function: attribute_load ****************************
651 read attributes from classfile
653 *******************************************************************************/
655 static void attribute_load(u4 num, classinfo *c)
659 for (i = 0; i < num; i++) {
660 /* retrieve attribute name */
661 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
663 if (aname == utf_innerclasses) {
664 /* innerclasses attribute */
666 if (c->innerclass != NULL)
667 panic("Class has more than one InnerClasses attribute");
669 /* skip attribute length */
671 /* number of records */
672 c->innerclasscount = suck_u2();
673 /* allocate memory for innerclass structure */
674 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
676 for (j = 0; j < c->innerclasscount; j++) {
677 /* The innerclass structure contains a class with an encoded name,
678 its defining scope, its simple name and a bitmask of the access flags.
679 If an inner class is not a member, its outer_class is NULL,
680 if a class is anonymous, its name is NULL. */
682 innerclassinfo *info = c->innerclass + j;
684 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
685 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
686 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
687 info->flags = suck_u2(); /* access_flags bitmask */
691 /* unknown attribute */
698 /******************* function: checkfielddescriptor ****************************
700 checks whether a field-descriptor is valid and aborts otherwise
701 all referenced classes are inserted into the list of unloaded classes
703 *******************************************************************************/
705 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
707 class_from_descriptor(utf_ptr,end_pos,NULL,
709 | CLASSLOAD_NULLPRIMITIVE
711 | CLASSLOAD_CHECKEND);
713 /* XXX use the following if -noverify */
715 char *tstart; /* pointer to start of classname */
717 char *start = utf_ptr;
719 switch (*utf_ptr++) {
733 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
734 panic ("Ill formed descriptor");
738 panic ("Ill formed descriptor");
741 /* exceeding characters */
742 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
747 /******************* function checkmethoddescriptor ****************************
749 checks whether a method-descriptor is valid and aborts otherwise.
750 All referenced classes are inserted into the list of unloaded classes.
752 The number of arguments is returned. A long or double argument is counted
755 *******************************************************************************/
757 static int checkmethoddescriptor (utf *d)
759 char *utf_ptr = d->text; /* current position in utf text */
760 char *end_pos = utf_end(d); /* points behind utf string */
761 int argcount = 0; /* number of arguments */
763 /* method descriptor must start with parenthesis */
764 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
766 /* check arguments */
767 while (utf_ptr != end_pos && *utf_ptr != ')') {
768 /* We cannot count the this argument here because
769 * we don't know if the method is static. */
770 if (*utf_ptr == 'J' || *utf_ptr == 'D')
774 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
776 | CLASSLOAD_NULLPRIMITIVE
780 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
781 utf_ptr++; /* skip ')' */
783 class_from_descriptor(utf_ptr,end_pos,NULL,
785 | CLASSLOAD_NULLPRIMITIVE
786 | CLASSLOAD_CHECKEND);
789 panic("Invalid method descriptor: too many arguments");
793 /* XXX use the following if -noverify */
795 /* check arguments */
796 while ((c = *utf_ptr++) != ')') {
813 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
814 panic ("Ill formed method descriptor");
818 panic ("Ill formed methodtype-descriptor");
822 /* check returntype */
824 /* returntype void */
825 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
828 /* treat as field-descriptor */
829 checkfielddescriptor (utf_ptr,end_pos);
834 /***************** Function: print_arraydescriptor ****************************
836 Debugging helper for displaying an arraydescriptor
838 *******************************************************************************/
840 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
843 fprintf(file, "<NULL>");
848 if (desc->componentvftbl) {
849 if (desc->componentvftbl->class)
850 utf_fprint(file, desc->componentvftbl->class->name);
852 fprintf(file, "<no classinfo>");
858 if (desc->elementvftbl) {
859 if (desc->elementvftbl->class)
860 utf_fprint(file, desc->elementvftbl->class->name);
862 fprintf(file, "<no classinfo>");
866 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
867 desc->dataoffset, desc->componentsize);
871 /******************************************************************************/
872 /************************** Functions for fields ****************************/
873 /******************************************************************************/
876 /************************ Function: field_load *********************************
878 Load everything about a class field from the class file and fill a
879 'fieldinfo' structure. For static fields, space in the data segment is
882 *******************************************************************************/
884 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
886 static void field_load(fieldinfo *f, classinfo *c)
890 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
892 f->flags = suck_u2(); /* ACC flags */
893 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
894 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
898 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
899 panic("Field with invalid name");
901 /* check flag consistency */
902 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
903 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
904 panic("Field has invalid access flags");
905 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
906 panic("Field is declared final and volatile");
907 if ((c->flags & ACC_INTERFACE) != 0) {
908 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
909 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
910 panic("Interface field is not declared static final public");
911 if ((f->flags & ACC_TRANSIENT) != 0)
912 panic("Interface field declared transient");
915 /* check descriptor */
916 checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
919 f->type = jtype = desc_to_type(f->descriptor); /* data type */
920 f->offset = 0; /* offset from start of object */
925 case TYPE_INT: f->value.i = 0; break;
926 case TYPE_FLOAT: f->value.f = 0.0; break;
927 case TYPE_DOUBLE: f->value.d = 0.0; break;
928 case TYPE_ADDRESS: f->value.a = NULL; break;
931 f->value.l = 0; break;
933 f->value.l.low = 0; f->value.l.high = 0; break;
937 /* read attributes */
939 for (i = 0; i < attrnum; i++) {
942 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
944 if (aname != utf_constantvalue) {
945 /* unknown attribute */
949 /* constant value attribute */
951 if (pindex != field_load_NOVALUE)
952 panic("Field has more than one ConstantValue attribute");
954 /* check attribute length */
956 panic("ConstantValue attribute has invalid length");
958 /* index of value in constantpool */
961 /* initialize field with value from constantpool */
964 constant_integer *ci =
965 class_getconstant(c, pindex, CONSTANT_Integer);
966 f->value.i = ci->value;
972 class_getconstant(c, pindex, CONSTANT_Long);
973 f->value.l = cl->value;
979 class_getconstant(c, pindex, CONSTANT_Float);
980 f->value.f = cf->value;
985 constant_double *cd =
986 class_getconstant(c, pindex, CONSTANT_Double);
987 f->value.d = cd->value;
992 utf *u = class_getconstant(c, pindex, CONSTANT_String);
993 /* create javastring from compressed utf8-string */
994 f->value.a = literalstring_new(u);
999 log_text ("Invalid Constant - Type");
1006 /********************** function: field_free **********************************/
1008 static void field_free (fieldinfo *f)
1014 /**************** Function: field_display (debugging only) ********************/
1016 void field_display(fieldinfo *f)
1019 printflags(f->flags);
1021 utf_display(f->name);
1023 utf_display(f->descriptor);
1024 printf(" offset: %ld\n", (long int) (f->offset));
1028 /******************************************************************************/
1029 /************************* Functions for methods ******************************/
1030 /******************************************************************************/
1033 /*********************** Function: method_load *********************************
1035 Loads a method from the class file and fills an existing 'methodinfo'
1036 structure. For native methods, the function pointer field is set to the
1037 real function pointer, for JavaVM methods a pointer to the compiler is used
1040 *******************************************************************************/
1042 static void method_load(methodinfo *m, classinfo *c)
1048 count_all_methods++;
1050 m->thrownexceptionscount=0;
1051 m->linenumbercount=0;
1055 m->flags = suck_u2();
1056 m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1059 if (!is_valid_name_utf(m->name))
1060 panic("Method with invalid name");
1061 if (m->name->text[0] == '<'
1062 && m->name != utf_init && m->name != utf_clinit)
1063 panic("Method with invalid special name");
1066 m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1067 argcount = checkmethoddescriptor(m->descriptor);
1068 if ((m->flags & ACC_STATIC) == 0)
1069 argcount++; /* count the 'this' argument */
1073 panic("Method has more than 255 arguments");
1075 /* check flag consistency */
1076 if (m->name != utf_clinit) {
1077 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1078 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1079 panic("Method has invalid access flags");
1080 if ((m->flags & ACC_ABSTRACT) != 0) {
1081 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1082 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1083 panic("Abstract method has invalid flags set");
1085 if ((c->flags & ACC_INTERFACE) != 0) {
1086 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1087 != (ACC_ABSTRACT | ACC_PUBLIC))
1088 panic("Interface method is not declared abstract and public");
1090 if (m->name == utf_init) {
1091 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1092 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1093 panic("Instance initialization method has invalid flags set");
1099 m->exceptiontable = NULL;
1100 m->entrypoint = NULL;
1102 m->stubroutine = NULL;
1103 m->methodUsed = NOTUSED;
1106 m->subRedefsUsed = 0;
1110 if (!(m->flags & ACC_NATIVE)) {
1111 m->stubroutine = createcompilerstub(m);
1114 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1115 (m->flags & ACC_STATIC) != 0);
1117 m->stubroutine = createnativestub(f, m);
1122 attrnum = suck_u2();
1123 for (i = 0; i < attrnum; i++) {
1126 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1128 if (aname != utf_code) {
1129 if (aname == utf_exceptions) {
1132 suck_u4(); /*length*/
1133 exceptionCount=suck_u2();
1134 m->thrownexceptionscount=exceptionCount;
1135 m->thrownexceptions=MNEW(classinfo*,exceptionCount);
1136 for (exceptionID=0;exceptionID<exceptionCount;exceptionID++) {
1137 (m->thrownexceptions)[exceptionID]=class_getconstant(c,suck_u2(),CONSTANT_Class);
1141 skipattributebody();
1145 if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
1146 panic("Code attribute for native or abstract method");
1149 panic("Method has more than one Code attribute");
1152 m->maxstack = suck_u2();
1153 m->maxlocals = suck_u2();
1154 if (m->maxlocals < argcount)
1155 panic("max_locals is smaller than the number of arguments");
1157 codelen = suck_u4();
1159 panic("bytecode has zero length");
1160 if (codelen > 65536)
1161 panic("bytecode too long");
1162 m->jcodelength = codelen;
1163 m->jcode = MNEW(u1, m->jcodelength);
1164 suck_nbytes(m->jcode, m->jcodelength);
1165 m->exceptiontablelength = suck_u2();
1167 MNEW(exceptiontable, m->exceptiontablelength);
1170 count_vmcode_len += m->jcodelength + 18;
1171 count_extable_len += 8 * m->exceptiontablelength;
1174 for (e = 0; e < m->exceptiontablelength; e++) {
1176 m->exceptiontable[e].startpc = suck_u2();
1177 m->exceptiontable[e].endpc = suck_u2();
1178 m->exceptiontable[e].handlerpc = suck_u2();
1182 m->exceptiontable[e].catchtype = NULL;
1185 m->exceptiontable[e].catchtype =
1186 class_getconstant(c, idx, CONSTANT_Class);
1191 for (codeattrnum=suck_u2();codeattrnum>0;codeattrnum--) {
1192 utf * caname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1193 if (caname==utf_linenumbertable) {
1195 /*log_text("LineNumberTable found");*/
1197 m->linenumbercount=suck_u2();
1198 /*printf("length:%d\n",m->linenumbercount);*/
1199 m->linenumbers=MNEW(lineinfo,m->linenumbercount);
1200 for (lncid=0;lncid<m->linenumbercount;lncid++) {
1201 m->linenumbers[lncid].start_pc=suck_u2();
1202 m->linenumbers[lncid].line_number=suck_u2();
1205 skipattributes(codeattrnum);
1207 } else skipattributebody();
1214 if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
1215 panic("Method missing Code attribute");
1219 /********************* Function: method_free ***********************************
1221 frees all memory that was allocated for this method
1223 *******************************************************************************/
1225 static void method_free(methodinfo *m)
1228 MFREE(m->jcode, u1, m->jcodelength);
1230 if (m->exceptiontable)
1231 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1234 CFREE(m->mcode, m->mcodelength);
1236 if (m->stubroutine) {
1237 if (m->flags & ACC_NATIVE) {
1238 removenativestub(m->stubroutine);
1241 removecompilerstub(m->stubroutine);
1247 /************** Function: method_display (debugging only) **************/
1249 void method_display(methodinfo *m)
1252 printflags(m->flags);
1254 utf_display(m->name);
1256 utf_display(m->descriptor);
1260 /************** Function: method_display_flags_last (debugging only) **************/
1262 void method_display_flags_last(methodinfo *m)
1265 utf_display(m->name);
1267 utf_display(m->descriptor);
1269 printflags(m->flags);
1274 /******************** Function: method_canoverwrite ****************************
1276 Check if m and old are identical with respect to type and name. This means
1277 that old can be overwritten with m.
1279 *******************************************************************************/
1281 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1283 if (m->name != old->name) return false;
1284 if (m->descriptor != old->descriptor) return false;
1285 if (m->flags & ACC_STATIC) return false;
1292 /******************************************************************************/
1293 /************************ Functions for class *********************************/
1294 /******************************************************************************/
1297 /******************** function:: class_getconstant ******************************
1299 retrieves the value at position 'pos' of the constantpool of a class
1300 if the type of the value is other than 'ctype' the system is stopped
1302 *******************************************************************************/
1304 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1306 /* invalid position in constantpool */
1307 /* (pos == 0 is caught by type comparison) */
1308 if (pos >= c->cpcount)
1309 panic("Attempt to access constant outside range");
1311 /* check type of constantpool entry */
1313 if (c->cptags[pos] != ctype) {
1314 class_showconstantpool(c);
1315 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1316 (int) ctype, (int) c->cptags[pos]);
1319 return c->cpinfos[pos];
1323 /********************* Function: class_constanttype ****************************
1325 Determines the type of a class entry in the ConstantPool
1327 *******************************************************************************/
1329 u4 class_constanttype(classinfo *c, u4 pos)
1331 if (pos >= c->cpcount)
1332 panic("Attempt to access constant outside range");
1334 return c->cptags[pos];
1338 /******************** function: class_loadcpool ********************************
1340 loads the constantpool of a class,
1341 the entries are transformed into a simpler format
1342 by resolving references
1343 (a detailed overview of the compact structures can be found in global.h)
1345 *******************************************************************************/
1347 static void class_loadcpool(classinfo *c)
1350 /* The following structures are used to save information which cannot be
1351 processed during the first pass. After the complete constantpool has
1352 been traversed the references can be resolved.
1353 (only in specific order) */
1355 /* CONSTANT_Class_info entries */
1356 typedef struct forward_class {
1357 struct forward_class *next;
1362 /* CONSTANT_String */
1363 typedef struct forward_string {
1364 struct forward_string *next;
1369 /* CONSTANT_NameAndType */
1370 typedef struct forward_nameandtype {
1371 struct forward_nameandtype *next;
1375 } forward_nameandtype;
1377 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1378 typedef struct forward_fieldmethint {
1379 struct forward_fieldmethint *next;
1383 u2 nameandtype_index;
1384 } forward_fieldmethint;
1388 long int dumpsize = dump_size ();
1390 forward_class *forward_classes = NULL;
1391 forward_string *forward_strings = NULL;
1392 forward_nameandtype *forward_nameandtypes = NULL;
1393 forward_fieldmethint *forward_fieldmethints = NULL;
1395 /* number of entries in the constant_pool table plus one */
1396 u4 cpcount = c -> cpcount = suck_u2();
1397 /* allocate memory */
1398 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1399 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1402 panic("Invalid constant_pool_count (0)");
1405 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1408 /* initialize constantpool */
1409 for (idx=0; idx<cpcount; idx++) {
1410 cptags[idx] = CONSTANT_UNUSED;
1411 cpinfos[idx] = NULL;
1415 /******* first pass *******/
1416 /* entries which cannot be resolved now are written into
1417 temporary structures and traversed again later */
1420 while (idx < cpcount) {
1421 /* get constant type */
1425 case CONSTANT_Class: {
1426 forward_class *nfc = DNEW(forward_class);
1428 nfc -> next = forward_classes;
1429 forward_classes = nfc;
1431 nfc -> thisindex = idx;
1432 /* reference to CONSTANT_NameAndType */
1433 nfc -> name_index = suck_u2 ();
1439 case CONSTANT_Fieldref:
1440 case CONSTANT_Methodref:
1441 case CONSTANT_InterfaceMethodref: {
1442 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1444 nff -> next = forward_fieldmethints;
1445 forward_fieldmethints = nff;
1447 nff -> thisindex = idx;
1450 /* class or interface type that contains the declaration of the field or method */
1451 nff -> class_index = suck_u2 ();
1452 /* name and descriptor of the field or method */
1453 nff -> nameandtype_index = suck_u2 ();
1459 case CONSTANT_String: {
1460 forward_string *nfs = DNEW (forward_string);
1462 nfs -> next = forward_strings;
1463 forward_strings = nfs;
1465 nfs -> thisindex = idx;
1466 /* reference to CONSTANT_Utf8_info with string characters */
1467 nfs -> string_index = suck_u2 ();
1473 case CONSTANT_NameAndType: {
1474 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1476 nfn -> next = forward_nameandtypes;
1477 forward_nameandtypes = nfn;
1479 nfn -> thisindex = idx;
1480 /* reference to CONSTANT_Utf8_info containing simple name */
1481 nfn -> name_index = suck_u2 ();
1482 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1483 nfn -> sig_index = suck_u2 ();
1489 case CONSTANT_Integer: {
1490 constant_integer *ci = NEW (constant_integer);
1493 count_const_pool_len += sizeof(constant_integer);
1496 ci -> value = suck_s4 ();
1497 cptags [idx] = CONSTANT_Integer;
1504 case CONSTANT_Float: {
1505 constant_float *cf = NEW (constant_float);
1508 count_const_pool_len += sizeof(constant_float);
1511 cf -> value = suck_float ();
1512 cptags [idx] = CONSTANT_Float;
1518 case CONSTANT_Long: {
1519 constant_long *cl = NEW(constant_long);
1522 count_const_pool_len += sizeof(constant_long);
1525 cl -> value = suck_s8 ();
1526 cptags [idx] = CONSTANT_Long;
1530 panic("Long constant exceeds constant pool");
1534 case CONSTANT_Double: {
1535 constant_double *cd = NEW(constant_double);
1538 count_const_pool_len += sizeof(constant_double);
1541 cd -> value = suck_double ();
1542 cptags [idx] = CONSTANT_Double;
1546 panic("Double constant exceeds constant pool");
1550 case CONSTANT_Utf8: {
1552 /* number of bytes in the bytes array (not string-length) */
1553 u4 length = suck_u2();
1554 cptags [idx] = CONSTANT_Utf8;
1555 /* validate the string */
1556 ASSERT_LEFT(length);
1558 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1560 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1561 panic("Invalid UTF-8 string");
1563 /* insert utf-string into the utf-symboltable */
1564 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1565 /* skip bytes of the string */
1566 skip_nbytes(length);
1572 error ("Unkown constant type: %d",(int) t);
1580 /* resolve entries in temporary structures */
1582 while (forward_classes) {
1584 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1586 if (opt_verify && !is_valid_name_utf(name))
1587 panic("Class reference with invalid name");
1589 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1590 /* retrieve class from class-table */
1591 cpinfos [forward_classes -> thisindex] = class_new (name);
1593 forward_classes = forward_classes -> next;
1597 while (forward_strings) {
1599 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1601 log_text("forward_string:");
1602 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1604 log_text("\n------------------"); */
1605 /* resolve utf-string */
1606 cptags [forward_strings -> thisindex] = CONSTANT_String;
1607 cpinfos [forward_strings -> thisindex] = text;
1609 forward_strings = forward_strings -> next;
1612 while (forward_nameandtypes) {
1613 constant_nameandtype *cn = NEW (constant_nameandtype);
1616 count_const_pool_len += sizeof(constant_nameandtype);
1619 /* resolve simple name and descriptor */
1620 cn -> name = class_getconstant
1621 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1622 cn -> descriptor = class_getconstant
1623 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1627 if (!is_valid_name_utf(cn->name))
1628 panic("NameAndType with invalid name");
1629 /* disallow referencing <clinit> among others */
1630 if (cn->name->text[0] == '<' && cn->name != utf_init)
1631 panic("NameAndType with invalid special name");
1634 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1635 cpinfos [forward_nameandtypes -> thisindex] = cn;
1637 forward_nameandtypes = forward_nameandtypes -> next;
1641 while (forward_fieldmethints) {
1642 constant_nameandtype *nat;
1643 constant_FMIref *fmi = NEW (constant_FMIref);
1646 count_const_pool_len += sizeof(constant_FMIref);
1648 /* resolve simple name and descriptor */
1649 nat = class_getconstant
1650 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1653 log_text("trying to resolve:");
1654 log_text(nat->name->text);
1655 switch(forward_fieldmethints ->tag) {
1656 case CONSTANT_Fieldref:
1657 log_text("CONSTANT_Fieldref");
1659 case CONSTANT_InterfaceMethodref:
1660 log_text("CONSTANT_InterfaceMethodref");
1662 case CONSTANT_Methodref:
1663 log_text("CONSTANT_Methodref");
1667 fmi -> class = class_getconstant
1668 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1669 fmi -> name = nat -> name;
1670 fmi -> descriptor = nat -> descriptor;
1672 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1673 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1675 switch (forward_fieldmethints -> tag) {
1676 case CONSTANT_Fieldref: /* check validity of descriptor */
1677 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1679 case CONSTANT_InterfaceMethodref:
1680 case CONSTANT_Methodref: /* check validity of descriptor */
1681 checkmethoddescriptor (fmi->descriptor);
1685 forward_fieldmethints = forward_fieldmethints -> next;
1689 /* class_showconstantpool(c); */
1691 dump_release (dumpsize);
1695 /********************** Function: class_load ***********************************
1697 Loads everything interesting about a class from the class file. The
1698 'classinfo' structure must have been allocated previously.
1700 The super class and the interfaces implemented by this class need not be
1701 loaded. The link is set later by the function 'class_link'.
1703 The loaded class is removed from the list 'unloadedclasses' and added to
1704 the list 'unlinkedclasses'.
1706 *******************************************************************************/
1708 static int class_load(classinfo *c)
1714 count_class_loads++;
1717 /* output for debugging purposes */
1719 char logtext[MAXLOGTEXT];
1720 sprintf(logtext, "Loading class: ");
1721 utf_sprint(logtext + strlen(logtext), c->name);
1725 /* load classdata, throw exception on error */
1727 if (!suck_start(c->name)) {
1728 throw_noclassdeffounderror_message(c->name);
1732 /* check signature */
1733 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1737 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1738 error("File version %d.%d is not supported", (int) ma, (int) mi);
1743 c->erroneous_state = 0;
1744 c->initializing_thread = 0;
1746 c->classUsed = NOTUSED; /* not used initially CO-RT */
1750 c->flags = suck_u2();
1751 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1753 /* check ACC flags consistency */
1754 if ((c->flags & ACC_INTERFACE) != 0) {
1755 if ((c->flags & ACC_ABSTRACT) == 0) {
1756 /* We work around this because interfaces in JDK 1.1 are
1757 * not declared abstract. */
1759 c->flags |= ACC_ABSTRACT;
1760 /* panic("Interface class not declared abstract"); */
1762 if ((c->flags & (ACC_FINAL)) != 0)
1763 panic("Interface class has invalid flags");
1764 if ((c->flags & (ACC_SUPER)) != 0)
1765 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1767 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1768 panic("Class is declared both abstract and final");
1772 if (class_getconstant(c, i, CONSTANT_Class) != c)
1773 panic("Invalid this_class in class file");
1775 /* retrieve superclass */
1776 if ((i = suck_u2())) {
1777 c->super = class_getconstant(c, i, CONSTANT_Class);
1779 /* java.lang.Object may not have a super class. */
1780 if (c->name == utf_java_lang_Object)
1781 panic("java.lang.Object with super class");
1783 /* Interfaces must have j.l.O as super class. */
1784 if ((c->flags & ACC_INTERFACE) != 0
1785 && c->super->name != utf_java_lang_Object)
1787 panic("Interface with super class other than java.lang.Object");
1792 /* This is only allowed for java.lang.Object. */
1793 if (c->name != utf_java_lang_Object)
1794 panic("Class (not java.lang.Object) without super class");
1797 /* retrieve interfaces */
1798 c->interfacescount = suck_u2();
1799 c->interfaces = MNEW(classinfo*, c->interfacescount);
1800 for (i = 0; i < c->interfacescount; i++) {
1802 class_getconstant(c, suck_u2(), CONSTANT_Class);
1806 c->fieldscount = suck_u2();
1807 /* utf_display(c->name);
1808 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1810 c->fields = GCNEW(fieldinfo, c->fieldscount);
1811 for (i = 0; i < c->fieldscount; i++) {
1812 field_load(&(c->fields[i]), c);
1816 c->methodscount = suck_u2();
1817 c->methods = MNEW(methodinfo, c->methodscount);
1818 for (i = 0; i < c->methodscount; i++) {
1819 method_load(&(c->methods[i]), c);
1822 /* Check if all fields and methods can be uniquely
1823 * identified by (name,descriptor). */
1825 /* We use a hash table here to avoid making the
1826 * average case quadratic in # of methods, fields.
1828 static int shift = 0;
1830 u2 *next; /* for chaining colliding hash entries */
1836 /* Allocate hashtable */
1837 len = c->methodscount;
1838 if (len < c->fieldscount) len = c->fieldscount;
1840 hashtab = MNEW(u2,(hashlen + len));
1841 next = hashtab + hashlen;
1843 /* Determine bitshift (to get good hash values) */
1853 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1854 for (i = 0; i<c->fieldscount; ++i) {
1855 fieldinfo *fi = c->fields + i;
1856 /* It's ok if we lose bits here */
1857 index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
1859 if ((old = hashtab[index]) != 0) {
1861 /* dolog("HASHHIT %d --> %d",index,old); */
1864 /* dolog("HASHCHECK %d",old); */
1865 if (c->fields[old].name == fi->name
1866 && c->fields[old].descriptor == fi->descriptor)
1868 dolog("Duplicate field (%d,%d):",i,old);
1869 log_utf(fi->name); log_utf(fi->descriptor);
1870 panic("Fields with same name and descriptor");
1872 } while ((old = next[old]) != 0);
1874 /* else dolog("HASHLUCKY"); */
1875 hashtab[index] = i+1;
1879 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1880 for (i = 0; i<c->methodscount; ++i) {
1881 methodinfo *mi = c->methods + i;
1882 /* It's ok if we lose bits here */
1883 index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
1885 if ((old = hashtab[index]) != 0) {
1887 /* dolog("HASHHIT %d --> %d",index,old); */
1890 /* dolog("HASHCHECK %d",old); */
1891 if (c->methods[old].name == mi->name
1892 && c->methods[old].descriptor == mi->descriptor)
1894 dolog("Duplicate method (%d,%d):",i,old);
1895 log_utf(mi->name); log_utf(mi->descriptor);
1896 panic("Methods with same name and descriptor");
1898 } while ((old = next[old]) != 0);
1900 /* else dolog("HASHLUCKY"); */
1901 hashtab[index] = i+1;
1904 MFREE(hashtab,u2,(hashlen + len));
1908 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1909 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1910 count_class_infos += sizeof(methodinfo) * c->methodscount;
1913 /* load variable-length attribute structures */
1914 attribute_load(suck_u2(), c);
1919 /* remove class from list of unloaded classes and
1920 add to list of unlinked classes */
1921 list_remove(&unloadedclasses, c);
1922 list_addlast(&unlinkedclasses, c);
1931 /************** internal Function: class_highestinterface ***********************
1933 Used by the function class_link to determine the amount of memory needed
1934 for the interface table.
1936 *******************************************************************************/
1938 static s4 class_highestinterface(classinfo *c)
1943 if (!(c->flags & ACC_INTERFACE)) {
1944 char logtext[MAXLOGTEXT];
1945 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1946 utf_sprint(logtext + strlen(logtext), c->name);
1947 error("%s",logtext);
1951 for (i = 0; i < c->interfacescount; i++) {
1952 s4 h2 = class_highestinterface(c->interfaces[i]);
1960 /* class_addinterface **********************************************************
1962 Is needed by class_link for adding a VTBL to a class. All interfaces
1963 implemented by ic are added as well.
1965 *******************************************************************************/
1967 static void class_addinterface (classinfo *c, classinfo *ic)
1971 vftbl *vftbl = c->vftbl;
1973 if (i >= vftbl->interfacetablelength)
1974 panic ("Inernal error: interfacetable overflow");
1975 if (vftbl->interfacetable[-i])
1978 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1979 vftbl->interfacevftbllength[i] = 1;
1980 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1981 vftbl->interfacetable[-i][0] = NULL;
1984 vftbl->interfacevftbllength[i] = ic->methodscount;
1985 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1988 count_vftbl_len += sizeof(methodptr) *
1989 (ic->methodscount + (ic->methodscount == 0));
1992 for (j=0; j<ic->methodscount; j++) {
1995 for (m = 0; m < sc->methodscount; m++) {
1996 methodinfo *mi = &(sc->methods[m]);
1997 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1998 vftbl->interfacetable[-i][j] =
1999 vftbl->table[mi->vftblindex];
2009 for (j = 0; j < ic->interfacescount; j++)
2010 class_addinterface(c, ic->interfaces[j]);
2014 /******************* Function: class_new_array *********************************
2016 This function is called by class_new to setup an array class.
2018 *******************************************************************************/
2020 void class_new_array(classinfo *c)
2022 classinfo *comp = NULL;
2026 /* DEBUG */ /* dolog("class_new_array: %s",c->name->text); */
2028 /* Array classes are not loaded from classfiles. */
2029 list_remove(&unloadedclasses, c);
2031 /* Check array class name */
2032 namelen = c->name->blength;
2033 if (namelen < 2 || c->name->text[0] != '[')
2034 panic("Invalid array class name");
2036 /* Check the component type */
2037 switch (c->name->text[1]) {
2039 /* c is an array of arrays. We have to create the component class. */
2040 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
2044 /* c is an array of objects. */
2045 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2046 panic("Invalid array class name");
2047 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
2051 /* Setup the array class */
2052 c->super = class_java_lang_Object;
2053 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2055 c->interfacescount = 2;
2056 c->interfaces = MNEW(classinfo*,2);
2057 c->interfaces[0] = class_java_lang_Cloneable;
2058 c->interfaces[1] = class_java_io_Serializable;
2060 c->methodscount = 1;
2061 c->methods = MNEW (methodinfo, c->methodscount);
2064 memset(clone, 0, sizeof(methodinfo));
2065 clone->flags = ACC_PUBLIC;
2066 clone->name = utf_new_char("clone");
2067 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2069 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2070 clone->monoPoly = MONO;
2072 /* XXX: field: length? */
2074 /* The array class has to be linked */
2075 list_addlast(&unlinkedclasses,c);
2078 * Array classes which are created after the other classes have been
2079 * loaded and linked are linked explicitely.
2084 loader_load(c->name); /* XXX handle errors */
2088 /****************** Function: class_link_array *********************************
2090 This function is called by class_link to create the
2091 arraydescriptor for an array class.
2093 This function returns NULL if the array cannot be linked because
2094 the component type has not been linked yet.
2096 *******************************************************************************/
2098 static arraydescriptor *class_link_array(classinfo *c)
2100 classinfo *comp = NULL;
2101 int namelen = c->name->blength;
2102 arraydescriptor *desc;
2105 /* Check the component type */
2106 switch (c->name->text[1]) {
2108 /* c is an array of arrays. */
2109 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
2110 if (!comp) panic("Could not find component array class.");
2114 /* c is an array of objects. */
2115 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
2116 if (!comp) panic("Could not find component class.");
2120 /* If the component type has not been linked return NULL */
2121 if (comp && !comp->linked)
2124 /* Allocate the arraydescriptor */
2125 desc = NEW(arraydescriptor);
2128 /* c is an array of references */
2129 desc->arraytype = ARRAYTYPE_OBJECT;
2130 desc->componentsize = sizeof(void*);
2131 desc->dataoffset = OFFSET(java_objectarray,data);
2133 compvftbl = comp->vftbl;
2135 panic("Component class has no vftbl");
2136 desc->componentvftbl = compvftbl;
2138 if (compvftbl->arraydesc) {
2139 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2140 if (compvftbl->arraydesc->dimension >= 255)
2141 panic("Creating array of dimension >255");
2142 desc->dimension = compvftbl->arraydesc->dimension + 1;
2143 desc->elementtype = compvftbl->arraydesc->elementtype;
2146 desc->elementvftbl = compvftbl;
2147 desc->dimension = 1;
2148 desc->elementtype = ARRAYTYPE_OBJECT;
2152 /* c is an array of a primitive type */
2153 switch (c->name->text[1]) {
2154 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
2155 desc->dataoffset = OFFSET(java_booleanarray,data);
2156 desc->componentsize = sizeof(u1);
2159 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
2160 desc->dataoffset = OFFSET(java_bytearray,data);
2161 desc->componentsize = sizeof(u1);
2164 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
2165 desc->dataoffset = OFFSET(java_chararray,data);
2166 desc->componentsize = sizeof(u2);
2169 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
2170 desc->dataoffset = OFFSET(java_doublearray,data);
2171 desc->componentsize = sizeof(double);
2174 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
2175 desc->dataoffset = OFFSET(java_floatarray,data);
2176 desc->componentsize = sizeof(float);
2179 case 'I': desc->arraytype = ARRAYTYPE_INT;
2180 desc->dataoffset = OFFSET(java_intarray,data);
2181 desc->componentsize = sizeof(s4);
2184 case 'J': desc->arraytype = ARRAYTYPE_LONG;
2185 desc->dataoffset = OFFSET(java_longarray,data);
2186 desc->componentsize = sizeof(s8);
2189 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
2190 desc->dataoffset = OFFSET(java_shortarray,data);
2191 desc->componentsize = sizeof(s2);
2195 panic("Invalid array class name");
2198 desc->componentvftbl = NULL;
2199 desc->elementvftbl = NULL;
2200 desc->dimension = 1;
2201 desc->elementtype = desc->arraytype;
2208 /********************** Function: class_link ***********************************
2210 Tries to link a class. The super class and every implemented interface must
2211 already have been linked. The function calculates the length in bytes that
2212 an instance of this class requires as well as the VTBL for methods and
2215 If the class can be linked, it is removed from the list 'unlinkedclasses'
2216 and added to 'linkedclasses'. Otherwise, it is moved to the end of
2219 Attention: If cyclical class definitions are encountered, the program gets
2220 into an infinite loop (we'll have to work that out)
2222 *******************************************************************************/
2224 void class_link(classinfo *c)
2226 s4 supervftbllength; /* vftbllegnth of super class */
2227 s4 vftbllength; /* vftbllength of current class */
2228 s4 interfacetablelength; /* interface table length */
2229 classinfo *super = c->super; /* super class */
2230 classinfo *ic, *c2; /* intermediate class variables */
2231 vftbl *v; /* vftbl of current class */
2232 s4 i; /* interface/method/field counter */
2233 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2236 /* check if all superclasses are already linked, if not put c at end of
2237 unlinked list and return. Additionally initialize class fields. */
2239 /* check interfaces */
2241 for (i = 0; i < c->interfacescount; i++) {
2242 ic = c->interfaces[i];
2244 list_remove(&unlinkedclasses, c);
2245 list_addlast(&unlinkedclasses, c);
2248 if ((ic->flags & ACC_INTERFACE) == 0) {
2249 dolog("Specified interface is not declared as interface:");
2253 panic("Specified interface is not declared as interface");
2257 /* check super class */
2259 if (super == NULL) { /* class java.long.Object */
2261 c->classUsed = USED; /* Object class is always used CO-RT*/
2263 c->instancesize = sizeof(java_objectheader);
2265 vftbllength = supervftbllength = 0;
2267 c->finalizer = NULL;
2270 if (!super->linked) {
2271 list_remove(&unlinkedclasses, c);
2272 list_addlast(&unlinkedclasses, c);
2276 if ((super->flags & ACC_INTERFACE) != 0)
2277 panic("Interface specified as super class");
2279 /* handle array classes */
2280 /* The component class must have been linked already. */
2281 if (c->name->text[0] == '[')
2282 if ((arraydesc = class_link_array(c)) == NULL) {
2283 list_remove(&unlinkedclasses, c);
2284 list_addlast(&unlinkedclasses, c);
2288 /* Don't allow extending final classes */
2289 if ((super->flags & ACC_FINAL) != 0)
2290 panic("Trying to extend final class");
2292 if (c->flags & ACC_INTERFACE)
2293 c->index = interfaceindex++;
2295 c->index = super->index + 1;
2297 c->instancesize = super->instancesize;
2299 vftbllength = supervftbllength = super->vftbl->vftbllength;
2301 c->finalizer = super->finalizer;
2306 char logtext[MAXLOGTEXT];
2307 sprintf(logtext, "Linking Class: ");
2308 utf_sprint(logtext + strlen(logtext), c->name );
2312 /* compute vftbl length */
2314 for (i = 0; i < c->methodscount; i++) {
2315 methodinfo *m = &(c->methods[i]);
2317 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2318 classinfo *sc = super;
2321 for (j = 0; j < sc->methodscount; j++) {
2322 if (method_canoverwrite(m, &(sc->methods[j]))) {
2323 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2324 goto notfoundvftblindex;
2325 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2328 log_utf(sc->methods[j].name);
2329 log_utf(sc->methods[j].descriptor);
2330 panic("Trying to overwrite final method");
2332 m->vftblindex = sc->methods[j].vftblindex;
2333 goto foundvftblindex;
2339 m->vftblindex = (vftbllength++);
2345 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2348 /* compute interfacetable length */
2350 interfacetablelength = 0;
2353 for (i = 0; i < c2->interfacescount; i++) {
2354 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2355 if (h > interfacetablelength)
2356 interfacetablelength = h;
2361 /* allocate virtual function table */
2363 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2364 (vftbllength - 1) + sizeof(methodptr*) *
2365 (interfacetablelength - (interfacetablelength > 0)));
2366 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2367 (interfacetablelength > 1));
2368 c->header.vftbl = c->vftbl = v;
2370 v->vftbllength = vftbllength;
2371 v->interfacetablelength = interfacetablelength;
2372 v->arraydesc = arraydesc;
2374 /* store interface index in vftbl */
2375 if (c->flags & ACC_INTERFACE)
2376 v->baseval = -(c->index);
2378 /* copy virtual function table of super class */
2380 for (i = 0; i < supervftbllength; i++)
2381 v->table[i] = super->vftbl->table[i];
2383 /* add method stubs into virtual function table */
2385 for (i = 0; i < c->methodscount; i++) {
2386 methodinfo *m = &(c->methods[i]);
2387 if (!(m->flags & ACC_STATIC)) {
2388 v->table[m->vftblindex] = m->stubroutine;
2392 /* compute instance size and offset of each field */
2394 for (i = 0; i < c->fieldscount; i++) {
2396 fieldinfo *f = &(c->fields[i]);
2398 if (!(f->flags & ACC_STATIC) ) {
2399 dsize = desc_typesize(f->descriptor);
2400 c->instancesize = ALIGN(c->instancesize, dsize);
2401 f->offset = c->instancesize;
2402 c->instancesize += dsize;
2406 /* initialize interfacetable and interfacevftbllength */
2408 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2411 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2414 for (i = 0; i < interfacetablelength; i++) {
2415 v->interfacevftbllength[i] = 0;
2416 v->interfacetable[-i] = NULL;
2419 /* add interfaces */
2421 for (c2 = c; c2 != NULL; c2 = c2->super)
2422 for (i = 0; i < c2->interfacescount; i++) {
2423 class_addinterface(c, c2->interfaces[i]);
2426 /* add finalizer method (not for java.lang.Object) */
2428 if (super != NULL) {
2430 static utf *finame = NULL;
2431 static utf *fidesc = NULL;
2434 finame = utf_finalize;
2436 fidesc = utf_fidesc;
2438 fi = class_findmethod(c, finame, fidesc);
2440 if (!(fi->flags & ACC_STATIC)) {
2450 list_remove(&unlinkedclasses, c);
2451 list_addlast(&linkedclasses, c);
2455 /******************* Function: class_freepool **********************************
2457 Frees all resources used by this classes Constant Pool.
2459 *******************************************************************************/
2461 static void class_freecpool (classinfo *c)
2467 for (idx=0; idx < c->cpcount; idx++) {
2468 tag = c->cptags[idx];
2469 info = c->cpinfos[idx];
2473 case CONSTANT_Fieldref:
2474 case CONSTANT_Methodref:
2475 case CONSTANT_InterfaceMethodref:
2476 FREE (info, constant_FMIref);
2478 case CONSTANT_Integer:
2479 FREE (info, constant_integer);
2481 case CONSTANT_Float:
2482 FREE (info, constant_float);
2485 FREE (info, constant_long);
2487 case CONSTANT_Double:
2488 FREE (info, constant_double);
2490 case CONSTANT_NameAndType:
2491 FREE (info, constant_nameandtype);
2497 MFREE (c -> cptags, u1, c -> cpcount);
2498 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2502 /*********************** Function: class_free **********************************
2504 Frees all resources used by the class.
2506 *******************************************************************************/
2508 static void class_free(classinfo *c)
2515 MFREE(c->interfaces, classinfo*, c->interfacescount);
2517 for (i = 0; i < c->fieldscount; i++)
2518 field_free(&(c->fields[i]));
2520 for (i = 0; i < c->methodscount; i++)
2521 method_free(&(c->methods[i]));
2522 MFREE(c->methods, methodinfo, c->methodscount);
2524 if ((v = c->vftbl) != NULL) {
2526 mem_free(v->arraydesc,sizeof(arraydescriptor));
2528 for (i = 0; i < v->interfacetablelength; i++) {
2529 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2531 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2533 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2534 sizeof(methodptr*) * (v->interfacetablelength -
2535 (v->interfacetablelength > 0));
2536 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2537 (v->interfacetablelength > 1));
2541 if (c->innerclasscount)
2542 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2544 /* if (c->classvftbl)
2545 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2551 /************************* Function: class_findfield ***************************
2553 Searches a 'classinfo' structure for a field having the given name and
2556 *******************************************************************************/
2558 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2562 for (i = 0; i < c->fieldscount; i++) {
2563 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2564 return &(c->fields[i]);
2567 panic("Can not find field given in CONSTANT_Fieldref");
2569 /* keep compiler happy */
2574 /************************* Function: class_findmethod **************************
2576 Searches a 'classinfo' structure for a method having the given name and
2577 type and returns the index in the class info structure.
2578 If type is NULL, it is ignored.
2580 *******************************************************************************/
2582 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2585 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2587 int buffer_len, pos;
2589 #ifdef JOWENN_DEBUG1
2592 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2594 buffer = MNEW(char, buffer_len);
2596 strcpy(buffer, "class_findmethod: method:");
2597 utf_sprint(buffer + strlen(buffer), name);
2598 strcpy(buffer + strlen(buffer), ", desc: ");
2599 utf_sprint(buffer + strlen(buffer), desc);
2600 strcpy(buffer + strlen(buffer), ", classname: ");
2601 utf_sprint(buffer + strlen(buffer), c->name);
2605 MFREE(buffer, char, buffer_len);
2607 for (i = 0; i < c->methodscount; i++) {
2608 #ifdef JOWENN_DEBUG2
2610 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2612 buffer = MNEW(char, buffer_len);
2614 strcpy(buffer, "class_findmethod: comparing to method:");
2615 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2616 strcpy(buffer + strlen(buffer), ", desc: ");
2617 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2621 MFREE(buffer, char, buffer_len);
2625 if ((c->methods[i].name == name) && ((desc == NULL) ||
2626 (c->methods[i].descriptor == desc))) {
2631 #ifdef JOWENN_DEBUG2
2632 class_showconstantpool(c);
2633 log_text("class_findmethod: returning NULL");
2640 /************************* Function: class_findmethod **************************
2642 Searches a 'classinfo' structure for a method having the given name and
2644 If type is NULL, it is ignored.
2646 *******************************************************************************/
2648 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2652 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2654 int buffer_len, pos;
2656 #ifdef JOWENN_DEBUG1
2659 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2661 buffer = MNEW(char, buffer_len);
2663 strcpy(buffer, "class_findmethod: method:");
2664 utf_sprint(buffer + strlen(buffer), name);
2665 strcpy(buffer + strlen(buffer), ", desc: ");
2666 utf_sprint(buffer + strlen(buffer), desc);
2667 strcpy(buffer + strlen(buffer), ", classname: ");
2668 utf_sprint(buffer + strlen(buffer), c->name);
2672 MFREE(buffer, char, buffer_len);
2674 for (i = 0; i < c->methodscount; i++) {
2675 #ifdef JOWENN_DEBUG2
2677 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2679 buffer = MNEW(char, buffer_len);
2681 strcpy(buffer, "class_findmethod: comparing to method:");
2682 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2683 strcpy(buffer + strlen(buffer), ", desc: ");
2684 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2688 MFREE(buffer, char, buffer_len);
2691 if ((c->methods[i].name == name) && ((desc == NULL) ||
2692 (c->methods[i].descriptor == desc))) {
2693 return &(c->methods[i]);
2696 #ifdef JOWENN_DEBUG2
2697 class_showconstantpool(c);
2698 log_text("class_findmethod: returning NULL");
2703 s4 idx=class_findmethodIndex(c, name, desc);
2704 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2705 if (idx == -1) return NULL;
2707 return &(c->methods[idx]);
2711 /*********************** Function: class_fetchmethod **************************
2713 like class_findmethod, but aborts with an error if the method is not found
2715 *******************************************************************************/
2717 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2720 mi = class_findmethod(c, name, desc);
2723 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2724 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2725 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2726 panic("Method not found");
2733 /*********************** Function: class_findmethod_w**************************
2735 like class_findmethod, but logs a warning if the method is not found
2737 *******************************************************************************/
2739 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
2742 mi = class_findmethod(c, name, desc);
2745 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2746 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2747 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2749 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
2750 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
2751 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
2752 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
2753 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
2754 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
2755 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
2756 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
2757 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
2758 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
2759 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
2762 log_plain(" : WARNING: Method not found");log_nl( );
2769 /************************* Function: class_findmethod_approx ******************
2771 like class_findmethod but ignores the return value when comparing the
2774 *******************************************************************************/
2776 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2780 for (i = 0; i < c->methodscount; i++) {
2781 if (c->methods[i].name == name) {
2782 utf *meth_descr = c->methods[i].descriptor;
2786 return &(c->methods[i]);
2788 if (desc->blength <= meth_descr->blength) {
2789 /* current position in utf text */
2790 char *desc_utf_ptr = desc->text;
2791 char *meth_utf_ptr = meth_descr->text;
2792 /* points behind utf strings */
2793 char *desc_end = utf_end(desc);
2794 char *meth_end = utf_end(meth_descr);
2797 /* compare argument types */
2798 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2800 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2801 break; /* no match */
2804 return &(c->methods[i]); /* all parameter types equal */
2814 /***************** Function: class_resolvemethod_approx ***********************
2816 Searches a class and every super class for a method (without paying
2817 attention to the return value)
2819 *******************************************************************************/
2821 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2824 /* search for method (ignore returntype) */
2825 methodinfo *m = class_findmethod_approx(c, name, desc);
2828 /* search superclass */
2836 /************************* Function: class_resolvemethod ***********************
2838 Searches a class and every super class for a method.
2840 *******************************************************************************/
2842 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2845 methodinfo *m = class_findmethod(c, name, desc);
2847 /* search superclass */
2855 /************************* Function: class_issubclass **************************
2857 Checks if sub is a descendant of super.
2859 *******************************************************************************/
2861 bool class_issubclass(classinfo *sub, classinfo *super)
2864 if (!sub) return false;
2865 if (sub == super) return true;
2871 /****************** Initialization function for classes ******************
2873 In Java, every class can have a static initialization function. This
2874 function has to be called BEFORE calling other methods or accessing static
2877 *******************************************************************************/
2879 void class_init(classinfo *c)
2882 native_stackframeinfo **info;
2884 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2888 if (!makeinitializations)
2893 c->initialized = true;
2896 count_class_inits++;
2899 /* initialize super class */
2902 char logtext[MAXLOGTEXT];
2903 sprintf(logtext, "Initialize super class ");
2904 utf_sprint(logtext + strlen(logtext), c->super->name);
2905 sprintf(logtext + strlen(logtext), " from ");
2906 utf_sprint(logtext + strlen(logtext), c->name);
2909 class_init(c->super);
2912 /* initialize interface classes */
2913 for (i = 0; i < c->interfacescount; i++) {
2915 char logtext[MAXLOGTEXT];
2916 sprintf(logtext, "Initialize interface class ");
2917 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
2918 sprintf(logtext + strlen(logtext), " from ");
2919 utf_sprint(logtext + strlen(logtext), c->name);
2922 class_init(c->interfaces[i]); /* real */
2925 m = class_findmethod(c, utf_clinit, utf_fidesc);
2928 char logtext[MAXLOGTEXT];
2929 sprintf(logtext, "Class ");
2930 utf_sprint(logtext + strlen(logtext), c->name);
2931 sprintf(logtext + strlen(logtext), " has no initializer");
2934 /* goto callinitialize;*/
2938 if (!(m->flags & ACC_STATIC))
2939 panic("Class initializer is not static!");
2942 char logtext[MAXLOGTEXT];
2943 sprintf(logtext, "Starting initializer for class: ");
2944 utf_sprint(logtext + strlen(logtext), c->name);
2948 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2953 info = builtin_asm_new_stackframeinfo();
2954 (*info)->method = m;
2955 (*info)->returnFromNative = 0;
2956 (*info)->addrReturnFromNative = 0;
2957 log_text("cl_init");
2958 utf_display(m->class->name);
2960 /* now call the initializer */
2961 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2963 *info = (*info)->prev;
2965 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2966 assert(blockInts == 0);
2970 /* we have to throw an exception */
2971 if (*exceptionptr) {
2972 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2973 printf("Caused by: ");
2974 utf_display((*exceptionptr)->vftbl->class->name);
2981 char logtext[MAXLOGTEXT];
2982 sprintf(logtext, "Finished initializer for class: ");
2983 utf_sprint(logtext + strlen(logtext), c->name);
2987 if (c->name == utf_systemclass) {
2988 /* class java.lang.System requires explicit initialization */
2991 printf("#### Initializing class System");
2993 /* find initializing method */
2994 m = class_findmethod(c,
2995 utf_initsystemclass,
2999 /* no method found */
3000 /* printf("initializeSystemClass failed"); */
3004 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3009 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3011 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3012 assert(blockInts == 0);
3016 if (*exceptionptr) {
3017 printf("#### initializeSystemClass has thrown: ");
3018 utf_display((*exceptionptr)->vftbl->class->name);
3026 /********* Function: find_class_method_constant *********/
3028 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
3033 for (i=0; i<c->cpcount; i++) {
3035 e = c -> cpinfos [i];
3038 switch (c -> cptags [i]) {
3039 case CONSTANT_Methodref:
3041 constant_FMIref *fmi = e;
3042 if ( (fmi->class->name == c1)
3043 && (fmi->name == m1)
3044 && (fmi->descriptor == d1)) {
3051 case CONSTANT_InterfaceMethodref:
3053 constant_FMIref *fmi = e;
3054 if ( (fmi->class->name == c1)
3055 && (fmi->name == m1)
3056 && (fmi->descriptor == d1)) {
3070 void class_showconstanti(classinfo *c, int ii)
3076 printf ("#%d: ", (int) i);
3078 switch (c->cptags [i]) {
3079 case CONSTANT_Class:
3080 printf("Classreference -> ");
3081 utf_display(((classinfo*)e)->name);
3084 case CONSTANT_Fieldref:
3085 printf("Fieldref -> "); goto displayFMIi;
3086 case CONSTANT_Methodref:
3087 printf("Methodref -> "); goto displayFMIi;
3088 case CONSTANT_InterfaceMethodref:
3089 printf("InterfaceMethod -> "); goto displayFMIi;
3092 constant_FMIref *fmi = e;
3093 utf_display(fmi->class->name);
3095 utf_display(fmi->name);
3097 utf_display(fmi->descriptor);
3101 case CONSTANT_String:
3102 printf("String -> ");
3105 case CONSTANT_Integer:
3106 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3108 case CONSTANT_Float:
3109 printf("Float -> %f", ((constant_float*)e)->value);
3111 case CONSTANT_Double:
3112 printf("Double -> %f", ((constant_double*)e)->value);
3116 u8 v = ((constant_long*)e)->value;
3118 printf("Long -> %ld", (long int) v);
3120 printf("Long -> HI: %ld, LO: %ld\n",
3121 (long int) v.high, (long int) v.low);
3125 case CONSTANT_NameAndType:
3127 constant_nameandtype *cnt = e;
3128 printf("NameAndType: ");
3129 utf_display(cnt->name);
3131 utf_display(cnt->descriptor);
3139 panic("Invalid type of ConstantPool-Entry");
3146 void class_showconstantpool (classinfo *c)
3151 printf ("---- dump of constant pool ----\n");
3153 for (i=0; i<c->cpcount; i++) {
3154 printf ("#%d: ", (int) i);
3156 e = c -> cpinfos [i];
3159 switch (c -> cptags [i]) {
3160 case CONSTANT_Class:
3161 printf ("Classreference -> ");
3162 utf_display ( ((classinfo*)e) -> name );
3165 case CONSTANT_Fieldref:
3166 printf ("Fieldref -> "); goto displayFMI;
3167 case CONSTANT_Methodref:
3168 printf ("Methodref -> "); goto displayFMI;
3169 case CONSTANT_InterfaceMethodref:
3170 printf ("InterfaceMethod -> "); goto displayFMI;
3173 constant_FMIref *fmi = e;
3174 utf_display ( fmi->class->name );
3176 utf_display ( fmi->name);
3178 utf_display ( fmi->descriptor );
3182 case CONSTANT_String:
3183 printf ("String -> ");
3186 case CONSTANT_Integer:
3187 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3189 case CONSTANT_Float:
3190 printf ("Float -> %f", ((constant_float*)e) -> value);
3192 case CONSTANT_Double:
3193 printf ("Double -> %f", ((constant_double*)e) -> value);
3197 u8 v = ((constant_long*)e) -> value;
3199 printf ("Long -> %ld", (long int) v);
3201 printf ("Long -> HI: %ld, LO: %ld\n",
3202 (long int) v.high, (long int) v.low);
3206 case CONSTANT_NameAndType:
3208 constant_nameandtype *cnt = e;
3209 printf ("NameAndType: ");
3210 utf_display (cnt->name);
3212 utf_display (cnt->descriptor);
3216 printf ("Utf8 -> ");
3220 panic ("Invalid type of ConstantPool-Entry");
3230 /********** Function: class_showmethods (debugging only) *************/
3232 void class_showmethods (classinfo *c)
3236 printf ("--------- Fields and Methods ----------------\n");
3237 printf ("Flags: "); printflags (c->flags); printf ("\n");
3239 printf ("This: "); utf_display (c->name); printf ("\n");
3241 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3243 printf ("Index: %d\n", c->index);
3245 printf ("interfaces:\n");
3246 for (i=0; i < c-> interfacescount; i++) {
3248 utf_display (c -> interfaces[i] -> name);
3249 printf (" (%d)\n", c->interfaces[i] -> index);
3252 printf ("fields:\n");
3253 for (i=0; i < c -> fieldscount; i++) {
3254 field_display (&(c -> fields[i]));
3257 printf ("methods:\n");
3258 for (i=0; i < c -> methodscount; i++) {
3259 methodinfo *m = &(c->methods[i]);
3260 if ( !(m->flags & ACC_STATIC))
3261 printf ("vftblindex: %d ", m->vftblindex);
3263 method_display ( m );
3267 printf ("Virtual function table:\n");
3268 for (i=0; i<c->vftbl->vftbllength; i++) {
3269 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3276 /******************************************************************************/
3277 /******************* General functions for the class loader *******************/
3278 /******************************************************************************/
3280 /********************* Function: loader_load ***********************************
3282 Loads and links the class desired class and each class and interface
3284 Returns: a pointer to this class
3286 *******************************************************************************/
3288 static int loader_load_running = 0;
3290 classinfo *loader_load(utf *topname)
3296 classinfo *notlinkable;
3298 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3299 pthread_mutex_lock(&compiler_mutex);
3302 /* avoid recursive calls */
3303 if (loader_load_running)
3304 return class_new(topname);
3306 loader_load_running++;
3308 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3313 starttime = getcputime();
3315 top = class_new(topname);
3318 while ((c = list_first(&unloadedclasses))) {
3319 if (!class_load(c)) {
3321 dolog("Failed to load class");
3322 list_remove(&unloadedclasses, c);
3329 dolog("Linking...");
3331 /* Added a hack to break infinite linking loops. A better
3332 * linking algorithm would be nice. -Edwin */
3334 while ((c = list_first(&unlinkedclasses))) {
3339 else if (notlinkable == c) {
3340 /* We tried to link this class for the second time and
3341 * no other classes were linked in between, so we are
3345 dolog("Cannot resolve linking dependencies");
3348 throw_linkageerror_message(c->name);
3356 dolog("Linking done.");
3359 loader_compute_subclasses();
3362 if (getloadingtime) {
3363 stoptime = getcputime();
3364 loadingtime += (stoptime - starttime);
3368 loader_load_running--;
3370 /* check if a former loader_load call tried to load/link the class and
3371 failed. This is needed because the class didn't appear in the
3372 undloadclasses or unlinkedclasses list during this class. */
3375 if (linkverbose) dolog("Failed to load class (former call)");
3376 throw_noclassdeffounderror_message(top->name);
3379 } else if (!top->linked) {
3381 dolog("Failed to link class (former call)");
3382 throw_linkageerror_message(top->name);
3387 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3391 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3392 pthread_mutex_unlock(&compiler_mutex);
3395 /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3401 /****************** Function: loader_load_sysclass ****************************
3403 Loads and links the class desired class and each class and interface
3406 The pointer to the classinfo is stored in *top if top != NULL.
3407 The pointer is also returned.
3409 If the class could not be loaded the function aborts with an error.
3411 *******************************************************************************/
3413 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3417 if ((cls = loader_load(topname)) == NULL) {
3418 log_plain("Could not load important system class: ");
3419 log_plain_utf(topname);
3421 panic("Could not load important system class");
3424 if (top) *top = cls;
3430 /**************** function: create_primitive_classes ***************************
3432 create classes representing primitive types
3434 ********************************************************************************/
3437 void create_primitive_classes()
3441 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3442 /* create primitive class */
3443 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3444 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3445 c -> impldBy = NULL;
3447 /* prevent loader from loading primitive class */
3448 list_remove (&unloadedclasses, c);
3450 /* add to unlinked classes */
3451 list_addlast (&unlinkedclasses, c);
3452 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3455 primitivetype_table[i].class_primitive = c;
3457 /* create class for wrapping the primitive type */
3458 primitivetype_table[i].class_wrap =
3459 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3460 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3461 primitivetype_table[i].class_wrap -> impldBy = NULL;
3463 /* create the primitive array class */
3464 if (primitivetype_table[i].arrayname) {
3465 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3466 primitivetype_table[i].arrayclass = c;
3468 if (!c->linked) class_link(c);
3469 primitivetype_table[i].arrayvftbl = c->vftbl;
3474 /**************** function: class_primitive_from_sig ***************************
3476 return the primitive class indicated by the given signature character
3478 If the descriptor does not indicate a valid primitive type the
3479 return value is NULL.
3481 ********************************************************************************/
3483 classinfo *class_primitive_from_sig(char sig)
3486 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3487 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3488 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3489 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3490 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3491 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3492 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3493 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3494 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3499 /****************** function: class_from_descriptor ****************************
3501 return the class indicated by the given descriptor
3503 utf_ptr....first character of descriptor
3504 end_ptr....first character after the end of the string
3505 next.......if non-NULL, *next is set to the first character after
3506 the descriptor. (Undefined if an error occurs.)
3508 mode.......a combination (binary or) of the following flags:
3510 (Flags marked with * are the default settings.)
3512 What to do if a reference type descriptor is parsed successfully:
3514 CLASSLOAD_SKIP...skip it and return something != NULL
3515 * CLASSLOAD_NEW....get classinfo * via class_new
3516 CLASSLOAD_LOAD...get classinfo * via loader_load
3518 How to handle primitive types:
3520 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3521 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3523 How to handle "V" descriptors:
3525 * CLASSLOAD_VOID.....handle it like other primitive types
3526 CLASSLOAD_NOVOID...treat it as an error
3528 How to deal with extra characters after the end of the
3531 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3532 CLASSLOAD_CHECKEND.....treat them as an error
3534 How to deal with errors:
3536 * CLASSLOAD_PANIC....abort execution with an error message
3537 CLASSLOAD_NOPANIC..return NULL on error
3539 ********************************************************************************/
3541 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3542 char **next, int mode)
3544 char *start = utf_ptr;
3548 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3550 if (mode & CLASSLOAD_CHECKEND)
3551 error |= (utf_ptr != end_ptr);
3554 if (next) *next = utf_ptr;
3558 if (mode & CLASSLOAD_NOVOID)
3569 return (mode & CLASSLOAD_NULLPRIMITIVE)
3571 : class_primitive_from_sig(*start);
3578 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3579 name = utf_new(start,utf_ptr-start);
3580 return (mode & CLASSLOAD_LOAD)
3581 ? loader_load(name) : class_new(name); /* XXX handle errors */
3585 /* An error occurred */
3586 if (mode & CLASSLOAD_NOPANIC)
3589 log_plain("Invalid descriptor at beginning of '");
3590 log_plain_utf(utf_new(start, end_ptr-start));
3594 panic("Invalid descriptor");
3596 /* keep compiler happy */
3601 /******************* function: type_from_descriptor ****************************
3603 return the basic type indicated by the given descriptor
3605 This function parses a descriptor and returns its basic type as
3606 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3608 cls...if non-NULL the referenced variable is set to the classinfo *
3609 returned by class_from_descriptor.
3611 For documentation of the arguments utf_ptr, end_ptr, next and mode
3612 see class_from_descriptor. The only difference is that
3613 type_from_descriptor always uses CLASSLOAD_PANIC.
3615 ********************************************************************************/
3617 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3618 char **next, int mode)
3621 if (!cls) cls = &mycls;
3622 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3639 return TYPE_ADDRESS;
3644 /*************** function: create_system_exception_classes *******************************
3646 create system exception classes needed by default
3648 ********************************************************************************/
3650 static void create_system_exception_classes()
3653 if (verbose) log_text("loader_init: create_system_exception_classs: loader_load: java/lang/ClassCastException");
3654 loader_load_sysclass(&class_java_lang_ClassCastException,
3655 utf_new_char ("java/lang/ClassCastException"));
3656 loader_load_sysclass(&class_java_lang_NullPointerException,
3657 utf_new_char ("java/lang/NullPointerException"));
3658 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3659 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3660 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3661 utf_new_char ("java/lang/NegativeArraySizeException"));
3662 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3663 utf_new_char ("java/lang/OutOfMemoryError"));
3664 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3665 utf_new_char ("java/lang/ArrayStoreException"));
3666 loader_load_sysclass(&class_java_lang_ArithmeticException,
3667 utf_new_char ("java/lang/ArithmeticException"));
3668 loader_load_sysclass(&class_java_lang_ThreadDeath,
3669 utf_new_char ("java/lang/ThreadDeath"));
3675 /*************** function: create_system_exception_classes *******************************
3677 create system exception proto classes needed by default
3679 ********************************************************************************/
3681 static void create_system_exception_proto_classes()
3684 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3685 proto_java_lang_ClassCastException =
3686 builtin_new(class_java_lang_ClassCastException);
3688 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3690 proto_java_lang_NullPointerException =
3691 builtin_new(class_java_lang_NullPointerException);
3692 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3694 proto_java_lang_ArrayIndexOutOfBoundsException =
3695 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3697 proto_java_lang_NegativeArraySizeException =
3698 builtin_new(class_java_lang_NegativeArraySizeException);
3700 proto_java_lang_OutOfMemoryError =
3701 builtin_new(class_java_lang_OutOfMemoryError);
3703 proto_java_lang_ArithmeticException =
3704 builtin_new(class_java_lang_ArithmeticException);
3706 proto_java_lang_ArrayStoreException =
3707 builtin_new(class_java_lang_ArrayStoreException);
3709 proto_java_lang_ThreadDeath =
3710 builtin_new(class_java_lang_ThreadDeath);
3717 /*************** function: create_pseudo_classes *******************************
3719 create pseudo classes used by the typechecker
3721 ********************************************************************************/
3723 static void create_pseudo_classes()
3725 /* pseudo class for Arraystubs (extends java.lang.Object) */
3727 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3728 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3730 pseudo_class_Arraystub->super = class_java_lang_Object;
3731 pseudo_class_Arraystub->interfacescount = 2;
3732 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3733 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3734 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3736 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3737 class_link(pseudo_class_Arraystub);
3739 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3741 /* pseudo class representing the null type */
3743 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3744 list_remove(&unloadedclasses, pseudo_class_Null);
3746 pseudo_class_Null->super = class_java_lang_Object;
3748 list_addlast(&unlinkedclasses, pseudo_class_Null);
3749 class_link(pseudo_class_Null);
3751 /* pseudo class representing new uninitialized objects */
3753 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3754 list_remove(&unloadedclasses, pseudo_class_New);
3756 pseudo_class_New->super = class_java_lang_Object;
3758 list_addlast(&unlinkedclasses, pseudo_class_New);
3759 class_link(pseudo_class_New);
3763 /********************** Function: loader_init **********************************
3765 Initializes all lists and loads all classes required for the system or the
3768 *******************************************************************************/
3770 void loader_init(u1 *stackbottom)
3774 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3775 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3776 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3778 /* create utf-symbols for pointer comparison of frequently used strings */
3779 utf_innerclasses = utf_new_char("InnerClasses");
3780 utf_constantvalue = utf_new_char("ConstantValue");
3781 utf_code = utf_new_char("Code");
3782 utf_exceptions = utf_new_char("Exceptions");
3783 utf_linenumbertable = utf_new_char("LineNumberTable");
3784 utf_finalize = utf_new_char("finalize");
3785 utf_fidesc = utf_new_char("()V");
3786 utf_init = utf_new_char("<init>");
3787 utf_clinit = utf_new_char("<clinit>");
3788 utf_initsystemclass = utf_new_char("initializeSystemClass");
3789 utf_systemclass = utf_new_char("java/lang/System");
3790 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3791 utf_initialize = utf_new_char("initialize");
3792 utf_initializedesc = utf_new_char("(I)V");
3794 utf_vmclass = utf_new_char("java/lang/VMClass");
3795 utf_java_lang_Object= utf_new_char("java/lang/Object");
3797 array_packagename = utf_new_char("<the array package>");
3799 /* create some important classes */
3800 /* These classes have to be created now because the classinfo
3801 * pointers are used in the loading code.
3803 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3804 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3805 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3806 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3808 if (verbose) log_text("loader_init: java/lang/Object");
3809 /* load the classes which were created above */
3810 loader_load_sysclass(NULL, class_java_lang_Object->name);
3812 loader_inited = 1; /*JOWENN*/
3814 loader_load_sysclass(&class_java_lang_Throwable,
3815 utf_new_char("java/lang/Throwable"));
3817 create_system_exception_classes();
3819 /* create classes representing primitive types */
3820 create_primitive_classes();
3822 /* create classes used by the typechecker */
3823 create_pseudo_classes();
3825 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3826 stringtable_update();
3828 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3832 create_system_exception_proto_classes();
3838 /********************* Function: loader_initclasses ****************************
3840 Initializes all loaded but uninitialized classes
3842 *******************************************************************************/
3845 /* XXX TWISTI: i think we do not need this */
3846 void loader_initclasses ()
3850 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3851 pthread_mutex_lock(&compiler_mutex);
3854 intsDisable(); /* schani */
3856 if (makeinitializations) {
3857 c = list_first(&linkedclasses);
3860 c = list_next(&linkedclasses, c);
3864 intsRestore(); /* schani */
3866 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3867 pthread_mutex_unlock(&compiler_mutex);
3873 static void loader_compute_class_values(classinfo *c)
3877 c->vftbl->baseval = ++classvalue;
3880 while (subs != NULL) {
3881 loader_compute_class_values(subs);
3882 subs = subs->nextsub;
3884 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3889 for (i = 0; i < c->index; i++)
3891 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3892 utf_display(c->name);
3899 void loader_compute_subclasses()
3903 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3904 intsDisable(); /* schani */
3907 c = list_first(&linkedclasses);
3909 if (!(c->flags & ACC_INTERFACE)) {
3913 c = list_next(&linkedclasses, c);
3916 c = list_first(&linkedclasses);
3918 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3919 c->nextsub = c->super->sub;
3922 c = list_next(&linkedclasses, c);
3926 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3929 loader_compute_class_values(class_java_lang_Object);
3930 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3934 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3935 intsRestore(); /* schani */
3940 /******************** function classloader_buffer ******************************
3942 sets buffer for reading classdata
3944 *******************************************************************************/
3946 void classload_buffer(u1 *buf, int len)
3949 classbuffer_size = len;
3950 classbuf_pos = buf - 1;
3954 /******************** Function: loader_close ***********************************
3958 *******************************************************************************/
3964 while ((c = list_first(&unloadedclasses))) {
3965 list_remove(&unloadedclasses, c);
3968 while ((c = list_first(&unlinkedclasses))) {
3969 list_remove(&unlinkedclasses, c);
3972 while ((c = list_first(&linkedclasses))) {
3973 list_remove(&linkedclasses, c);
3980 * These are local overrides for various environment variables in Emacs.
3981 * Please do not remove this and leave it at the end of the file, where
3982 * Emacs will automagically detect them.
3983 * ---------------------------------------------------------------------
3986 * indent-tabs-mode: t