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 849 2004-01-05 21:27:29Z stefan $
50 #include "toolbox/memory.h"
51 #include "toolbox/loging.h"
52 #include "threads/thread.h"
53 #include "threads/locks.h"
64 /* global variables ***********************************************************/
66 int count_class_infos = 0; /* variables for measurements */
67 int count_const_pool_len = 0;
68 int count_vftbl_len = 0;
69 int count_all_methods = 0;
70 int count_vmcode_len = 0;
71 int count_extable_len = 0;
72 int count_class_loads = 0;
73 int count_class_inits = 0;
75 static s4 interfaceindex; /* sequential numbering of interfaces */
78 list unloadedclasses; /* list of all referenced but not loaded classes */
79 list unlinkedclasses; /* list of all loaded but not linked classes */
80 list linkedclasses; /* list of all completely linked classes */
83 /* utf-symbols for pointer comparison of frequently used strings */
85 static utf *utf_innerclasses; /* InnerClasses */
86 static utf *utf_constantvalue; /* ConstantValue */
87 static utf *utf_code; /* Code */
88 static utf *utf_finalize; /* finalize */
89 static utf *utf_fidesc; /* ()V changed */
90 static utf *utf_clinit; /* <clinit> */
91 static utf *utf_initsystemclass; /* initializeSystemClass */
92 static utf *utf_systemclass; /* java/lang/System */
93 static utf *utf_vmclassloader; /* java/lang/VMClassLoader */
94 static utf *utf_vmclass; /* java/lang/VMClassLoader */
95 static utf *utf_initialize;
96 static utf *utf_initializedesc;
109 /* important system classes ***************************************************/
111 classinfo *class_java_lang_Object;
112 classinfo *class_java_lang_String;
114 classinfo *class_java_lang_Throwable;
115 classinfo *class_java_lang_Cloneable;
116 classinfo *class_java_io_Serializable;
118 /* Pseudo classes for the typechecker */
119 classinfo *pseudo_class_Arraystub = NULL;
120 classinfo *pseudo_class_Null = NULL;
121 classinfo *pseudo_class_New = NULL;
122 vftbl *pseudo_class_Arraystub_vftbl = NULL;
125 /* These are made static so they cannot be used for throwing in native */
127 static classinfo *class_java_lang_ClassCastException;
128 static classinfo *class_java_lang_NullPointerException;
129 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
130 static classinfo *class_java_lang_NegativeArraySizeException;
131 static classinfo *class_java_lang_OutOfMemoryError;
132 static classinfo *class_java_lang_ArithmeticException;
133 static classinfo *class_java_lang_ArrayStoreException;
134 static classinfo *class_java_lang_ThreadDeath;
136 static methodinfo method_clone_array;
138 static int loader_inited = 0;
141 /********************************************************************
142 list of classpath entries (either filesystem directories or
144 ********************************************************************/
145 static classpath_info *classpath_entries=0;
148 /******************************************************************************
150 structure for primitive classes: contains the class for wrapping the
151 primitive type, the primitive class, the name of the class for wrapping,
152 the one character type signature and the name of the primitive class
154 ******************************************************************************/
156 /* CAUTION: Don't change the order of the types. This table is indexed
157 * by the ARRAYTYPE_ constants (expcept ARRAYTYPE_OBJECT).
159 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
160 { NULL, NULL, "java/lang/Integer", 'I', "int" , "[I", NULL, NULL },
161 { NULL, NULL, "java/lang/Long", 'J', "long" , "[J", NULL, NULL },
162 { NULL, NULL, "java/lang/Float", 'F', "float" , "[F", NULL, NULL },
163 { NULL, NULL, "java/lang/Double", 'D', "double" , "[D", NULL, NULL },
164 { NULL, NULL, "java/lang/Byte", 'B', "byte" , "[B", NULL, NULL },
165 { NULL, NULL, "java/lang/Character", 'C', "char" , "[C", NULL, NULL },
166 { NULL, NULL, "java/lang/Short", 'S', "short" , "[S", NULL, NULL },
167 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" , "[Z", NULL, NULL },
168 { NULL, NULL, "java/lang/Void", 'V', "void" , NULL, NULL, NULL }
172 /* instances of important system classes **************************************/
174 java_objectheader *proto_java_lang_ClassCastException;
175 java_objectheader *proto_java_lang_NullPointerException;
176 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
177 java_objectheader *proto_java_lang_NegativeArraySizeException;
178 java_objectheader *proto_java_lang_OutOfMemoryError;
179 java_objectheader *proto_java_lang_ArithmeticException;
180 java_objectheader *proto_java_lang_ArrayStoreException;
181 java_objectheader *proto_java_lang_ThreadDeath;
183 /************* functions for reading classdata *********************************
185 getting classdata in blocks of variable size
186 (8,16,32,64-bit integer or float)
188 *******************************************************************************/
190 static char *classpath = ""; /* searchpath for classfiles */
191 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
192 static u1 *classbuf_pos; /* current position in classfile buffer */
193 static int classbuffer_size; /* size of classfile-data */
195 /* assert that at least <len> bytes are left to read */
196 /* <len> is limited to the range of non-negative s4 values */
197 #define ASSERT_LEFT(len) \
198 do {if ( ((s4)(len)) < 0 \
199 || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
200 panic("Unexpected end of classfile"); } while(0)
202 /* transfer block of classfile data into a buffer */
204 #define suck_nbytes(buffer,len) \
205 do {ASSERT_LEFT(len); \
206 memcpy(buffer,classbuf_pos+1,len); \
207 classbuf_pos+=len;} while (0)
209 /* skip block of classfile data */
211 #define skip_nbytes(len) \
212 do {ASSERT_LEFT(len); \
213 classbuf_pos+=len;} while(0)
218 return *++classbuf_pos;
222 u1 a=suck_u1(), b=suck_u1();
223 return ((u2)a<<8)+(u2)b;
227 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
228 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
230 #define suck_s8() (s8) suck_u8()
231 #define suck_s2() (s2) suck_u2()
232 #define suck_s4() (s4) suck_u4()
233 #define suck_s1() (s1) suck_u1()
236 /* get u8 from classfile data */
243 return (hi << 32) + lo;
253 /* get float from classfile data */
254 static float suck_float()
261 for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
262 memcpy((u1*) (&f), buffer, 4);
264 suck_nbytes((u1*) (&f), 4);
267 PANICIF (sizeof(float) != 4, "Incompatible float-format");
273 /* get double from classfile data */
274 static double suck_double()
281 for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
282 memcpy((u1*) (&d), buffer, 8);
284 suck_nbytes((u1*) (&d), 8);
287 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
293 /************************** function suck_init *********************************
295 called once at startup, sets the searchpath for the classfiles
297 *******************************************************************************/
299 void suck_init(char *cpath)
306 union classpath_info *tmp;
307 union classpath_info *insertAfter=0;
312 if (classpath_entries) panic("suck_init should be called only once");
313 for(start=classpath;(*start)!='\0';) {
314 for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
317 filenamelen=(end-start);
351 ( ( (*(end - 1)) == 'p') || ( (*(end - 1)) == 'P')) &&
352 (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
353 (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z')))
356 } else if ( (( (*(end - 1)) == 'r') || ( (*(end - 1)) == 'R')) &&
357 ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
358 (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
363 if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init");
365 filename=(char*)malloc(CLASSPATH_MAXFILENAME);
366 strncpy(filename,start,filenamelen);
367 filename[filenamelen+1]='\0';
372 unzFile uf=unzOpen(filename);
374 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
375 tmp->archive.type=CLASSPATH_ARCHIVE;
381 panic("Zip/JAR not supported");
385 tmp=(union classpath_info*)malloc(sizeof(classpath_info));
386 tmp->filepath.type=CLASSPATH_PATH;
387 tmp->filepath.next=0;
388 if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
389 filename[filenamelen]='/';
390 filename[filenamelen+1]='\0';
394 tmp->filepath.filename=filename;
395 tmp->filepath.pathlen=filenamelen;
401 insertAfter->filepath.next=tmp;
403 classpath_entries=tmp;
408 if ((*end)==':') start=end+1; else start=end;
411 if (filename!=0) free(filename);
416 /************************** function suck_start ********************************
418 returns true if classbuffer is already loaded or a file for the
419 specified class has succussfully been read in. All directories of
420 the searchpath are used to find the classfile (<classname>.class).
421 Returns false if no classfile is found and writes an error message.
423 *******************************************************************************/
425 bool suck_start(utf *classname)
427 classpath_info *currPos;
430 char filename[CLASSPATH_MAXFILENAME+10]; /* room for '.class' */
436 if (classbuffer) return true; /* classbuffer is already valid */
438 utf_ptr = classname->text;
439 while (utf_ptr < utf_end(classname)) {
440 PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
442 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
444 filename[filenamelen++] = c;
446 strcpy(filename + filenamelen, ".class");
448 for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
450 if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
451 if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
452 unz_file_info file_info;
453 /*log_text("Class found in zip file");*/
454 if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
455 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
456 if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
457 classbuffer_size = file_info.uncompressed_size;
458 classbuffer = MNEW(u1, classbuffer_size);
459 classbuf_pos = classbuffer - 1;
460 /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
461 if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
462 unzCloseCurrentFile(currPos->archive.uf);
465 MFREE(classbuffer, u1, classbuffer_size);
466 log_text("Error while unzipping");
468 } else log_text("Error while opening file in archive");
469 } else log_text("Error while retrieving fileinfo");
471 unzCloseCurrentFile(currPos->archive.uf);
475 if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
476 strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
477 classfile = fopen(currPos->filepath.filename, "r");
478 if (classfile) { /* file exists */
480 /* determine size of classfile */
482 /* dolog("File: %s",filename); */
484 err = stat(currPos->filepath.filename, &buffer);
486 if (!err) { /* read classfile data */
487 classbuffer_size = buffer.st_size;
488 classbuffer = MNEW(u1, classbuffer_size);
489 classbuf_pos = classbuffer - 1;
490 fread(classbuffer, 1, classbuffer_size, classfile);
501 dolog("Warning: Can not open class file '%s'", filename);
508 /************************** function suck_stop *********************************
510 frees memory for buffer with classfile data.
511 Caution: this function may only be called if buffer has been allocated
512 by suck_start with reading a file
514 *******************************************************************************/
518 /* determine amount of classdata not retrieved by suck-operations */
520 int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
522 if (classdata_left > 0) {
524 dolog("There are %d access bytes at end of classfile",
531 MFREE(classbuffer, u1, classbuffer_size);
536 /******************************************************************************/
537 /******************* Some support functions ***********************************/
538 /******************************************************************************/
540 void fprintflags (FILE *fp, u2 f)
542 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
543 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
544 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
545 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
546 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
547 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
548 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
549 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
550 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
551 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
552 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
556 /********** internal function: printflags (only for debugging) ***************/
558 void printflags(u2 f)
560 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
561 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
562 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
563 if ( f & ACC_STATIC ) printf (" STATIC");
564 if ( f & ACC_FINAL ) printf (" FINAL");
565 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
566 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
567 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
568 if ( f & ACC_NATIVE ) printf (" NATIVE");
569 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
570 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
574 /************************* Function: skipattribute *****************************
576 skips a (1) 'attribute' structure in the class file
578 *******************************************************************************/
580 static void skipattribute()
589 /********************** Function: skipattributebody ****************************
591 skips an attribute after the 16 bit reference to attribute_name has already
594 *******************************************************************************/
596 static void skipattributebody()
604 /************************* Function: skipattributes ****************************
606 skips num attribute structures
608 *******************************************************************************/
610 static void skipattributes(u4 num)
613 for (i = 0; i < num; i++)
618 /******************** function: innerclass_getconstant ************************
620 like class_getconstant, but if cptags is ZERO null is returned
622 *******************************************************************************/
624 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
626 /* invalid position in constantpool */
627 if (pos >= c->cpcount)
628 panic("Attempt to access constant outside range");
630 /* constantpool entry of type 0 */
634 /* check type of constantpool entry */
635 if (c->cptags[pos] != ctype) {
636 error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
637 (int) ctype, (int) c->cptags[pos] );
640 return c->cpinfos[pos];
644 /************************ function: attribute_load ****************************
646 read attributes from classfile
648 *******************************************************************************/
650 static void attribute_load(u4 num, classinfo *c)
654 for (i = 0; i < num; i++) {
655 /* retrieve attribute name */
656 utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
658 if (aname == utf_innerclasses) {
659 /* innerclasses attribute */
661 /* skip attribute length */
663 /* number of records */
664 c->innerclasscount = suck_u2();
665 /* allocate memory for innerclass structure */
666 c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
668 for (j = 0; j < c->innerclasscount; j++) {
669 /* The innerclass structure contains a class with an encoded name,
670 its defining scope, its simple name and a bitmask of the access flags.
671 If an inner class is not a member, its outer_class is NULL,
672 if a class is anonymous, its name is NULL. */
674 innerclassinfo *info = c->innerclass + j;
676 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
677 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
678 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
679 info->flags = suck_u2(); /* access_flags bitmask */
683 /* unknown attribute */
690 /******************* function: checkfielddescriptor ****************************
692 checks whether a field-descriptor is valid and aborts otherwise
693 all referenced classes are inserted into the list of unloaded classes
695 *******************************************************************************/
697 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
699 class_from_descriptor(utf_ptr,end_pos,NULL,
701 | CLASSLOAD_NULLPRIMITIVE
703 | CLASSLOAD_CHECKEND);
705 char *tstart; /* pointer to start of classname */
707 char *start = utf_ptr;
709 switch (*utf_ptr++) {
723 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
724 panic ("Ill formed descriptor");
728 panic ("Ill formed descriptor");
731 /* exceeding characters */
732 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
737 /******************* function checkmethoddescriptor ****************************
739 checks whether a method-descriptor is valid and aborts otherwise.
740 All referenced classes are inserted into the list of unloaded classes.
742 *******************************************************************************/
744 static void checkmethoddescriptor (utf *d)
746 char *utf_ptr = d->text; /* current position in utf text */
747 char *end_pos = utf_end(d); /* points behind utf string */
749 /* method descriptor must start with parenthesis */
750 if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
752 /* check arguments */
753 while (utf_ptr != end_pos && *utf_ptr != ')') {
754 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
756 | CLASSLOAD_NULLPRIMITIVE
760 if (utf_ptr == end_pos) panic("Missing return type in method descriptor");
761 utf_ptr++; /* skip ')' */
763 class_from_descriptor(utf_ptr,end_pos,NULL,
765 | CLASSLOAD_NULLPRIMITIVE
766 | CLASSLOAD_CHECKEND);
769 /* XXX check length */
770 /* check arguments */
771 while ((c = *utf_ptr++) != ')') {
788 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
789 panic ("Ill formed method descriptor");
793 panic ("Ill formed methodtype-descriptor");
797 /* check returntype */
799 /* returntype void */
800 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
803 /* treat as field-descriptor */
804 checkfielddescriptor (utf_ptr,end_pos);
809 /***************** Function: print_arraydescriptor ****************************
811 Debugging helper for displaying an arraydescriptor
813 *******************************************************************************/
815 void print_arraydescriptor(FILE *file, arraydescriptor *desc)
818 fprintf(file, "<NULL>");
823 if (desc->componentvftbl) {
824 if (desc->componentvftbl->class)
825 utf_fprint(file, desc->componentvftbl->class->name);
827 fprintf(file, "<no classinfo>");
833 if (desc->elementvftbl) {
834 if (desc->elementvftbl->class)
835 utf_fprint(file, desc->elementvftbl->class->name);
837 fprintf(file, "<no classinfo>");
841 fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
842 desc->dataoffset, desc->componentsize);
846 /******************************************************************************/
847 /************************** Functions for fields ****************************/
848 /******************************************************************************/
851 /************************ Function: field_load *********************************
853 Load everything about a class field from the class file and fill a
854 'fieldinfo' structure. For static fields, space in the data segment is
857 *******************************************************************************/
859 static void field_load(fieldinfo *f, classinfo *c)
864 f->flags = suck_u2(); /* ACC flags */
865 f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* name of field */
866 f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
867 f->type = jtype = desc_to_type(f->descriptor); /* data type */
868 f->offset = 0; /* offset from start of object */
872 /* check flag consistency */
874 i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
875 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
876 panic("Field has invalid access flags");
877 if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
878 panic("Field is declared final and volatile");
879 if ((c->flags & ACC_INTERFACE) != 0) {
880 if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
881 != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
882 panic("Interface field is not declared static final public");
887 case TYPE_INT: f->value.i = 0; break;
888 case TYPE_FLOAT: f->value.f = 0.0; break;
889 case TYPE_DOUBLE: f->value.d = 0.0; break;
890 case TYPE_ADDRESS: f->value.a = NULL; break;
893 f->value.l = 0; break;
895 f->value.l.low = 0; f->value.l.high = 0; break;
899 /* read attributes */
901 for (i = 0; i < attrnum; i++) {
905 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
907 if (aname != utf_constantvalue) {
908 /* unknown attribute */
912 /* constant value attribute */
914 /* skip attribute length */
916 /* index of value in constantpool */
919 /* initialize field with value from constantpool */
922 constant_integer *ci =
923 class_getconstant(c, pindex, CONSTANT_Integer);
924 f->value.i = ci->value;
930 class_getconstant(c, pindex, CONSTANT_Long);
931 f->value.l = cl->value;
937 class_getconstant(c, pindex, CONSTANT_Float);
938 f->value.f = cf->value;
943 constant_double *cd =
944 class_getconstant(c, pindex, CONSTANT_Double);
945 f->value.d = cd->value;
950 utf *u = class_getconstant(c, pindex, CONSTANT_String);
951 /* create javastring from compressed utf8-string */
952 f->value.a = literalstring_new(u);
957 log_text ("Invalid Constant - Type");
964 /********************** function: field_free **********************************/
966 static void field_free (fieldinfo *f)
972 /**************** Function: field_display (debugging only) ********************/
974 void field_display(fieldinfo *f)
977 printflags(f->flags);
979 utf_display(f->name);
981 utf_display(f->descriptor);
982 printf(" offset: %ld\n", (long int) (f->offset));
986 /******************************************************************************/
987 /************************* Functions for methods ******************************/
988 /******************************************************************************/
991 /*********************** Function: method_load *********************************
993 Loads a method from the class file and fills an existing 'methodinfo'
994 structure. For native methods, the function pointer field is set to the
995 real function pointer, for JavaVM methods a pointer to the compiler is used
998 *******************************************************************************/
1000 static void method_load(methodinfo *m, classinfo *c)
1003 static utf* name_init = NULL;
1004 static utf* name_clinit = NULL;
1007 count_all_methods++;
1012 m->flags = suck_u2();
1013 m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1014 m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1015 checkmethoddescriptor(m->descriptor);
1017 /* check flag consistency */
1020 name_init = utf_new_char("<init>");
1021 name_clinit = utf_new_char("<clinit>");
1023 /* XXX could check if <clinit> is STATIC */
1024 if (m->name != name_clinit) {
1025 i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
1026 if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
1027 panic("Method has invalid access flags");
1028 if ((m->flags & ACC_ABSTRACT) != 0) {
1029 if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
1030 | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
1031 panic("Abstract method has invalid flags set");
1033 if ((c->flags & ACC_INTERFACE) != 0) {
1034 if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
1035 != (ACC_ABSTRACT | ACC_PUBLIC))
1036 panic("Interface method is not declared abstract and public");
1038 if (m->name == name_init) {
1039 if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
1040 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
1041 panic("Instance initialization method has invalid flags set");
1047 m->exceptiontable = NULL;
1048 m->entrypoint = NULL;
1050 m->stubroutine = NULL;
1051 m->methodUsed = NOTUSED;
1054 m->subRedefsUsed = 0;
1058 if (!(m->flags & ACC_NATIVE)) {
1059 m->stubroutine = createcompilerstub(m);
1062 functionptr f = native_findfunction(c->name, m->name, m->descriptor,
1063 (m->flags & ACC_STATIC) != 0);
1065 m->stubroutine = createnativestub(f, m);
1070 attrnum = suck_u2();
1071 for (i = 0; i < attrnum; i++) {
1074 aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
1076 if (aname != utf_code) {
1077 skipattributebody();
1082 panic("Two code-attributes for one method!");
1085 m->maxstack = suck_u2();
1086 m->maxlocals = suck_u2();
1087 codelen = suck_u4();
1089 panic("bytecode has zero length");
1090 if (codelen > 65536)
1091 panic("bytecode too long");
1092 m->jcodelength = codelen;
1093 m->jcode = MNEW(u1, m->jcodelength);
1094 suck_nbytes(m->jcode, m->jcodelength);
1095 m->exceptiontablelength = suck_u2();
1097 MNEW(exceptiontable, m->exceptiontablelength);
1100 count_vmcode_len += m->jcodelength + 18;
1101 count_extable_len += 8 * m->exceptiontablelength;
1104 for (e = 0; e < m->exceptiontablelength; e++) {
1106 m->exceptiontable[e].startpc = suck_u2();
1107 m->exceptiontable[e].endpc = suck_u2();
1108 m->exceptiontable[e].handlerpc = suck_u2();
1112 m->exceptiontable[e].catchtype = NULL;
1115 m->exceptiontable[e].catchtype =
1116 class_getconstant(c, idx, CONSTANT_Class);
1120 skipattributes(suck_u2());
1126 /********************* Function: method_free ***********************************
1128 frees all memory that was allocated for this method
1130 *******************************************************************************/
1132 static void method_free(methodinfo *m)
1135 MFREE(m->jcode, u1, m->jcodelength);
1137 if (m->exceptiontable)
1138 MFREE(m->exceptiontable, exceptiontable, m->exceptiontablelength);
1141 CFREE(m->mcode, m->mcodelength);
1143 if (m->stubroutine) {
1144 if (m->flags & ACC_NATIVE) {
1145 removenativestub(m->stubroutine);
1148 removecompilerstub(m->stubroutine);
1154 /************** Function: method_display (debugging only) **************/
1156 void method_display(methodinfo *m)
1159 printflags(m->flags);
1161 utf_display(m->name);
1163 utf_display(m->descriptor);
1168 /******************** Function: method_canoverwrite ****************************
1170 Check if m and old are identical with respect to type and name. This means
1171 that old can be overwritten with m.
1173 *******************************************************************************/
1175 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1177 if (m->name != old->name) return false;
1178 if (m->descriptor != old->descriptor) return false;
1179 if (m->flags & ACC_STATIC) return false;
1186 /******************************************************************************/
1187 /************************ Functions for class *********************************/
1188 /******************************************************************************/
1191 /******************** function:: class_getconstant ******************************
1193 retrieves the value at position 'pos' of the constantpool of a class
1194 if the type of the value is other than 'ctype' the system is stopped
1196 *******************************************************************************/
1198 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
1200 /* invalid position in constantpool */
1201 /* (pos == 0 is caught by type comparison) */
1202 if (pos >= c->cpcount)
1203 panic("Attempt to access constant outside range");
1205 /* check type of constantpool entry */
1207 if (c->cptags[pos] != ctype) {
1208 class_showconstantpool(c);
1209 error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
1210 (int) ctype, (int) c->cptags[pos]);
1213 return c->cpinfos[pos];
1217 /********************* Function: class_constanttype ****************************
1219 Determines the type of a class entry in the ConstantPool
1221 *******************************************************************************/
1223 u4 class_constanttype(classinfo *c, u4 pos)
1225 if (pos >= c->cpcount)
1226 panic("Attempt to access constant outside range");
1228 return c->cptags[pos];
1232 /******************** function: class_loadcpool ********************************
1234 loads the constantpool of a class,
1235 the entries are transformed into a simpler format
1236 by resolving references
1237 (a detailed overview of the compact structures can be found in global.h)
1239 *******************************************************************************/
1241 static void class_loadcpool(classinfo *c)
1244 /* The following structures are used to save information which cannot be
1245 processed during the first pass. After the complete constantpool has
1246 been traversed the references can be resolved.
1247 (only in specific order) */
1249 /* CONSTANT_Class_info entries */
1250 typedef struct forward_class {
1251 struct forward_class *next;
1256 /* CONSTANT_String */
1257 typedef struct forward_string {
1258 struct forward_string *next;
1263 /* CONSTANT_NameAndType */
1264 typedef struct forward_nameandtype {
1265 struct forward_nameandtype *next;
1269 } forward_nameandtype;
1271 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1272 typedef struct forward_fieldmethint {
1273 struct forward_fieldmethint *next;
1277 u2 nameandtype_index;
1278 } forward_fieldmethint;
1282 long int dumpsize = dump_size ();
1284 forward_class *forward_classes = NULL;
1285 forward_string *forward_strings = NULL;
1286 forward_nameandtype *forward_nameandtypes = NULL;
1287 forward_fieldmethint *forward_fieldmethints = NULL;
1289 /* number of entries in the constant_pool table plus one */
1290 u4 cpcount = c -> cpcount = suck_u2();
1291 /* allocate memory */
1292 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1293 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1296 panic("Invalid constant_pool_count (0)");
1299 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1302 /* initialize constantpool */
1303 for (idx=0; idx<cpcount; idx++) {
1304 cptags[idx] = CONSTANT_UNUSED;
1305 cpinfos[idx] = NULL;
1309 /******* first pass *******/
1310 /* entries which cannot be resolved now are written into
1311 temporary structures and traversed again later */
1314 while (idx < cpcount) {
1315 /* get constant type */
1319 case CONSTANT_Class: {
1320 forward_class *nfc = DNEW(forward_class);
1322 nfc -> next = forward_classes;
1323 forward_classes = nfc;
1325 nfc -> thisindex = idx;
1326 /* reference to CONSTANT_NameAndType */
1327 nfc -> name_index = suck_u2 ();
1333 case CONSTANT_Fieldref:
1334 case CONSTANT_Methodref:
1335 case CONSTANT_InterfaceMethodref: {
1336 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1338 nff -> next = forward_fieldmethints;
1339 forward_fieldmethints = nff;
1341 nff -> thisindex = idx;
1344 /* class or interface type that contains the declaration of the field or method */
1345 nff -> class_index = suck_u2 ();
1346 /* name and descriptor of the field or method */
1347 nff -> nameandtype_index = suck_u2 ();
1353 case CONSTANT_String: {
1354 forward_string *nfs = DNEW (forward_string);
1356 nfs -> next = forward_strings;
1357 forward_strings = nfs;
1359 nfs -> thisindex = idx;
1360 /* reference to CONSTANT_Utf8_info with string characters */
1361 nfs -> string_index = suck_u2 ();
1367 case CONSTANT_NameAndType: {
1368 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1370 nfn -> next = forward_nameandtypes;
1371 forward_nameandtypes = nfn;
1373 nfn -> thisindex = idx;
1374 /* reference to CONSTANT_Utf8_info containing simple name */
1375 nfn -> name_index = suck_u2 ();
1376 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1377 nfn -> sig_index = suck_u2 ();
1383 case CONSTANT_Integer: {
1384 constant_integer *ci = NEW (constant_integer);
1387 count_const_pool_len += sizeof(constant_integer);
1390 ci -> value = suck_s4 ();
1391 cptags [idx] = CONSTANT_Integer;
1398 case CONSTANT_Float: {
1399 constant_float *cf = NEW (constant_float);
1402 count_const_pool_len += sizeof(constant_float);
1405 cf -> value = suck_float ();
1406 cptags [idx] = CONSTANT_Float;
1412 case CONSTANT_Long: {
1413 constant_long *cl = NEW(constant_long);
1416 count_const_pool_len += sizeof(constant_long);
1419 cl -> value = suck_s8 ();
1420 cptags [idx] = CONSTANT_Long;
1424 panic("Long constant exceeds constant pool");
1428 case CONSTANT_Double: {
1429 constant_double *cd = NEW(constant_double);
1432 count_const_pool_len += sizeof(constant_double);
1435 cd -> value = suck_double ();
1436 cptags [idx] = CONSTANT_Double;
1440 panic("Double constant exceeds constant pool");
1444 case CONSTANT_Utf8: {
1446 /* number of bytes in the bytes array (not string-length) */
1447 u4 length = suck_u2();
1448 cptags [idx] = CONSTANT_Utf8;
1449 /* validate the string */
1450 ASSERT_LEFT(length);
1452 !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
1453 panic("Invalid UTF-8 string");
1454 /* insert utf-string into the utf-symboltable */
1455 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1456 /* skip bytes of the string */
1457 skip_nbytes(length);
1463 error ("Unkown constant type: %d",(int) t);
1471 /* resolve entries in temporary structures */
1473 while (forward_classes) {
1475 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1477 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1478 /* retrieve class from class-table */
1479 cpinfos [forward_classes -> thisindex] = class_new (name);
1481 forward_classes = forward_classes -> next;
1485 while (forward_strings) {
1487 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1489 log_text("forward_string:");
1490 printf( "classpoolid: %d\n",forward_strings -> thisindex);
1492 log_text("\n------------------"); */
1493 /* resolve utf-string */
1494 cptags [forward_strings -> thisindex] = CONSTANT_String;
1495 cpinfos [forward_strings -> thisindex] = text;
1497 forward_strings = forward_strings -> next;
1500 while (forward_nameandtypes) {
1501 constant_nameandtype *cn = NEW (constant_nameandtype);
1504 count_const_pool_len += sizeof(constant_nameandtype);
1507 /* resolve simple name and descriptor */
1508 cn -> name = class_getconstant
1509 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1510 cn -> descriptor = class_getconstant
1511 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1513 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1514 cpinfos [forward_nameandtypes -> thisindex] = cn;
1516 forward_nameandtypes = forward_nameandtypes -> next;
1520 while (forward_fieldmethints) {
1521 constant_nameandtype *nat;
1522 constant_FMIref *fmi = NEW (constant_FMIref);
1525 count_const_pool_len += sizeof(constant_FMIref);
1527 /* resolve simple name and descriptor */
1528 nat = class_getconstant
1529 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1532 log_text("trying to resolve:");
1533 log_text(nat->name->text);
1534 switch(forward_fieldmethints ->tag) {
1535 case CONSTANT_Fieldref:
1536 log_text("CONSTANT_Fieldref");
1538 case CONSTANT_InterfaceMethodref:
1539 log_text("CONSTANT_InterfaceMethodref");
1541 case CONSTANT_Methodref:
1542 log_text("CONSTANT_Methodref");
1546 fmi -> class = class_getconstant
1547 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1548 fmi -> name = nat -> name;
1549 fmi -> descriptor = nat -> descriptor;
1551 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1552 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1554 switch (forward_fieldmethints -> tag) {
1555 case CONSTANT_Fieldref: /* check validity of descriptor */
1556 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1558 case CONSTANT_InterfaceMethodref:
1559 case CONSTANT_Methodref: /* check validity of descriptor */
1560 /* XXX check special names (<init>) */
1561 checkmethoddescriptor (fmi->descriptor);
1565 forward_fieldmethints = forward_fieldmethints -> next;
1569 /* class_showconstantpool(c); */
1571 dump_release (dumpsize);
1575 /********************** Function: class_load ***********************************
1577 Loads everything interesting about a class from the class file. The
1578 'classinfo' structure must have been allocated previously.
1580 The super class and the interfaces implemented by this class need not be
1581 loaded. The link is set later by the function 'class_link'.
1583 The loaded class is removed from the list 'unloadedclasses' and added to
1584 the list 'unlinkedclasses'.
1586 *******************************************************************************/
1588 static int class_load(classinfo *c)
1594 count_class_loads++;
1597 /* output for debugging purposes */
1599 char logtext[MAXLOGTEXT];
1600 sprintf(logtext, "Loading class: ");
1601 utf_sprint(logtext + strlen(logtext), c->name);
1605 /* load classdata, throw exception on error */
1607 if (!suck_start(c->name)) {
1608 throw_noclassdeffounderror_message(c->name);
1612 /* check signature */
1613 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1617 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1618 error("File version %d.%d is not supported", (int) ma, (int) mi);
1623 c->erroneous_state = 0;
1624 c->initializing_thread = 0;
1626 c->classUsed = NOTUSED; /* not used initially CO-RT */
1630 c->flags = suck_u2();
1631 /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
1633 /* check ACC flags consistency */
1634 if ((c->flags & ACC_INTERFACE) != 0) {
1635 if ((c->flags & ACC_ABSTRACT) == 0)
1636 panic("Interface class not declared abstract");
1637 if ((c->flags & (ACC_FINAL | ACC_SUPER)) != 0)
1638 panic("Interface class has invalid flags");
1642 suck_u2(); /* XXX check it? */
1644 /* retrieve superclass */
1645 if ((i = suck_u2())) {
1646 c->super = class_getconstant(c, i, CONSTANT_Class);
1652 /* retrieve interfaces */
1653 c->interfacescount = suck_u2();
1654 c->interfaces = MNEW(classinfo*, c->interfacescount);
1655 for (i = 0; i < c->interfacescount; i++) {
1657 class_getconstant(c, suck_u2(), CONSTANT_Class);
1661 c->fieldscount = suck_u2();
1662 /* utf_display(c->name);
1663 printf(" ,Fieldscount: %d\n",c->fieldscount);*/
1665 c->fields = GCNEW(fieldinfo, c->fieldscount);
1666 for (i = 0; i < c->fieldscount; i++) {
1667 field_load(&(c->fields[i]), c);
1671 c->methodscount = suck_u2();
1672 c->methods = MNEW(methodinfo, c->methodscount);
1673 for (i = 0; i < c->methodscount; i++) {
1674 method_load(&(c->methods[i]), c);
1678 count_class_infos += sizeof(classinfo*) * c->interfacescount;
1679 count_class_infos += sizeof(fieldinfo) * c->fieldscount;
1680 count_class_infos += sizeof(methodinfo) * c->methodscount;
1683 /* load variable-length attribute structures */
1684 attribute_load(suck_u2(), c);
1689 /* remove class from list of unloaded classes and
1690 add to list of unlinked classes */
1691 list_remove(&unloadedclasses, c);
1692 list_addlast(&unlinkedclasses, c);
1701 /************** internal Function: class_highestinterface ***********************
1703 Used by the function class_link to determine the amount of memory needed
1704 for the interface table.
1706 *******************************************************************************/
1708 static s4 class_highestinterface(classinfo *c)
1713 if (!(c->flags & ACC_INTERFACE)) {
1714 char logtext[MAXLOGTEXT];
1715 sprintf(logtext, "Interface-methods count requested for non-interface: ");
1716 utf_sprint(logtext + strlen(logtext), c->name);
1717 error("%s",logtext);
1721 for (i = 0; i < c->interfacescount; i++) {
1722 s4 h2 = class_highestinterface(c->interfaces[i]);
1730 /* class_addinterface **********************************************************
1732 Is needed by class_link for adding a VTBL to a class. All interfaces
1733 implemented by ic are added as well.
1735 *******************************************************************************/
1737 static void class_addinterface (classinfo *c, classinfo *ic)
1741 vftbl *vftbl = c->vftbl;
1743 if (i >= vftbl->interfacetablelength)
1744 panic ("Inernal error: interfacetable overflow");
1745 if (vftbl->interfacetable[-i])
1748 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1749 vftbl->interfacevftbllength[i] = 1;
1750 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1751 vftbl->interfacetable[-i][0] = NULL;
1754 vftbl->interfacevftbllength[i] = ic->methodscount;
1755 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1758 count_vftbl_len += sizeof(methodptr) *
1759 (ic->methodscount + (ic->methodscount == 0));
1762 for (j=0; j<ic->methodscount; j++) {
1765 for (m = 0; m < sc->methodscount; m++) {
1766 methodinfo *mi = &(sc->methods[m]);
1767 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1768 vftbl->interfacetable[-i][j] =
1769 vftbl->table[mi->vftblindex];
1779 for (j = 0; j < ic->interfacescount; j++)
1780 class_addinterface(c, ic->interfaces[j]);
1784 /******************* Function: class_new_array *********************************
1786 This function is called by class_new to setup an array class.
1788 *******************************************************************************/
1790 void class_new_array(classinfo *c)
1792 classinfo *comp = NULL;
1796 /* XXX remove */ /* dolog("class_new_array: %s",c->name->text); */
1798 /* Array classes are not loaded from classfiles. */
1799 list_remove(&unloadedclasses, c);
1801 /* Check array class name */
1802 namelen = c->name->blength;
1803 if (namelen < 2 || c->name->text[0] != '[')
1804 panic("Invalid array class name");
1806 /* Check the component type */
1807 switch (c->name->text[1]) {
1809 /* c is an array of arrays. We have to create the component class. */
1810 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
1814 /* c is an array of objects. */
1815 if (namelen < 4 || c->name->text[namelen - 1] != ';')
1816 panic("Invalid array class name");
1817 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
1821 /* Setup the array class */
1822 c->super = class_java_lang_Object;
1823 c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
1825 c->interfacescount = 2;
1826 c->interfaces = MNEW(classinfo*,2); /* XXX use GC? */
1827 c->interfaces[0] = class_java_lang_Cloneable;
1828 c->interfaces[1] = class_java_io_Serializable;
1830 c->methodscount = 1;
1831 c->methods = MNEW (methodinfo, c->methodscount); /* XXX use GC? */
1834 memset(clone, 0, sizeof(methodinfo));
1835 clone->flags = ACC_PUBLIC; /* XXX protected? */
1836 clone->name = utf_new_char("clone");
1837 clone->descriptor = utf_new_char("()Ljava/lang/Object;");
1839 clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
1840 clone->monoPoly = MONO; /* XXX should be poly? */
1842 /* XXX: field: length? */
1844 /* The array class has to be linked */
1845 list_addlast(&unlinkedclasses,c);
1848 * Array classes which are created after the other classes have been
1849 * loaded and linked are linked explicitely.
1854 loader_load(c->name); /* XXX handle errors */
1858 /****************** Function: class_link_array *********************************
1860 This function is called by class_link to create the
1861 arraydescriptor for an array class.
1863 This function returns NULL if the array cannot be linked because
1864 the component type has not been linked yet.
1866 *******************************************************************************/
1868 static arraydescriptor *class_link_array(classinfo *c)
1870 classinfo *comp = NULL;
1871 int namelen = c->name->blength;
1872 arraydescriptor *desc;
1875 /* Check the component type */
1876 switch (c->name->text[1]) {
1878 /* c is an array of arrays. */
1879 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
1880 if (!comp) panic("Could not find component array class.");
1884 /* c is an array of objects. */
1885 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
1886 if (!comp) panic("Could not find component class.");
1890 /* If the component type has not been linked return NULL */
1891 if (comp && !comp->linked)
1894 /* Allocate the arraydescriptor */
1895 desc = NEW(arraydescriptor);
1898 /* c is an array of references */
1899 desc->arraytype = ARRAYTYPE_OBJECT;
1900 desc->componentsize = sizeof(void*);
1901 desc->dataoffset = OFFSET(java_objectarray,data);
1903 compvftbl = comp->vftbl;
1905 panic("Component class has no vftbl");
1906 desc->componentvftbl = compvftbl;
1908 if (compvftbl->arraydesc) {
1909 desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
1910 if (compvftbl->arraydesc->dimension >= 255)
1911 panic("Creating array of dimension >255");
1912 desc->dimension = compvftbl->arraydesc->dimension + 1;
1913 desc->elementtype = compvftbl->arraydesc->elementtype;
1916 desc->elementvftbl = compvftbl;
1917 desc->dimension = 1;
1918 desc->elementtype = ARRAYTYPE_OBJECT;
1922 /* c is an array of a primitive type */
1923 switch (c->name->text[1]) {
1924 case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
1925 desc->dataoffset = OFFSET(java_booleanarray,data);
1926 desc->componentsize = sizeof(u1);
1929 case 'B': desc->arraytype = ARRAYTYPE_BYTE;
1930 desc->dataoffset = OFFSET(java_bytearray,data);
1931 desc->componentsize = sizeof(u1);
1934 case 'C': desc->arraytype = ARRAYTYPE_CHAR;
1935 desc->dataoffset = OFFSET(java_chararray,data);
1936 desc->componentsize = sizeof(u2);
1939 case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
1940 desc->dataoffset = OFFSET(java_doublearray,data);
1941 desc->componentsize = sizeof(double);
1944 case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
1945 desc->dataoffset = OFFSET(java_floatarray,data);
1946 desc->componentsize = sizeof(float);
1949 case 'I': desc->arraytype = ARRAYTYPE_INT;
1950 desc->dataoffset = OFFSET(java_intarray,data);
1951 desc->componentsize = sizeof(s4);
1954 case 'J': desc->arraytype = ARRAYTYPE_LONG;
1955 desc->dataoffset = OFFSET(java_longarray,data);
1956 desc->componentsize = sizeof(s8);
1959 case 'S': desc->arraytype = ARRAYTYPE_SHORT;
1960 desc->dataoffset = OFFSET(java_shortarray,data);
1961 desc->componentsize = sizeof(s2);
1965 panic("Invalid array class name");
1968 desc->componentvftbl = NULL;
1969 desc->elementvftbl = NULL;
1970 desc->dimension = 1;
1971 desc->elementtype = desc->arraytype;
1978 /********************** Function: class_link ***********************************
1980 Tries to link a class. The super class and every implemented interface must
1981 already have been linked. The function calculates the length in bytes that
1982 an instance of this class requires as well as the VTBL for methods and
1985 If the class can be linked, it is removed from the list 'unlinkedclasses'
1986 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1989 Attention: If cyclical class definitions are encountered, the program gets
1990 into an infinite loop (we'll have to work that out)
1992 *******************************************************************************/
1994 void class_link(classinfo *c)
1996 s4 supervftbllength; /* vftbllegnth of super class */
1997 s4 vftbllength; /* vftbllength of current class */
1998 s4 interfacetablelength; /* interface table length */
1999 classinfo *super = c->super; /* super class */
2000 classinfo *ic, *c2; /* intermediate class variables */
2001 vftbl *v; /* vftbl of current class */
2002 s4 i; /* interface/method/field counter */
2003 arraydescriptor *arraydesc = NULL; /* descriptor for array classes */
2006 /* check if all superclasses are already linked, if not put c at end of
2007 unlinked list and return. Additionally initialize class fields. */
2009 /* check interfaces */
2011 for (i = 0; i < c->interfacescount; i++) {
2012 ic = c->interfaces[i];
2014 list_remove(&unlinkedclasses, c);
2015 list_addlast(&unlinkedclasses, c);
2020 /* check super class */
2022 if (super == NULL) { /* class java.long.Object */
2024 c->classUsed = USED; /* Object class is always used CO-RT*/
2026 c->instancesize = sizeof(java_objectheader);
2028 vftbllength = supervftbllength = 0;
2030 c->finalizer = NULL;
2033 if (!super->linked) {
2034 list_remove(&unlinkedclasses, c);
2035 list_addlast(&unlinkedclasses, c);
2039 /* handle array classes */
2040 /* The component class must have been linked already. */
2041 if (c->name->text[0] == '[')
2042 if ((arraydesc = class_link_array(c)) == NULL) {
2043 list_remove(&unlinkedclasses, c);
2044 list_addlast(&unlinkedclasses, c);
2048 /* Don't allow extending final classes */
2049 if ((super->flags & ACC_FINAL) != 0)
2050 panic("Trying to extend final class");
2052 if (c->flags & ACC_INTERFACE)
2053 c->index = interfaceindex++;
2055 c->index = super->index + 1;
2057 c->instancesize = super->instancesize;
2059 vftbllength = supervftbllength = super->vftbl->vftbllength;
2061 c->finalizer = super->finalizer;
2066 char logtext[MAXLOGTEXT];
2067 sprintf(logtext, "Linking Class: ");
2068 utf_sprint(logtext + strlen(logtext), c->name );
2072 /* compute vftbl length */
2074 for (i = 0; i < c->methodscount; i++) {
2075 methodinfo *m = &(c->methods[i]);
2077 if (!(m->flags & ACC_STATIC)) { /* is instance method */
2078 classinfo *sc = super;
2081 for (j = 0; j < sc->methodscount; j++) {
2082 if (method_canoverwrite(m, &(sc->methods[j]))) {
2083 if ((sc->methods[j].flags & ACC_FINAL) != 0)
2084 panic("Trying to overwrite final method");
2085 m->vftblindex = sc->methods[j].vftblindex;
2086 goto foundvftblindex;
2091 m->vftblindex = (vftbllength++);
2097 count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
2100 /* compute interfacetable length */
2102 interfacetablelength = 0;
2105 for (i = 0; i < c2->interfacescount; i++) {
2106 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
2107 if (h > interfacetablelength)
2108 interfacetablelength = h;
2113 /* allocate virtual function table */
2115 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
2116 (vftbllength - 1) + sizeof(methodptr*) *
2117 (interfacetablelength - (interfacetablelength > 0)));
2118 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
2119 (interfacetablelength > 1));
2120 c->header.vftbl = c->vftbl = v;
2122 v->vftbllength = vftbllength;
2123 v->interfacetablelength = interfacetablelength;
2124 v->arraydesc = arraydesc;
2126 /* store interface index in vftbl */
2127 if (c->flags & ACC_INTERFACE)
2128 v->baseval = -(c->index);
2130 /* copy virtual function table of super class */
2132 for (i = 0; i < supervftbllength; i++)
2133 v->table[i] = super->vftbl->table[i];
2135 /* add method stubs into virtual function table */
2137 for (i = 0; i < c->methodscount; i++) {
2138 methodinfo *m = &(c->methods[i]);
2139 if (!(m->flags & ACC_STATIC)) {
2140 v->table[m->vftblindex] = m->stubroutine;
2144 /* compute instance size and offset of each field */
2146 for (i = 0; i < c->fieldscount; i++) {
2148 fieldinfo *f = &(c->fields[i]);
2150 if (!(f->flags & ACC_STATIC) ) {
2151 dsize = desc_typesize(f->descriptor);
2152 c->instancesize = ALIGN(c->instancesize, dsize);
2153 f->offset = c->instancesize;
2154 c->instancesize += dsize;
2158 /* initialize interfacetable and interfacevftbllength */
2160 v->interfacevftbllength = MNEW(s4, interfacetablelength);
2163 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
2166 for (i = 0; i < interfacetablelength; i++) {
2167 v->interfacevftbllength[i] = 0;
2168 v->interfacetable[-i] = NULL;
2171 /* add interfaces */
2173 for (c2 = c; c2 != NULL; c2 = c2->super)
2174 for (i = 0; i < c2->interfacescount; i++) {
2175 class_addinterface(c, c2->interfaces[i]);
2178 /* add finalizer method (not for java.lang.Object) */
2180 if (super != NULL) {
2182 static utf *finame = NULL;
2183 static utf *fidesc = NULL;
2186 finame = utf_finalize;
2188 fidesc = utf_fidesc;
2190 fi = class_findmethod(c, finame, fidesc);
2192 if (!(fi->flags & ACC_STATIC)) {
2202 list_remove(&unlinkedclasses, c);
2203 list_addlast(&linkedclasses, c);
2207 /******************* Function: class_freepool **********************************
2209 Frees all resources used by this classes Constant Pool.
2211 *******************************************************************************/
2213 static void class_freecpool (classinfo *c)
2219 for (idx=0; idx < c->cpcount; idx++) {
2220 tag = c->cptags[idx];
2221 info = c->cpinfos[idx];
2225 case CONSTANT_Fieldref:
2226 case CONSTANT_Methodref:
2227 case CONSTANT_InterfaceMethodref:
2228 FREE (info, constant_FMIref);
2230 case CONSTANT_Integer:
2231 FREE (info, constant_integer);
2233 case CONSTANT_Float:
2234 FREE (info, constant_float);
2237 FREE (info, constant_long);
2239 case CONSTANT_Double:
2240 FREE (info, constant_double);
2242 case CONSTANT_NameAndType:
2243 FREE (info, constant_nameandtype);
2249 MFREE (c -> cptags, u1, c -> cpcount);
2250 MFREE (c -> cpinfos, voidptr, c -> cpcount);
2254 /*********************** Function: class_free **********************************
2256 Frees all resources used by the class.
2258 *******************************************************************************/
2260 static void class_free(classinfo *c)
2267 MFREE(c->interfaces, classinfo*, c->interfacescount);
2269 for (i = 0; i < c->fieldscount; i++)
2270 field_free(&(c->fields[i]));
2272 for (i = 0; i < c->methodscount; i++)
2273 method_free(&(c->methods[i]));
2274 MFREE(c->methods, methodinfo, c->methodscount);
2276 if ((v = c->vftbl) != NULL) {
2278 mem_free(v->arraydesc,sizeof(arraydescriptor));
2280 for (i = 0; i < v->interfacetablelength; i++) {
2281 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
2283 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
2285 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
2286 sizeof(methodptr*) * (v->interfacetablelength -
2287 (v->interfacetablelength > 0));
2288 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
2289 (v->interfacetablelength > 1));
2293 if (c->innerclasscount)
2294 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
2296 /* if (c->classvftbl)
2297 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
2303 /************************* Function: class_findfield ***************************
2305 Searches a 'classinfo' structure for a field having the given name and
2308 *******************************************************************************/
2310 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
2314 for (i = 0; i < c->fieldscount; i++) {
2315 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
2316 return &(c->fields[i]);
2319 panic("Can not find field given in CONSTANT_Fieldref");
2321 /* keep compiler happy */
2326 /************************* Function: class_findmethod **************************
2328 Searches a 'classinfo' structure for a method having the given name and
2329 type and returns the index in the class info structure.
2330 If type is NULL, it is ignored.
2332 *******************************************************************************/
2334 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
2337 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2339 int buffer_len, pos;
2341 #ifdef JOWENN_DEBUG1
2344 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2346 buffer = MNEW(char, buffer_len);
2348 strcpy(buffer, "class_findmethod: method:");
2349 utf_sprint(buffer + strlen(buffer), name);
2350 strcpy(buffer + strlen(buffer), ", desc: ");
2351 utf_sprint(buffer + strlen(buffer), desc);
2352 strcpy(buffer + strlen(buffer), ", classname: ");
2353 utf_sprint(buffer + strlen(buffer), c->name);
2357 MFREE(buffer, char, buffer_len);
2359 for (i = 0; i < c->methodscount; i++) {
2360 #ifdef JOWENN_DEBUG2
2362 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2364 buffer = MNEW(char, buffer_len);
2366 strcpy(buffer, "class_findmethod: comparing to method:");
2367 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2368 strcpy(buffer + strlen(buffer), ", desc: ");
2369 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2373 MFREE(buffer, char, buffer_len);
2377 if ((c->methods[i].name == name) && ((desc == NULL) ||
2378 (c->methods[i].descriptor == desc))) {
2383 #ifdef JOWENN_DEBUG2
2384 class_showconstantpool(c);
2385 log_text("class_findmethod: returning NULL");
2392 /************************* Function: class_findmethod **************************
2394 Searches a 'classinfo' structure for a method having the given name and
2396 If type is NULL, it is ignored.
2398 *******************************************************************************/
2400 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
2404 #if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
2406 int buffer_len, pos;
2408 #ifdef JOWENN_DEBUG1
2411 utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
2413 buffer = MNEW(char, buffer_len);
2415 strcpy(buffer, "class_findmethod: method:");
2416 utf_sprint(buffer + strlen(buffer), name);
2417 strcpy(buffer + strlen(buffer), ", desc: ");
2418 utf_sprint(buffer + strlen(buffer), desc);
2419 strcpy(buffer + strlen(buffer), ", classname: ");
2420 utf_sprint(buffer + strlen(buffer), c->name);
2424 MFREE(buffer, char, buffer_len);
2426 for (i = 0; i < c->methodscount; i++) {
2427 #ifdef JOWENN_DEBUG2
2429 utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
2431 buffer = MNEW(char, buffer_len);
2433 strcpy(buffer, "class_findmethod: comparing to method:");
2434 utf_sprint(buffer + strlen(buffer), c->methods[i].name);
2435 strcpy(buffer + strlen(buffer), ", desc: ");
2436 utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
2440 MFREE(buffer, char, buffer_len);
2443 if ((c->methods[i].name == name) && ((desc == NULL) ||
2444 (c->methods[i].descriptor == desc))) {
2445 return &(c->methods[i]);
2448 #ifdef JOWENN_DEBUG2
2449 class_showconstantpool(c);
2450 log_text("class_findmethod: returning NULL");
2455 s4 idx=class_findmethodIndex(c, name, desc);
2456 /* if (idx==-1) log_text("class_findmethod: method not found");*/
2457 if (idx == -1) return NULL;
2459 return &(c->methods[idx]);
2463 /*********************** Function: class_fetchmethod **************************
2465 like class_findmethod, but aborts with an error if the method is not found
2467 *******************************************************************************/
2469 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
2472 mi = class_findmethod(c, name, desc);
2475 log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
2476 log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
2477 log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
2478 panic("Method not found");
2485 /************************* Function: class_findmethod_approx ******************
2487 like class_findmethod but ignores the return value when comparing the
2490 *******************************************************************************/
2492 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
2496 for (i = 0; i < c->methodscount; i++) {
2497 if (c->methods[i].name == name) {
2498 utf *meth_descr = c->methods[i].descriptor;
2502 return &(c->methods[i]);
2504 if (desc->blength <= meth_descr->blength) {
2505 /* current position in utf text */
2506 char *desc_utf_ptr = desc->text;
2507 char *meth_utf_ptr = meth_descr->text;
2508 /* points behind utf strings */
2509 char *desc_end = utf_end(desc);
2510 char *meth_end = utf_end(meth_descr);
2513 /* compare argument types */
2514 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
2516 if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
2517 break; /* no match */
2520 return &(c->methods[i]); /* all parameter types equal */
2530 /***************** Function: class_resolvemethod_approx ***********************
2532 Searches a class and every super class for a method (without paying
2533 attention to the return value)
2535 *******************************************************************************/
2537 methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
2540 /* search for method (ignore returntype) */
2541 methodinfo *m = class_findmethod_approx(c, name, desc);
2544 /* search superclass */
2552 /************************* Function: class_resolvemethod ***********************
2554 Searches a class and every super class for a method.
2556 *******************************************************************************/
2558 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
2561 methodinfo *m = class_findmethod(c, name, desc);
2563 /* search superclass */
2571 /************************* Function: class_issubclass **************************
2573 Checks if sub is a descendant of super.
2575 *******************************************************************************/
2577 bool class_issubclass(classinfo *sub, classinfo *super)
2580 if (!sub) return false;
2581 if (sub == super) return true;
2587 /****************** Initialization function for classes ******************
2589 In Java, every class can have a static initialization function. This
2590 function has to be called BEFORE calling other methods or accessing static
2593 *******************************************************************************/
2595 void class_init(classinfo *c)
2603 if (!makeinitializations)
2608 c->initialized = true;
2611 count_class_inits++;
2615 class_init(c->super);
2616 for (i = 0; i < c->interfacescount; i++)
2617 class_init(c->interfaces[i]); /* real */
2619 m = class_findmethod(c, utf_clinit, utf_fidesc);
2622 char logtext[MAXLOGTEXT];
2623 sprintf(logtext, "Class ");
2624 utf_sprint(logtext + strlen(logtext), c->name);
2625 sprintf(logtext + strlen(logtext), " has no initializer");
2628 /* goto callinitialize;*/
2632 if (!(m->flags & ACC_STATIC))
2633 panic("Class initializer is not static!");
2636 char logtext[MAXLOGTEXT];
2637 sprintf(logtext, "Starting initializer for class: ");
2638 utf_sprint(logtext + strlen(logtext), c->name);
2647 /* now call the initializer */
2648 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2651 assert(blockInts == 0);
2655 /* we have to throw an exception */
2657 printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
2658 printf("Caused by: ");
2659 utf_display(exceptionptr->vftbl->class->name);
2666 char logtext[MAXLOGTEXT];
2667 sprintf(logtext, "Finished initializer for class: ");
2668 utf_sprint(logtext + strlen(logtext), c->name);
2672 if (c->name == utf_systemclass) {
2673 /* class java.lang.System requires explicit initialization */
2676 printf("#### Initializing class System");
2678 /* find initializing method */
2679 m = class_findmethod(c,
2680 utf_initsystemclass,
2684 /* no method found */
2685 /* printf("initializeSystemClass failed"); */
2694 asm_calljavafunction(m, NULL, NULL, NULL, NULL);
2697 assert(blockInts == 0);
2702 printf("#### initializeSystemClass has thrown: ");
2703 utf_display(exceptionptr->vftbl->class->name);
2711 /********* Function: find_class_method_constant *********/
2713 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2718 for (i=0; i<c->cpcount; i++) {
2720 e = c -> cpinfos [i];
2723 switch (c -> cptags [i]) {
2724 case CONSTANT_Methodref:
2726 constant_FMIref *fmi = e;
2727 if ( (fmi->class->name == c1)
2728 && (fmi->name == m1)
2729 && (fmi->descriptor == d1)) {
2736 case CONSTANT_InterfaceMethodref:
2738 constant_FMIref *fmi = e;
2739 if ( (fmi->class->name == c1)
2740 && (fmi->name == m1)
2741 && (fmi->descriptor == d1)) {
2755 void class_showconstanti(classinfo *c, int ii)
2761 printf ("#%d: ", (int) i);
2763 switch (c->cptags [i]) {
2764 case CONSTANT_Class:
2765 printf("Classreference -> ");
2766 utf_display(((classinfo*)e)->name);
2769 case CONSTANT_Fieldref:
2770 printf("Fieldref -> "); goto displayFMIi;
2771 case CONSTANT_Methodref:
2772 printf("Methodref -> "); goto displayFMIi;
2773 case CONSTANT_InterfaceMethodref:
2774 printf("InterfaceMethod -> "); goto displayFMIi;
2777 constant_FMIref *fmi = e;
2778 utf_display(fmi->class->name);
2780 utf_display(fmi->name);
2782 utf_display(fmi->descriptor);
2786 case CONSTANT_String:
2787 printf("String -> ");
2790 case CONSTANT_Integer:
2791 printf("Integer -> %d", (int) (((constant_integer*)e)->value));
2793 case CONSTANT_Float:
2794 printf("Float -> %f", ((constant_float*)e)->value);
2796 case CONSTANT_Double:
2797 printf("Double -> %f", ((constant_double*)e)->value);
2801 u8 v = ((constant_long*)e)->value;
2803 printf("Long -> %ld", (long int) v);
2805 printf("Long -> HI: %ld, LO: %ld\n",
2806 (long int) v.high, (long int) v.low);
2810 case CONSTANT_NameAndType:
2812 constant_nameandtype *cnt = e;
2813 printf("NameAndType: ");
2814 utf_display(cnt->name);
2816 utf_display(cnt->descriptor);
2824 panic("Invalid type of ConstantPool-Entry");
2831 void class_showconstantpool (classinfo *c)
2836 printf ("---- dump of constant pool ----\n");
2838 for (i=0; i<c->cpcount; i++) {
2839 printf ("#%d: ", (int) i);
2841 e = c -> cpinfos [i];
2844 switch (c -> cptags [i]) {
2845 case CONSTANT_Class:
2846 printf ("Classreference -> ");
2847 utf_display ( ((classinfo*)e) -> name );
2850 case CONSTANT_Fieldref:
2851 printf ("Fieldref -> "); goto displayFMI;
2852 case CONSTANT_Methodref:
2853 printf ("Methodref -> "); goto displayFMI;
2854 case CONSTANT_InterfaceMethodref:
2855 printf ("InterfaceMethod -> "); goto displayFMI;
2858 constant_FMIref *fmi = e;
2859 utf_display ( fmi->class->name );
2861 utf_display ( fmi->name);
2863 utf_display ( fmi->descriptor );
2867 case CONSTANT_String:
2868 printf ("String -> ");
2871 case CONSTANT_Integer:
2872 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2874 case CONSTANT_Float:
2875 printf ("Float -> %f", ((constant_float*)e) -> value);
2877 case CONSTANT_Double:
2878 printf ("Double -> %f", ((constant_double*)e) -> value);
2882 u8 v = ((constant_long*)e) -> value;
2884 printf ("Long -> %ld", (long int) v);
2886 printf ("Long -> HI: %ld, LO: %ld\n",
2887 (long int) v.high, (long int) v.low);
2891 case CONSTANT_NameAndType:
2893 constant_nameandtype *cnt = e;
2894 printf ("NameAndType: ");
2895 utf_display (cnt->name);
2897 utf_display (cnt->descriptor);
2901 printf ("Utf8 -> ");
2905 panic ("Invalid type of ConstantPool-Entry");
2915 /********** Function: class_showmethods (debugging only) *************/
2917 void class_showmethods (classinfo *c)
2921 printf ("--------- Fields and Methods ----------------\n");
2922 printf ("Flags: "); printflags (c->flags); printf ("\n");
2924 printf ("This: "); utf_display (c->name); printf ("\n");
2926 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2928 printf ("Index: %d\n", c->index);
2930 printf ("interfaces:\n");
2931 for (i=0; i < c-> interfacescount; i++) {
2933 utf_display (c -> interfaces[i] -> name);
2934 printf (" (%d)\n", c->interfaces[i] -> index);
2937 printf ("fields:\n");
2938 for (i=0; i < c -> fieldscount; i++) {
2939 field_display (&(c -> fields[i]));
2942 printf ("methods:\n");
2943 for (i=0; i < c -> methodscount; i++) {
2944 methodinfo *m = &(c->methods[i]);
2945 if ( !(m->flags & ACC_STATIC))
2946 printf ("vftblindex: %d ", m->vftblindex);
2948 method_display ( m );
2952 printf ("Virtual function table:\n");
2953 for (i=0; i<c->vftbl->vftbllength; i++) {
2954 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2961 /******************************************************************************/
2962 /******************* General functions for the class loader *******************/
2963 /******************************************************************************/
2965 /********************* Function: loader_load ***********************************
2967 Loads and links the class desired class and each class and interface
2969 Returns: a pointer to this class
2971 *******************************************************************************/
2973 static int loader_load_running = 0;
2975 classinfo *loader_load(utf *topname)
2981 classinfo *notlinkable;
2983 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2984 pthread_mutex_lock(&compiler_mutex);
2987 /* avoid recursive calls */
2988 if (loader_load_running)
2989 return class_new(topname);
2991 loader_load_running++;
2996 starttime = getcputime();
2998 top = class_new(topname);
3001 while ((c = list_first(&unloadedclasses))) {
3002 if (!class_load(c)) {
3004 dolog("Failed to load class");
3005 list_remove(&unloadedclasses, c);
3012 dolog("Linking...");
3014 /* XXX added a hack to break infinite linking loops. A better
3015 * linking algorithm would be nice. -Edwin */
3017 while ((c = list_first(&unlinkedclasses))) {
3022 else if (notlinkable == c) {
3023 /* We tried to link this class for the second time and
3024 * no other classes were linked in between, so we are
3028 dolog("Cannot resolve linking dependencies");
3031 throw_linkageerror_message(c->name);
3039 dolog("Linking done.");
3042 loader_compute_subclasses();
3045 if (getloadingtime) {
3046 stoptime = getcputime();
3047 loadingtime += (stoptime - starttime);
3051 loader_load_running--;
3053 /* check if a former loader_load call tried to load/link the class and
3054 failed. This is needed because the class didn't appear in the
3055 undloadclasses or unlinkedclasses list during this class. */
3058 if (linkverbose) dolog("Failed to load class (former call)");
3059 throw_noclassdeffounderror_message(top->name);
3062 } else if (!top->linked) {
3064 dolog("Failed to link class (former call)");
3065 throw_linkageerror_message(top->name);
3072 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3073 pthread_mutex_unlock(&compiler_mutex);
3076 /* XXX DEBUG */ if (linkverbose && !top) dolog("returning NULL from loader_load");
3082 /****************** Function: loader_load_sysclass ****************************
3084 Loads and links the class desired class and each class and interface
3087 The pointer to the classinfo is stored in *top if top != NULL.
3088 The pointer is also returned.
3090 If the class could not be loaded the function aborts with an error.
3092 *******************************************************************************/
3094 classinfo *loader_load_sysclass(classinfo **top, utf *topname)
3098 if ((cls = loader_load(topname)) == NULL) {
3099 log_plain("Could not load important system class: ");
3100 log_plain_utf(topname);
3102 panic("Could not load important system class");
3105 if (top) *top = cls;
3111 /**************** function: create_primitive_classes ***************************
3113 create classes representing primitive types
3115 ********************************************************************************/
3118 void create_primitive_classes()
3122 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
3123 /* create primitive class */
3124 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
3125 c -> classUsed = NOTUSED; /* not used initially CO-RT */
3126 c -> impldBy = NULL;
3128 /* prevent loader from loading primitive class */
3129 list_remove (&unloadedclasses, c);
3131 /* add to unlinked classes */
3132 list_addlast (&unlinkedclasses, c);
3133 /*JOWENN primitive types don't have objects as super class c -> super = class_java_lang_Object; */
3136 primitivetype_table[i].class_primitive = c;
3138 /* create class for wrapping the primitive type */
3139 primitivetype_table[i].class_wrap =
3140 class_new( utf_new_char(primitivetype_table[i].wrapname) );
3141 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
3142 primitivetype_table[i].class_wrap -> impldBy = NULL;
3144 /* create the primitive array class */
3145 if (primitivetype_table[i].arrayname) {
3146 c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
3147 primitivetype_table[i].arrayclass = c;
3149 if (!c->linked) class_link(c);
3150 primitivetype_table[i].arrayvftbl = c->vftbl;
3155 /**************** function: class_primitive_from_sig ***************************
3157 return the primitive class indicated by the given signature character
3159 If the descriptor does not indicate a valid primitive type the
3160 return value is NULL.
3162 ********************************************************************************/
3164 classinfo *class_primitive_from_sig(char sig)
3167 case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
3168 case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
3169 case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
3170 case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
3171 case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
3172 case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
3173 case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
3174 case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
3175 case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
3180 /****************** function: class_from_descriptor ****************************
3182 return the class indicated by the given descriptor
3184 utf_ptr....first character of descriptor
3185 end_ptr....first character after the end of the string
3186 next.......if non-NULL, *next is set to the first character after
3187 the descriptor. (Undefined if an error occurs.)
3189 mode.......a combination (binary or) of the following flags:
3191 (Flags marked with * are the default settings.)
3193 What to do if a reference type descriptor is parsed successfully:
3195 CLASSLOAD_SKIP...skip it and return something != NULL
3196 * CLASSLOAD_NEW....get classinfo * via class_new
3197 CLASSLOAD_LOAD...get classinfo * via loader_load
3199 How to handle primitive types:
3201 * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
3202 CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
3204 How to handle "V" descriptors:
3206 * CLASSLOAD_VOID.....handle it like other primitive types
3207 CLASSLOAD_NOVOID...treat it as an error
3209 How to deal with extra characters after the end of the
3212 * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
3213 CLASSLOAD_CHECKEND.....treat them as an error
3215 How to deal with errors:
3217 * CLASSLOAD_PANIC....abort execution with an error message
3218 CLASSLOAD_NOPANIC..return NULL on error
3220 ********************************************************************************/
3222 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
3223 char **next, int mode)
3225 char *start = utf_ptr;
3229 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
3231 if (mode & CLASSLOAD_CHECKEND)
3232 error |= (utf_ptr != end_ptr);
3235 if (next) *next = utf_ptr;
3239 if (mode & CLASSLOAD_NOVOID)
3250 return (mode & CLASSLOAD_NULLPRIMITIVE)
3252 : class_primitive_from_sig(*start);
3259 if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
3260 name = utf_new(start,utf_ptr-start);
3261 return (mode & CLASSLOAD_LOAD)
3262 ? loader_load(name) : class_new(name); /* XXX */
3266 /* An error occurred */
3267 if (mode & CLASSLOAD_NOPANIC)
3270 log_plain("Invalid descriptor at beginning of '");
3271 log_plain_utf(utf_new(start, end_ptr-start));
3275 panic("Invalid descriptor");
3277 /* keep compiler happy */
3282 /******************* function: type_from_descriptor ****************************
3284 return the basic type indicated by the given descriptor
3286 This function parses a descriptor and returns its basic type as
3287 TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
3289 cls...if non-NULL the referenced variable is set to the classinfo *
3290 returned by class_from_descriptor.
3292 For documentation of the arguments utf_ptr, end_ptr, next and mode
3293 see class_from_descriptor. The only difference is that
3294 type_from_descriptor always uses CLASSLOAD_PANIC.
3296 ********************************************************************************/
3298 int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
3299 char **next, int mode)
3302 if (!cls) cls = &mycls;
3303 *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
3320 return TYPE_ADDRESS;
3324 /*************** function: create_pseudo_classes *******************************
3326 create pseudo classes used by the typechecker
3328 ********************************************************************************/
3330 static void create_pseudo_classes()
3332 /* pseudo class for Arraystubs (extends java.lang.Object) */
3334 pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
3335 list_remove(&unloadedclasses, pseudo_class_Arraystub);
3337 pseudo_class_Arraystub->super = class_java_lang_Object;
3338 pseudo_class_Arraystub->interfacescount = 2;
3339 pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
3340 pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
3341 pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
3343 list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
3344 class_link(pseudo_class_Arraystub);
3346 pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
3348 /* pseudo class representing the null type */
3350 pseudo_class_Null = class_new(utf_new_char("$NULL$"));
3351 list_remove(&unloadedclasses, pseudo_class_Null);
3353 pseudo_class_Null->super = class_java_lang_Object;
3355 list_addlast(&unlinkedclasses, pseudo_class_Null);
3356 class_link(pseudo_class_Null);
3358 /* pseudo class representing new uninitialized objects */
3360 pseudo_class_New = class_new(utf_new_char("$NEW$"));
3361 list_remove(&unloadedclasses, pseudo_class_New);
3363 pseudo_class_New->super = class_java_lang_Object;
3365 list_addlast(&unlinkedclasses, pseudo_class_New);
3366 class_link(pseudo_class_New);
3370 /********************** Function: loader_init **********************************
3372 Initializes all lists and loads all classes required for the system or the
3375 *******************************************************************************/
3377 void loader_init(u1 *stackbottom)
3381 log_text("Entering loader_init");
3383 list_init(&unloadedclasses, OFFSET(classinfo, listnode));
3384 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
3385 list_init(&linkedclasses, OFFSET(classinfo, listnode));
3387 /* create utf-symbols for pointer comparison of frequently used strings */
3388 utf_innerclasses = utf_new_char("InnerClasses");
3389 utf_constantvalue = utf_new_char("ConstantValue");
3390 utf_code = utf_new_char("Code");
3391 utf_finalize = utf_new_char("finalize");
3392 utf_fidesc = utf_new_char("()V");
3393 utf_clinit = utf_new_char("<clinit>");
3394 utf_initsystemclass = utf_new_char("initializeSystemClass");
3395 utf_systemclass = utf_new_char("java/lang/System");
3396 utf_vmclassloader = utf_new_char("java/lang/VMClassLoader");
3397 utf_initialize = utf_new_char("initialize");
3398 utf_initializedesc = utf_new_char("(I)V");
3400 utf_vmclass = utf_new_char("java/lang/VMClass");
3402 /* create some important classes */
3403 /* These classes have to be created now because the classinfo
3404 * pointers are used in the loading code.
3406 class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
3407 class_java_lang_String = class_new(utf_new_char("java/lang/String"));
3408 class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
3409 class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
3411 if (verbose) log_text("loader_init: java/lang/Object");
3412 /* load the classes which were created above */
3413 loader_load_sysclass(NULL, class_java_lang_Object->name);
3415 loader_inited = 1; /*JOWENN*/
3417 loader_load_sysclass(&class_java_lang_Throwable,
3418 utf_new_char("java/lang/Throwable"));
3420 if (verbose) log_text("loader_init: loader_load: java/lang/ClassCastException");
3421 loader_load_sysclass(&class_java_lang_ClassCastException,
3422 utf_new_char ("java/lang/ClassCastException"));
3423 loader_load_sysclass(&class_java_lang_NullPointerException,
3424 utf_new_char ("java/lang/NullPointerException"));
3425 loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
3426 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
3427 loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
3428 utf_new_char ("java/lang/NegativeArraySizeException"));
3429 loader_load_sysclass(&class_java_lang_OutOfMemoryError,
3430 utf_new_char ("java/lang/OutOfMemoryError"));
3431 loader_load_sysclass(&class_java_lang_ArrayStoreException,
3432 utf_new_char ("java/lang/ArrayStoreException"));
3433 loader_load_sysclass(&class_java_lang_ArithmeticException,
3434 utf_new_char ("java/lang/ArithmeticException"));
3435 loader_load_sysclass(&class_java_lang_ThreadDeath,
3436 utf_new_char ("java/lang/ThreadDeath"));
3438 /* create classes representing primitive types */
3439 create_primitive_classes();
3441 /* create classes used by the typechecker */
3442 create_pseudo_classes();
3444 /* correct vftbl-entries (retarded loading of class java/lang/String) */
3445 stringtable_update();
3452 if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
3453 proto_java_lang_ClassCastException =
3454 builtin_new(class_java_lang_ClassCastException);
3456 if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
3458 proto_java_lang_NullPointerException =
3459 builtin_new(class_java_lang_NullPointerException);
3460 if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
3462 proto_java_lang_ArrayIndexOutOfBoundsException =
3463 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
3465 proto_java_lang_NegativeArraySizeException =
3466 builtin_new(class_java_lang_NegativeArraySizeException);
3468 proto_java_lang_OutOfMemoryError =
3469 builtin_new(class_java_lang_OutOfMemoryError);
3471 proto_java_lang_ArithmeticException =
3472 builtin_new(class_java_lang_ArithmeticException);
3474 proto_java_lang_ArrayStoreException =
3475 builtin_new(class_java_lang_ArrayStoreException);
3477 proto_java_lang_ThreadDeath =
3478 builtin_new(class_java_lang_ThreadDeath);
3484 /********************* Function: loader_initclasses ****************************
3486 Initializes all loaded but uninitialized classes
3488 *******************************************************************************/
3491 /* XXX TWISTI: i think we do not need this */
3492 void loader_initclasses ()
3496 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3497 pthread_mutex_lock(&compiler_mutex);
3500 intsDisable(); /* schani */
3502 if (makeinitializations) {
3503 c = list_first(&linkedclasses);
3506 c = list_next(&linkedclasses, c);
3510 intsRestore(); /* schani */
3512 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3513 pthread_mutex_unlock(&compiler_mutex);
3519 static void loader_compute_class_values(classinfo *c)
3523 c->vftbl->baseval = ++classvalue;
3526 while (subs != NULL) {
3527 loader_compute_class_values(subs);
3528 subs = subs->nextsub;
3530 c->vftbl->diffval = classvalue - c->vftbl->baseval;
3535 for (i = 0; i < c->index; i++)
3537 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
3538 utf_display(c->name);
3545 void loader_compute_subclasses()
3549 intsDisable(); /* schani */
3551 c = list_first(&linkedclasses);
3553 if (!(c->flags & ACC_INTERFACE)) {
3557 c = list_next(&linkedclasses, c);
3560 c = list_first(&linkedclasses);
3562 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
3563 c->nextsub = c->super->sub;
3566 c = list_next(&linkedclasses, c);
3570 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3573 loader_compute_class_values(class_java_lang_Object);
3574 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3578 intsRestore(); /* schani */
3582 /******************** function classloader_buffer ******************************
3584 sets buffer for reading classdata
3586 *******************************************************************************/
3588 void classload_buffer(u1 *buf, int len)
3591 classbuffer_size = len;
3592 classbuf_pos = buf - 1;
3596 /******************** Function: loader_close ***********************************
3600 *******************************************************************************/
3606 while ((c = list_first(&unloadedclasses))) {
3607 list_remove(&unloadedclasses, c);
3610 while ((c = list_first(&unlinkedclasses))) {
3611 list_remove(&unlinkedclasses, c);
3614 while ((c = list_first(&linkedclasses))) {
3615 list_remove(&linkedclasses, c);
3622 * These are local overrides for various environment variables in Emacs.
3623 * Please do not remove this and leave it at the end of the file, where
3624 * Emacs will automagically detect them.
3625 * ---------------------------------------------------------------------
3628 * indent-tabs-mode: t