2 /* loader.c ********************************************************************
4 Copyright (c) 1999 A. Krall, R. Grafl, R. Obermaiser, M. Probst
6 See file COPYRIGHT for information on usage and disclaimer of warranties
8 Contains the functions of the class loader.
10 Author: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
11 Changes: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
12 Roman Obermaiser EMAIL: cacao@complang.tuwien.ac.at
13 Mark Probst EMAIL: cacao@complang.tuwien.ac.at
15 Last Change: 1999/11/08
17 *******************************************************************************/
34 #include "toolbox/memory.h"
37 #include "threads/thread.h"
40 /* global variables ***********************************************************/
42 extern bool newcompiler; /* true if new compiler is used */
44 int count_class_infos = 0; /* variables for measurements */
45 int count_const_pool_len = 0;
46 int count_vftbl_len = 0;
47 int count_all_methods = 0;
48 int count_vmcode_len = 0;
49 int count_extable_len = 0;
50 int count_class_loads = 0;
51 int count_class_inits = 0;
53 bool loadverbose = false; /* switches for debug messages */
54 bool linkverbose = false;
55 bool initverbose = false;
57 bool makeinitializations = true;
59 bool getloadingtime = false; /* to measure the runtime */
60 long int loadingtime = 0;
62 static s4 interfaceindex; /* sequential numbering of interfaces */
64 list unloadedclasses; /* list of all referenced but not loaded classes */
65 list unlinkedclasses; /* list of all loaded but not linked classes */
66 list linkedclasses; /* list of all completely linked classes */
69 /* utf-symbols for pointer comparison of frequently used strings */
71 static utf *utf_innerclasses; /* InnerClasses */
72 static utf *utf_constantvalue; /* ConstantValue */
73 static utf *utf_code; /* Code */
74 static utf *utf_finalize; /* finalize */
75 static utf *utf_fidesc; /* ()V */
76 static utf *utf_clinit; /* <clinit> */
77 static utf *utf_initsystemclass; /* initializeSystemClass */
78 static utf *utf_systemclass; /* java/lang/System */
81 /* important system classes ***************************************************/
83 classinfo *class_java_lang_Object;
84 classinfo *class_java_lang_String;
85 classinfo *class_java_lang_ClassCastException;
86 classinfo *class_java_lang_NullPointerException;
87 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
88 classinfo *class_java_lang_NegativeArraySizeException;
89 classinfo *class_java_lang_OutOfMemoryError;
90 classinfo *class_java_lang_ArithmeticException;
91 classinfo *class_java_lang_ArrayStoreException;
92 classinfo *class_java_lang_ThreadDeath;
93 classinfo *class_array = NULL;
96 /******************************************************************************
98 structure for primitive classes: contains the class for wrapping the
99 primitive type, the primitive class, the name of the class for wrapping,
100 the one character type signature and the name of the primitive class
102 ******************************************************************************/
104 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
105 { NULL, NULL, "java/lang/Double", 'D', "double" },
106 { NULL, NULL, "java/lang/Float", 'F', "float" },
107 { NULL, NULL, "java/lang/Character", 'C', "char" },
108 { NULL, NULL, "java/lang/Integer", 'I', "int" },
109 { NULL, NULL, "java/lang/Long", 'J', "long" },
110 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
111 { NULL, NULL, "java/lang/Short", 'S', "short" },
112 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
113 { NULL, NULL, "java/lang/Void", 'V', "void" }};
116 /* instances of important system classes **************************************/
118 java_objectheader *proto_java_lang_ClassCastException;
119 java_objectheader *proto_java_lang_NullPointerException;
120 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
121 java_objectheader *proto_java_lang_NegativeArraySizeException;
122 java_objectheader *proto_java_lang_OutOfMemoryError;
123 java_objectheader *proto_java_lang_ArithmeticException;
124 java_objectheader *proto_java_lang_ArrayStoreException;
125 java_objectheader *proto_java_lang_ThreadDeath;
128 /************* functions for reading classdata *********************************
130 getting classdata in blocks of variable size
131 (8,16,32,64-bit integer or float)
133 *******************************************************************************/
135 static char *classpath = ""; /* searchpath for classfiles */
136 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
137 static u1 *classbuf_pos; /* current position in classfile buffer */
138 static int classbuffer_size; /* size of classfile-data */
140 /* transfer block of classfile data into a buffer */
142 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
145 /* skip block of classfile data */
147 #define skip_nbytes(len) classbuf_pos+=len;
151 return *++classbuf_pos;
155 u1 a=suck_u1(), b=suck_u1();
156 return ((u2)a<<8)+(u2)b;
160 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
161 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
163 #define suck_s8() (s8) suck_u8()
164 #define suck_s2() (s2) suck_u2()
165 #define suck_s4() (s4) suck_u4()
166 #define suck_s1() (s1) suck_u1()
169 /* get u8 from classfile data */
177 return (hi<<32) + lo;
186 /* get float from classfile data */
188 static float suck_float ()
195 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
196 memcpy ( (u1*) (&f), buffer, 4);
198 suck_nbytes ( (u1*) (&f), 4 );
201 PANICIF (sizeof(float) != 4, "Incompatible float-format");
206 /* get double from classfile data */
207 static double suck_double ()
214 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
215 memcpy ( (u1*) (&d), buffer, 8);
217 suck_nbytes ( (u1*) (&d), 8 );
220 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
225 /************************** function suck_init *********************************
227 called once at startup, sets the searchpath for the classfiles
229 *******************************************************************************/
231 void suck_init (char *cpath)
238 /************************** function suck_start ********************************
240 returns true if classbuffer is already loaded or a file for the
241 specified class has succussfully been read in. All directories of
242 the searchpath are used to find the classfile (<classname>.class).
243 Returns false if no classfile is found and writes an error message.
245 *******************************************************************************/
248 bool suck_start (utf *classname) {
250 #define MAXFILENAME 1000 /* maximum length of a filename */
252 char filename[MAXFILENAME+10]; /* room for '.class' */
253 char *pathpos; /* position in searchpath */
254 char c, *utf_ptr; /* pointer to the next utf8-character */
256 int filenamelen, err;
259 if (classbuffer) /* classbuffer is already valid */
266 /* skip path separator */
268 while (*pathpos == ':')
271 /* extract directory from searchpath */
274 while ((*pathpos) && (*pathpos!=':')) {
275 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
276 filename[filenamelen++] = *(pathpos++);
279 filename[filenamelen++] = '/';
281 /* add classname to filename */
283 utf_ptr = classname->text;
284 while (utf_ptr < utf_end(classname)) {
285 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
287 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
289 filename[filenamelen++] = c;
294 strcpy (filename+filenamelen, ".class");
296 classfile = fopen(filename, "r");
297 if (classfile) { /* file exists */
299 /* determine size of classfile */
301 err = stat (filename, &buffer);
303 if (!err) { /* read classfile data */
304 classbuffer_size = buffer.st_size;
305 classbuffer = MNEW(u1, classbuffer_size);
306 classbuf_pos = classbuffer-1;
307 fread(classbuffer, 1, classbuffer_size, classfile);
315 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
323 /************************** function suck_stop *********************************
325 frees memory for buffer with classfile data.
326 Caution: this function may only be called if buffer has been allocated
327 by suck_start with reading a file
329 *******************************************************************************/
333 /* determine amount of classdata not retrieved by suck-operations */
335 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
337 if (classdata_left > 0) {
339 sprintf (logtext,"There are %d access bytes at end of classfile",
346 MFREE(classbuffer, u1, classbuffer_size);
350 /******************************************************************************/
351 /******************* Some support functions ***********************************/
352 /******************************************************************************/
355 /********** internal function: printflags (only for debugging) ***************/
357 static void printflags (u2 f)
359 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
360 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
361 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
362 if ( f & ACC_STATIC ) printf (" STATIC");
363 if ( f & ACC_FINAL ) printf (" FINAL");
364 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
365 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
366 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
367 if ( f & ACC_NATIVE ) printf (" NATIVE");
368 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
369 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
373 /************************* Function: skipattribute *****************************
375 skips a (1) 'attribute' structure in the class file
377 *******************************************************************************/
379 static void skipattribute ()
382 skip_nbytes(suck_u4());
385 /********************** Function: skipattributebody ****************************
387 skips an attribute after the 16 bit reference to attribute_name has already
390 *******************************************************************************/
392 static void skipattributebody ()
394 skip_nbytes(suck_u4());
397 /************************* Function: skipattributes ****************************
399 skips num attribute structures
401 *******************************************************************************/
403 static void skipattributes (u4 num)
406 for (i = 0; i < num; i++)
410 /******************** function: innerclass_getconstant ************************
412 like class_getconstant, but if cptags is ZERO null is returned
414 *******************************************************************************/
416 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
418 /* invalid position in constantpool */
419 if (pos >= c->cpcount)
420 panic ("Attempt to access constant outside range");
422 /* constantpool entry of type 0 */
426 /* check type of constantpool entry */
427 if (c->cptags[pos] != ctype) {
428 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
429 (int) ctype, (int) c->cptags[pos] );
433 return c->cpinfos[pos];
436 /************************ function: attribute_load ****************************
438 read attributes from classfile
440 *******************************************************************************/
442 static void attribute_load (u4 num, classinfo *c)
446 for (i = 0; i < num; i++) {
447 /* retrieve attribute name */
448 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
450 if ( aname == utf_innerclasses) {
451 /* innerclasses attribute */
453 /* skip attribute length */
455 /* number of records */
456 c->innerclasscount = suck_u2();
457 /* allocate memory for innerclass structure */
458 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
460 for (j=0;j<c->innerclasscount;j++) {
462 /* The innerclass structure contains a class with an encoded name,
463 its defining scope, its simple name and a bitmask of the access flags.
464 If an inner class is not a member, its outer_class is NULL,
465 if a class is anonymous, its name is NULL. */
467 innerclassinfo *info = c->innerclass + j;
469 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
470 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
471 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
472 info->flags = suck_u2 (); /* access_flags bitmask */
475 /* unknown attribute */
476 skipattributebody ();
481 /******************* function: checkfielddescriptor ****************************
483 checks whether a field-descriptor is valid and aborts otherwise
484 all referenced classes are inserted into the list of unloaded classes
486 *******************************************************************************/
488 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
490 char *tstart; /* pointer to start of classname */
493 switch (*utf_ptr++) {
506 /* save start of classname */
509 /* determine length of classname */
510 while ( *utf_ptr++ != ';' )
511 if (utf_ptr>=end_pos)
512 panic ("Missing ';' in objecttype-descriptor");
514 /* cause loading of referenced class */
515 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
520 while ((ch = *utf_ptr++)=='[')
523 /* component type of array */
537 /* save start of classname */
540 /* determine length of classname */
541 while ( *utf_ptr++ != ';' )
542 if (utf_ptr>=end_pos)
543 panic ("Missing ';' in objecttype-descriptor");
545 /* cause loading of referenced class */
546 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
550 panic ("Ill formed methodtype-descriptor");
555 panic ("Ill formed methodtype-descriptor");
558 /* exceeding characters */
559 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
563 /******************* function checkmethoddescriptor ****************************
565 checks whether a method-descriptor is valid and aborts otherwise.
566 All referenced classes are inserted into the list of unloaded classes.
568 *******************************************************************************/
570 static void checkmethoddescriptor (utf *d)
572 char *utf_ptr = d->text; /* current position in utf text */
573 char *end_pos = utf_end(d); /* points behind utf string */
574 char *tstart; /* pointer to start of classname */
577 /* method descriptor must start with parenthesis */
578 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
580 /* check arguments */
581 while ((c = *utf_ptr++) != ')') {
595 /* save start of classname */
598 /* determine length of classname */
599 while ( *utf_ptr++ != ';' )
600 if (utf_ptr>=end_pos)
601 panic ("Missing ';' in objecttype-descriptor");
603 /* cause loading of referenced class */
604 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
609 while ((ch = *utf_ptr++)=='[')
612 /* component type of array */
626 /* save start of classname */
629 /* determine length of classname */
630 while ( *utf_ptr++ != ';' )
631 if (utf_ptr>=end_pos)
632 panic ("Missing ';' in objecttype-descriptor");
634 /* cause loading of referenced class */
635 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
639 panic ("Ill formed methodtype-descriptor");
644 panic ("Ill formed methodtype-descriptor");
648 /* check returntype */
650 /* returntype void */
651 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
654 /* treat as field-descriptor */
655 checkfielddescriptor (utf_ptr,end_pos);
659 /******************** Function: buildarraydescriptor ***************************
661 creates a constant_arraydescriptor structure for the array type named by an
664 *******************************************************************************/
666 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
668 constant_arraydescriptor *d;
670 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
672 d = NEW (constant_arraydescriptor);
673 d -> objectclass = NULL;
674 d -> elementdescriptor = NULL;
677 count_const_pool_len += sizeof(constant_arraydescriptor);
681 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
682 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
683 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
684 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
685 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
686 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
687 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
688 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
691 d -> arraytype = ARRAYTYPE_ARRAY;
692 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
696 d -> arraytype = ARRAYTYPE_OBJECT;
697 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
704 /******************* Function: freearraydescriptor *****************************
706 removes a structure created by buildarraydescriptor from memory
708 *******************************************************************************/
710 static void freearraydescriptor (constant_arraydescriptor *d)
713 constant_arraydescriptor *n = d->elementdescriptor;
714 FREE (d, constant_arraydescriptor);
719 /*********************** Function: displayarraydescriptor *********************/
721 static void displayarraydescriptor (constant_arraydescriptor *d)
723 switch (d->arraytype) {
724 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
725 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
726 case ARRAYTYPE_CHAR: printf ("char[]"); break;
727 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
728 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
729 case ARRAYTYPE_INT: printf ("int[]"); break;
730 case ARRAYTYPE_LONG: printf ("long[]"); break;
731 case ARRAYTYPE_SHORT: printf ("short[]"); break;
732 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
733 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
739 /******************************************************************************/
740 /************************** Functions for fields ****************************/
741 /******************************************************************************/
744 /************************ Function: field_load *********************************
746 Load everything about a class field from the class file and fill a
747 'fieldinfo' structure. For static fields, space in the data segment is
750 *******************************************************************************/
752 static void field_load (fieldinfo *f, classinfo *c)
757 f -> flags = suck_u2 (); /* ACC flags */
758 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
759 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
760 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
761 f -> offset = 0; /* offset from start of object */
764 case TYPE_INT: f->value.i = 0; break;
765 case TYPE_FLOAT: f->value.f = 0.0; break;
766 case TYPE_DOUBLE: f->value.d = 0.0; break;
767 case TYPE_ADDRESS: f->value.a = NULL;
768 heap_addreference (&(f->value.a)); /* make global reference (GC) */
772 f->value.l = 0; break;
774 f->value.l.low = 0; f->value.l.high = 0; break;
778 /* read attributes */
780 for (i=0; i<attrnum; i++) {
784 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
786 if ( aname != utf_constantvalue ) {
787 /* unknown attribute */
788 skipattributebody ();
791 /* constant value attribute */
793 /* skip attribute length */
795 /* index of value in constantpool */
798 /* initialize field with value from constantpool */
801 constant_integer *ci =
802 class_getconstant(c, pindex, CONSTANT_Integer);
803 f->value.i = ci -> value;
809 class_getconstant(c, pindex, CONSTANT_Long);
811 f->value.l = cl -> value;
817 class_getconstant(c, pindex, CONSTANT_Float);
819 f->value.f = cf->value;
824 constant_double *cd =
825 class_getconstant(c, pindex, CONSTANT_Double);
827 f->value.d = cd->value;
832 utf *u = class_getconstant(c, pindex, CONSTANT_String);
833 /* create javastring from compressed utf8-string */
834 f->value.a = literalstring_new(u);
839 log_text ("Invalid Constant - Type");
848 /********************** function: field_free **********************************/
850 static void field_free (fieldinfo *f)
856 /**************** Function: field_display (debugging only) ********************/
858 static void field_display (fieldinfo *f)
861 printflags (f -> flags);
863 utf_display (f -> name);
865 utf_display (f -> descriptor);
866 printf (" offset: %ld\n", (long int) (f -> offset) );
870 /******************************************************************************/
871 /************************* Functions for methods ******************************/
872 /******************************************************************************/
875 /*********************** Function: method_load *********************************
877 Loads a method from the class file and fills an existing 'methodinfo'
878 structure. For native methods, the function pointer field is set to the
879 real function pointer, for JavaVM methods a pointer to the compiler is used
882 *******************************************************************************/
884 static void method_load (methodinfo *m, classinfo *c)
894 m -> flags = suck_u2 ();
895 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
896 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
899 m -> exceptiontable = NULL;
900 m -> entrypoint = NULL;
902 m -> stubroutine = NULL;
904 if (! (m->flags & ACC_NATIVE) ) {
905 m -> stubroutine = createcompilerstub (m);
909 functionptr f = native_findfunction
910 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
915 m -> stubroutine = createnativestub (f, m);
918 m -> stubroutine = oldcreatenativestub (f, m);
925 for (i=0; i<attrnum; i++) {
928 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
930 if ( aname != utf_code) {
931 skipattributebody ();
934 if (m -> jcode) panic ("Two code-attributes for one method!");
937 m -> maxstack = suck_u2();
938 m -> maxlocals = suck_u2();
939 m -> jcodelength = suck_u4();
940 m -> jcode = MNEW (u1, m->jcodelength);
941 suck_nbytes (m->jcode, m->jcodelength);
942 m -> exceptiontablelength = suck_u2 ();
943 m -> exceptiontable =
944 MNEW (exceptiontable, m->exceptiontablelength);
947 count_vmcode_len += m->jcodelength + 18;
948 count_extable_len += 8 * m->exceptiontablelength;
951 for (e=0; e < m->exceptiontablelength; e++) {
953 m -> exceptiontable[e].startpc = suck_u2();
954 m -> exceptiontable[e].endpc = suck_u2();
955 m -> exceptiontable[e].handlerpc = suck_u2();
958 if (!idx) m -> exceptiontable[e].catchtype = NULL;
960 m -> exceptiontable[e].catchtype =
961 class_getconstant (c, idx, CONSTANT_Class);
965 skipattributes ( suck_u2() );
972 /********************* Function: method_free ***********************************
974 frees all memory that was allocated for this method
976 *******************************************************************************/
978 static void method_free (methodinfo *m)
980 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
981 if (m->exceptiontable)
982 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
983 if (m->mcode) CFREE (m->mcode, m->mcodelength);
984 if (m->stubroutine) {
985 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
986 else removecompilerstub (m->stubroutine);
991 /************** Function: method_display (debugging only) **************/
993 void method_display (methodinfo *m)
996 printflags (m -> flags);
998 utf_display (m -> name);
1000 utf_display (m -> descriptor);
1005 /******************** Function: method_canoverwrite ****************************
1007 Check if m and old are identical with respect to type and name. This means
1008 that old can be overwritten with m.
1010 *******************************************************************************/
1012 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1014 if (m->name != old->name) return false;
1015 if (m->descriptor != old->descriptor) return false;
1016 if (m->flags & ACC_STATIC) return false;
1023 /******************************************************************************/
1024 /************************ Functions for class *********************************/
1025 /******************************************************************************/
1028 /******************** function: class_getconstant ******************************
1030 retrieves the value at position 'pos' of the constantpool of a class
1031 if the type of the value is other than 'ctype' the system is stopped
1033 *******************************************************************************/
1035 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1037 /* invalid position in constantpool */
1038 if (pos >= c->cpcount)
1039 panic ("Attempt to access constant outside range");
1041 /* check type of constantpool entry */
1042 if (c->cptags[pos] != ctype) {
1043 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1044 (int) ctype, (int) c->cptags[pos] );
1048 return c->cpinfos[pos];
1052 /********************* Function: class_constanttype ****************************
1054 Determines the type of a class entry in the ConstantPool
1056 *******************************************************************************/
1058 u4 class_constanttype (classinfo *c, u4 pos)
1060 if (pos >= c->cpcount)
1061 panic ("Attempt to access constant outside range");
1062 return c->cptags[pos];
1066 /******************** function: class_loadcpool ********************************
1068 loads the constantpool of a class,
1069 the entries are transformed into a simpler format
1070 by resolving references
1071 (a detailed overview of the compact structures can be found in global.h)
1073 *******************************************************************************/
1075 static void class_loadcpool (classinfo *c)
1078 /* The following structures are used to save information which cannot be
1079 processed during the first pass. After the complete constantpool has
1080 been traversed the references can be resolved.
1081 (only in specific order) */
1083 /* CONSTANT_Class_info entries */
1084 typedef struct forward_class {
1085 struct forward_class *next;
1090 /* CONSTANT_String */
1091 typedef struct forward_string {
1092 struct forward_string *next;
1097 /* CONSTANT_NameAndType */
1098 typedef struct forward_nameandtype {
1099 struct forward_nameandtype *next;
1103 } forward_nameandtype;
1105 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1106 typedef struct forward_fieldmethint {
1107 struct forward_fieldmethint *next;
1111 u2 nameandtype_index;
1112 } forward_fieldmethint;
1116 long int dumpsize = dump_size ();
1118 forward_class *forward_classes = NULL;
1119 forward_string *forward_strings = NULL;
1120 forward_nameandtype *forward_nameandtypes = NULL;
1121 forward_fieldmethint *forward_fieldmethints = NULL;
1123 /* number of entries in the constant_pool table */
1124 u4 cpcount = c -> cpcount = suck_u2();
1125 /* allocate memory */
1126 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1127 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1130 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1133 /* initialize constantpool */
1134 for (idx=0; idx<cpcount; idx++) {
1135 cptags[idx] = CONSTANT_UNUSED;
1136 cpinfos[idx] = NULL;
1140 /******* first pass *******/
1141 /* entries which cannot be resolved now are written into
1142 temporary structures and traversed again later */
1145 while (idx < cpcount) {
1146 /* get constant type */
1150 case CONSTANT_Class: {
1151 forward_class *nfc = DNEW(forward_class);
1153 nfc -> next = forward_classes;
1154 forward_classes = nfc;
1156 nfc -> thisindex = idx;
1157 /* reference to CONSTANT_NameAndType */
1158 nfc -> name_index = suck_u2 ();
1164 case CONSTANT_Fieldref:
1165 case CONSTANT_Methodref:
1166 case CONSTANT_InterfaceMethodref: {
1167 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1169 nff -> next = forward_fieldmethints;
1170 forward_fieldmethints = nff;
1172 nff -> thisindex = idx;
1175 /* class or interface type that contains the declaration of the field or method */
1176 nff -> class_index = suck_u2 ();
1177 /* name and descriptor of the field or method */
1178 nff -> nameandtype_index = suck_u2 ();
1184 case CONSTANT_String: {
1185 forward_string *nfs = DNEW (forward_string);
1187 nfs -> next = forward_strings;
1188 forward_strings = nfs;
1190 nfs -> thisindex = idx;
1191 /* reference to CONSTANT_Utf8_info with string characters */
1192 nfs -> string_index = suck_u2 ();
1198 case CONSTANT_NameAndType: {
1199 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1201 nfn -> next = forward_nameandtypes;
1202 forward_nameandtypes = nfn;
1204 nfn -> thisindex = idx;
1205 /* reference to CONSTANT_Utf8_info containing simple name */
1206 nfn -> name_index = suck_u2 ();
1207 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1208 nfn -> sig_index = suck_u2 ();
1214 case CONSTANT_Integer: {
1215 constant_integer *ci = NEW (constant_integer);
1218 count_const_pool_len += sizeof(constant_integer);
1221 ci -> value = suck_s4 ();
1222 cptags [idx] = CONSTANT_Integer;
1229 case CONSTANT_Float: {
1230 constant_float *cf = NEW (constant_float);
1233 count_const_pool_len += sizeof(constant_float);
1236 cf -> value = suck_float ();
1237 cptags [idx] = CONSTANT_Float;
1243 case CONSTANT_Long: {
1244 constant_long *cl = NEW(constant_long);
1247 count_const_pool_len += sizeof(constant_long);
1250 cl -> value = suck_s8 ();
1251 cptags [idx] = CONSTANT_Long;
1257 case CONSTANT_Double: {
1258 constant_double *cd = NEW(constant_double);
1261 count_const_pool_len += sizeof(constant_double);
1264 cd -> value = suck_double ();
1265 cptags [idx] = CONSTANT_Double;
1271 case CONSTANT_Utf8: {
1273 /* number of bytes in the bytes array (not string-length) */
1274 u4 length = suck_u2();
1275 cptags [idx] = CONSTANT_Utf8;
1276 /* insert utf-string into the utf-symboltable */
1277 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1278 /* skip bytes of the string */
1279 skip_nbytes(length);
1285 sprintf (logtext, "Unkown constant type: %d",(int) t);
1294 /* resolve entries in temporary structures */
1296 while (forward_classes) {
1298 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1300 if ( (name->blength>0) && (name->text[0]=='[') ) {
1301 /* check validity of descriptor */
1302 checkfielddescriptor (name->text, utf_end(name));
1304 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1305 cpinfos [forward_classes -> thisindex] =
1306 buildarraydescriptor(name->text, name->blength);
1310 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1311 /* retrieve class from class-table */
1312 cpinfos [forward_classes -> thisindex] = class_new (name);
1314 forward_classes = forward_classes -> next;
1318 while (forward_strings) {
1320 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1322 /* resolve utf-string */
1323 cptags [forward_strings -> thisindex] = CONSTANT_String;
1324 cpinfos [forward_strings -> thisindex] = text;
1326 forward_strings = forward_strings -> next;
1329 while (forward_nameandtypes) {
1330 constant_nameandtype *cn = NEW (constant_nameandtype);
1333 count_const_pool_len += sizeof(constant_nameandtype);
1336 /* resolve simple name and descriptor */
1337 cn -> name = class_getconstant
1338 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1339 cn -> descriptor = class_getconstant
1340 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1342 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1343 cpinfos [forward_nameandtypes -> thisindex] = cn;
1345 forward_nameandtypes = forward_nameandtypes -> next;
1349 while (forward_fieldmethints) {
1350 constant_nameandtype *nat;
1351 constant_FMIref *fmi = NEW (constant_FMIref);
1354 count_const_pool_len += sizeof(constant_FMIref);
1356 /* resolve simple name and descriptor */
1357 nat = class_getconstant
1358 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1360 fmi -> class = class_getconstant
1361 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1362 fmi -> name = nat -> name;
1363 fmi -> descriptor = nat -> descriptor;
1365 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1366 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1368 switch (forward_fieldmethints -> tag) {
1369 case CONSTANT_Fieldref: /* check validity of descriptor */
1370 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1372 case CONSTANT_InterfaceMethodref:
1373 case CONSTANT_Methodref: /* check validity of descriptor */
1374 checkmethoddescriptor (fmi->descriptor);
1378 forward_fieldmethints = forward_fieldmethints -> next;
1383 dump_release (dumpsize);
1387 /********************** Function: class_load ***********************************
1389 Loads everything interesting about a class from the class file. The
1390 'classinfo' structure must have been allocated previously.
1392 The super class and the interfaces implemented by this class need not be
1393 loaded. The link is set later by the function 'class_link'.
1395 The loaded class is removed from the list 'unloadedclasses' and added to
1396 the list 'unlinkedclasses'.
1398 *******************************************************************************/
1400 static int class_load (classinfo *c)
1406 count_class_loads++;
1409 /* output for debugging purposes */
1411 sprintf (logtext, "Loading class: ");
1412 utf_sprint (logtext+strlen(logtext), c->name );
1416 /* load classdata, throw exception on error */
1417 if (!suck_start (c->name)) {
1418 throw_classnotfoundexception();
1422 /* check signature */
1423 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1427 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1428 sprintf (logtext, "File version %d.%d is not supported",
1429 (int) ma, (int) mi);
1434 class_loadcpool (c);
1437 c -> flags = suck_u2 ();
1441 /* retrieve superclass */
1442 if ( (i = suck_u2 () ) ) {
1443 c -> super = class_getconstant (c, i, CONSTANT_Class);
1449 /* retrieve interfaces */
1450 c -> interfacescount = suck_u2 ();
1451 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1452 for (i=0; i < c -> interfacescount; i++) {
1453 c -> interfaces [i] =
1454 class_getconstant (c, suck_u2(), CONSTANT_Class);
1458 c -> fieldscount = suck_u2 ();
1460 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1462 c -> fields = MNEW (fieldinfo, c -> fieldscount);
1464 for (i=0; i < c -> fieldscount; i++) {
1465 field_load (&(c->fields[i]), c);
1469 c -> methodscount = suck_u2 ();
1470 c -> methods = MNEW (methodinfo, c -> methodscount);
1471 for (i=0; i < c -> methodscount; i++) {
1472 method_load (&(c -> methods [i]), c);
1476 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1477 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1478 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1481 /* load variable-length attribute structures */
1482 attribute_load (suck_u2(), c);
1487 /* remove class from list of unloaded classes and
1488 add to list of unlinked classes */
1489 list_remove (&unloadedclasses, c);
1490 list_addlast (&unlinkedclasses, c);
1497 /************** internal Function: class_highestinterface ***********************
1499 Used by the function class_link to determine the amount of memory needed
1500 for the interface table.
1502 *******************************************************************************/
1504 static s4 class_highestinterface (classinfo *c)
1509 if ( ! (c->flags & ACC_INTERFACE) ) {
1510 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1511 utf_sprint (logtext+strlen(logtext), c->name);
1516 for (i=0; i<c->interfacescount; i++) {
1517 s4 h2 = class_highestinterface (c->interfaces[i]);
1524 /* class_addinterface **********************************************************
1526 Is needed by class_link for adding a VTBL to a class. All interfaces
1527 implemented by ic are added as well.
1529 *******************************************************************************/
1531 static void class_addinterface (classinfo *c, classinfo *ic)
1535 vftbl *vftbl = c->vftbl;
1537 if (i >= vftbl->interfacetablelength)
1538 panic ("Inernal error: interfacetable overflow");
1539 if (vftbl->interfacetable[-i])
1542 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1543 vftbl->interfacevftbllength[i] = 1;
1544 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1545 vftbl->interfacetable[-i][0] = NULL;
1548 vftbl->interfacevftbllength[i] = ic->methodscount;
1549 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1552 count_vftbl_len += sizeof(methodptr) *
1553 (ic->methodscount + (ic->methodscount == 0));
1556 for (j=0; j<ic->methodscount; j++) {
1559 for (m = 0; m < sc->methodscount; m++) {
1560 methodinfo *mi = &(sc->methods[m]);
1561 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1562 vftbl->interfacetable[-i][j] =
1563 vftbl->table[mi->vftblindex];
1573 for (j = 0; j < ic->interfacescount; j++)
1574 class_addinterface(c, ic->interfaces[j]);
1578 /********************** Function: class_link ***********************************
1580 Tries to link a class. The super class and every implemented interface must
1581 already have been linked. The function calculates the length in bytes that
1582 an instance of this class requires as well as the VTBL for methods and
1585 If the class can be linked, it is removed from the list 'unlinkedclasses'
1586 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1589 Attention: If cyclical class definitions are encountered, the program gets
1590 into an infinite loop (we'll have to work that out)
1592 *******************************************************************************/
1594 static void class_link (classinfo *c)
1596 s4 supervftbllength; /* vftbllegnth of super class */
1597 s4 vftbllength; /* vftbllength of current class */
1598 s4 interfacetablelength; /* interface table length */
1599 classinfo *super = c->super; /* super class */
1600 classinfo *ic, *c2; /* intermediate class variables */
1601 vftbl *v; /* vftbl of current class */
1602 s4 i; /* interface/method/field counter */
1605 /* check if all superclasses are already linked, if not put c at end of
1606 unlinked list and return. Additionally initialize class fields. */
1608 /* check interfaces */
1610 for (i = 0; i < c->interfacescount; i++) {
1611 ic = c->interfaces[i];
1613 list_remove(&unlinkedclasses, c);
1614 list_addlast(&unlinkedclasses, c);
1619 /* check super class */
1621 if (super == NULL) { /* class java.long.Object */
1623 c->instancesize = sizeof(java_objectheader);
1625 vftbllength = supervftbllength = 0;
1627 c->finalizer = NULL;
1630 if (!super->linked) {
1631 list_remove(&unlinkedclasses, c);
1632 list_addlast(&unlinkedclasses, c);
1636 if (c->flags & ACC_INTERFACE)
1637 c->index = interfaceindex++;
1639 c->index = super->index + 1;
1641 c->instancesize = super->instancesize;
1643 vftbllength = supervftbllength = super->vftbl->vftbllength;
1645 c->finalizer = super->finalizer;
1650 sprintf (logtext, "Linking Class: ");
1651 utf_sprint (logtext+strlen(logtext), c->name );
1655 /* compute vftbl length */
1657 for (i = 0; i < c->methodscount; i++) {
1658 methodinfo *m = &(c->methods[i]);
1660 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1661 classinfo *sc = super;
1664 for (j = 0; j < sc->methodscount; j++) {
1665 if (method_canoverwrite(m, &(sc->methods[j]))) {
1666 m->vftblindex = sc->methods[j].vftblindex;
1667 goto foundvftblindex;
1672 m->vftblindex = (vftbllength++);
1678 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1681 /* compute interfacetable length */
1683 interfacetablelength = 0;
1686 for (i = 0; i < c2->interfacescount; i++) {
1687 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1688 if (h > interfacetablelength)
1689 interfacetablelength = h;
1694 /* allocate virtual function table */
1696 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1697 (vftbllength - 1) + sizeof(methodptr*) *
1698 (interfacetablelength - (interfacetablelength > 0)));
1699 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1700 (interfacetablelength > 1));
1701 c->header.vftbl = c->vftbl = v;
1703 v->vftbllength = vftbllength;
1704 v->interfacetablelength = interfacetablelength;
1706 /* copy virtual function table of super class */
1708 for (i = 0; i < supervftbllength; i++)
1709 v->table[i] = super->vftbl->table[i];
1711 /* add method stubs into virtual function table */
1713 for (i = 0; i < c->methodscount; i++) {
1714 methodinfo *m = &(c->methods[i]);
1715 if (!(m->flags & ACC_STATIC)) {
1716 v->table[m->vftblindex] = m->stubroutine;
1720 /* compute instance size and offset of each field */
1722 for (i = 0; i < c->fieldscount; i++) {
1724 fieldinfo *f = &(c->fields[i]);
1726 if (!(f->flags & ACC_STATIC) ) {
1727 dsize = desc_typesize (f->descriptor);
1728 c->instancesize = ALIGN (c->instancesize, dsize);
1729 f->offset = c->instancesize;
1730 c->instancesize += dsize;
1734 /* initialize interfacetable and interfacevftbllength */
1736 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1739 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1742 for (i = 0; i < interfacetablelength; i++) {
1743 v->interfacevftbllength[i] = 0;
1744 v->interfacetable[-i] = NULL;
1747 /* add interfaces */
1749 for (c2 = c; c2 != NULL; c2 = c2->super)
1750 for (i = 0; i < c2->interfacescount; i++) {
1751 class_addinterface (c, c2->interfaces[i]);
1754 /* add finalizer method (not for java.lang.Object) */
1756 if (super != NULL) {
1758 static utf *finame = NULL;
1759 static utf *fidesc = NULL;
1762 finame = utf_finalize;
1764 fidesc = utf_fidesc;
1766 fi = class_findmethod (c, finame, fidesc);
1768 if (!(fi->flags & ACC_STATIC)) {
1778 list_remove (&unlinkedclasses, c);
1779 list_addlast (&linkedclasses, c);
1783 /******************* Function: class_freepool **********************************
1785 Frees all resources used by this classes Constant Pool.
1787 *******************************************************************************/
1789 static void class_freecpool (classinfo *c)
1795 for (idx=0; idx < c->cpcount; idx++) {
1796 tag = c->cptags[idx];
1797 info = c->cpinfos[idx];
1801 case CONSTANT_Fieldref:
1802 case CONSTANT_Methodref:
1803 case CONSTANT_InterfaceMethodref:
1804 FREE (info, constant_FMIref);
1806 case CONSTANT_Integer:
1807 FREE (info, constant_integer);
1809 case CONSTANT_Float:
1810 FREE (info, constant_float);
1813 FREE (info, constant_long);
1815 case CONSTANT_Double:
1816 FREE (info, constant_double);
1818 case CONSTANT_NameAndType:
1819 FREE (info, constant_nameandtype);
1821 case CONSTANT_Arraydescriptor:
1822 freearraydescriptor (info);
1828 MFREE (c -> cptags, u1, c -> cpcount);
1829 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1833 /*********************** Function: class_free **********************************
1835 Frees all resources used by the class.
1837 *******************************************************************************/
1839 static void class_free (classinfo *c)
1844 class_freecpool (c);
1846 MFREE (c->interfaces, classinfo*, c->interfacescount);
1848 for (i = 0; i < c->fieldscount; i++)
1849 field_free(&(c->fields[i]));
1851 MFREE (c->fields, fieldinfo, c->fieldscount);
1854 for (i = 0; i < c->methodscount; i++)
1855 method_free(&(c->methods[i]));
1856 MFREE (c->methods, methodinfo, c->methodscount);
1858 if ((v = c->vftbl) != NULL) {
1859 for (i = 0; i < v->interfacetablelength; i++) {
1860 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1862 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1864 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1865 sizeof(methodptr*) * (v->interfacetablelength -
1866 (v->interfacetablelength > 0));
1867 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1868 (v->interfacetablelength > 1));
1872 if (c->innerclasscount)
1873 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1876 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1));
1878 FREE (c, classinfo);
1881 /************************* Function: class_findfield ***************************
1883 Searches a 'classinfo' structure for a field having the given name and
1886 *******************************************************************************/
1889 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1893 for (i = 0; i < c->fieldscount; i++) {
1894 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1895 return &(c->fields[i]);
1898 panic ("Can not find field given in CONSTANT_Fieldref");
1903 /************************* Function: class_findmethod **************************
1905 Searches a 'classinfo' structure for a method having the given name and
1907 If type is NULL, it is ignored.
1909 *******************************************************************************/
1911 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1914 for (i = 0; i < c->methodscount; i++) {
1915 if ((c->methods[i].name == name) && ((desc == NULL) ||
1916 (c->methods[i].descriptor == desc)))
1917 return &(c->methods[i]);
1922 /************************* Function: class_findmethod_approx ******************
1924 like class_findmethod but ignores the return value when comparing the
1927 *******************************************************************************/
1929 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1933 for (i = 0; i < c->methodscount; i++)
1934 if (c->methods[i].name == name) {
1935 utf *meth_descr = c->methods[i].descriptor;
1939 return &(c->methods[i]);
1941 if (desc->blength <= meth_descr->blength) {
1942 /* current position in utf text */
1943 char *desc_utf_ptr = desc->text;
1944 char *meth_utf_ptr = meth_descr->text;
1945 /* points behind utf strings */
1946 char *desc_end = utf_end(desc);
1947 char *meth_end = utf_end(meth_descr);
1950 /* compare argument types */
1951 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1953 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1954 break; /* no match */
1957 return &(c->methods[i]); /* all parameter types equal */
1965 /***************** Function: class_resolvemethod_approx ***********************
1967 Searches a class and every super class for a method (without paying
1968 attention to the return value)
1970 *******************************************************************************/
1972 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
1975 /* search for method (ignore returntype) */
1976 methodinfo *m = class_findmethod_approx (c, name, desc);
1979 /* search superclass */
1986 /************************* Function: class_resolvemethod ***********************
1988 Searches a class and every super class for a method.
1990 *******************************************************************************/
1993 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
1996 methodinfo *m = class_findmethod (c, name, desc);
1998 /* search superclass */
2006 /************************* Function: class_issubclass **************************
2008 Checks if sub is a descendant of super.
2010 *******************************************************************************/
2012 bool class_issubclass (classinfo *sub, classinfo *super)
2015 if (!sub) return false;
2016 if (sub==super) return true;
2023 /****************** Initialization function for classes ******************
2025 In Java, every class can have a static initialization function. This
2026 function has to be called BEFORE calling other methods or accessing static
2029 *******************************************************************************/
2032 extern int blockInts;
2035 void class_init (classinfo *c)
2038 java_objectheader *exceptionptr;
2042 if (!makeinitializations)
2046 c -> initialized = true;
2049 count_class_inits++;
2053 class_init (c->super);
2054 for (i=0; i < c->interfacescount; i++)
2055 class_init(c->interfaces[i]);
2057 m = class_findmethod (c, utf_clinit, utf_fidesc);
2060 sprintf (logtext, "Class ");
2061 utf_sprint (logtext+strlen(logtext), c->name);
2062 sprintf (logtext+strlen(logtext), " has no initializer");
2068 if (! (m->flags & ACC_STATIC))
2069 panic ("Class initializer is not static!");
2072 sprintf (logtext, "Starting initializer for class: ");
2073 utf_sprint (logtext+strlen(logtext), c->name);
2082 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2085 assert(blockInts == 0);
2090 printf ("#### Initializer of ");
2091 utf_display (c->name);
2092 printf (" has thrown: ");
2093 utf_display (exceptionptr->vftbl->class->name);
2099 sprintf (logtext, "Finished initializer for class: ");
2100 utf_sprint (logtext+strlen(logtext), c->name);
2104 if (c->name == utf_systemclass) {
2105 /* class java.lang.System requires explicit initialization */
2108 printf ("#### Initializing class System");
2110 /* find initializing method */
2111 m = class_findmethod (c,
2112 utf_initsystemclass,
2116 /* no method found */
2117 log("initializeSystemClass failed");
2126 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2129 assert(blockInts == 0);
2134 printf ("#### initializeSystemClass has thrown: ");
2135 utf_display (exceptionptr->vftbl->class->name);
2145 /********* Function: class_showconstantpool (debugging only) *********/
2147 void class_showconstantpool (classinfo *c)
2152 printf ("---- dump of constant pool ----\n");
2154 for (i=0; i<c->cpcount; i++) {
2155 printf ("#%d: ", (int) i);
2157 e = c -> cpinfos [i];
2160 switch (c -> cptags [i]) {
2161 case CONSTANT_Class:
2162 printf ("Classreference -> ");
2163 utf_display ( ((classinfo*)e) -> name );
2166 case CONSTANT_Fieldref:
2167 printf ("Fieldref -> "); goto displayFMI;
2168 case CONSTANT_Methodref:
2169 printf ("Methodref -> "); goto displayFMI;
2170 case CONSTANT_InterfaceMethodref:
2171 printf ("InterfaceMethod -> "); goto displayFMI;
2174 constant_FMIref *fmi = e;
2175 utf_display ( fmi->class->name );
2177 utf_display ( fmi->name);
2179 utf_display ( fmi->descriptor );
2183 case CONSTANT_String:
2184 printf ("String -> ");
2187 case CONSTANT_Integer:
2188 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2190 case CONSTANT_Float:
2191 printf ("Float -> %f", ((constant_float*)e) -> value);
2193 case CONSTANT_Double:
2194 printf ("Double -> %f", ((constant_double*)e) -> value);
2198 u8 v = ((constant_long*)e) -> value;
2200 printf ("Long -> %ld", (long int) v);
2202 printf ("Long -> HI: %ld, LO: %ld\n",
2203 (long int) v.high, (long int) v.low);
2207 case CONSTANT_NameAndType:
2208 { constant_nameandtype *cnt = e;
2209 printf ("NameAndType: ");
2210 utf_display (cnt->name);
2212 utf_display (cnt->descriptor);
2216 printf ("Utf8 -> ");
2219 case CONSTANT_Arraydescriptor: {
2220 printf ("Arraydescriptor: ");
2221 displayarraydescriptor (e);
2225 panic ("Invalid type of ConstantPool-Entry");
2237 /********** Function: class_showmethods (debugging only) *************/
2239 void class_showmethods (classinfo *c)
2243 printf ("--------- Fields and Methods ----------------\n");
2244 printf ("Flags: "); printflags (c->flags); printf ("\n");
2246 printf ("This: "); utf_display (c->name); printf ("\n");
2248 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2250 printf ("Index: %d\n", c->index);
2252 printf ("interfaces:\n");
2253 for (i=0; i < c-> interfacescount; i++) {
2255 utf_display (c -> interfaces[i] -> name);
2256 printf (" (%d)\n", c->interfaces[i] -> index);
2259 printf ("fields:\n");
2260 for (i=0; i < c -> fieldscount; i++) {
2261 field_display (&(c -> fields[i]));
2264 printf ("methods:\n");
2265 for (i=0; i < c -> methodscount; i++) {
2266 methodinfo *m = &(c->methods[i]);
2267 if ( !(m->flags & ACC_STATIC))
2268 printf ("vftblindex: %d ", m->vftblindex);
2270 method_display ( m );
2274 printf ("Virtual function table:\n");
2275 for (i=0; i<c->vftbl->vftbllength; i++) {
2276 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2283 /******************************************************************************/
2284 /******************* General functions for the class loader *******************/
2285 /******************************************************************************/
2287 static int loader_inited = 0;
2289 /********************* Function: loader_load ***********************************
2291 Loads and links the class desired class and each class and interface
2293 Returns: a pointer to this class
2295 *******************************************************************************/
2297 classinfo *loader_load (utf *topname)
2301 long int starttime=0,stoptime=0;
2303 intsDisable(); /* schani */
2306 starttime = getcputime();
2308 top = class_new (topname);
2311 while ( (c = list_first(&unloadedclasses)) ) {
2312 if (!class_load (c)) {
2313 list_remove (&unloadedclasses, c);
2319 while ( (c = list_first(&unlinkedclasses)) ) {
2324 loader_compute_subclasses();
2327 if (getloadingtime) {
2328 stoptime = getcputime();
2329 loadingtime += (stoptime-starttime);
2332 intsRestore(); /* schani */
2338 /**************** function: create_primitive_classes ***************************
2340 create classes representing primitive types
2342 ********************************************************************************/
2345 void create_primitive_classes()
2349 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2350 /* create primitive class */
2351 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2353 /* prevent loader from loading primitive class */
2354 list_remove (&unloadedclasses, c);
2355 /* add to unlinked classes */
2356 list_addlast (&unlinkedclasses, c);
2357 c -> super = class_java_lang_Object;
2360 primitivetype_table[i].class_primitive = c;
2362 /* create class for wrapping the primitive type */
2363 primitivetype_table[i].class_wrap =
2364 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2368 /***************** function: create_array_class ********************************
2370 create class representing an array
2372 ********************************************************************************/
2375 classinfo *create_array_class(utf *u)
2377 classinfo *c = class_new (u);
2378 /* prevent loader from loading the array class */
2379 list_remove (&unloadedclasses, c);
2380 /* add to unlinked classes */
2381 list_addlast (&unlinkedclasses, c);
2382 c -> super = class_java_lang_Object;
2388 /********************** Function: loader_init **********************************
2390 Initializes all lists and loads all classes required for the system or the
2393 *******************************************************************************/
2400 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2401 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2402 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2404 /* create utf-symbols for pointer comparison of frequently used strings */
2405 utf_innerclasses = utf_new_char("InnerClasses");
2406 utf_constantvalue = utf_new_char("ConstantValue");
2407 utf_code = utf_new_char("Code");
2408 utf_finalize = utf_new_char("finalize");
2409 utf_fidesc = utf_new_char("()V");
2410 utf_clinit = utf_new_char("<clinit>");
2411 utf_initsystemclass = utf_new_char("initializeSystemClass");
2412 utf_systemclass = utf_new_char("java/lang/System");
2414 /* create class for arrays */
2415 class_array = class_new ( utf_new_char ("The_Array_Class") );
2416 list_remove (&unloadedclasses, class_array);
2418 /* create class for strings, load it after class Object was loaded */
2419 string_class = utf_new_char ("java/lang/String");
2420 class_java_lang_String = class_new(string_class);
2421 list_remove (&unloadedclasses, class_java_lang_String);
2423 class_java_lang_Object =
2424 loader_load ( utf_new_char ("java/lang/Object") );
2426 list_addlast(&unloadedclasses, class_java_lang_String);
2428 class_java_lang_String =
2429 loader_load ( string_class );
2430 class_java_lang_ClassCastException =
2431 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2432 class_java_lang_NullPointerException =
2433 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2434 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2435 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2436 class_java_lang_NegativeArraySizeException = loader_load (
2437 utf_new_char ("java/lang/NegativeArraySizeException") );
2438 class_java_lang_OutOfMemoryError = loader_load (
2439 utf_new_char ("java/lang/OutOfMemoryError") );
2440 class_java_lang_ArrayStoreException =
2441 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2442 class_java_lang_ArithmeticException =
2443 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2444 class_java_lang_ThreadDeath = /* schani */
2445 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2447 /* link class for arrays */
2448 list_addlast (&unlinkedclasses, class_array);
2449 class_array -> super = class_java_lang_Object;
2450 class_link (class_array);
2452 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2453 stringtable_update();
2455 /* create classes representing primitive types */
2456 create_primitive_classes();
2458 proto_java_lang_ClassCastException =
2459 builtin_new(class_java_lang_ClassCastException);
2460 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2462 proto_java_lang_NullPointerException =
2463 builtin_new(class_java_lang_NullPointerException);
2464 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2466 proto_java_lang_ArrayIndexOutOfBoundsException =
2467 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2468 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2470 proto_java_lang_NegativeArraySizeException =
2471 builtin_new(class_java_lang_NegativeArraySizeException);
2472 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2474 proto_java_lang_OutOfMemoryError =
2475 builtin_new(class_java_lang_OutOfMemoryError);
2476 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2478 proto_java_lang_ArithmeticException =
2479 builtin_new(class_java_lang_ArithmeticException);
2480 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2482 proto_java_lang_ArrayStoreException =
2483 builtin_new(class_java_lang_ArrayStoreException);
2484 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2486 proto_java_lang_ThreadDeath = /* schani */
2487 builtin_new(class_java_lang_ThreadDeath);
2488 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2496 /********************* Function: loader_initclasses ****************************
2498 Initializes all loaded but uninitialized classes
2500 *******************************************************************************/
2502 void loader_initclasses ()
2506 intsDisable(); /* schani */
2508 if (makeinitializations) {
2509 c = list_first (&linkedclasses);
2512 c = list_next (&linkedclasses, c);
2516 intsRestore(); /* schani */
2519 static s4 classvalue;
2521 static void loader_compute_class_values (classinfo *c)
2525 c->vftbl->baseval = ++classvalue;
2527 while (subs != NULL) {
2528 loader_compute_class_values(subs);
2529 subs = subs->nextsub;
2531 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2535 for (i = 0; i < c->index; i++)
2537 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2538 utf_display(c->name);
2545 void loader_compute_subclasses ()
2549 intsDisable(); /* schani */
2551 c = list_first (&linkedclasses);
2553 if (!(c->flags & ACC_INTERFACE)) {
2557 c = list_next (&linkedclasses, c);
2560 c = list_first (&linkedclasses);
2562 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2563 c->nextsub = c->super->sub;
2566 c = list_next (&linkedclasses, c);
2570 loader_compute_class_values(class_java_lang_Object);
2572 intsRestore(); /* schani */
2577 /******************** function classloader_buffer ******************************
2579 sets buffer for reading classdata
2581 *******************************************************************************/
2583 void classload_buffer(u1 *buf, int len)
2586 classbuffer_size = len;
2587 classbuf_pos = buf - 1;
2591 /******************** Function: loader_close ***********************************
2595 *******************************************************************************/
2597 void loader_close ()
2601 while ( (c=list_first(&unloadedclasses)) ) {
2602 list_remove (&unloadedclasses,c);
2605 while ( (c=list_first(&unlinkedclasses)) ) {
2606 list_remove (&unlinkedclasses,c);
2609 while ( (c=list_first(&linkedclasses)) ) {
2610 list_remove (&linkedclasses,c);
2617 * These are local overrides for various environment variables in Emacs.
2618 * Please do not remove this and leave it at the end of the file, where
2619 * Emacs will automagically detect them.
2620 * ---------------------------------------------------------------------
2623 * indent-tabs-mode: t