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 991 2004-03-29 11:22:34Z stefan $
50 #include "toolbox/memory.h"
51 #include "toolbox/loging.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
54 #include "nat/java_lang_Throwable.h"
64 /* global variables ***********************************************************/
66 int count_class_infos = 0; /* variables for measurements */
67 int count_const_pool_len = 0;
68 int count_vftbl_len = 0;
69 int count_all_methods = 0;
70 int count_vmcode_len = 0;
71 int count_extable_len = 0;
72 int count_class_loads = 0;
73 int count_class_inits = 0;
75 static s4 interfaceindex; /* sequential numbering of interfaces */
78 list unloadedclasses; /* list of all referenced but not loaded classes */
79 list unlinkedclasses; /* list of all loaded but not linked classes */
80 list linkedclasses; /* list of all completely linked classes */
83 /* utf-symbols for pointer comparison of frequently used strings */
85 static utf *utf_innerclasses; /* InnerClasses */
86 static utf *utf_constantvalue; /* ConstantValue */
87 static utf *utf_code; /* Code */
88 static utf *utf_exceptions; /* Exceptions */
89 static utf *utf_linenumbertable; /* LineNumberTable */
90 static utf *utf_sourcefile; /*SourceFile*/
91 static utf *utf_finalize; /* finalize */
92 static utf *utf_fidesc; /* ()V changed */
93 static utf *utf_init; /* <init> */
94 static utf *utf_clinit; /* <clinit> */
95 static utf *utf_initsystemclass; /* initializeSystemClass */
96 static utf *utf_systemclass; /* java/lang/System */
97 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
98 static utf *utf_vmclass; /* java/lang/VMClassLoader */
99 static utf *utf_initialize;
100 static utf *utf_initializedesc;
101 static utf *utf_java_lang_Object; /* java/lang/Object */
114 /* important system classes ***************************************************/
116 classinfo *class_java_lang_Object;
117 classinfo *class_java_lang_String;
119 classinfo *class_java_lang_Throwable;
120 classinfo *class_java_lang_Cloneable;
121 classinfo *class_java_io_Serializable;
123 /* Pseudo classes for the typechecker */
124 classinfo *pseudo_class_Arraystub = NULL;
125 classinfo *pseudo_class_Null = NULL;
126 classinfo *pseudo_class_New = NULL;
127 vftbl *pseudo_class_Arraystub_vftbl = NULL;
130 /* These are made static so they cannot be used for throwing in native */
132 static classinfo *class_java_lang_ClassCastException;
133 static classinfo *class_java_lang_NullPointerException;
134 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
135 static classinfo *class_java_lang_NegativeArraySizeException;
136 static classinfo *class_java_lang_OutOfMemoryError;
137 static classinfo *class_java_lang_ArithmeticException;
138 static classinfo *class_java_lang_ArrayStoreException;
139 static classinfo *class_java_lang_ThreadDeath;
141 utf *array_packagename = NULL;
143 static int loader_inited = 0;
146 /********************************************************************
147 list of classpath entries (either filesystem directories or
149 ********************************************************************/
150 static classpath_info *classpath_entries=0;
153 /******************************************************************************
155 structure for primitive classes: contains the class for wrapping the
156 primitive type, the primitive class, the name of the class for wrapping,
157 the one character type signature and the name of the primitive class
159 ******************************************************************************/
161 /* CAUTION: Don't change the order of the types. This table is indexed
162 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
164 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
165 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
166 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
167 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
168 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
169 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
170 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
171 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
172 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
173 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
177 /* instances of important system classes **************************************/
179 java_objectheader *proto_java_lang_ClassCastException;
180 java_objectheader *proto_java_lang_NullPointerException;
181 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
182 java_objectheader *proto_java_lang_NegativeArraySizeException;
183 java_objectheader *proto_java_lang_OutOfMemoryError;
184 java_objectheader *proto_java_lang_ArithmeticException;
185 java_objectheader *proto_java_lang_ArrayStoreException;
186 java_objectheader *proto_java_lang_ThreadDeath;
188 /************* functions for reading classdata *********************************
190 getting classdata in blocks of variable size
191 (8,16,32,64-bit integer or float)
193 *******************************************************************************/
195 static char *classpath = ""; /* searchpath for classfiles */
196 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
197 static u1 *classbuf_pos; /* current position in classfile buffer */
198 static int classbuffer_size; /* size of classfile-data */
200 /* assert that at least <len> bytes are left to read */
201 /* <len> is limited to the range of non-negative s4 values */
202 #define ASSERT_LEFT(len) \
203 do {if ( ((s4)(len)) < 0 \
204 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
205 panic("Unexpected end of classfile"); } while(0)
207 /* transfer block of classfile data into a buffer */
209 #define suck_nbytes(buffer,len) \
210 do {ASSERT_LEFT(len); \
211 memcpy(buffer,classbuf_pos+1,len); \
212 classbuf_pos+=len;} while (0)
214 /* skip block of classfile data */
216 #define skip_nbytes(len) \
217 do {ASSERT_LEFT(len); \
218 classbuf_pos+=len;} while(0)
224 return *++classbuf_pos;
232 return ((u2) a << 8) + (u2) b;
242 return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
245 #define suck_s8() (s8) suck_u8()
246 #define suck_s2() (s2) suck_u2()
247 #define suck_s4() (s4) suck_u4()
248 #define suck_s1() (s1) suck_u1()
251 /* get u8 from classfile data */
258 return (hi << 32) + lo;
268 /* get float from classfile data */
269 static float suck_float()
276 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
277 memcpy((u1*) (&f), buffer, 4);
279 suck_nbytes((u1*) (&f), 4);
282 PANICIF (sizeof(float) != 4, "Incompatible float-format");
288 /* get double from classfile data */
289 static double suck_double()
296 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
297 memcpy((u1*) (&d), buffer, 8);
299 suck_nbytes((u1*) (&d), 8);
302 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
308 /************************** function suck_init *********************************
310 called once at startup, sets the searchpath for the classfiles
312 *******************************************************************************/
314 void suck_init(char *cpath)
321 union classpath_info *tmp;
322 union classpath_info *insertAfter=0;
327 if (classpath_entries) panic("suck_init should be called only once");
328 for(start=classpath;(*start)!='\0';) {
329 for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
332 filenamelen=(end-start);
366 ( ( (*(end - 1)) == 'p') || ( (*(end - 1)) == 'P')) &&
367 (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
368 (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z')))
371 } else if ( (( (*(end - 1)) == 'r') || ( (*(end - 1)) == 'R')) &&
372 ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
373 (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
378 if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init");
380 filename=(char*)malloc(CLASSPATH_MAXFILENAME);
381 strncpy(filename,start,filenamelen);
382 filename[filenamelen+1]='\0';
387 unzFile uf=unzOpen(filename);
389 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
390 tmp->archive.type=CLASSPATH_ARCHIVE;
396 panic("Zip/JAR not supported");
400 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
401 tmp->filepath.type=CLASSPATH_PATH;
402 tmp->filepath.next=0;
403 if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
404 filename[filenamelen]='/';
405 filename[filenamelen+1]='\0';
409 tmp->filepath.filename=filename;
410 tmp->filepath.pathlen=filenamelen;
416 insertAfter->filepath.next=tmp;
418 classpath_entries=tmp;
423 if ((*end)==':') start=end+1; else start=end;
426 if (filename!=0) free(filename);
431 /************************** function suck_start ********************************
433 returns true if classbuffer is already loaded or a file for the
434 specified class has succussfully been read in. All directories of
435 the searchpath are used to find the classfile (<classname>.class).
436 Returns false if no classfile is found and writes an error message.
438 *******************************************************************************/
440 bool suck_start(utf *classname)
442 classpath_info *currPos;
445 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
451 if (classbuffer) return true; /* classbuffer is already valid */
453 utf_ptr = classname->text;
454 while (utf_ptr < utf_end(classname)) {
455 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
457 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
459 filename[filenamelen++] = c;
461 strcpy(filename + filenamelen, ".class");
463 for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
465 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
466 if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
467 unz_file_info file_info;
468 /*log_text("Class found in zip file");*/
469 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
470 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
471 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
472 classbuffer_size = file_info.uncompressed_size;
473 classbuffer = MNEW(u1, classbuffer_size);
474 classbuf_pos = classbuffer - 1;
475 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
476 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
477 unzCloseCurrentFile(currPos->archive.uf);
480 MFREE(classbuffer, u1, classbuffer_size);
481 log_text("Error while unzipping");
483 } else log_text("Error while opening file in archive");
484 } else log_text("Error while retrieving fileinfo");
486 unzCloseCurrentFile(currPos->archive.uf);
490 if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
491 strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
492 classfile = fopen(currPos->filepath.filename, "r");
493 if (classfile) { /* file exists */
495 /* determine size of classfile */
497 /* dolog("File: %s",filename); */
499 err = stat(currPos->filepath.filename, &buffer);
501 if (!err) { /* read classfile data */
502 classbuffer_size = buffer.st_size;
503 classbuffer = MNEW(u1, classbuffer_size);
504 classbuf_pos = classbuffer - 1;
505 fread(classbuffer, 1, classbuffer_size, classfile);
516 dolog("Warning: Can not open class file '%s'", filename);
523 /************************** function suck_stop *********************************
525 frees memory for buffer with classfile data.
526 Caution: this function may only be called if buffer has been allocated
527 by suck_start with reading a file
529 *******************************************************************************/
533 /* determine amount of classdata not retrieved by suck-operations */
535 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
537 if (classdata_left > 0) {
539 dolog("There are %d extra bytes at end of classfile",
541 /* The JVM spec disallows extra bytes. */
542 panic("Extra bytes at end of classfile");
547 MFREE(classbuffer, u1, classbuffer_size);
552 /******************************************************************************/
553 /******************* Some support functions ***********************************/
554 /******************************************************************************/
556 void fprintflags (FILE *fp, u2 f)
558 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
559 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
560 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
561 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
562 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
563 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
564 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
565 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
566 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
567 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
568 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
572 /********** internal function: printflags (only for debugging) ***************/
574 void printflags(u2 f)
576 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
577 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
578 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
579 if ( f & ACC_STATIC ) printf (" STATIC");
580 if ( f & ACC_FINAL ) printf (" FINAL");
581 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
582 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
583 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
584 if ( f & ACC_NATIVE ) printf (" NATIVE");
585 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
586 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
590 /************************* Function: skipattribute *****************************
592 skips a (1) 'attribute' structure in the class file
594 *******************************************************************************/
596 static void skipattribute()
605 /********************** Function: skipattributebody ****************************
607 skips an attribute after the 16 bit reference to attribute_name has already
610 *******************************************************************************/
612 static void skipattributebody()
620 /************************* Function: skipattributes ****************************
622 skips num attribute structures
624 *******************************************************************************/
626 static void skipattributes(u4 num)
629 for (i = 0; i < num; i++)
634 /******************** function: innerclass_getconstant ************************
636 like class_getconstant, but if cptags is ZERO null is returned
638 *******************************************************************************/
640 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
642 /* invalid position in constantpool */
643 if (pos >= c->cpcount)
644 panic("Attempt to access constant outside range");
646 /* constantpool entry of type 0 */
650 /* check type of constantpool entry */
651 if (c->cptags[pos] != ctype) {
652 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
653 (int) ctype, (int) c->cptags[pos] );
656 return c->cpinfos[pos];
660 /************************ function: attribute_load ****************************
662 read attributes from classfile
664 *******************************************************************************/
666 static void attribute_load(u4 num, classinfo *c)
670 for (i = 0; i < num; i++) {
671 /* retrieve attribute name */
672 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
674 if (aname == utf_innerclasses) {
675 /* innerclasses attribute */
677 if (c->innerclass != NULL)
678 panic("Class has more than one InnerClasses attribute");
680 /* skip attribute length */
682 /* number of records */
683 c->innerclasscount = suck_u2();
684 /* allocate memory for innerclass structure */
685 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
687 for (j = 0; j < c->innerclasscount; j++) {
688 /* The innerclass structure contains a class with an encoded name,
689 its defining scope, its simple name and a bitmask of the access flags.
690 If an inner class is not a member, its outer_class is NULL,
691 if a class is anonymous, its name is NULL. */
693 innerclassinfo *info = c->innerclass + j;
695 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
696 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
697 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
698 info->flags = suck_u2(); /* access_flags bitmask */
700 } else if (aname==utf_sourcefile) {
702 /*log_text("source file attribute found");*/
703 c->sourcefile = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
705 /* unknown attribute */
712 /******************* function: checkfielddescriptor ****************************
714 checks whether a field-descriptor is valid and aborts otherwise
715 all referenced classes are inserted into the list of unloaded classes
717 *******************************************************************************/
719 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
721 class_from_descriptor(utf_ptr,end_pos,NULL,
723 | CLASSLOAD_NULLPRIMITIVE
725 | CLASSLOAD_CHECKEND);
727 /* XXX use the following if -noverify */
729 char *tstart; /* pointer to start of classname */
731 char *start = utf_ptr;
733 switch (*utf_ptr++) {
747 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
748 panic ("Ill formed descriptor");
752 panic ("Ill formed descriptor");
755 /* exceeding characters */
756 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
761 /******************* function checkmethoddescriptor ****************************
763 checks whether a method-descriptor is valid and aborts otherwise.
764 All referenced classes are inserted into the list of unloaded classes.
766 The number of arguments is returned. A long or double argument is counted
769 *******************************************************************************/
771 static int checkmethoddescriptor (utf *d)
773 char *utf_ptr = d->text; /* current position in utf text */
774 char *end_pos = utf_end(d); /* points behind utf string */
775 int argcount = 0; /* number of arguments */
777 /* method descriptor must start with parenthesis */
778 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
780 /* check arguments */
781 while (utf_ptr != end_pos && *utf_ptr != ')') {
782 /* We cannot count the this argument here because
783 * we don't know if the method is static. */
784 if (*utf_ptr == 'J' || *utf_ptr == 'D')
788 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
790 | CLASSLOAD_NULLPRIMITIVE
794 if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
795 utf_ptr++; /* skip ')' */
797 class_from_descriptor(utf_ptr,end_pos,NULL,
799 | CLASSLOAD_NULLPRIMITIVE
800 | CLASSLOAD_CHECKEND);
803 panic("Invalid method descriptor: too many arguments");
807 /* XXX use the following if -noverify */
809 /* check arguments */
810 while ((c = *utf_ptr++) != ')') {
827 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
828 panic ("Ill formed method descriptor");
832 panic ("Ill formed methodtype-descriptor");
836 /* check returntype */
838 /* returntype void */
839 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
842 /* treat as field-descriptor */
843 checkfielddescriptor (utf_ptr,end_pos);
848 /***************** Function: print_arraydescriptor ****************************
850 Debugging helper for displaying an arraydescriptor
852 *******************************************************************************/
854 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
857 fprintf(file, "<NULL>");
862 if (desc->componentvftbl) {
863 if (desc->componentvftbl->class)
864 utf_fprint(file, desc->componentvftbl->class->name);
866 fprintf(file, "<no classinfo>");
872 if (desc->elementvftbl) {
873 if (desc->elementvftbl->class)
874 utf_fprint(file, desc->elementvftbl->class->name);
876 fprintf(file, "<no classinfo>");
880 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
881 desc->dataoffset, desc->componentsize);
885 /******************************************************************************/
886 /************************** Functions for fields ****************************/
887 /******************************************************************************/
890 /************************ Function: field_load *********************************
892 Load everything about a class field from the class file and fill a
893 'fieldinfo' structure. For static fields, space in the data segment is
896 *******************************************************************************/
898 #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
900 static void field_load(fieldinfo *f, classinfo *c)
904 u4 pindex = field_load_NOVALUE; /* constantvalue_index */
906 f->flags = suck_u2(); /* ACC flags */
907 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
908 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
912 if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
913 panic("Field with invalid name");
915 /* check flag consistency */
916 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
917 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
918 panic("Field has invalid access flags");
919 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
920 panic("Field is declared final and volatile");
921 if ((c->flags & ACC_INTERFACE) != 0) {
922 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
923 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
924 panic("Interface field is not declared static final public");
925 if ((f->flags & ACC_TRANSIENT) != 0)
926 panic("Interface field declared transient");
929 /* check descriptor */
930 checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
933 f->type = jtype = desc_to_type(f->descriptor); /* data type */
934 f->offset = 0; /* offset from start of object */
939 case TYPE_INT: f->value.i = 0; break;
940 case TYPE_FLOAT: f->value.f = 0.0; break;
941 case TYPE_DOUBLE: f->value.d = 0.0; break;
942 case TYPE_ADDRESS: f->value.a = NULL; break;
945 f->value.l = 0; break;
947 f->value.l.low = 0; f->value.l.high = 0; break;
951 /* read attributes */
953 for (i = 0; i < attrnum; i++) {
956 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
958 if (aname != utf_constantvalue) {
959 /* unknown attribute */
963 /* constant value attribute */
965 if (pindex != field_load_NOVALUE)
966 panic("Field has more than one ConstantValue attribute");
968 /* check attribute length */
970 panic("ConstantValue attribute has invalid length");
972 /* index of value in constantpool */
975 /* initialize field with value from constantpool */
978 constant_integer *ci =
979 class_getconstant(c, pindex, CONSTANT_Integer);
980 f->value.i = ci->value;
986 class_getconstant(c, pindex, CONSTANT_Long);
987 f->value.l = cl->value;
993 class_getconstant(c, pindex, CONSTANT_Float);
994 f->value.f = cf->value;
999 constant_double *cd =
1000 class_getconstant(c, pindex, CONSTANT_Double);
1001 f->value.d = cd->value;
1005 case TYPE_ADDRESS: {
1006 utf *u = class_getconstant(c, pindex, CONSTANT_String);
1007 /* create javastring from compressed utf8-string */
1008 f->value.a = literalstring_new(u);
1013 log_text ("Invalid Constant - Type");
1020 /********************** function: field_free **********************************/
1022 static void field_free (fieldinfo *f)
1028 /**************** Function: field_display (debugging only) ********************/
1030 void field_display(fieldinfo *f)
1033 printflags(f->flags);
1035 utf_display(f->name);
1037 utf_display(f->descriptor);
1038 printf(" offset: %ld\n", (long int) (f->offset));
1042 /******************************************************************************/
1043 /************************* Functions for methods ******************************/
1044 /******************************************************************************/
1047 /*********************** Function: method_load *********************************
1049 Loads a method from the class file and fills an existing 'methodinfo'
1050 structure. For native methods, the function pointer field is set to the
1051 real function pointer, for JavaVM methods a pointer to the compiler is used
1054 *******************************************************************************/
1056 static void method_load(methodinfo *m, classinfo *c)
1062 count_all_methods++;
1064 m->thrownexceptionscount=0;
1065 m->linenumbercount=0;
1069 m->flags = suck_u2();
1070 m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1073 if (!is_valid_name_utf(m->name))
1074 panic("Method with invalid name");
1075 if (m->name->text[0] == '<'
1076 && m->name != utf_init && m->name != utf_clinit)
1077 panic("Method with invalid special name");
1080 m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1081 argcount = checkmethoddescriptor(m->descriptor);
1082 if ((m->flags & ACC_STATIC) == 0)
1083 argcount++; /* count the 'this' argument */
1087 panic("Method has more than 255 arguments");
1089 /* check flag consistency */
1090 if (m->name != utf_clinit) {
1091 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1092 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1093 panic("Method has invalid access flags");
1094 if ((m->flags & ACC_ABSTRACT) != 0) {
1095 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1096 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1097 panic("Abstract method has invalid flags set");
1099 if ((c->flags & ACC_INTERFACE) != 0) {
1100 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1101 != (ACC_ABSTRACT | ACC_PUBLIC))
1102 panic("Interface method is not declared abstract and public");
1104 if (m->name == utf_init) {
1105 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1106 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1107 panic("Instance initialization method has invalid flags set");
1113 m->exceptiontable = NULL;
1114 m->entrypoint = NULL;
1116 m->stubroutine = NULL;
1117 m->methodUsed = NOTUSED;
1120 m->subRedefsUsed = 0;
1124 if (!(m->flags & ACC_NATIVE)) {
1125 m->stubroutine = createcompilerstub(m);
1128 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1129 (m->flags & ACC_STATIC) != 0);
1131 m->stubroutine = createnativestub(f, m);
1136 attrnum = suck_u2();
1137 for (i = 0; i < attrnum; i++) {
1140 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1142 if (aname != utf_code) {
1143 if (aname == utf_exceptions) {
1146 suck_u4(); /*length*/
1147 exceptionCount=suck_u2();
1148 m->thrownexceptionscount=exceptionCount;
1149 m->thrownexceptions=MNEW(classinfo*,exceptionCount);
1150 for (exceptionID=0;exceptionID<exceptionCount;exceptionID++) {
1151 (m->thrownexceptions)[exceptionID]=class_getconstant(c,suck_u2(),CONSTANT_Class);
1155 skipattributebody();
1159 if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
1160 panic("Code attribute for native or abstract method");
1163 panic("Method has more than one Code attribute");
1166 m->maxstack = suck_u2();
1167 m->maxlocals = suck_u2();
1168 if (m->maxlocals < argcount)
1169 panic("max_locals is smaller than the number of arguments");
1171 codelen = suck_u4();
1173 panic("bytecode has zero length");
1174 if (codelen > 65536)
1175 panic("bytecode too long");
1176 m->jcodelength = codelen;
1177 m->jcode = MNEW(u1, m->jcodelength);
1178 suck_nbytes(m->jcode, m->jcodelength);
1179 m->exceptiontablelength = suck_u2();
1181 MNEW(exceptiontable, m->exceptiontablelength);
1184 count_vmcode_len += m->jcodelength + 18;
1185 count_extable_len += 8 * m->exceptiontablelength;
1188 for (e = 0; e < m->exceptiontablelength; e++) {
1190 m->exceptiontable[e].startpc = suck_u2();
1191 m->exceptiontable[e].endpc = suck_u2();
1192 m->exceptiontable[e].handlerpc = suck_u2();
1196 m->exceptiontable[e].catchtype = NULL;
1199 m->exceptiontable[e].catchtype =
1200 class_getconstant(c, idx, CONSTANT_Class);
1205 for (codeattrnum=suck_u2();codeattrnum>0;codeattrnum--) {
1206 utf * caname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1207 if (caname==utf_linenumbertable) {
1209 /*log_text("LineNumberTable found");*/
1211 m->linenumbercount=suck_u2();
1212 /*printf("length:%d\n",m->linenumbercount);*/
1213 m->linenumbers=MNEW(lineinfo,m->linenumbercount);
1214 for (lncid=0;lncid<m->linenumbercount;lncid++) {
1215 m->linenumbers[lncid].start_pc=suck_u2();
1216 m->linenumbers[lncid].line_number=suck_u2();
1219 skipattributes(codeattrnum);
1221 } else skipattributebody();
1228 if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
1229 panic("Method missing Code attribute");
1233 /********************* Function: method_free ***********************************
1235 frees all memory that was allocated for this method
1237 *******************************************************************************/
1239 static void method_free(methodinfo *m)
1242 MFREE(m->jcode, u1, m->jcodelength);
1244 if (m->exceptiontable)
1245 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1248 CFREE(m->mcode, m->mcodelength);
1250 if (m->stubroutine) {
1251 if (m->flags & ACC_NATIVE) {
1252 removenativestub(m->stubroutine);
1255 removecompilerstub(m->stubroutine);
1261 /************** Function: method_display (debugging only) **************/
1263 void method_display(methodinfo *m)
1266 printflags(m->flags);
1268 utf_display(m->name);
1270 utf_display(m->descriptor);
1274 /************** Function: method_display_flags_last (debugging only) **************/
1276 void method_display_flags_last(methodinfo *m)
1279 utf_display(m->name);
1281 utf_display(m->descriptor);
1283 printflags(m->flags);
1288 /******************** Function: method_canoverwrite ****************************
1290 Check if m and old are identical with respect to type and name. This means
1291 that old can be overwritten with m.
1293 *******************************************************************************/
1295 static bool method_canoverwrite(methodinfo *m, methodinfo *old)
1297 if (m->name != old->name) return false;
1298 if (m->descriptor != old->descriptor) return false;
1299 if (m->flags & ACC_STATIC) return false;
1306 /******************************************************************************/
1307 /************************ Functions for class *********************************/
1308 /******************************************************************************/
1311 /******************** function:: class_getconstant ******************************
1313 retrieves the value at position 'pos' of the constantpool of a class
1314 if the type of the value is other than 'ctype' the system is stopped
1316 *******************************************************************************/
1318 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1320 /* invalid position in constantpool */
1321 /* (pos == 0 is caught by type comparison) */
1322 if (pos >= c->cpcount)
1323 panic("Attempt to access constant outside range");
1325 /* check type of constantpool entry */
1327 if (c->cptags[pos] != ctype) {
1328 class_showconstantpool(c);
1329 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1330 (int) ctype, (int) c->cptags[pos]);
1333 return c->cpinfos[pos];
1337 /********************* Function: class_constanttype ****************************
1339 Determines the type of a class entry in the ConstantPool
1341 *******************************************************************************/
1343 u4 class_constanttype(classinfo *c, u4 pos)
1345 if (pos >= c->cpcount)
1346 panic("Attempt to access constant outside range");
1348 return c->cptags[pos];
1352 /******************** function: class_loadcpool ********************************
1354 loads the constantpool of a class,
1355 the entries are transformed into a simpler format
1356 by resolving references
1357 (a detailed overview of the compact structures can be found in global.h)
1359 *******************************************************************************/
1361 static void class_loadcpool(classinfo *c)
1364 /* The following structures are used to save information which cannot be
1365 processed during the first pass. After the complete constantpool has
1366 been traversed the references can be resolved.
1367 (only in specific order) */
1369 /* CONSTANT_Class_info entries */
1370 typedef struct forward_class {
1371 struct forward_class *next;
1376 /* CONSTANT_String */
1377 typedef struct forward_string {
1378 struct forward_string *next;
1383 /* CONSTANT_NameAndType */
1384 typedef struct forward_nameandtype {
1385 struct forward_nameandtype *next;
1389 } forward_nameandtype;
1391 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1392 typedef struct forward_fieldmethint {
1393 struct forward_fieldmethint *next;
1397 u2 nameandtype_index;
1398 } forward_fieldmethint;
1402 long int dumpsize = dump_size ();
1404 forward_class *forward_classes = NULL;
1405 forward_string *forward_strings = NULL;
1406 forward_nameandtype *forward_nameandtypes = NULL;
1407 forward_fieldmethint *forward_fieldmethints = NULL;
1409 /* number of entries in the constant_pool table plus one */
1410 u4 cpcount = c->cpcount = suck_u2();
1412 /* allocate memory */
1413 u1 *cptags = c->cptags = MNEW(u1, cpcount);
1414 voidptr *cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
1417 panic("Invalid constant_pool_count (0)");
1420 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1423 /* initialize constantpool */
1424 for (idx = 0; idx < cpcount; idx++) {
1425 cptags[idx] = CONSTANT_UNUSED;
1426 cpinfos[idx] = NULL;
1430 /******* first pass *******/
1431 /* entries which cannot be resolved now are written into
1432 temporary structures and traversed again later */
1435 while (idx < cpcount) {
1436 /* get constant type */
1440 case CONSTANT_Class: {
1441 forward_class *nfc = DNEW(forward_class);
1443 nfc -> next = forward_classes;
1444 forward_classes = nfc;
1446 nfc -> thisindex = idx;
1447 /* reference to CONSTANT_NameAndType */
1448 nfc -> name_index = suck_u2 ();
1454 case CONSTANT_Fieldref:
1455 case CONSTANT_Methodref:
1456 case CONSTANT_InterfaceMethodref: {
1457 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1459 nff -> next = forward_fieldmethints;
1460 forward_fieldmethints = nff;
1462 nff -> thisindex = idx;
1465 /* class or interface type that contains the declaration of the field or method */
1466 nff -> class_index = suck_u2 ();
1467 /* name and descriptor of the field or method */
1468 nff -> nameandtype_index = suck_u2 ();
1474 case CONSTANT_String: {
1475 forward_string *nfs = DNEW(forward_string);
1477 nfs->next = forward_strings;
1478 forward_strings = nfs;
1480 nfs->thisindex = idx;
1481 /* reference to CONSTANT_Utf8_info with string characters */
1482 nfs->string_index = suck_u2();
1488 case CONSTANT_NameAndType: {
1489 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1491 nfn -> next = forward_nameandtypes;
1492 forward_nameandtypes = nfn;
1494 nfn -> thisindex = idx;
1495 /* reference to CONSTANT_Utf8_info containing simple name */
1496 nfn -> name_index = suck_u2 ();
1497 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1498 nfn -> sig_index = suck_u2 ();
1504 case CONSTANT_Integer: {
1505 constant_integer *ci = NEW (constant_integer);
1508 count_const_pool_len += sizeof(constant_integer);
1511 ci -> value = suck_s4 ();
1512 cptags [idx] = CONSTANT_Integer;
1519 case CONSTANT_Float: {
1520 constant_float *cf = NEW (constant_float);
1523 count_const_pool_len += sizeof(constant_float);
1526 cf -> value = suck_float ();
1527 cptags [idx] = CONSTANT_Float;
1533 case CONSTANT_Long: {
1534 constant_long *cl = NEW(constant_long);
1537 count_const_pool_len += sizeof(constant_long);
1540 cl -> value = suck_s8 ();
1541 cptags [idx] = CONSTANT_Long;
1545 panic("Long constant exceeds constant pool");
1549 case CONSTANT_Double: {
1550 constant_double *cd = NEW(constant_double);
1553 count_const_pool_len += sizeof(constant_double);
1556 cd -> value = suck_double ();
1557 cptags [idx] = CONSTANT_Double;
1561 panic("Double constant exceeds constant pool");
1565 case CONSTANT_Utf8: {
1567 /* number of bytes in the bytes array (not string-length) */
1568 u4 length = suck_u2();
1569 cptags [idx] = CONSTANT_Utf8;
1570 /* validate the string */
1571 ASSERT_LEFT(length);
1573 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1575 dolog("Invalid UTF-8 string (constant pool index %d)",idx);
1576 panic("Invalid UTF-8 string");
1578 /* insert utf-string into the utf-symboltable */
1579 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1580 /* skip bytes of the string */
1581 skip_nbytes(length);
1587 error ("Unkown constant type: %d",(int) t);
1595 /* resolve entries in temporary structures */
1597 while (forward_classes) {
1599 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1601 if (opt_verify && !is_valid_name_utf(name))
1602 panic("Class reference with invalid name");
1604 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1605 /* retrieve class from class-table */
1606 cpinfos [forward_classes -> thisindex] = class_new (name);
1608 forward_classes = forward_classes -> next;
1612 while (forward_strings) {
1614 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1616 log_text("forward_string:");
1617 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1619 log_text("\n------------------"); */
1620 /* resolve utf-string */
1621 cptags [forward_strings -> thisindex] = CONSTANT_String;
1622 cpinfos [forward_strings -> thisindex] = text;
1624 forward_strings = forward_strings -> next;
1627 while (forward_nameandtypes) {
1628 constant_nameandtype *cn = NEW (constant_nameandtype);
1631 count_const_pool_len += sizeof(constant_nameandtype);
1634 /* resolve simple name and descriptor */
1635 cn -> name = class_getconstant
1636 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1637 cn -> descriptor = class_getconstant
1638 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1642 if (!is_valid_name_utf(cn->name))
1643 panic("NameAndType with invalid name");
1644 /* disallow referencing <clinit> among others */
1645 if (cn->name->text[0] == '<' && cn->name != utf_init)
1646 panic("NameAndType with invalid special name");
1649 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1650 cpinfos [forward_nameandtypes -> thisindex] = cn;
1652 forward_nameandtypes = forward_nameandtypes -> next;
1656 while (forward_fieldmethints) {
1657 constant_nameandtype *nat;
1658 constant_FMIref *fmi = NEW (constant_FMIref);
1661 count_const_pool_len += sizeof(constant_FMIref);
1663 /* resolve simple name and descriptor */
1664 nat = class_getconstant
1665 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1668 log_text("trying to resolve:");
1669 log_text(nat->name->text);
1670 switch(forward_fieldmethints ->tag) {
1671 case CONSTANT_Fieldref:
1672 log_text("CONSTANT_Fieldref");
1674 case CONSTANT_InterfaceMethodref:
1675 log_text("CONSTANT_InterfaceMethodref");
1677 case CONSTANT_Methodref:
1678 log_text("CONSTANT_Methodref");
1682 fmi -> class = class_getconstant
1683 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1684 fmi -> name = nat -> name;
1685 fmi -> descriptor = nat -> descriptor;
1687 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1688 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1690 switch (forward_fieldmethints -> tag) {
1691 case CONSTANT_Fieldref: /* check validity of descriptor */
1692 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1694 case CONSTANT_InterfaceMethodref:
1695 case CONSTANT_Methodref: /* check validity of descriptor */
1696 checkmethoddescriptor (fmi->descriptor);
1700 forward_fieldmethints = forward_fieldmethints -> next;
1704 /* class_showconstantpool(c); */
1706 dump_release(dumpsize);
1710 /********************** Function: class_load ***********************************
1712 Loads everything interesting about a class from the class file. The
1713 'classinfo' structure must have been allocated previously.
1715 The super class and the interfaces implemented by this class need not be
1716 loaded. The link is set later by the function 'class_link'.
1718 The loaded class is removed from the list 'unloadedclasses' and added to
1719 the list 'unlinkedclasses'.
1721 *******************************************************************************/
1723 static int class_load(classinfo *c)
1729 count_class_loads++;
1732 /* output for debugging purposes */
1734 char logtext[MAXLOGTEXT];
1735 sprintf(logtext, "Loading class: ");
1736 utf_sprint(logtext + strlen(logtext), c->name);
1740 /* load classdata, throw exception on error */
1742 if (!suck_start(c->name)) {
1743 throw_noclassdeffounderror_message(c->name);
1747 /* check signature */
1748 if (suck_u4() != MAGIC)
1749 panic("Can not find class-file signature");
1755 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1756 error("File version %d.%d is not supported", (int) ma, (int) mi);
1762 c->erroneous_state = 0;
1763 c->initializing_thread = 0;
1765 c->classUsed = NOTUSED; /* not used initially CO-RT */
1769 c->flags = suck_u2();
1770 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1772 /* check ACC flags consistency */
1773 if ((c->flags & ACC_INTERFACE) != 0) {
1774 if ((c->flags & ACC_ABSTRACT) == 0) {
1775 /* We work around this because interfaces in JDK 1.1 are
1776 * not declared abstract. */
1778 c->flags |= ACC_ABSTRACT;
1779 /* panic("Interface class not declared abstract"); */
1781 if ((c->flags & (ACC_FINAL)) != 0)
1782 panic("Interface class has invalid flags");
1783 if ((c->flags & (ACC_SUPER)) != 0)
1784 c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
1786 if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
1787 panic("Class is declared both abstract and final");
1791 if (class_getconstant(c, i, CONSTANT_Class) != c) {
1792 /* char message[MAXLOGTEXT]; */
1793 /* utf_sprint(message, c->name); */
1794 /* sprintf(message + strlen(message), " (wrong name: "); */
1795 /* utf_sprint(message + strlen(message), class_getconstant(c, i, CONSTANT_Class)); */
1796 /* sprintf(message + strlen(message), ")"); */
1798 /* *exceptionptr = new_exception_message("java/lang/NoClassDefFoundError", */
1801 panic("Invalid this_class in class file");
1804 /* retrieve superclass */
1805 if ((i = suck_u2())) {
1806 c->super = class_getconstant(c, i, CONSTANT_Class);
1808 /* java.lang.Object may not have a super class. */
1809 if (c->name == utf_java_lang_Object)
1810 panic("java.lang.Object with super class");
1812 /* Interfaces must have j.l.O as super class. */
1813 if ((c->flags & ACC_INTERFACE) != 0
1814 && c->super->name != utf_java_lang_Object)
1816 panic("Interface with super class other than java.lang.Object");
1821 /* This is only allowed for java.lang.Object. */
1822 if (c->name != utf_java_lang_Object)
1823 panic("Class (not java.lang.Object) without super class");
1826 /* retrieve interfaces */
1827 c->interfacescount = suck_u2();
1828 c->interfaces = MNEW(classinfo*, c->interfacescount);
1829 for (i = 0; i < c->interfacescount; i++) {
1831 class_getconstant(c, suck_u2(), CONSTANT_Class);
1835 c->fieldscount = suck_u2();
1836 /* utf_display(c->name);
1837 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1839 c->fields = GCNEW(fieldinfo, c->fieldscount);
1840 for (i = 0; i < c->fieldscount; i++) {
1841 field_load(&(c->fields[i]), c);
1845 c->methodscount = suck_u2();
1846 c->methods = MNEW(methodinfo, c->methodscount);
1847 for (i = 0; i < c->methodscount; i++) {
1848 method_load(&(c->methods[i]), c);
1851 /* Check if all fields and methods can be uniquely
1852 * identified by (name,descriptor). */
1854 /* We use a hash table here to avoid making the
1855 * average case quadratic in # of methods, fields.
1857 static int shift = 0;
1859 u2 *next; /* for chaining colliding hash entries */
1865 /* Allocate hashtable */
1866 len = c->methodscount;
1867 if (len < c->fieldscount) len = c->fieldscount;
1869 hashtab = MNEW(u2,(hashlen + len));
1870 next = hashtab + hashlen;
1872 /* Determine bitshift (to get good hash values) */
1882 memset(hashtab, 0, sizeof(u2) * (hashlen + len));
1883 for (i = 0; i < c->fieldscount; ++i) {
1884 fieldinfo *fi = c->fields + i;
1885 /* It's ok if we lose bits here */
1886 index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
1888 if ((old = hashtab[index]) != 0) {
1890 /* dolog("HASHHIT %d --> %d",index,old); */
1893 /* dolog("HASHCHECK %d",old); */
1894 if (c->fields[old].name == fi->name
1895 && c->fields[old].descriptor == fi->descriptor)
1897 dolog("Duplicate field (%d,%d):",i,old);
1898 log_utf(fi->name); log_utf(fi->descriptor);
1899 panic("Fields with same name and descriptor");
1901 } while ((old = next[old]) != 0);
1903 /* else dolog("HASHLUCKY"); */
1904 hashtab[index] = i+1;
1908 memset(hashtab,0,sizeof(u2) * (hashlen + len));
1909 for (i = 0; i < c->methodscount; ++i) {
1910 methodinfo *mi = c->methods + i;
1911 /* It's ok if we lose bits here */
1912 index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
1914 if ((old = hashtab[index]) != 0) {
1916 /* dolog("HASHHIT %d --> %d",index,old); */
1919 /* dolog("HASHCHECK %d",old); */
1920 if (c->methods[old].name == mi->name
1921 && c->methods[old].descriptor == mi->descriptor)
1923 dolog("Duplicate method (%d,%d):",i,old);
1924 log_utf(mi->name); log_utf(mi->descriptor);
1925 panic("Methods with same name and descriptor");
1927 } while ((old = next[old]) != 0);
1929 /* else dolog("HASHLUCKY"); */
1930 hashtab[index] = i+1;
1933 MFREE(hashtab,u2,(hashlen + len));
1937 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1938 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1939 count_class_infos += sizeof(methodinfo) * c->methodscount;
1942 /* load variable-length attribute structures */
1943 attribute_load(suck_u2(), c);
1948 /* remove class from list of unloaded classes and
1949 add to list of unlinked classes */
1950 list_remove(&unloadedclasses, c);
1951 list_addlast(&unlinkedclasses, c);
1960 /************** internal Function: class_highestinterface ***********************
1962 Used by the function class_link to determine the amount of memory needed
1963 for the interface table.
1965 *******************************************************************************/
1967 static s4 class_highestinterface(classinfo *c)
1972 if (!(c->flags & ACC_INTERFACE)) {
1973 char logtext[MAXLOGTEXT];
1974 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1975 utf_sprint(logtext + strlen(logtext), c->name);
1976 error("%s",logtext);
1980 for (i = 0; i < c->interfacescount; i++) {
1981 s4 h2 = class_highestinterface(c->interfaces[i]);
1989 /* class_addinterface **********************************************************
1991 Is needed by class_link for adding a VTBL to a class. All interfaces
1992 implemented by ic are added as well.
1994 *******************************************************************************/
1996 static void class_addinterface (classinfo *c, classinfo *ic)
2000 vftbl *vftbl = c->vftbl;
2002 if (i >= vftbl->interfacetablelength)
2003 panic ("Inernal error: interfacetable overflow");
2004 if (vftbl->interfacetable[-i])
2007 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
2008 vftbl->interfacevftbllength[i] = 1;
2009 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
2010 vftbl->interfacetable[-i][0] = NULL;
2013 vftbl->interfacevftbllength[i] = ic->methodscount;
2014 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
2017 count_vftbl_len += sizeof(methodptr) *
2018 (ic->methodscount + (ic->methodscount == 0));
2021 for (j=0; j<ic->methodscount; j++) {
2024 for (m = 0; m < sc->methodscount; m++) {
2025 methodinfo *mi = &(sc->methods[m]);
2026 if (method_canoverwrite(mi, &(ic->methods[j]))) {
2027 vftbl->interfacetable[-i][j] =
2028 vftbl->table[mi->vftblindex];
2038 for (j = 0; j < ic->interfacescount; j++)
2039 class_addinterface(c, ic->interfaces[j]);
2043 /******************* Function: class_new_array *********************************
2045 This function is called by class_new to setup an array class.
2047 *******************************************************************************/
2049 void class_new_array(classinfo *c)
2051 classinfo *comp = NULL;
2055 /* DEBUG */ /* dolog("class_new_array: %s",c->name->text); */
2057 /* Array classes are not loaded from classfiles. */
2058 list_remove(&unloadedclasses, c);
2060 /* Check array class name */
2061 namelen = c->name->blength;
2062 if (namelen < 2 || c->name->text[0] != '[')
2063 panic("Invalid array class name");
2065 /* Check the component type */
2066 switch (c->name->text[1]) {
2068 /* c is an array of arrays. We have to create the component class. */
2069 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
2073 /* c is an array of objects. */
2074 if (namelen < 4 || c->name->text[namelen - 1] != ';')
2075 panic("Invalid array class name");
2076 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
2080 /* Setup the array class */
2081 c->super = class_java_lang_Object;
2082 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
2084 c->interfacescount = 2;
2085 c->interfaces = MNEW(classinfo*,2);
2086 c->interfaces[0] = class_java_lang_Cloneable;
2087 c->interfaces[1] = class_java_io_Serializable;
2089 c->methodscount = 1;
2090 c->methods = MNEW (methodinfo, c->methodscount);
2093 memset(clone, 0, sizeof(methodinfo));
2094 clone->flags = ACC_PUBLIC;
2095 clone->name = utf_new_char("clone");
2096 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
2098 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
2099 clone->monoPoly = MONO;
2101 /* XXX: field: length? */
2103 /* The array class has to be linked */
2104 list_addlast(&unlinkedclasses,c);
2107 * Array classes which are created after the other classes have been
2108 * loaded and linked are linked explicitely.
2113 loader_load(c->name); /* XXX handle errors */
2117 /****************** Function: class_link_array *********************************
2119 This function is called by class_link to create the
2120 arraydescriptor for an array class.
2122 This function returns NULL if the array cannot be linked because
2123 the component type has not been linked yet.
2125 *******************************************************************************/
2127 static arraydescriptor *class_link_array(classinfo *c)
2129 classinfo *comp = NULL;
2130 int namelen = c->name->blength;
2131 arraydescriptor *desc;
2134 /* Check the component type */
2135 switch (c->name->text[1]) {
2137 /* c is an array of arrays. */
2138 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
2139 if (!comp) panic("Could not find component array class.");
2143 /* c is an array of objects. */
2144 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
2145 if (!comp) panic("Could not find component class.");
2149 /* If the component type has not been linked return NULL */
2150 if (comp && !comp->linked)
2153 /* Allocate the arraydescriptor */
2154 desc = NEW(arraydescriptor);
2157 /* c is an array of references */
2158 desc->arraytype = ARRAYTYPE_OBJECT;
2159 desc->componentsize = sizeof(void*);
2160 desc->dataoffset = OFFSET(java_objectarray,data);
2162 compvftbl = comp->vftbl;
2164 panic("Component class has no vftbl");
2165 desc->componentvftbl = compvftbl;
2167 if (compvftbl->arraydesc) {
2168 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
2169 if (compvftbl->arraydesc->dimension >= 255)
2170 panic("Creating array of dimension >255");
2171 desc->dimension = compvftbl->arraydesc->dimension + 1;
2172 desc->elementtype = compvftbl->arraydesc->elementtype;
2175 desc->elementvftbl = compvftbl;
2176 desc->dimension = 1;
2177 desc->elementtype = ARRAYTYPE_OBJECT;
2181 /* c is an array of a primitive type */
2182 switch (c->name->text[1]) {
2183 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
2184 desc->dataoffset = OFFSET(java_booleanarray,data);
2185 desc->componentsize = sizeof(u1);
2188 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
2189 desc->dataoffset = OFFSET(java_bytearray,data);
2190 desc->componentsize = sizeof(u1);
2193 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
2194 desc->dataoffset = OFFSET(java_chararray,data);
2195 desc->componentsize = sizeof(u2);
2198 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
2199 desc->dataoffset = OFFSET(java_doublearray,data);
2200 desc->componentsize = sizeof(double);
2203 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
2204 desc->dataoffset = OFFSET(java_floatarray,data);
2205 desc->componentsize = sizeof(float);
2208 case 'I': desc->arraytype = ARRAYTYPE_INT;
2209 desc->dataoffset = OFFSET(java_intarray,data);
2210 desc->componentsize = sizeof(s4);
2213 case 'J': desc->arraytype = ARRAYTYPE_LONG;
2214 desc->dataoffset = OFFSET(java_longarray,data);
2215 desc->componentsize = sizeof(s8);
2218 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
2219 desc->dataoffset = OFFSET(java_shortarray,data);
2220 desc->componentsize = sizeof(s2);
2224 panic("Invalid array class name");
2227 desc->componentvftbl = NULL;
2228 desc->elementvftbl = NULL;
2229 desc->dimension = 1;
2230 desc->elementtype = desc->arraytype;
2237 /********************** Function: class_link ***********************************
2239 Tries to link a class. The super class and every implemented interface must
2240 already have been linked. The function calculates the length in bytes that
2241 an instance of this class requires as well as the VTBL for methods and
2244 If the class can be linked, it is removed from the list 'unlinkedclasses'
2245 and added to 'linkedclasses'. Otherwise, it is moved to the end of
2248 Attention: If cyclical class definitions are encountered, the program gets
2249 into an infinite loop (we'll have to work that out)
2251 *******************************************************************************/
2253 void class_link(classinfo *c)
2255 s4 supervftbllength; /* vftbllegnth of super class */
2256 s4 vftbllength; /* vftbllength of current class */
2257 s4 interfacetablelength; /* interface table length */
2258 classinfo *super = c->super; /* super class */
2259 classinfo *ic, *c2; /* intermediate class variables */
2260 vftbl *v; /* vftbl of current class */
2261 s4 i; /* interface/method/field counter */
2262 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2265 /* check if all superclasses are already linked, if not put c at end of
2266 unlinked list and return. Additionally initialize class fields. */
2268 /* check interfaces */
2270 for (i = 0; i < c->interfacescount; i++) {
2271 ic = c->interfaces[i];
2273 list_remove(&unlinkedclasses, c);
2274 list_addlast(&unlinkedclasses, c);
2277 if ((ic->flags & ACC_INTERFACE) == 0) {
2278 dolog("Specified interface is not declared as interface:");
2282 panic("Specified interface is not declared as interface");
2286 /* check super class */
2288 if (super == NULL) { /* class java.lang.Object */
2290 c->classUsed = USED; /* Object class is always used CO-RT*/
2292 c->instancesize = sizeof(java_objectheader);
2294 vftbllength = supervftbllength = 0;
2296 c->finalizer = NULL;
2299 if (!super->linked) {
2300 list_remove(&unlinkedclasses, c);
2301 list_addlast(&unlinkedclasses, c);
2305 if (super->flags & ACC_INTERFACE)
2306 panic("Interface specified as super class");
2308 /* handle array classes */
2309 /* The component class must have been linked already. */
2310 if (c->name->text[0] == '[')
2311 if ((arraydesc = class_link_array(c)) == NULL) {
2312 list_remove(&unlinkedclasses, c);
2313 list_addlast(&unlinkedclasses, c);
2317 /* Don't allow extending final classes */
2318 if (super->flags & ACC_FINAL)
2319 panic("Trying to extend final class");
2321 if (c->flags & ACC_INTERFACE)
2322 c->index = interfaceindex++;
2324 c->index = super->index + 1;
2326 c->instancesize = super->instancesize;
2328 vftbllength = supervftbllength = super->vftbl->vftbllength;
2330 c->finalizer = super->finalizer;
2335 char logtext[MAXLOGTEXT];
2336 sprintf(logtext, "Linking Class: ");
2337 utf_sprint(logtext + strlen(logtext), c->name );
2341 /* compute vftbl length */
2343 for (i = 0; i < c->methodscount; i++) {
2344 methodinfo *m = &(c->methods[i]);
2346 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2347 classinfo *sc = super;
2350 for (j = 0; j < sc->methodscount; j++) {
2351 if (method_canoverwrite(m, &(sc->methods[j]))) {
2352 if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
2353 goto notfoundvftblindex;
2354 if ((sc->methods[j].flags & ACC_FINAL) != 0) {
2357 log_utf(sc->methods[j].name);
2358 log_utf(sc->methods[j].descriptor);
2359 panic("Trying to overwrite final method");
2361 m->vftblindex = sc->methods[j].vftblindex;
2362 goto foundvftblindex;
2368 m->vftblindex = (vftbllength++);
2374 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2377 /* compute interfacetable length */
2379 interfacetablelength = 0;
2382 for (i = 0; i < c2->interfacescount; i++) {
2383 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2384 if (h > interfacetablelength)
2385 interfacetablelength = h;
2390 /* allocate virtual function table */
2392 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2393 (vftbllength - 1) + sizeof(methodptr*) *
2394 (interfacetablelength - (interfacetablelength > 0)));
2395 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2396 (interfacetablelength > 1));
2397 c->header.vftbl = c->vftbl = v;
2399 v->vftbllength = vftbllength;
2400 v->interfacetablelength = interfacetablelength;
2401 v->arraydesc = arraydesc;
2403 /* store interface index in vftbl */
2404 if (c->flags & ACC_INTERFACE)
2405 v->baseval = -(c->index);
2407 /* copy virtual function table of super class */
2409 for (i = 0; i < supervftbllength; i++)
2410 v->table[i] = super->vftbl->table[i];
2412 /* add method stubs into virtual function table */
2414 for (i = 0; i < c->methodscount; i++) {
2415 methodinfo *m = &(c->methods[i]);
2416 if (!(m->flags & ACC_STATIC)) {
2417 v->table[m->vftblindex] = m->stubroutine;
2421 /* compute instance size and offset of each field */
2423 for (i = 0; i < c->fieldscount; i++) {
2425 fieldinfo *f = &(c->fields[i]);
2427 if (!(f->flags & ACC_STATIC) ) {
2428 dsize = desc_typesize(f->descriptor);
2429 c->instancesize = ALIGN(c->instancesize, dsize);
2430 f->offset = c->instancesize;
2431 c->instancesize += dsize;
2435 /* initialize interfacetable and interfacevftbllength */
2437 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2440 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2443 for (i = 0; i < interfacetablelength; i++) {
2444 v->interfacevftbllength[i] = 0;
2445 v->interfacetable[-i] = NULL;
2448 /* add interfaces */
2450 for (c2 = c; c2 != NULL; c2 = c2->super)
2451 for (i = 0; i < c2->interfacescount; i++) {
2452 class_addinterface(c, c2->interfaces[i]);
2455 /* add finalizer method (not for java.lang.Object) */
2457 if (super != NULL) {
2459 static utf *finame = NULL;
2460 static utf *fidesc = NULL;
2463 finame = utf_finalize;
2465 fidesc = utf_fidesc;
2467 fi = class_findmethod(c, finame, fidesc);
2469 if (!(fi->flags & ACC_STATIC)) {
2479 list_remove(&unlinkedclasses, c);
2480 list_addlast(&linkedclasses, c);
2484 /******************* Function: class_freepool **********************************
2486 Frees all resources used by this classes Constant Pool.
2488 *******************************************************************************/
2490 static void class_freecpool (classinfo *c)
2496 for (idx=0; idx < c->cpcount; idx++) {
2497 tag = c->cptags[idx];
2498 info = c->cpinfos[idx];
2502 case CONSTANT_Fieldref:
2503 case CONSTANT_Methodref:
2504 case CONSTANT_InterfaceMethodref:
2505 FREE (info, constant_FMIref);
2507 case CONSTANT_Integer:
2508 FREE (info, constant_integer);
2510 case CONSTANT_Float:
2511 FREE (info, constant_float);
2514 FREE (info, constant_long);
2516 case CONSTANT_Double:
2517 FREE (info, constant_double);
2519 case CONSTANT_NameAndType:
2520 FREE (info, constant_nameandtype);
2526 MFREE (c -> cptags, u1, c -> cpcount);
2527 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2531 /*********************** Function: class_free **********************************
2533 Frees all resources used by the class.
2535 *******************************************************************************/
2537 static void class_free(classinfo *c)
2544 MFREE(c->interfaces, classinfo*, c->interfacescount);
2546 for (i = 0; i < c->fieldscount; i++)
2547 field_free(&(c->fields[i]));
2549 for (i = 0; i < c->methodscount; i++)
2550 method_free(&(c->methods[i]));
2551 MFREE(c->methods, methodinfo, c->methodscount);
2553 if ((v = c->vftbl) != NULL) {
2555 mem_free(v->arraydesc,sizeof(arraydescriptor));
2557 for (i = 0; i < v->interfacetablelength; i++) {
2558 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2560 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2562 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2563 sizeof(methodptr*) * (v->interfacetablelength -
2564 (v->interfacetablelength > 0));
2565 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2566 (v->interfacetablelength > 1));
2570 if (c->innerclasscount)
2571 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2573 /* if (c->classvftbl)
2574 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2580 /************************* Function: class_findfield ***************************
2582 Searches a 'classinfo' structure for a field having the given name and
2585 *******************************************************************************/
2587 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2591 for (i = 0; i < c->fieldscount; i++) {
2592 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2593 return &(c->fields[i]);
2596 panic("Can not find field given in CONSTANT_Fieldref");
2598 /* keep compiler happy */
2603 /****************** Function: class_resolvefield_int ***************************
2605 This is an internally used helper function. Do not use this directly.
2607 Tries to resolve a field having the given name and type.
2608 If the field cannot be resolved, NULL is returned.
2610 *******************************************************************************/
2613 fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
2618 /* search for field in class c */
2619 for (i = 0; i < c->fieldscount; i++) {
2620 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2621 return &(c->fields[i]);
2624 /* try superinterfaces recursively */
2625 for (i=0; i<c->interfacescount; ++i) {
2626 fi = class_resolvefield_int(c->interfaces[i],name,desc);
2631 /* try superclass */
2633 return class_resolvefield_int(c->super,name,desc);
2640 /********************* Function: class_resolvefield ***************************
2642 Resolves a reference from REFERER to a field with NAME and DESC in class C.
2643 If the field cannot be resolved this function panics.
2645 *******************************************************************************/
2647 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
2652 /* XXX resolve class c */
2653 /* XXX check access from REFERER to C */
2655 fi = class_resolvefield_int(c,name,desc);
2661 panic("Cannot find field given in CONSTANT_Fieldref");
2662 /* XXX should throw NoSuchFieldError */
2665 /* XXX check access rights */
2671 /************************* Function: class_findmethod **************************
2673 Searches a 'classinfo' structure for a method having the given name and
2674 type and returns the index in the class info structure.
2675 If type is NULL, it is ignored.
2677 *******************************************************************************/
2679 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2682 //#define JOWENN_DEBUG1
2683 //#define JOWENN_DEBUG2
2684 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2686 int buffer_len, pos;
2689 #ifdef JOWENN_DEBUG1
2692 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2694 buffer = MNEW(char, buffer_len);
2696 strcpy(buffer, "class_findmethod: method:");
2697 utf_sprint(buffer + strlen(buffer), name);
2698 strcpy(buffer + strlen(buffer), ", desc: ");
2699 utf_sprint(buffer + strlen(buffer), desc);
2700 strcpy(buffer + strlen(buffer), ", classname: ");
2701 utf_sprint(buffer + strlen(buffer), c->name);
2705 MFREE(buffer, char, buffer_len);
2707 for (i = 0; i < c->methodscount; i++) {
2708 #ifdef JOWENN_DEBUG2
2710 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2712 buffer = MNEW(char, buffer_len);
2714 strcpy(buffer, "class_findmethod: comparing to method:");
2715 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2716 strcpy(buffer + strlen(buffer), ", desc: ");
2717 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2721 MFREE(buffer, char, buffer_len);
2725 if ((c->methods[i].name == name) && ((desc == NULL) ||
2726 (c->methods[i].descriptor == desc))) {
2731 #ifdef JOWENN_DEBUG2
2732 class_showconstantpool(c);
2733 log_text("class_findmethod: returning NULL");
2740 /************************* Function: class_findmethod **************************
2742 Searches a 'classinfo' structure for a method having the given name and
2744 If type is NULL, it is ignored.
2746 *******************************************************************************/
2748 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2752 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2754 int buffer_len, pos;
2756 #ifdef JOWENN_DEBUG1
2759 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2761 buffer = MNEW(char, buffer_len);
2763 strcpy(buffer, "class_findmethod: method:");
2764 utf_sprint(buffer + strlen(buffer), name);
2765 strcpy(buffer + strlen(buffer), ", desc: ");
2766 utf_sprint(buffer + strlen(buffer), desc);
2767 strcpy(buffer + strlen(buffer), ", classname: ");
2768 utf_sprint(buffer + strlen(buffer), c->name);
2772 MFREE(buffer, char, buffer_len);
2774 for (i = 0; i < c->methodscount; i++) {
2775 #ifdef JOWENN_DEBUG2
2777 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2779 buffer = MNEW(char, buffer_len);
2781 strcpy(buffer, "class_findmethod: comparing to method:");
2782 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2783 strcpy(buffer + strlen(buffer), ", desc: ");
2784 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2788 MFREE(buffer, char, buffer_len);
2791 if ((c->methods[i].name == name) && ((desc == NULL) ||
2792 (c->methods[i].descriptor == desc))) {
2793 return &(c->methods[i]);
2796 #ifdef JOWENN_DEBUG2
2797 class_showconstantpool(c);
2798 log_text("class_findmethod: returning NULL");
2803 s4 idx=class_findmethodIndex(c, name, desc);
2804 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2805 if (idx == -1) return NULL;
2807 return &(c->methods[idx]);
2811 /*********************** Function: class_fetchmethod **************************
2813 like class_findmethod, but aborts with an error if the method is not found
2815 *******************************************************************************/
2817 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2820 mi = class_findmethod(c, name, desc);
2823 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2824 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2825 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2826 panic("Method not found");
2833 /*********************** Function: class_findmethod_w**************************
2835 like class_findmethod, but logs a warning if the method is not found
2837 *******************************************************************************/
2839 methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
2842 mi = class_findmethod(c, name, desc);
2845 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2846 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2847 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2849 if ( c->flags & ACC_PUBLIC ) log_plain(" PUBLIC ");
2850 if ( c->flags & ACC_PRIVATE ) log_plain(" PRIVATE ");
2851 if ( c->flags & ACC_PROTECTED ) log_plain(" PROTECTED ");
2852 if ( c->flags & ACC_STATIC ) log_plain(" STATIC ");
2853 if ( c->flags & ACC_FINAL ) log_plain(" FINAL ");
2854 if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
2855 if ( c->flags & ACC_VOLATILE ) log_plain(" VOLATILE ");
2856 if ( c->flags & ACC_TRANSIENT ) log_plain(" TRANSIENT ");
2857 if ( c->flags & ACC_NATIVE ) log_plain(" NATIVE ");
2858 if ( c->flags & ACC_INTERFACE ) log_plain(" INTERFACE ");
2859 if ( c->flags & ACC_ABSTRACT ) log_plain(" ABSTRACT ");
2862 log_plain(" : WARNING: Method not found");log_nl( );
2869 /************************* Function: class_findmethod_approx ******************
2871 like class_findmethod but ignores the return value when comparing the
2874 *******************************************************************************/
2876 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2880 for (i = 0; i < c->methodscount; i++) {
2881 if (c->methods[i].name == name) {
2882 utf *meth_descr = c->methods[i].descriptor;
2886 return &(c->methods[i]);
2888 if (desc->blength <= meth_descr->blength) {
2889 /* current position in utf text */
2890 char *desc_utf_ptr = desc->text;
2891 char *meth_utf_ptr = meth_descr->text;
2892 /* points behind utf strings */
2893 char *desc_end = utf_end(desc);
2894 char *meth_end = utf_end(meth_descr);
2897 /* compare argument types */
2898 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2900 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2901 break; /* no match */
2904 return &(c->methods[i]); /* all parameter types equal */
2914 /***************** Function: class_resolvemethod_approx ***********************
2916 Searches a class and every super class for a method (without paying
2917 attention to the return value)
2919 *******************************************************************************/
2921 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2924 /* search for method (ignore returntype) */
2925 methodinfo *m = class_findmethod_approx(c, name, desc);
2928 /* search superclass */
2936 /************************* Function: class_resolvemethod ***********************
2938 Searches a class and every super class for a method.
2940 *******************************************************************************/
2942 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2945 methodinfo *m = class_findmethod(c, name, desc);
2947 /* search superclass */
2955 /****************** Function: class_resolveinterfacemethod_int ****************
2957 Internally used helper function. Do not use this directly.
2959 *******************************************************************************/
2962 methodinfo *class_resolveinterfacemethod_int(classinfo *c, utf *name, utf *desc)
2967 mi = class_findmethod(c,name,desc);
2971 /* try the superinterfaces */
2972 for (i=0; i<c->interfacescount; ++i) {
2973 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
2981 /******************** Function: class_resolveinterfacemethod ******************
2983 Resolves a reference from REFERER to a method with NAME and DESC in
2986 *******************************************************************************/
2988 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
2993 /* XXX resolve class c */
2994 /* XXX check access from REFERER to C */
2996 if ((c->flags & ACC_INTERFACE) == 0)
2997 return NULL; /* should throw IncompatibleClassChangeError */
2999 mi = class_resolveinterfacemethod_int(c,name,desc);
3003 /* try class java.lang.Object */
3004 mi = class_findmethod(class_java_lang_Object,name,desc);
3008 return NULL; /* should throw NoSuchMethodError */
3014 /********************* Function: class_resolveclassmethod *********************
3016 Resolves a reference from REFERER to a method with NAME and DESC in
3019 *******************************************************************************/
3021 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
3028 /* XXX resolve class c */
3029 /* XXX check access from REFERER to C */
3031 if ((c->flags & ACC_INTERFACE) != 0)
3032 return NULL; /* should throw IncompatibleClassChangeError */
3034 /* try class c and its superclasses */
3037 mi = class_findmethod(cls,name,desc);
3040 } while ((cls = cls->super) != NULL); /* try the superclass */
3042 /* try the superinterfaces */
3043 for (i=0; i<c->interfacescount; ++i) {
3044 mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
3049 return NULL; /* should throw NoSuchMethodError */
3052 if ((mi->flags & ACC_ABSTRACT) != 0 &&
3053 (c->flags & ACC_ABSTRACT) == 0)
3054 return NULL; /* should throw AbstractMethodError */
3056 /* XXX check access rights */
3062 /************************* Function: class_issubclass **************************
3064 Checks if sub is a descendant of super.
3066 *******************************************************************************/
3068 bool class_issubclass(classinfo *sub, classinfo *super)
3071 if (!sub) return false;
3072 if (sub == super) return true;
3078 /****************** Initialization function for classes ******************
3080 In Java, every class can have a static initialization function. This
3081 function has to be called BEFORE calling other methods or accessing static
3084 *******************************************************************************/
3086 void class_init(classinfo *c)
3090 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3094 if (!makeinitializations)
3099 c->initialized = true;
3102 count_class_inits++;
3105 /* initialize super class */
3108 char logtext[MAXLOGTEXT];
3109 sprintf(logtext, "Initialize super class ");
3110 utf_sprint(logtext + strlen(logtext), c->super->name);
3111 sprintf(logtext + strlen(logtext), " from ");
3112 utf_sprint(logtext + strlen(logtext), c->name);
3115 class_init(c->super);
3118 /* initialize interface classes */
3119 for (i = 0; i < c->interfacescount; i++) {
3121 char logtext[MAXLOGTEXT];
3122 sprintf(logtext, "Initialize interface class ");
3123 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
3124 sprintf(logtext + strlen(logtext), " from ");
3125 utf_sprint(logtext + strlen(logtext), c->name);
3128 class_init(c->interfaces[i]); /* real */
3131 m = class_findmethod(c, utf_clinit, utf_fidesc);
3134 char logtext[MAXLOGTEXT];
3135 sprintf(logtext, "Class ");
3136 utf_sprint(logtext + strlen(logtext), c->name);
3137 sprintf(logtext + strlen(logtext), " has no initializer");
3140 /* goto callinitialize;*/
3144 if (!(m->flags & ACC_STATIC))
3145 panic("Class initializer is not static!");
3148 char logtext[MAXLOGTEXT];
3149 sprintf(logtext, "Starting initializer for class: ");
3150 utf_sprint(logtext + strlen(logtext), c->name);
3154 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3159 /* now call the initializer */
3160 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3162 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3163 assert(blockInts == 0);
3167 /* we have to throw an exception */
3168 if (*exceptionptr) {
3169 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
3170 printf("Caused by: ");
3171 utf_display((*exceptionptr)->vftbl->class->name);
3173 /* do we have a detail message? */
3174 if (((java_lang_Throwable *) *exceptionptr)->detailMessage) {
3176 utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false));
3185 char logtext[MAXLOGTEXT];
3186 sprintf(logtext, "Finished initializer for class: ");
3187 utf_sprint(logtext + strlen(logtext), c->name);
3191 if (c->name == utf_systemclass) {
3192 /* class java.lang.System requires explicit initialization */
3195 printf("#### Initializing class System");
3197 /* find initializing method */
3198 m = class_findmethod(c,
3199 utf_initsystemclass,
3203 /* no method found */
3204 /* printf("initializeSystemClass failed"); */
3208 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3213 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3215 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3216 assert(blockInts == 0);
3220 if (*exceptionptr) {
3221 printf("#### initializeSystemClass has thrown: ");
3222 utf_display((*exceptionptr)->vftbl->class->name);
3230 /********* Function: find_class_method_constant *********/
3232 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
3237 for (i=0; i<c->cpcount; i++) {
3239 e = c -> cpinfos [i];
3242 switch (c -> cptags [i]) {
3243 case CONSTANT_Methodref:
3245 constant_FMIref *fmi = e;
3246 if ( (fmi->class->name == c1)
3247 && (fmi->name == m1)
3248 && (fmi->descriptor == d1)) {
3255 case CONSTANT_InterfaceMethodref:
3257 constant_FMIref *fmi = e;
3258 if ( (fmi->class->name == c1)
3259 && (fmi->name == m1)
3260 && (fmi->descriptor == d1)) {
3274 void class_showconstanti(classinfo *c, int ii)
3280 printf ("#%d: ", (int) i);
3282 switch (c->cptags [i]) {
3283 case CONSTANT_Class:
3284 printf("Classreference -> ");
3285 utf_display(((classinfo*)e)->name);
3288 case CONSTANT_Fieldref:
3289 printf("Fieldref -> "); goto displayFMIi;
3290 case CONSTANT_Methodref:
3291 printf("Methodref -> "); goto displayFMIi;
3292 case CONSTANT_InterfaceMethodref:
3293 printf("InterfaceMethod -> "); goto displayFMIi;
3296 constant_FMIref *fmi = e;
3297 utf_display(fmi->class->name);
3299 utf_display(fmi->name);
3301 utf_display(fmi->descriptor);
3305 case CONSTANT_String:
3306 printf("String -> ");
3309 case CONSTANT_Integer:
3310 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3312 case CONSTANT_Float:
3313 printf("Float -> %f", ((constant_float*)e)->value);
3315 case CONSTANT_Double:
3316 printf("Double -> %f", ((constant_double*)e)->value);
3320 u8 v = ((constant_long*)e)->value;
3322 printf("Long -> %ld", (long int) v);
3324 printf("Long -> HI: %ld, LO: %ld\n",
3325 (long int) v.high, (long int) v.low);
3329 case CONSTANT_NameAndType:
3331 constant_nameandtype *cnt = e;
3332 printf("NameAndType: ");
3333 utf_display(cnt->name);
3335 utf_display(cnt->descriptor);
3343 panic("Invalid type of ConstantPool-Entry");
3350 void class_showconstantpool (classinfo *c)
3355 printf ("---- dump of constant pool ----\n");
3357 for (i=0; i<c->cpcount; i++) {
3358 printf ("#%d: ", (int) i);
3360 e = c -> cpinfos [i];
3363 switch (c -> cptags [i]) {
3364 case CONSTANT_Class:
3365 printf ("Classreference -> ");
3366 utf_display ( ((classinfo*)e) -> name );
3369 case CONSTANT_Fieldref:
3370 printf ("Fieldref -> "); goto displayFMI;
3371 case CONSTANT_Methodref:
3372 printf ("Methodref -> "); goto displayFMI;
3373 case CONSTANT_InterfaceMethodref:
3374 printf ("InterfaceMethod -> "); goto displayFMI;
3377 constant_FMIref *fmi = e;
3378 utf_display ( fmi->class->name );
3380 utf_display ( fmi->name);
3382 utf_display ( fmi->descriptor );
3386 case CONSTANT_String:
3387 printf ("String -> ");
3390 case CONSTANT_Integer:
3391 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3393 case CONSTANT_Float:
3394 printf ("Float -> %f", ((constant_float*)e) -> value);
3396 case CONSTANT_Double:
3397 printf ("Double -> %f", ((constant_double*)e) -> value);
3401 u8 v = ((constant_long*)e) -> value;
3403 printf ("Long -> %ld", (long int) v);
3405 printf ("Long -> HI: %ld, LO: %ld\n",
3406 (long int) v.high, (long int) v.low);
3410 case CONSTANT_NameAndType:
3412 constant_nameandtype *cnt = e;
3413 printf ("NameAndType: ");
3414 utf_display (cnt->name);
3416 utf_display (cnt->descriptor);
3420 printf ("Utf8 -> ");
3424 panic ("Invalid type of ConstantPool-Entry");
3434 /********** Function: class_showmethods (debugging only) *************/
3436 void class_showmethods (classinfo *c)
3440 printf ("--------- Fields and Methods ----------------\n");
3441 printf ("Flags: "); printflags (c->flags); printf ("\n");
3443 printf ("This: "); utf_display (c->name); printf ("\n");
3445 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3447 printf ("Index: %d\n", c->index);
3449 printf ("interfaces:\n");
3450 for (i=0; i < c-> interfacescount; i++) {
3452 utf_display (c -> interfaces[i] -> name);
3453 printf (" (%d)\n", c->interfaces[i] -> index);
3456 printf ("fields:\n");
3457 for (i=0; i < c -> fieldscount; i++) {
3458 field_display (&(c -> fields[i]));
3461 printf ("methods:\n");
3462 for (i=0; i < c -> methodscount; i++) {
3463 methodinfo *m = &(c->methods[i]);
3464 if ( !(m->flags & ACC_STATIC))
3465 printf ("vftblindex: %d ", m->vftblindex);
3467 method_display ( m );
3471 printf ("Virtual function table:\n");
3472 for (i=0; i<c->vftbl->vftbllength; i++) {
3473 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3480 /******************************************************************************/
3481 /******************* General functions for the class loader *******************/
3482 /******************************************************************************/
3484 /********************* Function: loader_load ***********************************
3486 Loads and links the class desired class and each class and interface
3488 Returns: a pointer to this class
3490 *******************************************************************************/
3492 static int loader_load_running = 0;
3494 classinfo *loader_load(utf *topname)
3500 classinfo *notlinkable;
3502 /* avoid recursive calls */
3503 if (loader_load_running)
3504 return class_new(topname);
3506 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3510 loader_load_running++;
3512 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3517 starttime = getcputime();
3519 top = class_new(topname);
3522 while ((c = list_first(&unloadedclasses))) {
3523 if (!class_load(c)) {
3525 dolog("Failed to load class");
3526 list_remove(&unloadedclasses, c);
3533 dolog("Linking...");
3535 /* Added a hack to break infinite linking loops. A better
3536 * linking algorithm would be nice. -Edwin */
3538 while ((c = list_first(&unlinkedclasses))) {
3543 else if (notlinkable == c) {
3544 /* We tried to link this class for the second time and
3545 * no other classes were linked in between, so we are
3549 dolog("Cannot resolve linking dependencies");
3552 throw_linkageerror_message(c->name);
3560 dolog("Linking done.");
3563 loader_compute_subclasses();
3566 if (getloadingtime) {
3567 stoptime = getcputime();
3568 loadingtime += (stoptime - starttime);
3572 loader_load_running--;
3574 /* check if a former loader_load call tried to load/link the class and
3575 failed. This is needed because the class didn't appear in the
3576 undloadclasses or unlinkedclasses list during this class. */
3579 if (linkverbose) dolog("Failed to load class (former call)");
3580 throw_noclassdeffounderror_message(top->name);
3583 } else if (!top->linked) {
3585 dolog("Failed to link class (former call)");
3586 throw_linkageerror_message(top->name);
3591 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3595 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3599 /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3605 /****************** Function: loader_load_sysclass ****************************
3607 Loads and links the class desired class and each class and interface
3610 The pointer to the classinfo is stored in *top if top != NULL.
3611 The pointer is also returned.
3613 If the class could not be loaded the function aborts with an error.
3615 *******************************************************************************/
3617 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3621 if ((cls = loader_load(topname)) == NULL) {
3622 log_plain("Could not load important system class: ");
3623 log_plain_utf(topname);
3625 panic("Could not load important system class");
3628 if (top) *top = cls;
3634 /**************** function: create_primitive_classes ***************************
3636 create classes representing primitive types
3638 ********************************************************************************/
3640 void create_primitive_classes()
3644 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3645 /* create primitive class */
3646 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3647 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3648 c -> impldBy = NULL;
3650 /* prevent loader from loading primitive class */
3651 list_remove (&unloadedclasses, c);
3653 /* add to unlinked classes */
3654 list_addlast (&unlinkedclasses, c);
3655 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3658 primitivetype_table[i].class_primitive = c;
3660 /* create class for wrapping the primitive type */
3661 primitivetype_table[i].class_wrap =
3662 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3663 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3664 primitivetype_table[i].class_wrap -> impldBy = NULL;
3666 /* create the primitive array class */
3667 if (primitivetype_table[i].arrayname) {
3668 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3669 primitivetype_table[i].arrayclass = c;
3671 if (!c->linked) class_link(c);
3672 primitivetype_table[i].arrayvftbl = c->vftbl;
3677 /**************** function: class_primitive_from_sig ***************************
3679 return the primitive class indicated by the given signature character
3681 If the descriptor does not indicate a valid primitive type the
3682 return value is NULL.
3684 ********************************************************************************/
3686 classinfo *class_primitive_from_sig(char sig)
3689 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3690 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3691 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3692 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3693 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3694 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3695 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3696 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3697 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3702 /****************** function: class_from_descriptor ****************************
3704 return the class indicated by the given descriptor
3706 utf_ptr....first character of descriptor
3707 end_ptr....first character after the end of the string
3708 next.......if non-NULL, *next is set to the first character after
3709 the descriptor. (Undefined if an error occurs.)
3711 mode.......a combination (binary or) of the following flags:
3713 (Flags marked with * are the default settings.)
3715 What to do if a reference type descriptor is parsed successfully:
3717 CLASSLOAD_SKIP...skip it and return something != NULL
3718 * CLASSLOAD_NEW....get classinfo * via class_new
3719 CLASSLOAD_LOAD...get classinfo * via loader_load
3721 How to handle primitive types:
3723 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3724 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3726 How to handle "V" descriptors:
3728 * CLASSLOAD_VOID.....handle it like other primitive types
3729 CLASSLOAD_NOVOID...treat it as an error
3731 How to deal with extra characters after the end of the
3734 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3735 CLASSLOAD_CHECKEND.....treat them as an error
3737 How to deal with errors:
3739 * CLASSLOAD_PANIC....abort execution with an error message
3740 CLASSLOAD_NOPANIC..return NULL on error
3742 ********************************************************************************/
3744 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3745 char **next, int mode)
3747 char *start = utf_ptr;
3751 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3753 if (mode & CLASSLOAD_CHECKEND)
3754 error |= (utf_ptr != end_ptr);
3757 if (next) *next = utf_ptr;
3761 if (mode & CLASSLOAD_NOVOID)
3772 return (mode & CLASSLOAD_NULLPRIMITIVE)
3774 : class_primitive_from_sig(*start);
3781 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3782 name = utf_new(start, utf_ptr - start);
3783 return (mode & CLASSLOAD_LOAD)
3784 ? loader_load(name) : class_new(name); /* XXX handle errors */
3788 /* An error occurred */
3789 if (mode & CLASSLOAD_NOPANIC)
3792 log_plain("Invalid descriptor at beginning of '");
3793 log_plain_utf(utf_new(start, end_ptr - start));
3797 panic("Invalid descriptor");
3799 /* keep compiler happy */
3804 /******************* function: type_from_descriptor ****************************
3806 return the basic type indicated by the given descriptor
3808 This function parses a descriptor and returns its basic type as
3809 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3811 cls...if non-NULL the referenced variable is set to the classinfo *
3812 returned by class_from_descriptor.
3814 For documentation of the arguments utf_ptr, end_ptr, next and mode
3815 see class_from_descriptor. The only difference is that
3816 type_from_descriptor always uses CLASSLOAD_PANIC.
3818 ********************************************************************************/
3820 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3821 char **next, int mode)
3824 if (!cls) cls = &mycls;
3825 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3842 return TYPE_ADDRESS;
3847 /*************** function: create_system_exception_classes *******************************
3849 create system exception classes needed by default
3851 ********************************************************************************/
3853 static void create_system_exception_classes()
3856 log_text("loader_init: create_system_exception_classs: loader_load: java/lang/ClassCastException");
3858 loader_load_sysclass(&class_java_lang_ClassCastException,
3859 utf_new_char("java/lang/ClassCastException"));
3860 loader_load_sysclass(&class_java_lang_NullPointerException,
3861 utf_new_char("java/lang/NullPointerException"));
3862 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3863 utf_new_char("java/lang/ArrayIndexOutOfBoundsException"));
3864 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3865 utf_new_char("java/lang/NegativeArraySizeException"));
3866 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3867 utf_new_char("java/lang/OutOfMemoryError"));
3868 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3869 utf_new_char("java/lang/ArrayStoreException"));
3870 loader_load_sysclass(&class_java_lang_ArithmeticException,
3871 utf_new_char("java/lang/ArithmeticException"));
3872 loader_load_sysclass(&class_java_lang_ThreadDeath,
3873 utf_new_char("java/lang/ThreadDeath"));
3877 /*************** function: create_system_exception_classes *******************************
3879 create system exception proto classes needed by default
3881 ********************************************************************************/
3883 static void create_system_exception_proto_classes()
3886 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3887 proto_java_lang_ClassCastException =
3888 builtin_new(class_java_lang_ClassCastException);
3890 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3892 proto_java_lang_NullPointerException =
3893 builtin_new(class_java_lang_NullPointerException);
3894 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3896 proto_java_lang_ArrayIndexOutOfBoundsException =
3897 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3899 proto_java_lang_NegativeArraySizeException =
3900 builtin_new(class_java_lang_NegativeArraySizeException);
3902 proto_java_lang_OutOfMemoryError =
3903 builtin_new(class_java_lang_OutOfMemoryError);
3905 proto_java_lang_ArithmeticException =
3906 builtin_new(class_java_lang_ArithmeticException);
3908 proto_java_lang_ArrayStoreException =
3909 builtin_new(class_java_lang_ArrayStoreException);
3911 proto_java_lang_ThreadDeath =
3912 builtin_new(class_java_lang_ThreadDeath);
3919 /*************** function: create_pseudo_classes *******************************
3921 create pseudo classes used by the typechecker
3923 ********************************************************************************/
3925 static void create_pseudo_classes()
3927 /* pseudo class for Arraystubs (extends java.lang.Object) */
3929 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3930 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3932 pseudo_class_Arraystub->super = class_java_lang_Object;
3933 pseudo_class_Arraystub->interfacescount = 2;
3934 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3935 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3936 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3938 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3939 class_link(pseudo_class_Arraystub);
3941 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3943 /* pseudo class representing the null type */
3945 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3946 list_remove(&unloadedclasses, pseudo_class_Null);
3948 pseudo_class_Null->super = class_java_lang_Object;
3950 list_addlast(&unlinkedclasses, pseudo_class_Null);
3951 class_link(pseudo_class_Null);
3953 /* pseudo class representing new uninitialized objects */
3955 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3956 list_remove(&unloadedclasses, pseudo_class_New);
3958 pseudo_class_New->super = class_java_lang_Object;
3960 list_addlast(&unlinkedclasses, pseudo_class_New);
3961 class_link(pseudo_class_New);
3965 /********************** Function: loader_init **********************************
3967 Initializes all lists and loads all classes required for the system or the
3970 *******************************************************************************/
3972 void loader_init(u1 *stackbottom)
3976 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3977 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3978 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3980 /* create utf-symbols for pointer comparison of frequently used strings */
3981 utf_innerclasses = utf_new_char("InnerClasses");
3982 utf_constantvalue = utf_new_char("ConstantValue");
3983 utf_code = utf_new_char("Code");
3984 utf_exceptions = utf_new_char("Exceptions");
3985 utf_linenumbertable = utf_new_char("LineNumberTable");
3986 utf_sourcefile = utf_new_char("SourceFile");
3987 utf_finalize = utf_new_char("finalize");
3988 utf_fidesc = utf_new_char("()V");
3989 utf_init = utf_new_char("<init>");
3990 utf_clinit = utf_new_char("<clinit>");
3991 utf_initsystemclass = utf_new_char("initializeSystemClass");
3992 utf_systemclass = utf_new_char("java/lang/System");
3993 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3994 utf_initialize = utf_new_char("initialize");
3995 utf_initializedesc = utf_new_char("(I)V");
3997 utf_vmclass = utf_new_char("java/lang/VMClass");
3998 utf_java_lang_Object= utf_new_char("java/lang/Object");
4000 array_packagename = utf_new_char("<the array package>");
4002 /* create some important classes */
4003 /* These classes have to be created now because the classinfo
4004 * pointers are used in the loading code.
4006 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
4007 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
4008 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
4009 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
4011 if (verbose) log_text("loader_init: java/lang/Object");
4012 /* load the classes which were created above */
4013 loader_load_sysclass(NULL, class_java_lang_Object->name);
4015 loader_inited = 1; /*JOWENN*/
4017 loader_load_sysclass(&class_java_lang_Throwable,
4018 utf_new_char("java/lang/Throwable"));
4020 create_system_exception_classes();
4022 /* create classes representing primitive types */
4023 create_primitive_classes();
4025 /* create classes used by the typechecker */
4026 create_pseudo_classes();
4028 /* correct vftbl-entries (retarded loading of class java/lang/String) */
4029 stringtable_update();
4031 #if defined(USE_THREADS)
4035 create_system_exception_proto_classes();
4041 /********************* Function: loader_initclasses ****************************
4043 Initializes all loaded but uninitialized classes
4045 *******************************************************************************/
4048 /* XXX TWISTI: i think we do not need this */
4049 void loader_initclasses ()
4053 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4054 pthread_mutex_lock(&compiler_mutex);
4057 intsDisable(); /* schani */
4059 if (makeinitializations) {
4060 c = list_first(&linkedclasses);
4063 c = list_next(&linkedclasses, c);
4067 intsRestore(); /* schani */
4069 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4070 pthread_mutex_unlock(&compiler_mutex);
4076 static void loader_compute_class_values(classinfo *c)
4080 c->vftbl->baseval = ++classvalue;
4083 while (subs != NULL) {
4084 loader_compute_class_values(subs);
4085 subs = subs->nextsub;
4087 c->vftbl->diffval = classvalue - c->vftbl->baseval;
4092 for (i = 0; i < c->index; i++)
4094 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
4095 utf_display(c->name);
4102 void loader_compute_subclasses()
4106 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4107 intsDisable(); /* schani */
4110 c = list_first(&linkedclasses);
4112 if (!(c->flags & ACC_INTERFACE)) {
4116 c = list_next(&linkedclasses, c);
4119 c = list_first(&linkedclasses);
4121 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
4122 c->nextsub = c->super->sub;
4125 c = list_next(&linkedclasses, c);
4129 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4132 loader_compute_class_values(class_java_lang_Object);
4133 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4137 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4138 intsRestore(); /* schani */
4143 /******************** function classloader_buffer ******************************
4145 sets buffer for reading classdata
4147 *******************************************************************************/
4149 void classload_buffer(u1 *buf, int len)
4152 classbuffer_size = len;
4153 classbuf_pos = buf - 1;
4157 /******************** Function: loader_close ***********************************
4161 *******************************************************************************/
4167 while ((c = list_first(&unloadedclasses))) {
4168 list_remove(&unloadedclasses, c);
4169 /* class_free(c); */
4171 while ((c = list_first(&unlinkedclasses))) {
4172 list_remove(&unlinkedclasses, c);
4173 /* class_free(c); */
4175 while ((c = list_first(&linkedclasses))) {
4176 list_remove(&linkedclasses, c);
4177 /* class_free(c); */
4183 * These are local overrides for various environment variables in Emacs.
4184 * Please do not remove this and leave it at the end of the file, where
4185 * Emacs will automagically detect them.
4186 * ---------------------------------------------------------------------
4189 * indent-tabs-mode: t