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 972 2004-03-24 22:48:01Z edwin $
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)
3089 native_stackframeinfo **info;
3091 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3095 if (!makeinitializations)
3100 c->initialized = true;
3103 count_class_inits++;
3106 /* initialize super class */
3109 char logtext[MAXLOGTEXT];
3110 sprintf(logtext, "Initialize super class ");
3111 utf_sprint(logtext + strlen(logtext), c->super->name);
3112 sprintf(logtext + strlen(logtext), " from ");
3113 utf_sprint(logtext + strlen(logtext), c->name);
3116 class_init(c->super);
3119 /* initialize interface classes */
3120 for (i = 0; i < c->interfacescount; i++) {
3122 char logtext[MAXLOGTEXT];
3123 sprintf(logtext, "Initialize interface class ");
3124 utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
3125 sprintf(logtext + strlen(logtext), " from ");
3126 utf_sprint(logtext + strlen(logtext), c->name);
3129 class_init(c->interfaces[i]); /* real */
3132 m = class_findmethod(c, utf_clinit, utf_fidesc);
3135 char logtext[MAXLOGTEXT];
3136 sprintf(logtext, "Class ");
3137 utf_sprint(logtext + strlen(logtext), c->name);
3138 sprintf(logtext + strlen(logtext), " has no initializer");
3141 /* goto callinitialize;*/
3145 if (!(m->flags & ACC_STATIC))
3146 panic("Class initializer is not static!");
3149 char logtext[MAXLOGTEXT];
3150 sprintf(logtext, "Starting initializer for class: ");
3151 utf_sprint(logtext + strlen(logtext), c->name);
3155 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3160 /* now call the initializer */
3161 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3163 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3164 assert(blockInts == 0);
3168 /* we have to throw an exception */
3169 if (*exceptionptr) {
3170 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
3171 printf("Caused by: ");
3172 utf_display((*exceptionptr)->vftbl->class->name);
3174 /* do we have a detail message? */
3175 if (((java_lang_Throwable *) *exceptionptr)->detailMessage) {
3177 utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false));
3186 char logtext[MAXLOGTEXT];
3187 sprintf(logtext, "Finished initializer for class: ");
3188 utf_sprint(logtext + strlen(logtext), c->name);
3192 if (c->name == utf_systemclass) {
3193 /* class java.lang.System requires explicit initialization */
3196 printf("#### Initializing class System");
3198 /* find initializing method */
3199 m = class_findmethod(c,
3200 utf_initsystemclass,
3204 /* no method found */
3205 /* printf("initializeSystemClass failed"); */
3209 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3214 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
3216 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3217 assert(blockInts == 0);
3221 if (*exceptionptr) {
3222 printf("#### initializeSystemClass has thrown: ");
3223 utf_display((*exceptionptr)->vftbl->class->name);
3231 /********* Function: find_class_method_constant *********/
3233 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
3238 for (i=0; i<c->cpcount; i++) {
3240 e = c -> cpinfos [i];
3243 switch (c -> cptags [i]) {
3244 case CONSTANT_Methodref:
3246 constant_FMIref *fmi = e;
3247 if ( (fmi->class->name == c1)
3248 && (fmi->name == m1)
3249 && (fmi->descriptor == d1)) {
3256 case CONSTANT_InterfaceMethodref:
3258 constant_FMIref *fmi = e;
3259 if ( (fmi->class->name == c1)
3260 && (fmi->name == m1)
3261 && (fmi->descriptor == d1)) {
3275 void class_showconstanti(classinfo *c, int ii)
3281 printf ("#%d: ", (int) i);
3283 switch (c->cptags [i]) {
3284 case CONSTANT_Class:
3285 printf("Classreference -> ");
3286 utf_display(((classinfo*)e)->name);
3289 case CONSTANT_Fieldref:
3290 printf("Fieldref -> "); goto displayFMIi;
3291 case CONSTANT_Methodref:
3292 printf("Methodref -> "); goto displayFMIi;
3293 case CONSTANT_InterfaceMethodref:
3294 printf("InterfaceMethod -> "); goto displayFMIi;
3297 constant_FMIref *fmi = e;
3298 utf_display(fmi->class->name);
3300 utf_display(fmi->name);
3302 utf_display(fmi->descriptor);
3306 case CONSTANT_String:
3307 printf("String -> ");
3310 case CONSTANT_Integer:
3311 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
3313 case CONSTANT_Float:
3314 printf("Float -> %f", ((constant_float*)e)->value);
3316 case CONSTANT_Double:
3317 printf("Double -> %f", ((constant_double*)e)->value);
3321 u8 v = ((constant_long*)e)->value;
3323 printf("Long -> %ld", (long int) v);
3325 printf("Long -> HI: %ld, LO: %ld\n",
3326 (long int) v.high, (long int) v.low);
3330 case CONSTANT_NameAndType:
3332 constant_nameandtype *cnt = e;
3333 printf("NameAndType: ");
3334 utf_display(cnt->name);
3336 utf_display(cnt->descriptor);
3344 panic("Invalid type of ConstantPool-Entry");
3351 void class_showconstantpool (classinfo *c)
3356 printf ("---- dump of constant pool ----\n");
3358 for (i=0; i<c->cpcount; i++) {
3359 printf ("#%d: ", (int) i);
3361 e = c -> cpinfos [i];
3364 switch (c -> cptags [i]) {
3365 case CONSTANT_Class:
3366 printf ("Classreference -> ");
3367 utf_display ( ((classinfo*)e) -> name );
3370 case CONSTANT_Fieldref:
3371 printf ("Fieldref -> "); goto displayFMI;
3372 case CONSTANT_Methodref:
3373 printf ("Methodref -> "); goto displayFMI;
3374 case CONSTANT_InterfaceMethodref:
3375 printf ("InterfaceMethod -> "); goto displayFMI;
3378 constant_FMIref *fmi = e;
3379 utf_display ( fmi->class->name );
3381 utf_display ( fmi->name);
3383 utf_display ( fmi->descriptor );
3387 case CONSTANT_String:
3388 printf ("String -> ");
3391 case CONSTANT_Integer:
3392 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
3394 case CONSTANT_Float:
3395 printf ("Float -> %f", ((constant_float*)e) -> value);
3397 case CONSTANT_Double:
3398 printf ("Double -> %f", ((constant_double*)e) -> value);
3402 u8 v = ((constant_long*)e) -> value;
3404 printf ("Long -> %ld", (long int) v);
3406 printf ("Long -> HI: %ld, LO: %ld\n",
3407 (long int) v.high, (long int) v.low);
3411 case CONSTANT_NameAndType:
3413 constant_nameandtype *cnt = e;
3414 printf ("NameAndType: ");
3415 utf_display (cnt->name);
3417 utf_display (cnt->descriptor);
3421 printf ("Utf8 -> ");
3425 panic ("Invalid type of ConstantPool-Entry");
3435 /********** Function: class_showmethods (debugging only) *************/
3437 void class_showmethods (classinfo *c)
3441 printf ("--------- Fields and Methods ----------------\n");
3442 printf ("Flags: "); printflags (c->flags); printf ("\n");
3444 printf ("This: "); utf_display (c->name); printf ("\n");
3446 printf ("Super: "); utf_display (c->super->name); printf ("\n");
3448 printf ("Index: %d\n", c->index);
3450 printf ("interfaces:\n");
3451 for (i=0; i < c-> interfacescount; i++) {
3453 utf_display (c -> interfaces[i] -> name);
3454 printf (" (%d)\n", c->interfaces[i] -> index);
3457 printf ("fields:\n");
3458 for (i=0; i < c -> fieldscount; i++) {
3459 field_display (&(c -> fields[i]));
3462 printf ("methods:\n");
3463 for (i=0; i < c -> methodscount; i++) {
3464 methodinfo *m = &(c->methods[i]);
3465 if ( !(m->flags & ACC_STATIC))
3466 printf ("vftblindex: %d ", m->vftblindex);
3468 method_display ( m );
3472 printf ("Virtual function table:\n");
3473 for (i=0; i<c->vftbl->vftbllength; i++) {
3474 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
3481 /******************************************************************************/
3482 /******************* General functions for the class loader *******************/
3483 /******************************************************************************/
3485 /********************* Function: loader_load ***********************************
3487 Loads and links the class desired class and each class and interface
3489 Returns: a pointer to this class
3491 *******************************************************************************/
3493 static int loader_load_running = 0;
3495 classinfo *loader_load(utf *topname)
3501 classinfo *notlinkable;
3503 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3504 pthread_mutex_lock(&compiler_mutex);
3507 /* avoid recursive calls */
3508 if (loader_load_running)
3509 return class_new(topname);
3511 loader_load_running++;
3513 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3518 starttime = getcputime();
3520 top = class_new(topname);
3523 while ((c = list_first(&unloadedclasses))) {
3524 if (!class_load(c)) {
3526 dolog("Failed to load class");
3527 list_remove(&unloadedclasses, c);
3534 dolog("Linking...");
3536 /* Added a hack to break infinite linking loops. A better
3537 * linking algorithm would be nice. -Edwin */
3539 while ((c = list_first(&unlinkedclasses))) {
3544 else if (notlinkable == c) {
3545 /* We tried to link this class for the second time and
3546 * no other classes were linked in between, so we are
3550 dolog("Cannot resolve linking dependencies");
3553 throw_linkageerror_message(c->name);
3561 dolog("Linking done.");
3564 loader_compute_subclasses();
3567 if (getloadingtime) {
3568 stoptime = getcputime();
3569 loadingtime += (stoptime - starttime);
3573 loader_load_running--;
3575 /* check if a former loader_load call tried to load/link the class and
3576 failed. This is needed because the class didn't appear in the
3577 undloadclasses or unlinkedclasses list during this class. */
3580 if (linkverbose) dolog("Failed to load class (former call)");
3581 throw_noclassdeffounderror_message(top->name);
3584 } else if (!top->linked) {
3586 dolog("Failed to link class (former call)");
3587 throw_linkageerror_message(top->name);
3592 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
3596 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3597 pthread_mutex_unlock(&compiler_mutex);
3600 /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
3606 /****************** Function: loader_load_sysclass ****************************
3608 Loads and links the class desired class and each class and interface
3611 The pointer to the classinfo is stored in *top if top != NULL.
3612 The pointer is also returned.
3614 If the class could not be loaded the function aborts with an error.
3616 *******************************************************************************/
3618 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3622 if ((cls = loader_load(topname)) == NULL) {
3623 log_plain("Could not load important system class: ");
3624 log_plain_utf(topname);
3626 panic("Could not load important system class");
3629 if (top) *top = cls;
3635 /**************** function: create_primitive_classes ***************************
3637 create classes representing primitive types
3639 ********************************************************************************/
3641 void create_primitive_classes()
3645 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3646 /* create primitive class */
3647 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3648 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3649 c -> impldBy = NULL;
3651 /* prevent loader from loading primitive class */
3652 list_remove (&unloadedclasses, c);
3654 /* add to unlinked classes */
3655 list_addlast (&unlinkedclasses, c);
3656 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3659 primitivetype_table[i].class_primitive = c;
3661 /* create class for wrapping the primitive type */
3662 primitivetype_table[i].class_wrap =
3663 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3664 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3665 primitivetype_table[i].class_wrap -> impldBy = NULL;
3667 /* create the primitive array class */
3668 if (primitivetype_table[i].arrayname) {
3669 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3670 primitivetype_table[i].arrayclass = c;
3672 if (!c->linked) class_link(c);
3673 primitivetype_table[i].arrayvftbl = c->vftbl;
3678 /**************** function: class_primitive_from_sig ***************************
3680 return the primitive class indicated by the given signature character
3682 If the descriptor does not indicate a valid primitive type the
3683 return value is NULL.
3685 ********************************************************************************/
3687 classinfo *class_primitive_from_sig(char sig)
3690 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3691 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3692 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3693 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3694 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3695 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3696 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3697 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3698 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3703 /****************** function: class_from_descriptor ****************************
3705 return the class indicated by the given descriptor
3707 utf_ptr....first character of descriptor
3708 end_ptr....first character after the end of the string
3709 next.......if non-NULL, *next is set to the first character after
3710 the descriptor. (Undefined if an error occurs.)
3712 mode.......a combination (binary or) of the following flags:
3714 (Flags marked with * are the default settings.)
3716 What to do if a reference type descriptor is parsed successfully:
3718 CLASSLOAD_SKIP...skip it and return something != NULL
3719 * CLASSLOAD_NEW....get classinfo * via class_new
3720 CLASSLOAD_LOAD...get classinfo * via loader_load
3722 How to handle primitive types:
3724 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3725 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3727 How to handle "V" descriptors:
3729 * CLASSLOAD_VOID.....handle it like other primitive types
3730 CLASSLOAD_NOVOID...treat it as an error
3732 How to deal with extra characters after the end of the
3735 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3736 CLASSLOAD_CHECKEND.....treat them as an error
3738 How to deal with errors:
3740 * CLASSLOAD_PANIC....abort execution with an error message
3741 CLASSLOAD_NOPANIC..return NULL on error
3743 ********************************************************************************/
3745 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3746 char **next, int mode)
3748 char *start = utf_ptr;
3752 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
3754 if (mode & CLASSLOAD_CHECKEND)
3755 error |= (utf_ptr != end_ptr);
3758 if (next) *next = utf_ptr;
3762 if (mode & CLASSLOAD_NOVOID)
3773 return (mode & CLASSLOAD_NULLPRIMITIVE)
3775 : class_primitive_from_sig(*start);
3782 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3783 name = utf_new(start, utf_ptr - start);
3784 return (mode & CLASSLOAD_LOAD)
3785 ? loader_load(name) : class_new(name); /* XXX handle errors */
3789 /* An error occurred */
3790 if (mode & CLASSLOAD_NOPANIC)
3793 log_plain("Invalid descriptor at beginning of '");
3794 log_plain_utf(utf_new(start, end_ptr - start));
3798 panic("Invalid descriptor");
3800 /* keep compiler happy */
3805 /******************* function: type_from_descriptor ****************************
3807 return the basic type indicated by the given descriptor
3809 This function parses a descriptor and returns its basic type as
3810 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3812 cls...if non-NULL the referenced variable is set to the classinfo *
3813 returned by class_from_descriptor.
3815 For documentation of the arguments utf_ptr, end_ptr, next and mode
3816 see class_from_descriptor. The only difference is that
3817 type_from_descriptor always uses CLASSLOAD_PANIC.
3819 ********************************************************************************/
3821 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3822 char **next, int mode)
3825 if (!cls) cls = &mycls;
3826 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3843 return TYPE_ADDRESS;
3848 /*************** function: create_system_exception_classes *******************************
3850 create system exception classes needed by default
3852 ********************************************************************************/
3854 static void create_system_exception_classes()
3857 log_text("loader_init: create_system_exception_classs: loader_load: java/lang/ClassCastException");
3859 loader_load_sysclass(&class_java_lang_ClassCastException,
3860 utf_new_char("java/lang/ClassCastException"));
3861 loader_load_sysclass(&class_java_lang_NullPointerException,
3862 utf_new_char("java/lang/NullPointerException"));
3863 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3864 utf_new_char("java/lang/ArrayIndexOutOfBoundsException"));
3865 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3866 utf_new_char("java/lang/NegativeArraySizeException"));
3867 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3868 utf_new_char("java/lang/OutOfMemoryError"));
3869 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3870 utf_new_char("java/lang/ArrayStoreException"));
3871 loader_load_sysclass(&class_java_lang_ArithmeticException,
3872 utf_new_char("java/lang/ArithmeticException"));
3873 loader_load_sysclass(&class_java_lang_ThreadDeath,
3874 utf_new_char("java/lang/ThreadDeath"));
3878 /*************** function: create_system_exception_classes *******************************
3880 create system exception proto classes needed by default
3882 ********************************************************************************/
3884 static void create_system_exception_proto_classes()
3887 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3888 proto_java_lang_ClassCastException =
3889 builtin_new(class_java_lang_ClassCastException);
3891 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3893 proto_java_lang_NullPointerException =
3894 builtin_new(class_java_lang_NullPointerException);
3895 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3897 proto_java_lang_ArrayIndexOutOfBoundsException =
3898 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3900 proto_java_lang_NegativeArraySizeException =
3901 builtin_new(class_java_lang_NegativeArraySizeException);
3903 proto_java_lang_OutOfMemoryError =
3904 builtin_new(class_java_lang_OutOfMemoryError);
3906 proto_java_lang_ArithmeticException =
3907 builtin_new(class_java_lang_ArithmeticException);
3909 proto_java_lang_ArrayStoreException =
3910 builtin_new(class_java_lang_ArrayStoreException);
3912 proto_java_lang_ThreadDeath =
3913 builtin_new(class_java_lang_ThreadDeath);
3920 /*************** function: create_pseudo_classes *******************************
3922 create pseudo classes used by the typechecker
3924 ********************************************************************************/
3926 static void create_pseudo_classes()
3928 /* pseudo class for Arraystubs (extends java.lang.Object) */
3930 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3931 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3933 pseudo_class_Arraystub->super = class_java_lang_Object;
3934 pseudo_class_Arraystub->interfacescount = 2;
3935 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3936 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3937 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3939 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3940 class_link(pseudo_class_Arraystub);
3942 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3944 /* pseudo class representing the null type */
3946 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3947 list_remove(&unloadedclasses, pseudo_class_Null);
3949 pseudo_class_Null->super = class_java_lang_Object;
3951 list_addlast(&unlinkedclasses, pseudo_class_Null);
3952 class_link(pseudo_class_Null);
3954 /* pseudo class representing new uninitialized objects */
3956 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3957 list_remove(&unloadedclasses, pseudo_class_New);
3959 pseudo_class_New->super = class_java_lang_Object;
3961 list_addlast(&unlinkedclasses, pseudo_class_New);
3962 class_link(pseudo_class_New);
3966 /********************** Function: loader_init **********************************
3968 Initializes all lists and loads all classes required for the system or the
3971 *******************************************************************************/
3973 void loader_init(u1 *stackbottom)
3977 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3978 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3979 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3981 /* create utf-symbols for pointer comparison of frequently used strings */
3982 utf_innerclasses = utf_new_char("InnerClasses");
3983 utf_constantvalue = utf_new_char("ConstantValue");
3984 utf_code = utf_new_char("Code");
3985 utf_exceptions = utf_new_char("Exceptions");
3986 utf_linenumbertable = utf_new_char("LineNumberTable");
3987 utf_sourcefile = utf_new_char("SourceFile");
3988 utf_finalize = utf_new_char("finalize");
3989 utf_fidesc = utf_new_char("()V");
3990 utf_init = utf_new_char("<init>");
3991 utf_clinit = utf_new_char("<clinit>");
3992 utf_initsystemclass = utf_new_char("initializeSystemClass");
3993 utf_systemclass = utf_new_char("java/lang/System");
3994 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3995 utf_initialize = utf_new_char("initialize");
3996 utf_initializedesc = utf_new_char("(I)V");
3998 utf_vmclass = utf_new_char("java/lang/VMClass");
3999 utf_java_lang_Object= utf_new_char("java/lang/Object");
4001 array_packagename = utf_new_char("<the array package>");
4003 /* create some important classes */
4004 /* These classes have to be created now because the classinfo
4005 * pointers are used in the loading code.
4007 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
4008 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
4009 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
4010 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
4012 if (verbose) log_text("loader_init: java/lang/Object");
4013 /* load the classes which were created above */
4014 loader_load_sysclass(NULL, class_java_lang_Object->name);
4016 loader_inited = 1; /*JOWENN*/
4018 loader_load_sysclass(&class_java_lang_Throwable,
4019 utf_new_char("java/lang/Throwable"));
4021 create_system_exception_classes();
4023 /* create classes representing primitive types */
4024 create_primitive_classes();
4026 /* create classes used by the typechecker */
4027 create_pseudo_classes();
4029 /* correct vftbl-entries (retarded loading of class java/lang/String) */
4030 stringtable_update();
4032 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4036 create_system_exception_proto_classes();
4042 /********************* Function: loader_initclasses ****************************
4044 Initializes all loaded but uninitialized classes
4046 *******************************************************************************/
4049 /* XXX TWISTI: i think we do not need this */
4050 void loader_initclasses ()
4054 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4055 pthread_mutex_lock(&compiler_mutex);
4058 intsDisable(); /* schani */
4060 if (makeinitializations) {
4061 c = list_first(&linkedclasses);
4064 c = list_next(&linkedclasses, c);
4068 intsRestore(); /* schani */
4070 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4071 pthread_mutex_unlock(&compiler_mutex);
4077 static void loader_compute_class_values(classinfo *c)
4081 c->vftbl->baseval = ++classvalue;
4084 while (subs != NULL) {
4085 loader_compute_class_values(subs);
4086 subs = subs->nextsub;
4088 c->vftbl->diffval = classvalue - c->vftbl->baseval;
4093 for (i = 0; i < c->index; i++)
4095 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
4096 utf_display(c->name);
4103 void loader_compute_subclasses()
4107 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4108 intsDisable(); /* schani */
4111 c = list_first(&linkedclasses);
4113 if (!(c->flags & ACC_INTERFACE)) {
4117 c = list_next(&linkedclasses, c);
4120 c = list_first(&linkedclasses);
4122 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
4123 c->nextsub = c->super->sub;
4126 c = list_next(&linkedclasses, c);
4130 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4133 loader_compute_class_values(class_java_lang_Object);
4134 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4138 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
4139 intsRestore(); /* schani */
4144 /******************** function classloader_buffer ******************************
4146 sets buffer for reading classdata
4148 *******************************************************************************/
4150 void classload_buffer(u1 *buf, int len)
4153 classbuffer_size = len;
4154 classbuf_pos = buf - 1;
4158 /******************** Function: loader_close ***********************************
4162 *******************************************************************************/
4168 while ((c = list_first(&unloadedclasses))) {
4169 list_remove(&unloadedclasses, c);
4170 /* class_free(c); */
4172 while ((c = list_first(&unlinkedclasses))) {
4173 list_remove(&unlinkedclasses, c);
4174 /* class_free(c); */
4176 while ((c = list_first(&linkedclasses))) {
4177 list_remove(&linkedclasses, c);
4178 /* class_free(c); */
4184 * These are local overrides for various environment variables in Emacs.
4185 * Please do not remove this and leave it at the end of the file, where
4186 * Emacs will automagically detect them.
4187 * ---------------------------------------------------------------------
4190 * indent-tabs-mode: t