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);
1875 FREE (c, classinfo);
1878 /************************* Function: class_findfield ***************************
1880 Searches a 'classinfo' structure for a field having the given name and
1883 *******************************************************************************/
1886 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1890 for (i = 0; i < c->fieldscount; i++) {
1891 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1892 return &(c->fields[i]);
1895 panic ("Can not find field given in CONSTANT_Fieldref");
1900 /************************* Function: class_findmethod **************************
1902 Searches a 'classinfo' structure for a method having the given name and
1904 If type is NULL, it is ignored.
1906 *******************************************************************************/
1908 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1911 for (i = 0; i < c->methodscount; i++) {
1912 if ((c->methods[i].name == name) && ((desc == NULL) ||
1913 (c->methods[i].descriptor == desc)))
1914 return &(c->methods[i]);
1919 /************************* Function: class_findmethod_approx ******************
1921 like class_findmethod but ignores the return value when comparing the
1924 *******************************************************************************/
1926 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1930 for (i = 0; i < c->methodscount; i++)
1931 if (c->methods[i].name == name) {
1932 utf *meth_descr = c->methods[i].descriptor;
1936 return &(c->methods[i]);
1938 if (desc->blength <= meth_descr->blength) {
1939 /* current position in utf text */
1940 char *desc_utf_ptr = desc->text;
1941 char *meth_utf_ptr = meth_descr->text;
1942 /* points behind utf strings */
1943 char *desc_end = utf_end(desc);
1944 char *meth_end = utf_end(meth_descr);
1947 /* compare argument types */
1948 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1950 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1951 break; /* no match */
1954 return &(c->methods[i]); /* all parameter types equal */
1962 /***************** Function: class_resolvemethod_approx ***********************
1964 Searches a class and every super class for a method (without paying
1965 attention to the return value)
1967 *******************************************************************************/
1969 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
1972 /* search for method (ignore returntype) */
1973 methodinfo *m = class_findmethod_approx (c, name, desc);
1976 /* search superclass */
1983 /************************* Function: class_resolvemethod ***********************
1985 Searches a class and every super class for a method.
1987 *******************************************************************************/
1990 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
1993 methodinfo *m = class_findmethod (c, name, desc);
1995 /* search superclass */
2003 /************************* Function: class_issubclass **************************
2005 Checks if sub is a descendant of super.
2007 *******************************************************************************/
2009 bool class_issubclass (classinfo *sub, classinfo *super)
2012 if (!sub) return false;
2013 if (sub==super) return true;
2020 /****************** Initialization function for classes ******************
2022 In Java, every class can have a static initialization function. This
2023 function has to be called BEFORE calling other methods or accessing static
2026 *******************************************************************************/
2029 extern int blockInts;
2032 void class_init (classinfo *c)
2035 java_objectheader *exceptionptr;
2039 if (!makeinitializations)
2043 c -> initialized = true;
2046 count_class_inits++;
2050 class_init (c->super);
2051 for (i=0; i < c->interfacescount; i++)
2052 class_init(c->interfaces[i]);
2054 m = class_findmethod (c, utf_clinit, utf_fidesc);
2057 sprintf (logtext, "Class ");
2058 utf_sprint (logtext+strlen(logtext), c->name);
2059 sprintf (logtext+strlen(logtext), " has no initializer");
2065 if (! (m->flags & ACC_STATIC))
2066 panic ("Class initializer is not static!");
2069 sprintf (logtext, "Starting initializer for class: ");
2070 utf_sprint (logtext+strlen(logtext), c->name);
2079 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2082 assert(blockInts == 0);
2087 printf ("#### Initializer of ");
2088 utf_display (c->name);
2089 printf (" has thrown: ");
2090 utf_display (exceptionptr->vftbl->class->name);
2096 sprintf (logtext, "Finished initializer for class: ");
2097 utf_sprint (logtext+strlen(logtext), c->name);
2101 if (c->name == utf_systemclass) {
2102 /* class java.lang.System requires explicit initialization */
2105 printf ("#### Initializing class System");
2107 /* find initializing method */
2108 m = class_findmethod (c,
2109 utf_initsystemclass,
2113 /* no method found */
2114 log("initializeSystemClass failed");
2123 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2126 assert(blockInts == 0);
2131 printf ("#### initializeSystemClass has thrown: ");
2132 utf_display (exceptionptr->vftbl->class->name);
2142 /********* Function: class_showconstantpool (debugging only) *********/
2144 void class_showconstantpool (classinfo *c)
2149 printf ("---- dump of constant pool ----\n");
2151 for (i=0; i<c->cpcount; i++) {
2152 printf ("#%d: ", (int) i);
2154 e = c -> cpinfos [i];
2157 switch (c -> cptags [i]) {
2158 case CONSTANT_Class:
2159 printf ("Classreference -> ");
2160 utf_display ( ((classinfo*)e) -> name );
2163 case CONSTANT_Fieldref:
2164 printf ("Fieldref -> "); goto displayFMI;
2165 case CONSTANT_Methodref:
2166 printf ("Methodref -> "); goto displayFMI;
2167 case CONSTANT_InterfaceMethodref:
2168 printf ("InterfaceMethod -> "); goto displayFMI;
2171 constant_FMIref *fmi = e;
2172 utf_display ( fmi->class->name );
2174 utf_display ( fmi->name);
2176 utf_display ( fmi->descriptor );
2180 case CONSTANT_String:
2181 printf ("String -> ");
2184 case CONSTANT_Integer:
2185 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2187 case CONSTANT_Float:
2188 printf ("Float -> %f", ((constant_float*)e) -> value);
2190 case CONSTANT_Double:
2191 printf ("Double -> %f", ((constant_double*)e) -> value);
2195 u8 v = ((constant_long*)e) -> value;
2197 printf ("Long -> %ld", (long int) v);
2199 printf ("Long -> HI: %ld, LO: %ld\n",
2200 (long int) v.high, (long int) v.low);
2204 case CONSTANT_NameAndType:
2205 { constant_nameandtype *cnt = e;
2206 printf ("NameAndType: ");
2207 utf_display (cnt->name);
2209 utf_display (cnt->descriptor);
2213 printf ("Utf8 -> ");
2216 case CONSTANT_Arraydescriptor: {
2217 printf ("Arraydescriptor: ");
2218 displayarraydescriptor (e);
2222 panic ("Invalid type of ConstantPool-Entry");
2234 /********** Function: class_showmethods (debugging only) *************/
2236 void class_showmethods (classinfo *c)
2240 printf ("--------- Fields and Methods ----------------\n");
2241 printf ("Flags: "); printflags (c->flags); printf ("\n");
2243 printf ("This: "); utf_display (c->name); printf ("\n");
2245 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2247 printf ("Index: %d\n", c->index);
2249 printf ("interfaces:\n");
2250 for (i=0; i < c-> interfacescount; i++) {
2252 utf_display (c -> interfaces[i] -> name);
2253 printf (" (%d)\n", c->interfaces[i] -> index);
2256 printf ("fields:\n");
2257 for (i=0; i < c -> fieldscount; i++) {
2258 field_display (&(c -> fields[i]));
2261 printf ("methods:\n");
2262 for (i=0; i < c -> methodscount; i++) {
2263 methodinfo *m = &(c->methods[i]);
2264 if ( !(m->flags & ACC_STATIC))
2265 printf ("vftblindex: %d ", m->vftblindex);
2267 method_display ( m );
2271 printf ("Virtual function table:\n");
2272 for (i=0; i<c->vftbl->vftbllength; i++) {
2273 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2280 /******************************************************************************/
2281 /******************* General functions for the class loader *******************/
2282 /******************************************************************************/
2284 static int loader_inited = 0;
2286 /********************* Function: loader_load ***********************************
2288 Loads and links the class desired class and each class and interface
2290 Returns: a pointer to this class
2292 *******************************************************************************/
2294 classinfo *loader_load (utf *topname)
2298 long int starttime=0,stoptime=0;
2300 intsDisable(); /* schani */
2303 starttime = getcputime();
2305 top = class_new (topname);
2308 while ( (c = list_first(&unloadedclasses)) ) {
2309 if (!class_load (c)) {
2310 list_remove (&unloadedclasses, c);
2316 while ( (c = list_first(&unlinkedclasses)) ) {
2321 loader_compute_subclasses();
2324 if (getloadingtime) {
2325 stoptime = getcputime();
2326 loadingtime += (stoptime-starttime);
2329 intsRestore(); /* schani */
2335 /**************** function: create_primitive_classes ***************************
2337 create classes representing primitive types
2339 ********************************************************************************/
2342 void create_primitive_classes()
2346 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2347 /* create primitive class */
2348 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2350 /* prevent loader from loading primitive class */
2351 list_remove (&unloadedclasses, c);
2352 /* add to unlinked classes */
2353 list_addlast (&unlinkedclasses, c);
2354 c -> super = class_java_lang_Object;
2357 primitivetype_table[i].class_primitive = c;
2359 /* create class for wrapping the primitive type */
2360 primitivetype_table[i].class_wrap =
2361 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2365 /***************** function: create_array_class ********************************
2367 create class representing an array
2369 ********************************************************************************/
2372 classinfo *create_array_class(utf *u)
2374 classinfo *c = class_new (u);
2375 /* prevent loader from loading the array class */
2376 list_remove (&unloadedclasses, c);
2377 /* add to unlinked classes */
2378 list_addlast (&unlinkedclasses, c);
2379 c -> super = class_java_lang_Object;
2385 /********************** Function: loader_init **********************************
2387 Initializes all lists and loads all classes required for the system or the
2390 *******************************************************************************/
2397 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2398 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2399 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2401 /* create utf-symbols for pointer comparison of frequently used strings */
2402 utf_innerclasses = utf_new_char("InnerClasses");
2403 utf_constantvalue = utf_new_char("ConstantValue");
2404 utf_code = utf_new_char("Code");
2405 utf_finalize = utf_new_char("finalize");
2406 utf_fidesc = utf_new_char("()V");
2407 utf_clinit = utf_new_char("<clinit>");
2408 utf_initsystemclass = utf_new_char("initializeSystemClass");
2409 utf_systemclass = utf_new_char("java/lang/System");
2411 /* create class for arrays */
2412 class_array = class_new ( utf_new_char ("The_Array_Class") );
2413 list_remove (&unloadedclasses, class_array);
2415 /* create class for strings, load it after class Object was loaded */
2416 string_class = utf_new_char ("java/lang/String");
2417 class_java_lang_String = class_new(string_class);
2418 list_remove (&unloadedclasses, class_java_lang_String);
2420 class_java_lang_Object =
2421 loader_load ( utf_new_char ("java/lang/Object") );
2423 list_addlast(&unloadedclasses, class_java_lang_String);
2425 class_java_lang_String =
2426 loader_load ( string_class );
2427 class_java_lang_ClassCastException =
2428 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2429 class_java_lang_NullPointerException =
2430 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2431 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2432 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2433 class_java_lang_NegativeArraySizeException = loader_load (
2434 utf_new_char ("java/lang/NegativeArraySizeException") );
2435 class_java_lang_OutOfMemoryError = loader_load (
2436 utf_new_char ("java/lang/OutOfMemoryError") );
2437 class_java_lang_ArrayStoreException =
2438 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2439 class_java_lang_ArithmeticException =
2440 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2441 class_java_lang_ThreadDeath = /* schani */
2442 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2444 /* link class for arrays */
2445 list_addlast (&unlinkedclasses, class_array);
2446 class_array -> super = class_java_lang_Object;
2447 class_link (class_array);
2449 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2450 stringtable_update();
2452 /* create classes representing primitive types */
2453 create_primitive_classes();
2455 proto_java_lang_ClassCastException =
2456 builtin_new(class_java_lang_ClassCastException);
2457 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2459 proto_java_lang_NullPointerException =
2460 builtin_new(class_java_lang_NullPointerException);
2461 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2463 proto_java_lang_ArrayIndexOutOfBoundsException =
2464 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2465 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2467 proto_java_lang_NegativeArraySizeException =
2468 builtin_new(class_java_lang_NegativeArraySizeException);
2469 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2471 proto_java_lang_OutOfMemoryError =
2472 builtin_new(class_java_lang_OutOfMemoryError);
2473 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2475 proto_java_lang_ArithmeticException =
2476 builtin_new(class_java_lang_ArithmeticException);
2477 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2479 proto_java_lang_ArrayStoreException =
2480 builtin_new(class_java_lang_ArrayStoreException);
2481 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2483 proto_java_lang_ThreadDeath = /* schani */
2484 builtin_new(class_java_lang_ThreadDeath);
2485 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2493 /********************* Function: loader_initclasses ****************************
2495 Initializes all loaded but uninitialized classes
2497 *******************************************************************************/
2499 void loader_initclasses ()
2503 intsDisable(); /* schani */
2505 if (makeinitializations) {
2506 c = list_first (&linkedclasses);
2509 c = list_next (&linkedclasses, c);
2513 intsRestore(); /* schani */
2516 static s4 classvalue;
2518 static void loader_compute_class_values (classinfo *c)
2522 c->vftbl->baseval = ++classvalue;
2524 while (subs != NULL) {
2525 loader_compute_class_values(subs);
2526 subs = subs->nextsub;
2528 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2532 for (i = 0; i < c->index; i++)
2534 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2535 utf_display(c->name);
2542 void loader_compute_subclasses ()
2546 intsDisable(); /* schani */
2548 c = list_first (&linkedclasses);
2550 if (!(c->flags & ACC_INTERFACE)) {
2554 c = list_next (&linkedclasses, c);
2557 c = list_first (&linkedclasses);
2559 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2560 c->nextsub = c->super->sub;
2563 c = list_next (&linkedclasses, c);
2567 loader_compute_class_values(class_java_lang_Object);
2569 intsRestore(); /* schani */
2574 /******************** function classloader_buffer ******************************
2576 sets buffer for reading classdata
2578 *******************************************************************************/
2580 void classload_buffer(u1 *buf, int len)
2583 classbuffer_size = len;
2584 classbuf_pos = buf - 1;
2588 /******************** Function: loader_close ***********************************
2592 *******************************************************************************/
2594 void loader_close ()
2598 while ( (c=list_first(&unloadedclasses)) ) {
2599 list_remove (&unloadedclasses,c);
2602 while ( (c=list_first(&unlinkedclasses)) ) {
2603 list_remove (&unlinkedclasses,c);
2606 while ( (c=list_first(&linkedclasses)) ) {
2607 list_remove (&linkedclasses,c);
2614 * These are local overrides for various environment variables in Emacs.
2615 * Please do not remove this and leave it at the end of the file, where
2616 * Emacs will automagically detect them.
2617 * ---------------------------------------------------------------------
2620 * indent-tabs-mode: t