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 940 2004-03-06 14:04:15Z jowenn $
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_finalize; /* finalize */
90 static utf *utf_fidesc; /* ()V changed */
91 static utf *utf_init; /* <init> */
92 static utf *utf_clinit; /* <clinit> */
93 static utf *utf_initsystemclass; /* initializeSystemClass */
94 static utf *utf_systemclass; /* java/lang/System */
95 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
96 static utf *utf_vmclass; /* java/lang/VMClassLoader */
97 static utf *utf_initialize;
98 static utf *utf_initializedesc;
99 static utf *utf_java_lang_Object; /* java/lang/Object */
112 /* important system classes ***************************************************/
114 classinfo *class_java_lang_Object;
115 classinfo *class_java_lang_String;
117 classinfo *class_java_lang_Throwable;
118 classinfo *class_java_lang_Cloneable;
119 classinfo *class_java_io_Serializable;
121 /* Pseudo classes for the typechecker */
122 classinfo *pseudo_class_Arraystub = NULL;
123 classinfo *pseudo_class_Null = NULL;
124 classinfo *pseudo_class_New = NULL;
125 vftbl *pseudo_class_Arraystub_vftbl = NULL;
128 /* These are made static so they cannot be used for throwing in native */
130 static classinfo *class_java_lang_ClassCastException;
131 static classinfo *class_java_lang_NullPointerException;
132 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
133 static classinfo *class_java_lang_NegativeArraySizeException;
134 static classinfo *class_java_lang_OutOfMemoryError;
135 static classinfo *class_java_lang_ArithmeticException;
136 static classinfo *class_java_lang_ArrayStoreException;
137 static classinfo *class_java_lang_ThreadDeath;
139 utf *array_packagename = NULL;
141 static int loader_inited = 0;
144 /********************************************************************
145 list of classpath entries (either filesystem directories or
147 ********************************************************************/
148 static classpath_info *classpath_entries=0;
151 /******************************************************************************
153 structure for primitive classes: contains the class for wrapping the
154 primitive type, the primitive class, the name of the class for wrapping,
155 the one character type signature and the name of the primitive class
157 ******************************************************************************/
159 /* CAUTION: Don't change the order of the types. This table is indexed
160 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
162 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
163 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
164 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
165 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
166 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
167 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
168 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
169 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
170 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
171 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
175 /* instances of important system classes **************************************/
177 java_objectheader *proto_java_lang_ClassCastException;
178 java_objectheader *proto_java_lang_NullPointerException;
179 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
180 java_objectheader *proto_java_lang_NegativeArraySizeException;
181 java_objectheader *proto_java_lang_OutOfMemoryError;
182 java_objectheader *proto_java_lang_ArithmeticException;
183 java_objectheader *proto_java_lang_ArrayStoreException;
184 java_objectheader *proto_java_lang_ThreadDeath;
186 /************* functions for reading classdata *********************************
188 getting classdata in blocks of variable size
189 (8,16,32,64-bit integer or float)
191 *******************************************************************************/
193 static char *classpath = ""; /* searchpath for classfiles */
194 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
195 static u1 *classbuf_pos; /* current position in classfile buffer */
196 static int classbuffer_size; /* size of classfile-data */
198 /* assert that at least <len> bytes are left to read */
199 /* <len> is limited to the range of non-negative s4 values */
200 #define ASSERT_LEFT(len) \
201 do {if ( ((s4)(len)) < 0 \
202 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
203 panic("Unexpected end of classfile"); } while(0)
205 /* transfer block of classfile data into a buffer */
207 #define suck_nbytes(buffer,len) \
208 do {ASSERT_LEFT(len); \
209 memcpy(buffer,classbuf_pos+1,len); \
210 classbuf_pos+=len;} while (0)
212 /* skip block of classfile data */
214 #define skip_nbytes(len) \
215 do {ASSERT_LEFT(len); \
216 classbuf_pos+=len;} while(0)
221 return *++classbuf_pos;
225 u1 a=suck_u1(), b=suck_u1();
226 return ((u2)a<<8)+(u2)b;
230 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
231 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
233 #define suck_s8() (s8) suck_u8()
234 #define suck_s2() (s2) suck_u2()
235 #define suck_s4() (s4) suck_u4()
236 #define suck_s1() (s1) suck_u1()
239 /* get u8 from classfile data */
246 return (hi << 32) + lo;
256 /* get float from classfile data */
257 static float suck_float()
264 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
265 memcpy((u1*) (&f), buffer, 4);
267 suck_nbytes((u1*) (&f), 4);
270 PANICIF (sizeof(float) != 4, "Incompatible float-format");
276 /* get double from classfile data */
277 static double suck_double()
284 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
285 memcpy((u1*) (&d), buffer, 8);
287 suck_nbytes((u1*) (&d), 8);
290 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
296 /************************** function suck_init *********************************
298 called once at startup, sets the searchpath for the classfiles
300 *******************************************************************************/
302 void suck_init(char *cpath)
309 union classpath_info *tmp;
310 union classpath_info *insertAfter=0;
315 if (classpath_entries) panic("suck_init should be called only once");
316 for(start=classpath;(*start)!='\0';) {
317 for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
320 filenamelen=(end-start);
354 ( ( (*(end - 1)) == 'p') || ( (*(end - 1)) == 'P')) &&
355 (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
356 (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z')))
359 } else if ( (( (*(end - 1)) == 'r') || ( (*(end - 1)) == 'R')) &&
360 ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
361 (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
366 if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init");
368 filename=(char*)malloc(CLASSPATH_MAXFILENAME);
369 strncpy(filename,start,filenamelen);
370 filename[filenamelen+1]='\0';
375 unzFile uf=unzOpen(filename);
377 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
378 tmp->archive.type=CLASSPATH_ARCHIVE;
384 panic("Zip/JAR not supported");
388 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
389 tmp->filepath.type=CLASSPATH_PATH;
390 tmp->filepath.next=0;
391 if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
392 filename[filenamelen]='/';
393 filename[filenamelen+1]='\0';
397 tmp->filepath.filename=filename;
398 tmp->filepath.pathlen=filenamelen;
404 insertAfter->filepath.next=tmp;
406 classpath_entries=tmp;
411 if ((*end)==':') start=end+1; else start=end;
414 if (filename!=0) free(filename);
419 /************************** function suck_start ********************************
421 returns true if classbuffer is already loaded or a file for the
422 specified class has succussfully been read in. All directories of
423 the searchpath are used to find the classfile (<classname>.class).
424 Returns false if no classfile is found and writes an error message.
426 *******************************************************************************/
428 bool suck_start(utf *classname)
430 classpath_info *currPos;
433 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
439 if (classbuffer) return true; /* classbuffer is already valid */
441 utf_ptr = classname->text;
442 while (utf_ptr < utf_end(classname)) {
443 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
445 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
447 filename[filenamelen++] = c;
449 strcpy(filename + filenamelen, ".class");
451 for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
453 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
454 if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
455 unz_file_info file_info;
456 /*log_text("Class found in zip file");*/
457 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
458 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
459 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
460 classbuffer_size = file_info.uncompressed_size;
461 classbuffer = MNEW(u1, classbuffer_size);
462 classbuf_pos = classbuffer - 1;
463 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
464 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
465 unzCloseCurrentFile(currPos->archive.uf);
468 MFREE(classbuffer, u1, classbuffer_size);
469 log_text("Error while unzipping");
471 } else log_text("Error while opening file in archive");
472 } else log_text("Error while retrieving fileinfo");
474 unzCloseCurrentFile(currPos->archive.uf);
478 if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
479 strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
480 classfile = fopen(currPos->filepath.filename, "r");
481 if (classfile) { /* file exists */
483 /* determine size of classfile */
485 /* dolog("File: %s",filename); */
487 err = stat(currPos->filepath.filename, &buffer);
489 if (!err) { /* read classfile data */
490 classbuffer_size = buffer.st_size;
491 classbuffer = MNEW(u1, classbuffer_size);
492 classbuf_pos = classbuffer - 1;
493 fread(classbuffer, 1, classbuffer_size, classfile);
504 dolog("Warning: Can not open class file '%s'", filename);
511 /************************** function suck_stop *********************************
513 frees memory for buffer with classfile data.
514 Caution: this function may only be called if buffer has been allocated
515 by suck_start with reading a file
517 *******************************************************************************/
521 /* determine amount of classdata not retrieved by suck-operations */
523 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
525 if (classdata_left > 0) {
527 dolog("There are %d extra bytes at end of classfile",
529 /* The JVM spec disallows extra bytes. */
530 panic("Extra bytes at end of classfile");
535 MFREE(classbuffer, u1, classbuffer_size);
540 /******************************************************************************/
541 /******************* Some support functions ***********************************/
542 /******************************************************************************/
544 void fprintflags (FILE *fp, u2 f)
546 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
547 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
548 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
549 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
550 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
551 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
552 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
553 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
554 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
555 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
556 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
560 /********** internal function: printflags (only for debugging) ***************/
562 void printflags(u2 f)
564 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
565 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
566 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
567 if ( f & ACC_STATIC ) printf (" STATIC");
568 if ( f & ACC_FINAL ) printf (" FINAL");
569 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
570 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
571 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
572 if ( f & ACC_NATIVE ) printf (" NATIVE");
573 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
574 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
578 /************************* Function: skipattribute *****************************
580 skips a (1) 'attribute' structure in the class file
582 *******************************************************************************/
584 static void skipattribute()
593 /********************** Function: skipattributebody ****************************
595 skips an attribute after the 16 bit reference to attribute_name has already
598 *******************************************************************************/
600 static void skipattributebody()
608 /************************* Function: skipattributes ****************************
610 skips num attribute structures
612 *******************************************************************************/
614 static void skipattributes(u4 num)
617 for (i = 0; i < num; i++)
622 /******************** function: innerclass_getconstant ************************
624 like class_getconstant, but if cptags is ZERO null is returned
626 *******************************************************************************/
628 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
630 /* invalid position in constantpool */
631 if (pos >= c->cpcount)
632 panic("Attempt to access constant outside range");
634 /* constantpool entry of type 0 */
638 /* check type of constantpool entry */
639 if (c->cptags[pos] != ctype) {
640 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
641 (int) ctype, (int) c->cptags[pos] );
644 return c->cpinfos[pos];
648 /************************ function: attribute_load ****************************
650 read attributes from classfile
652 *******************************************************************************/
654 static void attribute_load(u4 num, classinfo *c)
658 for (i = 0; i < num; i++) {
659 /* retrieve attribute name */
660 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
662 if (aname == utf_innerclasses) {
663 /* innerclasses attribute */
665 if (c->innerclass != NULL)
666 panic("Class has more than one InnerClasses attribute");
668 /* skip attribute length */
670 /* number of records */
671 c->innerclasscount = suck_u2();
672 /* allocate memory for innerclass structure */
673 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
675 for (j = 0; j < c->innerclasscount; j++) {
676 /* The innerclass structure contains a class with an encoded name,
677 its defining scope, its simple name and a bitmask of the access flags.
678 If an inner class is not a member, its outer_class is NULL,
679 if a class is anonymous, its name is NULL. */
681 innerclassinfo *info = c->innerclass + j;
683 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
684 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
685 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
686 info->flags = suck_u2(); /* access_flags bitmask */
690 /* unknown attribute */
697 /******************* function: checkfielddescriptor ****************************
699 checks whether a field-descriptor is valid and aborts otherwise
700 all referenced classes are inserted into the list of unloaded classes
702 *******************************************************************************/
704 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
706 class_from_descriptor(utf_ptr,end_pos,NULL,
708 | CLASSLOAD_NULLPRIMITIVE
710 | CLASSLOAD_CHECKEND);
712 /* XXX use the following if -noverify */
714 char *tstart; /* pointer to start of classname */
716 char *start = utf_ptr;
718 switch (*utf_ptr++) {
732 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
733 panic ("Ill formed descriptor");
737 panic ("Ill formed descriptor");
740 /* exceeding characters */
741 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
746 /******************* function checkmethoddescriptor ****************************
748 checks whether a method-descriptor is valid and aborts otherwise.
749 All referenced classes are inserted into the list of unloaded classes.
751 The number of arguments is returned. A long or double argument is counted
754 *******************************************************************************/
756 static int checkmethoddescriptor (utf *d)
758 char *utf_ptr = d->text; /* current position in utf text */
759 char *end_pos = utf_end(d); /* points behind utf string */
760 int argcount = 0; /* number of arguments */
762 /* method descriptor must start with parenthesis */
763 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
765 /* check arguments */
766 while (utf_ptr != end_pos && *utf_ptr != ')') {
767 /* We cannot count the this argument here because
768 * we don't know if the method is static. */
769 if (*utf_ptr == 'J' || *utf_ptr == 'D')
773 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
775 | CLASSLOAD_NULLPRIMITIVE
779 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
780 utf_ptr++; /* skip ')' */
782 class_from_descriptor(utf_ptr,end_pos,NULL,
784 | CLASSLOAD_NULLPRIMITIVE
785 | CLASSLOAD_CHECKEND);
788 panic("Invalid method descriptor: too many arguments");
792 /* XXX use the following if -noverify */
794 /* check arguments */
795 while ((c = *utf_ptr++) != ')') {
812 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
813 panic ("Ill formed method descriptor");
817 panic ("Ill formed methodtype-descriptor");
821 /* check returntype */
823 /* returntype void */
824 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
827 /* treat as field-descriptor */
828 checkfielddescriptor (utf_ptr,end_pos);
833 /***************** Function: print_arraydescriptor ****************************
835 Debugging helper for displaying an arraydescriptor
837 *******************************************************************************/
839 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
842 fprintf(file, "<NULL>");
847 if (desc->componentvftbl) {
848 if (desc->componentvftbl->class)
849 utf_fprint(file, desc->componentvftbl->class->name);
851 fprintf(file, "<no classinfo>");
857 if (desc->elementvftbl) {
858 if (desc->elementvftbl->class)
859 utf_fprint(file, desc->elementvftbl->class->name);
861 fprintf(file, "<no classinfo>");
865 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
866 desc->dataoffset, desc->componentsize);
870 /******************************************************************************/
871 /************************** Functions for fields ****************************/
872 /******************************************************************************/
875 /************************ Function: field_load *********************************
877 Load everything about a class field from the class file and fill a
878 'fieldinfo' structure. For static fields, space in the data segment is
881 *******************************************************************************/
883 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
885 static void field_load(fieldinfo *f, classinfo *c)
889 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
891 f->flags = suck_u2(); /* ACC flags */
892 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
893 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
897 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
898 panic("Field with invalid name");
900 /* check flag consistency */
901 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
902 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
903 panic("Field has invalid access flags");
904 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
905 panic("Field is declared final and volatile");
906 if ((c->flags & ACC_INTERFACE) != 0) {
907 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
908 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
909 panic("Interface field is not declared static final public");
910 if ((f->flags & ACC_TRANSIENT) != 0)
911 panic("Interface field declared transient");
914 /* check descriptor */
915 checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
918 f->type = jtype = desc_to_type(f->descriptor); /* data type */
919 f->offset = 0; /* offset from start of object */
924 case TYPE_INT: f->value.i = 0; break;
925 case TYPE_FLOAT: f->value.f = 0.0; break;
926 case TYPE_DOUBLE: f->value.d = 0.0; break;
927 case TYPE_ADDRESS: f->value.a = NULL; break;
930 f->value.l = 0; break;
932 f->value.l.low = 0; f->value.l.high = 0; break;
936 /* read attributes */
938 for (i = 0; i < attrnum; i++) {
941 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
943 if (aname != utf_constantvalue) {
944 /* unknown attribute */
948 /* constant value attribute */
950 if (pindex != field_load_NOVALUE)
951 panic("Field has more than one ConstantValue attribute");
953 /* check attribute length */
955 panic("ConstantValue attribute has invalid length");
957 /* index of value in constantpool */
960 /* initialize field with value from constantpool */
963 constant_integer *ci =
964 class_getconstant(c, pindex, CONSTANT_Integer);
965 f->value.i = ci->value;
971 class_getconstant(c, pindex, CONSTANT_Long);
972 f->value.l = cl->value;
978 class_getconstant(c, pindex, CONSTANT_Float);
979 f->value.f = cf->value;
984 constant_double *cd =
985 class_getconstant(c, pindex, CONSTANT_Double);
986 f->value.d = cd->value;
991 utf *u = class_getconstant(c, pindex, CONSTANT_String);
992 /* create javastring from compressed utf8-string */
993 f->value.a = literalstring_new(u);
998 log_text ("Invalid Constant - Type");
1005 /********************** function: field_free **********************************/
1007 static void field_free (fieldinfo *f)
1013 /**************** Function: field_display (debugging only) ********************/
1015 void field_display(fieldinfo *f)
1018 printflags(f->flags);
1020 utf_display(f->name);
1022 utf_display(f->descriptor);
1023 printf(" offset: %ld\n", (long int) (f->offset));
1027 /******************************************************************************/
1028 /************************* Functions for methods ******************************/
1029 /******************************************************************************/
1032 /*********************** Function: method_load *********************************
1034 Loads a method from the class file and fills an existing 'methodinfo'
1035 structure. For native methods, the function pointer field is set to the
1036 real function pointer, for JavaVM methods a pointer to the compiler is used
1039 *******************************************************************************/
1041 static void method_load(methodinfo *m, classinfo *c)
1047 count_all_methods++;
1049 m->thrownexceptionscount=0;
1052 m->flags = suck_u2();
1053 m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1056 if (!is_valid_name_utf(m->name))
1057 panic("Method with invalid name");
1058 if (m->name->text[0] == '<'
1059 && m->name != utf_init && m->name != utf_clinit)
1060 panic("Method with invalid special name");
1063 m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1064 argcount = checkmethoddescriptor(m->descriptor);
1065 if ((m->flags & ACC_STATIC) == 0)
1066 argcount++; /* count the 'this' argument */
1070 panic("Method has more than 255 arguments");
1072 /* check flag consistency */
1073 if (m->name != utf_clinit) {
1074 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1075 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1076 panic("Method has invalid access flags");
1077 if ((m->flags & ACC_ABSTRACT) != 0) {
1078 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1079 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1080 panic("Abstract method has invalid flags set");
1082 if ((c->flags & ACC_INTERFACE) != 0) {
1083 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1084 != (ACC_ABSTRACT | ACC_PUBLIC))
1085 panic("Interface method is not declared abstract and public");
1087 if (m->name == utf_init) {
1088 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1089 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1090 panic("Instance initialization method has invalid flags set");
1096 m->exceptiontable = NULL;
1097 m->entrypoint = NULL;
1099 m->stubroutine = NULL;
1100 m->methodUsed = NOTUSED;
1103 m->subRedefsUsed = 0;
1107 if (!(m->flags & ACC_NATIVE)) {
1108 m->stubroutine = createcompilerstub(m);
1111 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1112 (m->flags & ACC_STATIC) != 0);
1114 m->stubroutine = createnativestub(f, m);
1119 attrnum = suck_u2();
1120 for (i = 0; i < attrnum; i++) {
1123 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1125 if (aname != utf_code) {
1126 if (aname == utf_exceptions) {
1129 suck_u4(); /*length*/
1130 exceptionCount=suck_u2();
1131 m->thrownexceptionscount=exceptionCount;
1132 m->thrownexceptions=MNEW(classinfo*,exceptionCount);
1133 for (exceptionID=0;exceptionID<exceptionCount;exceptionID++) {
1134 (m->thrownexceptions)[exceptionID]=class_getconstant(c,suck_u2(),CONSTANT_Class);
1138 skipattributebody();
1142 if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
1143 panic("Code attribute for native or abstract method");
1146 panic("Method has more than one Code attribute");
1149 m->maxstack = suck_u2();
1150 m->maxlocals = suck_u2();
1151 if (m->maxlocals < argcount)
1152 panic("max_locals is smaller than the number of arguments");
1154 codelen = suck_u4();
1156 panic("bytecode has zero length");
1157 if (codelen > 65536)
1158 panic("bytecode too long");
1159 m->jcodelength = codelen;
1160 m->jcode = MNEW(u1, m->jcodelength);
1161 suck_nbytes(m->jcode, m->jcodelength);
1162 m->exceptiontablelength = suck_u2();
1164 MNEW(exceptiontable, m->exceptiontablelength);
1167 count_vmcode_len += m->jcodelength + 18;
1168 count_extable_len += 8 * m->exceptiontablelength;
1171 for (e = 0; e < m->exceptiontablelength; e++) {
1173 m->exceptiontable[e].startpc = suck_u2();
1174 m->exceptiontable[e].endpc = suck_u2();
1175 m->exceptiontable[e].handlerpc = suck_u2();
1179 m->exceptiontable[e].catchtype = NULL;
1182 m->exceptiontable[e].catchtype =
1183 class_getconstant(c, idx, CONSTANT_Class);
1187 skipattributes(suck_u2());
1191 if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
1192 panic("Method missing Code attribute");
1196 /********************* Function: method_free ***********************************
1198 frees all memory that was allocated for this method
1200 *******************************************************************************/
1202 static void method_free(methodinfo *m)
1205 MFREE(m->jcode, u1, m->jcodelength);
1207 if (m->exceptiontable)
1208 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1211 CFREE(m->mcode, m->mcodelength);
1213 if (m->stubroutine) {
1214 if (m->flags & ACC_NATIVE) {
1215 removenativestub(m->stubroutine);
1218 removecompilerstub(m->stubroutine);
1224 /************** Function: method_display (debugging only) **************/
1226 void method_display(methodinfo *m)
1229 printflags(m->flags);
1231 utf_display(m->name);
1233 utf_display(m->descriptor);
1237 /************** Function: method_display_flags_last (debugging only) **************/
1239 void method_display_flags_last(methodinfo *m)
1242 utf_display(m->name);
1244 utf_display(m->descriptor);
1246 printflags(m->flags);
1251 /******************** Function: method_canoverwrite ****************************
1253 Check if m and old are identical with respect to type and name. This means
1254 that old can be overwritten with m.
1256 *******************************************************************************/
1258 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1260 if (m->name != old->name) return false;
1261 if (m->descriptor != old->descriptor) return false;
1262 if (m->flags & ACC_STATIC) return false;
1269 /******************************************************************************/
1270 /************************ Functions for class *********************************/
1271 /******************************************************************************/
1274 /******************** function:: class_getconstant ******************************
1276 retrieves the value at position 'pos' of the constantpool of a class
1277 if the type of the value is other than 'ctype' the system is stopped
1279 *******************************************************************************/
1281 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1283 /* invalid position in constantpool */
1284 /* (pos == 0 is caught by type comparison) */
1285 if (pos >= c->cpcount)
1286 panic("Attempt to access constant outside range");
1288 /* check type of constantpool entry */
1290 if (c->cptags[pos] != ctype) {
1291 class_showconstantpool(c);
1292 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1293 (int) ctype, (int) c->cptags[pos]);
1296 return c->cpinfos[pos];
1300 /********************* Function: class_constanttype ****************************
1302 Determines the type of a class entry in the ConstantPool
1304 *******************************************************************************/
1306 u4 class_constanttype(classinfo *c, u4 pos)
1308 if (pos >= c->cpcount)
1309 panic("Attempt to access constant outside range");
1311 return c->cptags[pos];
1315 /******************** function: class_loadcpool ********************************
1317 loads the constantpool of a class,
1318 the entries are transformed into a simpler format
1319 by resolving references
1320 (a detailed overview of the compact structures can be found in global.h)
1322 *******************************************************************************/
1324 static void class_loadcpool(classinfo *c)
1327 /* The following structures are used to save information which cannot be
1328 processed during the first pass. After the complete constantpool has
1329 been traversed the references can be resolved.
1330 (only in specific order) */
1332 /* CONSTANT_Class_info entries */
1333 typedef struct forward_class {
1334 struct forward_class *next;
1339 /* CONSTANT_String */
1340 typedef struct forward_string {
1341 struct forward_string *next;
1346 /* CONSTANT_NameAndType */
1347 typedef struct forward_nameandtype {
1348 struct forward_nameandtype *next;
1352 } forward_nameandtype;
1354 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1355 typedef struct forward_fieldmethint {
1356 struct forward_fieldmethint *next;
1360 u2 nameandtype_index;
1361 } forward_fieldmethint;
1365 long int dumpsize = dump_size ();
1367 forward_class *forward_classes = NULL;
1368 forward_string *forward_strings = NULL;
1369 forward_nameandtype *forward_nameandtypes = NULL;
1370 forward_fieldmethint *forward_fieldmethints = NULL;
1372 /* number of entries in the constant_pool table plus one */
1373 u4 cpcount = c -> cpcount = suck_u2();
1374 /* allocate memory */
1375 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1376 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1379 panic("Invalid constant_pool_count (0)");
1382 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1385 /* initialize constantpool */
1386 for (idx=0; idx<cpcount; idx++) {
1387 cptags[idx] = CONSTANT_UNUSED;
1388 cpinfos[idx] = NULL;
1392 /******* first pass *******/
1393 /* entries which cannot be resolved now are written into
1394 temporary structures and traversed again later */
1397 while (idx < cpcount) {
1398 /* get constant type */
1402 case CONSTANT_Class: {
1403 forward_class *nfc = DNEW(forward_class);
1405 nfc -> next = forward_classes;
1406 forward_classes = nfc;
1408 nfc -> thisindex = idx;
1409 /* reference to CONSTANT_NameAndType */
1410 nfc -> name_index = suck_u2 ();
1416 case CONSTANT_Fieldref:
1417 case CONSTANT_Methodref:
1418 case CONSTANT_InterfaceMethodref: {
1419 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1421 nff -> next = forward_fieldmethints;
1422 forward_fieldmethints = nff;
1424 nff -> thisindex = idx;
1427 /* class or interface type that contains the declaration of the field or method */
1428 nff -> class_index = suck_u2 ();
1429 /* name and descriptor of the field or method */
1430 nff -> nameandtype_index = suck_u2 ();
1436 case CONSTANT_String: {
1437 forward_string *nfs = DNEW (forward_string);
1439 nfs -> next = forward_strings;
1440 forward_strings = nfs;
1442 nfs -> thisindex = idx;
1443 /* reference to CONSTANT_Utf8_info with string characters */
1444 nfs -> string_index = suck_u2 ();
1450 case CONSTANT_NameAndType: {
1451 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1453 nfn -> next = forward_nameandtypes;
1454 forward_nameandtypes = nfn;
1456 nfn -> thisindex = idx;
1457 /* reference to CONSTANT_Utf8_info containing simple name */
1458 nfn -> name_index = suck_u2 ();
1459 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1460 nfn -> sig_index = suck_u2 ();
1466 case CONSTANT_Integer: {
1467 constant_integer *ci = NEW (constant_integer);
1470 count_const_pool_len += sizeof(constant_integer);
1473 ci -> value = suck_s4 ();
1474 cptags [idx] = CONSTANT_Integer;
1481 case CONSTANT_Float: {
1482 constant_float *cf = NEW (constant_float);
1485 count_const_pool_len += sizeof(constant_float);
1488 cf -> value = suck_float ();
1489 cptags [idx] = CONSTANT_Float;
1495 case CONSTANT_Long: {
1496 constant_long *cl = NEW(constant_long);
1499 count_const_pool_len += sizeof(constant_long);
1502 cl -> value = suck_s8 ();
1503 cptags [idx] = CONSTANT_Long;
1507 panic("Long constant exceeds constant pool");
1511 case CONSTANT_Double: {
1512 constant_double *cd = NEW(constant_double);
1515 count_const_pool_len += sizeof(constant_double);
1518 cd -> value = suck_double ();
1519 cptags [idx] = CONSTANT_Double;
1523 panic("Double constant exceeds constant pool");
1527 case CONSTANT_Utf8: {
1529 /* number of bytes in the bytes array (not string-length) */
1530 u4 length = suck_u2();
1531 cptags [idx] = CONSTANT_Utf8;
1532 /* validate the string */
1533 ASSERT_LEFT(length);
1535 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1537 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1538 panic("Invalid UTF-8 string");
1540 /* insert utf-string into the utf-symboltable */
1541 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1542 /* skip bytes of the string */
1543 skip_nbytes(length);
1549 error ("Unkown constant type: %d",(int) t);
1557 /* resolve entries in temporary structures */
1559 while (forward_classes) {
1561 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1563 if (opt_verify && !is_valid_name_utf(name))
1564 panic("Class reference with invalid name");
1566 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1567 /* retrieve class from class-table */
1568 cpinfos [forward_classes -> thisindex] = class_new (name);
1570 forward_classes = forward_classes -> next;
1574 while (forward_strings) {
1576 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1578 log_text("forward_string:");
1579 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1581 log_text("\n------------------"); */
1582 /* resolve utf-string */
1583 cptags [forward_strings -> thisindex] = CONSTANT_String;
1584 cpinfos [forward_strings -> thisindex] = text;
1586 forward_strings = forward_strings -> next;
1589 while (forward_nameandtypes) {
1590 constant_nameandtype *cn = NEW (constant_nameandtype);
1593 count_const_pool_len += sizeof(constant_nameandtype);
1596 /* resolve simple name and descriptor */
1597 cn -> name = class_getconstant
1598 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1599 cn -> descriptor = class_getconstant
1600 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1604 if (!is_valid_name_utf(cn->name))
1605 panic("NameAndType with invalid name");
1606 /* disallow referencing <clinit> among others */
1607 if (cn->name->text[0] == '<' && cn->name != utf_init)
1608 panic("NameAndType with invalid special name");
1611 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1612 cpinfos [forward_nameandtypes -> thisindex] = cn;
1614 forward_nameandtypes = forward_nameandtypes -> next;
1618 while (forward_fieldmethints) {
1619 constant_nameandtype *nat;
1620 constant_FMIref *fmi = NEW (constant_FMIref);
1623 count_const_pool_len += sizeof(constant_FMIref);
1625 /* resolve simple name and descriptor */
1626 nat = class_getconstant
1627 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1630 log_text("trying to resolve:");
1631 log_text(nat->name->text);
1632 switch(forward_fieldmethints ->tag) {
1633 case CONSTANT_Fieldref:
1634 log_text("CONSTANT_Fieldref");
1636 case CONSTANT_InterfaceMethodref:
1637 log_text("CONSTANT_InterfaceMethodref");
1639 case CONSTANT_Methodref:
1640 log_text("CONSTANT_Methodref");
1644 fmi -> class = class_getconstant
1645 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1646 fmi -> name = nat -> name;
1647 fmi -> descriptor = nat -> descriptor;
1649 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1650 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1652 switch (forward_fieldmethints -> tag) {
1653 case CONSTANT_Fieldref: /* check validity of descriptor */
1654 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1656 case CONSTANT_InterfaceMethodref:
1657 case CONSTANT_Methodref: /* check validity of descriptor */
1658 checkmethoddescriptor (fmi->descriptor);
1662 forward_fieldmethints = forward_fieldmethints -> next;
1666 /* class_showconstantpool(c); */
1668 dump_release (dumpsize);
1672 /********************** Function: class_load ***********************************
1674 Loads everything interesting about a class from the class file. The
1675 'classinfo' structure must have been allocated previously.
1677 The super class and the interfaces implemented by this class need not be
1678 loaded. The link is set later by the function 'class_link'.
1680 The loaded class is removed from the list 'unloadedclasses' and added to
1681 the list 'unlinkedclasses'.
1683 *******************************************************************************/
1685 static int class_load(classinfo *c)
1691 count_class_loads++;
1694 /* output for debugging purposes */
1696 char logtext[MAXLOGTEXT];
1697 sprintf(logtext, "Loading class: ");
1698 utf_sprint(logtext + strlen(logtext), c->name);
1702 /* load classdata, throw exception on error */
1704 if (!suck_start(c->name)) {
1705 throw_noclassdeffounderror_message(c->name);
1709 /* check signature */
1710 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1714 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1715 error("File version %d.%d is not supported", (int) ma, (int) mi);
1720 c->erroneous_state = 0;
1721 c->initializing_thread = 0;
1723 c->classUsed = NOTUSED; /* not used initially CO-RT */
1727 c->flags = suck_u2();
1728 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1730 /* check ACC flags consistency */
1731 if ((c->flags & ACC_INTERFACE) != 0) {
1732 if ((c->flags & ACC_ABSTRACT) == 0) {
1733 /* We work around this because interfaces in JDK 1.1 are
1734 * not declared abstract. */
1736 c->flags |= ACC_ABSTRACT;
1737 /* panic("Interface class not declared abstract"); */
1739 if ((c->flags & (ACC_FINAL)) != 0)
1740 panic("Interface class has invalid flags");
1741 if ((c->flags & (ACC_SUPER)) != 0)
1742 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1744 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1745 panic("Class is declared both abstract and final");
1749 if (class_getconstant(c, i, CONSTANT_Class) != c)
1750 panic("Invalid this_class in class file");
1752 /* retrieve superclass */
1753 if ((i = suck_u2())) {
1754 c->super = class_getconstant(c, i, CONSTANT_Class);
1756 /* java.lang.Object may not have a super class. */
1757 if (c->name == utf_java_lang_Object)
1758 panic("java.lang.Object with super class");
1760 /* Interfaces must have j.l.O as super class. */
1761 if ((c->flags & ACC_INTERFACE) != 0
1762 && c->super->name != utf_java_lang_Object)
1764 panic("Interface with super class other than java.lang.Object");
1769 /* This is only allowed for java.lang.Object. */
1770 if (c->name != utf_java_lang_Object)
1771 panic("Class (not java.lang.Object) without super class");
1774 /* retrieve interfaces */
1775 c->interfacescount = suck_u2();
1776 c->interfaces = MNEW(classinfo*, c->interfacescount);
1777 for (i = 0; i < c->interfacescount; i++) {
1779 class_getconstant(c, suck_u2(), CONSTANT_Class);
1783 c->fieldscount = suck_u2();
1784 /* utf_display(c->name);
1785 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1787 c->fields = GCNEW(fieldinfo, c->fieldscount);
1788 for (i = 0; i < c->fieldscount; i++) {
1789 field_load(&(c->fields[i]), c);
1793 c->methodscount = suck_u2();
1794 c->methods = MNEW(methodinfo, c->methodscount);
1795 for (i = 0; i < c->methodscount; i++) {
1796 method_load(&(c->methods[i]), c);
1799 /* Check if all fields and methods can be uniquely
1800 * identified by (name,descriptor). */
1802 /* We use a hash table here to avoid making the
1803 * average case quadratic in # of methods, fields.
1805 static int shift = 0;
1807 u2 *next; /* for chaining colliding hash entries */
1813 /* Allocate hashtable */
1814 len = c->methodscount;
1815 if (len < c->fieldscount) len = c->fieldscount;
1817 hashtab = MNEW(u2,(hashlen + len));
1818 next = hashtab + hashlen;
1820 /* Determine bitshift (to get good hash values) */
1830 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1831 for (i = 0; i<c->fieldscount; ++i) {
1832 fieldinfo *fi = c->fields + i;
1833 /* It's ok if we lose bits here */
1834 index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
1836 if ((old = hashtab[index]) != 0) {
1838 /* dolog("HASHHIT %d --> %d",index,old); */
1841 /* dolog("HASHCHECK %d",old); */
1842 if (c->fields[old].name == fi->name
1843 && c->fields[old].descriptor == fi->descriptor)
1845 dolog("Duplicate field (%d,%d):",i,old);
1846 log_utf(fi->name); log_utf(fi->descriptor);
1847 panic("Fields with same name and descriptor");
1849 } while ((old = next[old]) != 0);
1851 /* else dolog("HASHLUCKY"); */
1852 hashtab[index] = i+1;
1856 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1857 for (i = 0; i<c->methodscount; ++i) {
1858 methodinfo *mi = c->methods + i;
1859 /* It's ok if we lose bits here */
1860 index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
1862 if ((old = hashtab[index]) != 0) {
1864 /* dolog("HASHHIT %d --> %d",index,old); */
1867 /* dolog("HASHCHECK %d",old); */
1868 if (c->methods[old].name == mi->name
1869 && c->methods[old].descriptor == mi->descriptor)
1871 dolog("Duplicate method (%d,%d):",i,old);
1872 log_utf(mi->name); log_utf(mi->descriptor);
1873 panic("Methods with same name and descriptor");
1875 } while ((old = next[old]) != 0);
1877 /* else dolog("HASHLUCKY"); */
1878 hashtab[index] = i+1;
1881 MFREE(hashtab,u2,(hashlen + len));
1885 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1886 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1887 count_class_infos += sizeof(methodinfo) * c->methodscount;
1890 /* load variable-length attribute structures */
1891 attribute_load(suck_u2(), c);
1896 /* remove class from list of unloaded classes and
1897 add to list of unlinked classes */
1898 list_remove(&unloadedclasses, c);
1899 list_addlast(&unlinkedclasses, c);
1908 /************** internal Function: class_highestinterface ***********************
1910 Used by the function class_link to determine the amount of memory needed
1911 for the interface table.
1913 *******************************************************************************/
1915 static s4 class_highestinterface(classinfo *c)
1920 if (!(c->flags & ACC_INTERFACE)) {
1921 char logtext[MAXLOGTEXT];
1922 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1923 utf_sprint(logtext + strlen(logtext), c->name);
1924 error("%s",logtext);
1928 for (i = 0; i < c->interfacescount; i++) {
1929 s4 h2 = class_highestinterface(c->interfaces[i]);
1937 /* class_addinterface **********************************************************
1939 Is needed by class_link for adding a VTBL to a class. All interfaces
1940 implemented by ic are added as well.
1942 *******************************************************************************/
1944 static void class_addinterface (classinfo *c, classinfo *ic)
1948 vftbl *vftbl = c->vftbl;
1950 if (i >= vftbl->interfacetablelength)
1951 panic ("Inernal error: interfacetable overflow");
1952 if (vftbl->interfacetable[-i])
1955 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1956 vftbl->interfacevftbllength[i] = 1;
1957 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1958 vftbl->interfacetable[-i][0] = NULL;
1961 vftbl->interfacevftbllength[i] = ic->methodscount;
1962 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1965 count_vftbl_len += sizeof(methodptr) *
1966 (ic->methodscount + (ic->methodscount == 0));
1969 for (j=0; j<ic->methodscount; j++) {
1972 for (m = 0; m < sc->methodscount; m++) {
1973 methodinfo *mi = &(sc->methods[m]);
1974 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1975 vftbl->interfacetable[-i][j] =
1976 vftbl->table[mi->vftblindex];
1986 for (j = 0; j < ic->interfacescount; j++)
1987 class_addinterface(c, ic->interfaces[j]);
1991 /******************* Function: class_new_array *********************************
1993 This function is called by class_new to setup an array class.
1995 *******************************************************************************/
1997 void class_new_array(classinfo *c)
1999 classinfo *comp = NULL;
2003 /* DEBUG */ /* dolog("class_new_array: %s",c->name->text); */
2005 /* Array classes are not loaded from classfiles. */
2006 list_remove(&unloadedclasses, c);
2008 /* Check array class name */
2009 namelen = c->name->blength;
2010 if (namelen < 2 || c->name->text[0] != '[')
2011 panic("Invalid array class name");
2013 /* Check the component type */
2014 switch (c->name->text[1]) {
2016 /* c is an array of arrays. We have to create the component class. */
2017 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
2021 /* c is an array of objects. */
2022 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2023 panic("Invalid array class name");
2024 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
2028 /* Setup the array class */
2029 c->super = class_java_lang_Object;
2030 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2032 c->interfacescount = 2;
2033 c->interfaces = MNEW(classinfo*,2);
2034 c->interfaces[0] = class_java_lang_Cloneable;
2035 c->interfaces[1] = class_java_io_Serializable;
2037 c->methodscount = 1;
2038 c->methods = MNEW (methodinfo, c->methodscount);
2041 memset(clone, 0, sizeof(methodinfo));
2042 clone->flags = ACC_PUBLIC;
2043 clone->name = utf_new_char("clone");
2044 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2046 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2047 clone->monoPoly = MONO;
2049 /* XXX: field: length? */
2051 /* The array class has to be linked */
2052 list_addlast(&unlinkedclasses,c);
2055 * Array classes which are created after the other classes have been
2056 * loaded and linked are linked explicitely.
2061 loader_load(c->name); /* XXX handle errors */
2065 /****************** Function: class_link_array *********************************
2067 This function is called by class_link to create the
2068 arraydescriptor for an array class.
2070 This function returns NULL if the array cannot be linked because
2071 the component type has not been linked yet.
2073 *******************************************************************************/
2075 static arraydescriptor *class_link_array(classinfo *c)
2077 classinfo *comp = NULL;
2078 int namelen = c->name->blength;
2079 arraydescriptor *desc;
2082 /* Check the component type */
2083 switch (c->name->text[1]) {
2085 /* c is an array of arrays. */
2086 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
2087 if (!comp) panic("Could not find component array class.");
2091 /* c is an array of objects. */
2092 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
2093 if (!comp) panic("Could not find component class.");
2097 /* If the component type has not been linked return NULL */
2098 if (comp && !comp->linked)
2101 /* Allocate the arraydescriptor */
2102 desc = NEW(arraydescriptor);
2105 /* c is an array of references */
2106 desc->arraytype = ARRAYTYPE_OBJECT;
2107 desc->componentsize = sizeof(void*);
2108 desc->dataoffset = OFFSET(java_objectarray,data);
2110 compvftbl = comp->vftbl;
2112 panic("Component class has no vftbl");
2113 desc->componentvftbl = compvftbl;
2115 if (compvftbl->arraydesc) {
2116 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2117 if (compvftbl->arraydesc->dimension >= 255)
2118 panic("Creating array of dimension >255");
2119 desc->dimension = compvftbl->arraydesc->dimension + 1;
2120 desc->elementtype = compvftbl->arraydesc->elementtype;
2123 desc->elementvftbl = compvftbl;
2124 desc->dimension = 1;
2125 desc->elementtype = ARRAYTYPE_OBJECT;
2129 /* c is an array of a primitive type */
2130 switch (c->name->text[1]) {
2131 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
2132 desc->dataoffset = OFFSET(java_booleanarray,data);
2133 desc->componentsize = sizeof(u1);
2136 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
2137 desc->dataoffset = OFFSET(java_bytearray,data);
2138 desc->componentsize = sizeof(u1);
2141 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
2142 desc->dataoffset = OFFSET(java_chararray,data);
2143 desc->componentsize = sizeof(u2);
2146 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
2147 desc->dataoffset = OFFSET(java_doublearray,data);
2148 desc->componentsize = sizeof(double);
2151 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
2152 desc->dataoffset = OFFSET(java_floatarray,data);
2153 desc->componentsize = sizeof(float);
2156 case 'I': desc->arraytype = ARRAYTYPE_INT;
2157 desc->dataoffset = OFFSET(java_intarray,data);
2158 desc->componentsize = sizeof(s4);
2161 case 'J': desc->arraytype = ARRAYTYPE_LONG;
2162 desc->dataoffset = OFFSET(java_longarray,data);
2163 desc->componentsize = sizeof(s8);
2166 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
2167 desc->dataoffset = OFFSET(java_shortarray,data);
2168 desc->componentsize = sizeof(s2);
2172 panic("Invalid array class name");
2175 desc->componentvftbl = NULL;
2176 desc->elementvftbl = NULL;
2177 desc->dimension = 1;
2178 desc->elementtype = desc->arraytype;
2185 /********************** Function: class_link ***********************************
2187 Tries to link a class. The super class and every implemented interface must
2188 already have been linked. The function calculates the length in bytes that
2189 an instance of this class requires as well as the VTBL for methods and
2192 If the class can be linked, it is removed from the list 'unlinkedclasses'
2193 and added to 'linkedclasses'. Otherwise, it is moved to the end of
2196 Attention: If cyclical class definitions are encountered, the program gets
2197 into an infinite loop (we'll have to work that out)
2199 *******************************************************************************/
2201 void class_link(classinfo *c)
2203 s4 supervftbllength; /* vftbllegnth of super class */
2204 s4 vftbllength; /* vftbllength of current class */
2205 s4 interfacetablelength; /* interface table length */
2206 classinfo *super = c->super; /* super class */
2207 classinfo *ic, *c2; /* intermediate class variables */
2208 vftbl *v; /* vftbl of current class */
2209 s4 i; /* interface/method/field counter */
2210 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2213 /* check if all superclasses are already linked, if not put c at end of
2214 unlinked list and return. Additionally initialize class fields. */
2216 /* check interfaces */
2218 for (i = 0; i < c->interfacescount; i++) {
2219 ic = c->interfaces[i];
2221 list_remove(&unlinkedclasses, c);
2222 list_addlast(&unlinkedclasses, c);
2225 if ((ic->flags & ACC_INTERFACE) == 0) {
2226 dolog("Specified interface is not declared as interface:");
2230 panic("Specified interface is not declared as interface");
2234 /* check super class */
2236 if (super == NULL) { /* class java.long.Object */
2238 c->classUsed = USED; /* Object class is always used CO-RT*/
2240 c->instancesize = sizeof(java_objectheader);
2242 vftbllength = supervftbllength = 0;
2244 c->finalizer = NULL;
2247 if (!super->linked) {
2248 list_remove(&unlinkedclasses, c);
2249 list_addlast(&unlinkedclasses, c);
2253 if ((super->flags & ACC_INTERFACE) != 0)
2254 panic("Interface specified as super class");
2256 /* handle array classes */
2257 /* The component class must have been linked already. */
2258 if (c->name->text[0] == '[')
2259 if ((arraydesc = class_link_array(c)) == NULL) {
2260 list_remove(&unlinkedclasses, c);
2261 list_addlast(&unlinkedclasses, c);
2265 /* Don't allow extending final classes */
2266 if ((super->flags & ACC_FINAL) != 0)
2267 panic("Trying to extend final class");
2269 if (c->flags & ACC_INTERFACE)
2270 c->index = interfaceindex++;
2272 c->index = super->index + 1;
2274 c->instancesize = super->instancesize;
2276 vftbllength = supervftbllength = super->vftbl->vftbllength;
2278 c->finalizer = super->finalizer;
2283 char logtext[MAXLOGTEXT];
2284 sprintf(logtext, "Linking Class: ");
2285 utf_sprint(logtext + strlen(logtext), c->name );
2289 /* compute vftbl length */
2291 for (i = 0; i < c->methodscount; i++) {
2292 methodinfo *m = &(c->methods[i]);
2294 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2295 classinfo *sc = super;
2298 for (j = 0; j < sc->methodscount; j++) {
2299 if (method_canoverwrite(m, &(sc->methods[j]))) {
2300 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2301 goto notfoundvftblindex;
2302 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2305 log_utf(sc->methods[j].name);
2306 log_utf(sc->methods[j].descriptor);
2307 panic("Trying to overwrite final method");
2309 m->vftblindex = sc->methods[j].vftblindex;
2310 goto foundvftblindex;
2316 m->vftblindex = (vftbllength++);
2322 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2325 /* compute interfacetable length */
2327 interfacetablelength = 0;
2330 for (i = 0; i < c2->interfacescount; i++) {
2331 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2332 if (h > interfacetablelength)
2333 interfacetablelength = h;
2338 /* allocate virtual function table */
2340 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2341 (vftbllength - 1) + sizeof(methodptr*) *
2342 (interfacetablelength - (interfacetablelength > 0)));
2343 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2344 (interfacetablelength > 1));
2345 c->header.vftbl = c->vftbl = v;
2347 v->vftbllength = vftbllength;
2348 v->interfacetablelength = interfacetablelength;
2349 v->arraydesc = arraydesc;
2351 /* store interface index in vftbl */
2352 if (c->flags & ACC_INTERFACE)
2353 v->baseval = -(c->index);
2355 /* copy virtual function table of super class */
2357 for (i = 0; i < supervftbllength; i++)
2358 v->table[i] = super->vftbl->table[i];
2360 /* add method stubs into virtual function table */
2362 for (i = 0; i < c->methodscount; i++) {
2363 methodinfo *m = &(c->methods[i]);
2364 if (!(m->flags & ACC_STATIC)) {
2365 v->table[m->vftblindex] = m->stubroutine;
2369 /* compute instance size and offset of each field */
2371 for (i = 0; i < c->fieldscount; i++) {
2373 fieldinfo *f = &(c->fields[i]);
2375 if (!(f->flags & ACC_STATIC) ) {
2376 dsize = desc_typesize(f->descriptor);
2377 c->instancesize = ALIGN(c->instancesize, dsize);
2378 f->offset = c->instancesize;
2379 c->instancesize += dsize;
2383 /* initialize interfacetable and interfacevftbllength */
2385 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2388 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2391 for (i = 0; i < interfacetablelength; i++) {
2392 v->interfacevftbllength[i] = 0;
2393 v->interfacetable[-i] = NULL;
2396 /* add interfaces */
2398 for (c2 = c; c2 != NULL; c2 = c2->super)
2399 for (i = 0; i < c2->interfacescount; i++) {
2400 class_addinterface(c, c2->interfaces[i]);
2403 /* add finalizer method (not for java.lang.Object) */
2405 if (super != NULL) {
2407 static utf *finame = NULL;
2408 static utf *fidesc = NULL;
2411 finame = utf_finalize;
2413 fidesc = utf_fidesc;
2415 fi = class_findmethod(c, finame, fidesc);
2417 if (!(fi->flags & ACC_STATIC)) {
2427 list_remove(&unlinkedclasses, c);
2428 list_addlast(&linkedclasses, c);
2432 /******************* Function: class_freepool **********************************
2434 Frees all resources used by this classes Constant Pool.
2436 *******************************************************************************/
2438 static void class_freecpool (classinfo *c)
2444 for (idx=0; idx < c->cpcount; idx++) {
2445 tag = c->cptags[idx];
2446 info = c->cpinfos[idx];
2450 case CONSTANT_Fieldref:
2451 case CONSTANT_Methodref:
2452 case CONSTANT_InterfaceMethodref:
2453 FREE (info, constant_FMIref);
2455 case CONSTANT_Integer:
2456 FREE (info, constant_integer);
2458 case CONSTANT_Float:
2459 FREE (info, constant_float);
2462 FREE (info, constant_long);
2464 case CONSTANT_Double:
2465 FREE (info, constant_double);
2467 case CONSTANT_NameAndType:
2468 FREE (info, constant_nameandtype);
2474 MFREE (c -> cptags, u1, c -> cpcount);
2475 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2479 /*********************** Function: class_free **********************************
2481 Frees all resources used by the class.
2483 *******************************************************************************/
2485 static void class_free(classinfo *c)
2492 MFREE(c->interfaces, classinfo*, c->interfacescount);
2494 for (i = 0; i < c->fieldscount; i++)
2495 field_free(&(c->fields[i]));
2497 for (i = 0; i < c->methodscount; i++)
2498 method_free(&(c->methods[i]));
2499 MFREE(c->methods, methodinfo, c->methodscount);
2501 if ((v = c->vftbl) != NULL) {
2503 mem_free(v->arraydesc,sizeof(arraydescriptor));
2505 for (i = 0; i < v->interfacetablelength; i++) {
2506 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2508 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2510 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2511 sizeof(methodptr*) * (v->interfacetablelength -
2512 (v->interfacetablelength > 0));
2513 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2514 (v->interfacetablelength > 1));
2518 if (c->innerclasscount)
2519 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2521 /* if (c->classvftbl)
2522 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2528 /************************* Function: class_findfield ***************************
2530 Searches a 'classinfo' structure for a field having the given name and
2533 *******************************************************************************/
2535 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2539 for (i = 0; i < c->fieldscount; i++) {
2540 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2541 return &(c->fields[i]);
2544 panic("Can not find field given in CONSTANT_Fieldref");
2546 /* keep compiler happy */
2551 /************************* Function: class_findmethod **************************
2553 Searches a 'classinfo' structure for a method having the given name and
2554 type and returns the index in the class info structure.
2555 If type is NULL, it is ignored.
2557 *******************************************************************************/
2559 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2562 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2564 int buffer_len, pos;
2566 #ifdef JOWENN_DEBUG1
2569 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2571 buffer = MNEW(char, buffer_len);
2573 strcpy(buffer, "class_findmethod: method:");
2574 utf_sprint(buffer + strlen(buffer), name);
2575 strcpy(buffer + strlen(buffer), ", desc: ");
2576 utf_sprint(buffer + strlen(buffer), desc);
2577 strcpy(buffer + strlen(buffer), ", classname: ");
2578 utf_sprint(buffer + strlen(buffer), c->name);
2582 MFREE(buffer, char, buffer_len);
2584 for (i = 0; i < c->methodscount; i++) {
2585 #ifdef JOWENN_DEBUG2
2587 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2589 buffer = MNEW(char, buffer_len);
2591 strcpy(buffer, "class_findmethod: comparing to method:");
2592 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2593 strcpy(buffer + strlen(buffer), ", desc: ");
2594 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2598 MFREE(buffer, char, buffer_len);
2602 if ((c->methods[i].name == name) && ((desc == NULL) ||
2603 (c->methods[i].descriptor == desc))) {
2608 #ifdef JOWENN_DEBUG2
2609 class_showconstantpool(c);
2610 log_text("class_findmethod: returning NULL");
2617 /************************* Function: class_findmethod **************************
2619 Searches a 'classinfo' structure for a method having the given name and
2621 If type is NULL, it is ignored.
2623 *******************************************************************************/
2625 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2629 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2631 int buffer_len, pos;
2633 #ifdef JOWENN_DEBUG1
2636 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2638 buffer = MNEW(char, buffer_len);
2640 strcpy(buffer, "class_findmethod: method:");
2641 utf_sprint(buffer + strlen(buffer), name);
2642 strcpy(buffer + strlen(buffer), ", desc: ");
2643 utf_sprint(buffer + strlen(buffer), desc);
2644 strcpy(buffer + strlen(buffer), ", classname: ");
2645 utf_sprint(buffer + strlen(buffer), c->name);
2649 MFREE(buffer, char, buffer_len);
2651 for (i = 0; i < c->methodscount; i++) {
2652 #ifdef JOWENN_DEBUG2
2654 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2656 buffer = MNEW(char, buffer_len);
2658 strcpy(buffer, "class_findmethod: comparing to method:");
2659 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2660 strcpy(buffer + strlen(buffer), ", desc: ");
2661 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2665 MFREE(buffer, char, buffer_len);
2668 if ((c->methods[i].name == name) && ((desc == NULL) ||
2669 (c->methods[i].descriptor == desc))) {
2670 return &(c->methods[i]);
2673 #ifdef JOWENN_DEBUG2
2674 class_showconstantpool(c);
2675 log_text("class_findmethod: returning NULL");
2680 s4 idx=class_findmethodIndex(c, name, desc);
2681 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2682 if (idx == -1) return NULL;
2684 return &(c->methods[idx]);
2688 /*********************** Function: class_fetchmethod **************************
2690 like class_findmethod, but aborts with an error if the method is not found
2692 *******************************************************************************/
2694 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2697 mi = class_findmethod(c, name, desc);
2700 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2701 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2702 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2703 panic("Method not found");
2710 /*********************** Function: class_findmethod_w**************************
2712 like class_findmethod, but logs a warning if the method is not found
2714 *******************************************************************************/
2716 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
2719 mi = class_findmethod(c, name, desc);
2722 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2723 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2724 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2726 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
2727 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
2728 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
2729 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
2730 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
2731 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
2732 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
2733 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
2734 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
2735 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
2736 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
2739 log_plain(" : WARNING: Method not found");log_nl( );
2746 /************************* Function: class_findmethod_approx ******************
2748 like class_findmethod but ignores the return value when comparing the
2751 *******************************************************************************/
2753 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2757 for (i = 0; i < c->methodscount; i++) {
2758 if (c->methods[i].name == name) {
2759 utf *meth_descr = c->methods[i].descriptor;
2763 return &(c->methods[i]);
2765 if (desc->blength <= meth_descr->blength) {
2766 /* current position in utf text */
2767 char *desc_utf_ptr = desc->text;
2768 char *meth_utf_ptr = meth_descr->text;
2769 /* points behind utf strings */
2770 char *desc_end = utf_end(desc);
2771 char *meth_end = utf_end(meth_descr);
2774 /* compare argument types */
2775 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2777 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2778 break; /* no match */
2781 return &(c->methods[i]); /* all parameter types equal */
2791 /***************** Function: class_resolvemethod_approx ***********************
2793 Searches a class and every super class for a method (without paying
2794 attention to the return value)
2796 *******************************************************************************/
2798 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2801 /* search for method (ignore returntype) */
2802 methodinfo *m = class_findmethod_approx(c, name, desc);
2805 /* search superclass */
2813 /************************* Function: class_resolvemethod ***********************
2815 Searches a class and every super class for a method.
2817 *******************************************************************************/
2819 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2822 methodinfo *m = class_findmethod(c, name, desc);
2824 /* search superclass */
2832 /************************* Function: class_issubclass **************************
2834 Checks if sub is a descendant of super.
2836 *******************************************************************************/
2838 bool class_issubclass(classinfo *sub, classinfo *super)
2841 if (!sub) return false;
2842 if (sub == super) return true;
2848 /****************** Initialization function for classes ******************
2850 In Java, every class can have a static initialization function. This
2851 function has to be called BEFORE calling other methods or accessing static
2854 *******************************************************************************/
2856 void class_init(classinfo *c)
2860 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2864 if (!makeinitializations)
2869 c->initialized = true;
2872 count_class_inits++;
2875 /* initialize super class */
2878 char logtext[MAXLOGTEXT];
2879 sprintf(logtext, "Initialize super class ");
2880 utf_sprint(logtext + strlen(logtext), c->super->name);
2881 sprintf(logtext + strlen(logtext), " from ");
2882 utf_sprint(logtext + strlen(logtext), c->name);
2885 class_init(c->super);
2888 /* initialize interface classes */
2889 for (i = 0; i < c->interfacescount; i++) {
2891 char logtext[MAXLOGTEXT];
2892 sprintf(logtext, "Initialize interface class ");
2893 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
2894 sprintf(logtext + strlen(logtext), " from ");
2895 utf_sprint(logtext + strlen(logtext), c->name);
2898 class_init(c->interfaces[i]); /* real */
2901 m = class_findmethod(c, utf_clinit, utf_fidesc);
2904 char logtext[MAXLOGTEXT];
2905 sprintf(logtext, "Class ");
2906 utf_sprint(logtext + strlen(logtext), c->name);
2907 sprintf(logtext + strlen(logtext), " has no initializer");
2910 /* goto callinitialize;*/
2914 if (!(m->flags & ACC_STATIC))
2915 panic("Class initializer is not static!");
2918 char logtext[MAXLOGTEXT];
2919 sprintf(logtext, "Starting initializer for class: ");
2920 utf_sprint(logtext + strlen(logtext), c->name);
2924 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2930 native_stackframeinfo **info=builtin_asm_new_stackframeinfo();
2932 (*info)->returnFromNative=0;
2933 (*info)->addrReturnFromNative=0;
2934 log_text("cl_init");
2935 utf_display(m->class->name);
2936 /* now call the initializer */
2937 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2938 *info=(*info)->prev;
2940 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2941 assert(blockInts == 0);
2945 /* we have to throw an exception */
2946 if (*exceptionptr) {
2947 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2948 printf("Caused by: ");
2949 utf_display((*exceptionptr)->vftbl->class->name);
2956 char logtext[MAXLOGTEXT];
2957 sprintf(logtext, "Finished initializer for class: ");
2958 utf_sprint(logtext + strlen(logtext), c->name);
2962 if (c->name == utf_systemclass) {
2963 /* class java.lang.System requires explicit initialization */
2966 printf("#### Initializing class System");
2968 /* find initializing method */
2969 m = class_findmethod(c,
2970 utf_initsystemclass,
2974 /* no method found */
2975 /* printf("initializeSystemClass failed"); */
2979 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2984 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2986 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
2987 assert(blockInts == 0);
2991 if (*exceptionptr) {
2992 printf("#### initializeSystemClass has thrown: ");
2993 utf_display((*exceptionptr)->vftbl->class->name);
3001 /********* Function: find_class_method_constant *********/
3003 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
3008 for (i=0; i<c->cpcount; i++) {
3010 e = c -> cpinfos [i];
3013 switch (c -> cptags [i]) {
3014 case CONSTANT_Methodref:
3016 constant_FMIref *fmi = e;
3017 if ( (fmi->class->name == c1)
3018 && (fmi->name == m1)
3019 && (fmi->descriptor == d1)) {
3026 case CONSTANT_InterfaceMethodref:
3028 constant_FMIref *fmi = e;
3029 if ( (fmi->class->name == c1)
3030 && (fmi->name == m1)
3031 && (fmi->descriptor == d1)) {
3045 void class_showconstanti(classinfo *c, int ii)
3051 printf ("#%d: ", (int) i);
3053 switch (c->cptags [i]) {
3054 case CONSTANT_Class:
3055 printf("Classreference -> ");
3056 utf_display(((classinfo*)e)->name);
3059 case CONSTANT_Fieldref:
3060 printf("Fieldref -> "); goto displayFMIi;
3061 case CONSTANT_Methodref:
3062 printf("Methodref -> "); goto displayFMIi;
3063 case CONSTANT_InterfaceMethodref:
3064 printf("InterfaceMethod -> "); goto displayFMIi;
3067 constant_FMIref *fmi = e;
3068 utf_display(fmi->class->name);
3070 utf_display(fmi->name);
3072 utf_display(fmi->descriptor);
3076 case CONSTANT_String:
3077 printf("String -> ");
3080 case CONSTANT_Integer:
3081 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3083 case CONSTANT_Float:
3084 printf("Float -> %f", ((constant_float*)e)->value);
3086 case CONSTANT_Double:
3087 printf("Double -> %f", ((constant_double*)e)->value);
3091 u8 v = ((constant_long*)e)->value;
3093 printf("Long -> %ld", (long int) v);
3095 printf("Long -> HI: %ld, LO: %ld\n",
3096 (long int) v.high, (long int) v.low);
3100 case CONSTANT_NameAndType:
3102 constant_nameandtype *cnt = e;
3103 printf("NameAndType: ");
3104 utf_display(cnt->name);
3106 utf_display(cnt->descriptor);
3114 panic("Invalid type of ConstantPool-Entry");
3121 void class_showconstantpool (classinfo *c)
3126 printf ("---- dump of constant pool ----\n");
3128 for (i=0; i<c->cpcount; i++) {
3129 printf ("#%d: ", (int) i);
3131 e = c -> cpinfos [i];
3134 switch (c -> cptags [i]) {
3135 case CONSTANT_Class:
3136 printf ("Classreference -> ");
3137 utf_display ( ((classinfo*)e) -> name );
3140 case CONSTANT_Fieldref:
3141 printf ("Fieldref -> "); goto displayFMI;
3142 case CONSTANT_Methodref:
3143 printf ("Methodref -> "); goto displayFMI;
3144 case CONSTANT_InterfaceMethodref:
3145 printf ("InterfaceMethod -> "); goto displayFMI;
3148 constant_FMIref *fmi = e;
3149 utf_display ( fmi->class->name );
3151 utf_display ( fmi->name);
3153 utf_display ( fmi->descriptor );
3157 case CONSTANT_String:
3158 printf ("String -> ");
3161 case CONSTANT_Integer:
3162 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3164 case CONSTANT_Float:
3165 printf ("Float -> %f", ((constant_float*)e) -> value);
3167 case CONSTANT_Double:
3168 printf ("Double -> %f", ((constant_double*)e) -> value);
3172 u8 v = ((constant_long*)e) -> value;
3174 printf ("Long -> %ld", (long int) v);
3176 printf ("Long -> HI: %ld, LO: %ld\n",
3177 (long int) v.high, (long int) v.low);
3181 case CONSTANT_NameAndType:
3183 constant_nameandtype *cnt = e;
3184 printf ("NameAndType: ");
3185 utf_display (cnt->name);
3187 utf_display (cnt->descriptor);
3191 printf ("Utf8 -> ");
3195 panic ("Invalid type of ConstantPool-Entry");
3205 /********** Function: class_showmethods (debugging only) *************/
3207 void class_showmethods (classinfo *c)
3211 printf ("--------- Fields and Methods ----------------\n");
3212 printf ("Flags: "); printflags (c->flags); printf ("\n");
3214 printf ("This: "); utf_display (c->name); printf ("\n");
3216 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3218 printf ("Index: %d\n", c->index);
3220 printf ("interfaces:\n");
3221 for (i=0; i < c-> interfacescount; i++) {
3223 utf_display (c -> interfaces[i] -> name);
3224 printf (" (%d)\n", c->interfaces[i] -> index);
3227 printf ("fields:\n");
3228 for (i=0; i < c -> fieldscount; i++) {
3229 field_display (&(c -> fields[i]));
3232 printf ("methods:\n");
3233 for (i=0; i < c -> methodscount; i++) {
3234 methodinfo *m = &(c->methods[i]);
3235 if ( !(m->flags & ACC_STATIC))
3236 printf ("vftblindex: %d ", m->vftblindex);
3238 method_display ( m );
3242 printf ("Virtual function table:\n");
3243 for (i=0; i<c->vftbl->vftbllength; i++) {
3244 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3251 /******************************************************************************/
3252 /******************* General functions for the class loader *******************/
3253 /******************************************************************************/
3255 /********************* Function: loader_load ***********************************
3257 Loads and links the class desired class and each class and interface
3259 Returns: a pointer to this class
3261 *******************************************************************************/
3263 static int loader_load_running = 0;
3265 classinfo *loader_load(utf *topname)
3271 classinfo *notlinkable;
3273 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3274 pthread_mutex_lock(&compiler_mutex);
3277 /* avoid recursive calls */
3278 if (loader_load_running)
3279 return class_new(topname);
3281 loader_load_running++;
3283 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3288 starttime = getcputime();
3290 top = class_new(topname);
3293 while ((c = list_first(&unloadedclasses))) {
3294 if (!class_load(c)) {
3296 dolog("Failed to load class");
3297 list_remove(&unloadedclasses, c);
3304 dolog("Linking...");
3306 /* Added a hack to break infinite linking loops. A better
3307 * linking algorithm would be nice. -Edwin */
3309 while ((c = list_first(&unlinkedclasses))) {
3314 else if (notlinkable == c) {
3315 /* We tried to link this class for the second time and
3316 * no other classes were linked in between, so we are
3320 dolog("Cannot resolve linking dependencies");
3323 throw_linkageerror_message(c->name);
3331 dolog("Linking done.");
3334 loader_compute_subclasses();
3337 if (getloadingtime) {
3338 stoptime = getcputime();
3339 loadingtime += (stoptime - starttime);
3343 loader_load_running--;
3345 /* check if a former loader_load call tried to load/link the class and
3346 failed. This is needed because the class didn't appear in the
3347 undloadclasses or unlinkedclasses list during this class. */
3350 if (linkverbose) dolog("Failed to load class (former call)");
3351 throw_noclassdeffounderror_message(top->name);
3354 } else if (!top->linked) {
3356 dolog("Failed to link class (former call)");
3357 throw_linkageerror_message(top->name);
3362 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3366 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3367 pthread_mutex_unlock(&compiler_mutex);
3370 /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3376 /****************** Function: loader_load_sysclass ****************************
3378 Loads and links the class desired class and each class and interface
3381 The pointer to the classinfo is stored in *top if top != NULL.
3382 The pointer is also returned.
3384 If the class could not be loaded the function aborts with an error.
3386 *******************************************************************************/
3388 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3392 if ((cls = loader_load(topname)) == NULL) {
3393 log_plain("Could not load important system class: ");
3394 log_plain_utf(topname);
3396 panic("Could not load important system class");
3399 if (top) *top = cls;
3405 /**************** function: create_primitive_classes ***************************
3407 create classes representing primitive types
3409 ********************************************************************************/
3412 void create_primitive_classes()
3416 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3417 /* create primitive class */
3418 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3419 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3420 c -> impldBy = NULL;
3422 /* prevent loader from loading primitive class */
3423 list_remove (&unloadedclasses, c);
3425 /* add to unlinked classes */
3426 list_addlast (&unlinkedclasses, c);
3427 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3430 primitivetype_table[i].class_primitive = c;
3432 /* create class for wrapping the primitive type */
3433 primitivetype_table[i].class_wrap =
3434 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3435 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3436 primitivetype_table[i].class_wrap -> impldBy = NULL;
3438 /* create the primitive array class */
3439 if (primitivetype_table[i].arrayname) {
3440 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3441 primitivetype_table[i].arrayclass = c;
3443 if (!c->linked) class_link(c);
3444 primitivetype_table[i].arrayvftbl = c->vftbl;
3449 /**************** function: class_primitive_from_sig ***************************
3451 return the primitive class indicated by the given signature character
3453 If the descriptor does not indicate a valid primitive type the
3454 return value is NULL.
3456 ********************************************************************************/
3458 classinfo *class_primitive_from_sig(char sig)
3461 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3462 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3463 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3464 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3465 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3466 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3467 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3468 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3469 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3474 /****************** function: class_from_descriptor ****************************
3476 return the class indicated by the given descriptor
3478 utf_ptr....first character of descriptor
3479 end_ptr....first character after the end of the string
3480 next.......if non-NULL, *next is set to the first character after
3481 the descriptor. (Undefined if an error occurs.)
3483 mode.......a combination (binary or) of the following flags:
3485 (Flags marked with * are the default settings.)
3487 What to do if a reference type descriptor is parsed successfully:
3489 CLASSLOAD_SKIP...skip it and return something != NULL
3490 * CLASSLOAD_NEW....get classinfo * via class_new
3491 CLASSLOAD_LOAD...get classinfo * via loader_load
3493 How to handle primitive types:
3495 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3496 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3498 How to handle "V" descriptors:
3500 * CLASSLOAD_VOID.....handle it like other primitive types
3501 CLASSLOAD_NOVOID...treat it as an error
3503 How to deal with extra characters after the end of the
3506 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3507 CLASSLOAD_CHECKEND.....treat them as an error
3509 How to deal with errors:
3511 * CLASSLOAD_PANIC....abort execution with an error message
3512 CLASSLOAD_NOPANIC..return NULL on error
3514 ********************************************************************************/
3516 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3517 char **next, int mode)
3519 char *start = utf_ptr;
3523 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3525 if (mode & CLASSLOAD_CHECKEND)
3526 error |= (utf_ptr != end_ptr);
3529 if (next) *next = utf_ptr;
3533 if (mode & CLASSLOAD_NOVOID)
3544 return (mode & CLASSLOAD_NULLPRIMITIVE)
3546 : class_primitive_from_sig(*start);
3553 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3554 name = utf_new(start,utf_ptr-start);
3555 return (mode & CLASSLOAD_LOAD)
3556 ? loader_load(name) : class_new(name); /* XXX handle errors */
3560 /* An error occurred */
3561 if (mode & CLASSLOAD_NOPANIC)
3564 log_plain("Invalid descriptor at beginning of '");
3565 log_plain_utf(utf_new(start, end_ptr-start));
3569 panic("Invalid descriptor");
3571 /* keep compiler happy */
3576 /******************* function: type_from_descriptor ****************************
3578 return the basic type indicated by the given descriptor
3580 This function parses a descriptor and returns its basic type as
3581 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3583 cls...if non-NULL the referenced variable is set to the classinfo *
3584 returned by class_from_descriptor.
3586 For documentation of the arguments utf_ptr, end_ptr, next and mode
3587 see class_from_descriptor. The only difference is that
3588 type_from_descriptor always uses CLASSLOAD_PANIC.
3590 ********************************************************************************/
3592 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3593 char **next, int mode)
3596 if (!cls) cls = &mycls;
3597 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3614 return TYPE_ADDRESS;
3619 /*************** function: create_system_exception_classes *******************************
3621 create system exception classes needed by default
3623 ********************************************************************************/
3625 static void create_system_exception_classes()
3628 if (verbose) log_text("loader_init: create_system_exception_classs: loader_load: java/lang/ClassCastException");
3629 loader_load_sysclass(&class_java_lang_ClassCastException,
3630 utf_new_char ("java/lang/ClassCastException"));
3631 loader_load_sysclass(&class_java_lang_NullPointerException,
3632 utf_new_char ("java/lang/NullPointerException"));
3633 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3634 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3635 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3636 utf_new_char ("java/lang/NegativeArraySizeException"));
3637 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3638 utf_new_char ("java/lang/OutOfMemoryError"));
3639 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3640 utf_new_char ("java/lang/ArrayStoreException"));
3641 loader_load_sysclass(&class_java_lang_ArithmeticException,
3642 utf_new_char ("java/lang/ArithmeticException"));
3643 loader_load_sysclass(&class_java_lang_ThreadDeath,
3644 utf_new_char ("java/lang/ThreadDeath"));
3650 /*************** function: create_system_exception_classes *******************************
3652 create system exception proto classes needed by default
3654 ********************************************************************************/
3656 static void create_system_exception_proto_classes()
3659 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3660 proto_java_lang_ClassCastException =
3661 builtin_new(class_java_lang_ClassCastException);
3663 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3665 proto_java_lang_NullPointerException =
3666 builtin_new(class_java_lang_NullPointerException);
3667 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3669 proto_java_lang_ArrayIndexOutOfBoundsException =
3670 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3672 proto_java_lang_NegativeArraySizeException =
3673 builtin_new(class_java_lang_NegativeArraySizeException);
3675 proto_java_lang_OutOfMemoryError =
3676 builtin_new(class_java_lang_OutOfMemoryError);
3678 proto_java_lang_ArithmeticException =
3679 builtin_new(class_java_lang_ArithmeticException);
3681 proto_java_lang_ArrayStoreException =
3682 builtin_new(class_java_lang_ArrayStoreException);
3684 proto_java_lang_ThreadDeath =
3685 builtin_new(class_java_lang_ThreadDeath);
3692 /*************** function: create_pseudo_classes *******************************
3694 create pseudo classes used by the typechecker
3696 ********************************************************************************/
3698 static void create_pseudo_classes()
3700 /* pseudo class for Arraystubs (extends java.lang.Object) */
3702 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3703 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3705 pseudo_class_Arraystub->super = class_java_lang_Object;
3706 pseudo_class_Arraystub->interfacescount = 2;
3707 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3708 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3709 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3711 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3712 class_link(pseudo_class_Arraystub);
3714 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3716 /* pseudo class representing the null type */
3718 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3719 list_remove(&unloadedclasses, pseudo_class_Null);
3721 pseudo_class_Null->super = class_java_lang_Object;
3723 list_addlast(&unlinkedclasses, pseudo_class_Null);
3724 class_link(pseudo_class_Null);
3726 /* pseudo class representing new uninitialized objects */
3728 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3729 list_remove(&unloadedclasses, pseudo_class_New);
3731 pseudo_class_New->super = class_java_lang_Object;
3733 list_addlast(&unlinkedclasses, pseudo_class_New);
3734 class_link(pseudo_class_New);
3738 /********************** Function: loader_init **********************************
3740 Initializes all lists and loads all classes required for the system or the
3743 *******************************************************************************/
3745 void loader_init(u1 *stackbottom)
3749 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3750 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3751 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3753 /* create utf-symbols for pointer comparison of frequently used strings */
3754 utf_innerclasses = utf_new_char("InnerClasses");
3755 utf_constantvalue = utf_new_char("ConstantValue");
3756 utf_code = utf_new_char("Code");
3757 utf_exceptions = utf_new_char("Exceptions");
3758 utf_finalize = utf_new_char("finalize");
3759 utf_fidesc = utf_new_char("()V");
3760 utf_init = utf_new_char("<init>");
3761 utf_clinit = utf_new_char("<clinit>");
3762 utf_initsystemclass = utf_new_char("initializeSystemClass");
3763 utf_systemclass = utf_new_char("java/lang/System");
3764 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3765 utf_initialize = utf_new_char("initialize");
3766 utf_initializedesc = utf_new_char("(I)V");
3768 utf_vmclass = utf_new_char("java/lang/VMClass");
3769 utf_java_lang_Object= utf_new_char("java/lang/Object");
3771 array_packagename = utf_new_char("<the array package>");
3773 /* create some important classes */
3774 /* These classes have to be created now because the classinfo
3775 * pointers are used in the loading code.
3777 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3778 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3779 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3780 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3782 if (verbose) log_text("loader_init: java/lang/Object");
3783 /* load the classes which were created above */
3784 loader_load_sysclass(NULL, class_java_lang_Object->name);
3786 loader_inited = 1; /*JOWENN*/
3788 loader_load_sysclass(&class_java_lang_Throwable,
3789 utf_new_char("java/lang/Throwable"));
3791 create_system_exception_classes();
3793 /* create classes representing primitive types */
3794 create_primitive_classes();
3796 /* create classes used by the typechecker */
3797 create_pseudo_classes();
3799 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3800 stringtable_update();
3802 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3806 create_system_exception_proto_classes();
3812 /********************* Function: loader_initclasses ****************************
3814 Initializes all loaded but uninitialized classes
3816 *******************************************************************************/
3819 /* XXX TWISTI: i think we do not need this */
3820 void loader_initclasses ()
3824 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3825 pthread_mutex_lock(&compiler_mutex);
3828 intsDisable(); /* schani */
3830 if (makeinitializations) {
3831 c = list_first(&linkedclasses);
3834 c = list_next(&linkedclasses, c);
3838 intsRestore(); /* schani */
3840 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3841 pthread_mutex_unlock(&compiler_mutex);
3847 static void loader_compute_class_values(classinfo *c)
3851 c->vftbl->baseval = ++classvalue;
3854 while (subs != NULL) {
3855 loader_compute_class_values(subs);
3856 subs = subs->nextsub;
3858 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3863 for (i = 0; i < c->index; i++)
3865 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3866 utf_display(c->name);
3873 void loader_compute_subclasses()
3877 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3878 intsDisable(); /* schani */
3881 c = list_first(&linkedclasses);
3883 if (!(c->flags & ACC_INTERFACE)) {
3887 c = list_next(&linkedclasses, c);
3890 c = list_first(&linkedclasses);
3892 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3893 c->nextsub = c->super->sub;
3896 c = list_next(&linkedclasses, c);
3900 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3903 loader_compute_class_values(class_java_lang_Object);
3904 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3908 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3909 intsRestore(); /* schani */
3914 /******************** function classloader_buffer ******************************
3916 sets buffer for reading classdata
3918 *******************************************************************************/
3920 void classload_buffer(u1 *buf, int len)
3923 classbuffer_size = len;
3924 classbuf_pos = buf - 1;
3928 /******************** Function: loader_close ***********************************
3932 *******************************************************************************/
3938 while ((c = list_first(&unloadedclasses))) {
3939 list_remove(&unloadedclasses, c);
3942 while ((c = list_first(&unlinkedclasses))) {
3943 list_remove(&unlinkedclasses, c);
3946 while ((c = list_first(&linkedclasses))) {
3947 list_remove(&linkedclasses, c);
3954 * These are local overrides for various environment variables in Emacs.
3955 * Please do not remove this and leave it at the end of the file, where
3956 * Emacs will automagically detect them.
3957 * ---------------------------------------------------------------------
3960 * indent-tabs-mode: t