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 *******************************************************************************/
33 #include "threads/thread.h"
36 /* global variables ***********************************************************/
38 extern bool newcompiler; /* true if new compiler is used */
40 int count_class_infos = 0; /* variables for measurements */
41 int count_const_pool_len = 0;
42 int count_vftbl_len = 0;
43 int count_all_methods = 0;
44 int count_vmcode_len = 0;
45 int count_extable_len = 0;
46 int count_class_loads = 0;
47 int count_class_inits = 0;
49 bool loadverbose = false; /* switches for debug messages */
50 bool linkverbose = false;
51 bool initverbose = false;
53 bool makeinitializations = true;
55 bool getloadingtime = false; /* to measure the runtime */
56 long int loadingtime = 0;
58 static s4 interfaceindex; /* sequential numbering of interfaces */
60 list unloadedclasses; /* list of all referenced but not loaded classes */
61 list unlinkedclasses; /* list of all loaded but not linked classes */
62 list linkedclasses; /* list of all completely linked classes */
65 /* utf-symbols for pointer comparison of frequently used strings */
67 static utf *utf_innerclasses; /* InnerClasses */
68 static utf *utf_constantvalue; /* ConstantValue */
69 static utf *utf_code; /* Code */
70 static utf *utf_finalize; /* finalize */
71 static utf *utf_fidesc; /* ()V */
72 static utf *utf_clinit; /* <clinit> */
73 static utf *utf_initsystemclass; /* initializeSystemClass */
74 static utf *utf_systemclass; /* java/lang/System */
77 /* important system classes ***************************************************/
79 classinfo *class_java_lang_Object;
80 classinfo *class_java_lang_String;
81 classinfo *class_java_lang_ClassCastException;
82 classinfo *class_java_lang_NullPointerException;
83 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
84 classinfo *class_java_lang_NegativeArraySizeException;
85 classinfo *class_java_lang_OutOfMemoryError;
86 classinfo *class_java_lang_ArithmeticException;
87 classinfo *class_java_lang_ArrayStoreException;
88 classinfo *class_java_lang_ThreadDeath;
89 classinfo *class_array = NULL;
92 /******************************************************************************
94 structure for primitive classes: contains the class for wrapping the
95 primitive type, the primitive class, the name of the class for wrapping,
96 the one character type signature and the name of the primitive class
98 ******************************************************************************/
100 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
101 { NULL, NULL, "java/lang/Double", 'D', "double" },
102 { NULL, NULL, "java/lang/Float", 'F', "float" },
103 { NULL, NULL, "java/lang/Character", 'C', "char" },
104 { NULL, NULL, "java/lang/Integer", 'I', "int" },
105 { NULL, NULL, "java/lang/Long", 'J', "long" },
106 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
107 { NULL, NULL, "java/lang/Short", 'S', "short" },
108 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
109 { NULL, NULL, "java/lang/Void", 'V', "void" }};
112 /* instances of important system classes **************************************/
114 java_objectheader *proto_java_lang_ClassCastException;
115 java_objectheader *proto_java_lang_NullPointerException;
116 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
117 java_objectheader *proto_java_lang_NegativeArraySizeException;
118 java_objectheader *proto_java_lang_OutOfMemoryError;
119 java_objectheader *proto_java_lang_ArithmeticException;
120 java_objectheader *proto_java_lang_ArrayStoreException;
121 java_objectheader *proto_java_lang_ThreadDeath;
124 /************* functions for reading classdata *********************************
126 getting classdata in blocks of variable size
127 (8,16,32,64-bit integer or float)
129 *******************************************************************************/
131 static char *classpath = ""; /* searchpath for classfiles */
132 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
133 static u1 *classbuf_pos; /* current position in classfile buffer */
134 static int classbuffer_size; /* size of classfile-data */
136 /* transfer block of classfile data into a buffer */
138 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
141 /* skip block of classfile data */
143 #define skip_nbytes(len) classbuf_pos+=len;
145 #define suck_u1() (*++classbuf_pos)
146 #define suck_s8() (s8) suck_u8()
147 #define suck_s2() (s2) suck_u2()
148 #define suck_s4() (s4) suck_u4()
149 #define suck_s1() (s1) suck_u1()
150 #define suck_u2() (u2) ((suck_u1()<<8)+suck_u1())
151 #define suck_u4() (u4) ((((u4)suck_u1())<<24)+(((u4)suck_u1())<<16)+(((u4)suck_u1())<<8)+((u4)suck_u1()))
154 /* get u8 from classfile data */
162 return (hi<<32) + lo;
171 /* get float from classfile data */
173 static float suck_float ()
180 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
181 memcpy ( (u1*) (&f), buffer, 4);
183 suck_nbytes ( (u1*) (&f), 4 );
186 PANICIF (sizeof(float) != 4, "Incompatible float-format");
191 /* get double from classfile data */
192 static double suck_double ()
199 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
200 memcpy ( (u1*) (&d), buffer, 8);
202 suck_nbytes ( (u1*) (&d), 8 );
205 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
210 /************************** function suck_init *********************************
212 called once at startup, sets the searchpath for the classfiles
214 *******************************************************************************/
216 void suck_init (char *cpath)
223 /************************** function suck_start ********************************
225 returns true if classbuffer is already loaded or a file for the
226 specified class has succussfully been read in. All directories of
227 the searchpath are used to find the classfile (<classname>.class).
228 Returns false if no classfile is found and writes an error message.
230 *******************************************************************************/
233 bool suck_start (utf *classname) {
235 #define MAXFILENAME 1000 /* maximum length of a filename */
237 char filename[MAXFILENAME+10]; /* room for '.class' */
238 char *pathpos; /* position in searchpath */
239 char c, *utf_ptr; /* pointer to the next utf8-character */
241 int filenamelen, err;
244 if (classbuffer) /* classbuffer is already valid */
251 /* skip path separator */
253 while (*pathpos == ':')
256 /* extract directory from searchpath */
259 while ((*pathpos) && (*pathpos!=':')) {
260 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
261 filename[filenamelen++] = *(pathpos++);
264 filename[filenamelen++] = '/';
266 /* add classname to filename */
268 utf_ptr = classname->text;
269 while (utf_ptr < utf_end(classname)) {
270 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
272 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
274 filename[filenamelen++] = c;
279 strcpy (filename+filenamelen, ".class");
281 classfile = fopen(filename, "r");
282 if (classfile) { /* file exists */
284 /* determine size of classfile */
286 err = stat (filename, &buffer);
288 if (!err) { /* read classfile data */
289 classbuffer_size = buffer.st_size;
290 classbuffer = MNEW(u1, classbuffer_size);
291 classbuf_pos = classbuffer-1;
292 fread(classbuffer, 1, classbuffer_size, classfile);
300 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
308 /************************** function suck_stop *********************************
310 frees memory for buffer with classfile data.
311 Caution: this function may only be called if buffer has been allocated
312 by suck_start with reading a file
314 *******************************************************************************/
318 /* determine amount of classdata not retrieved by suck-operations */
320 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
322 if (classdata_left > 0) {
324 sprintf (logtext,"There are %d access bytes at end of classfile",
331 MFREE(classbuffer, u1, classbuffer_size);
335 /******************************************************************************/
336 /******************* Some support functions ***********************************/
337 /******************************************************************************/
340 /********** internal function: printflags (only for debugging) ***************/
342 static void printflags (u2 f)
344 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
345 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
346 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
347 if ( f & ACC_STATIC ) printf (" STATIC");
348 if ( f & ACC_FINAL ) printf (" FINAL");
349 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
350 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
351 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
352 if ( f & ACC_NATIVE ) printf (" NATIVE");
353 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
354 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
358 /************************* Function: skipattribute *****************************
360 skips a (1) 'attribute' structure in the class file
362 *******************************************************************************/
364 static void skipattribute ()
367 skip_nbytes(suck_u4());
370 /********************** Function: skipattributebody ****************************
372 skips an attribute after the 16 bit reference to attribute_name has already
375 *******************************************************************************/
377 static void skipattributebody ()
379 skip_nbytes(suck_u4());
382 /************************* Function: skipattributes ****************************
384 skips num attribute structures
386 *******************************************************************************/
388 static void skipattributes (u4 num)
391 for (i = 0; i < num; i++)
395 /******************** function: innerclass_getconstant ************************
397 like class_getconstant, but if cptags is ZERO null is returned
399 *******************************************************************************/
401 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
403 /* invalid position in constantpool */
404 if (pos >= c->cpcount)
405 panic ("Attempt to access constant outside range");
407 /* constantpool entry of type 0 */
411 /* check type of constantpool entry */
412 if (c->cptags[pos] != ctype) {
413 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
414 (int) ctype, (int) c->cptags[pos] );
418 return c->cpinfos[pos];
421 /************************ function: attribute_load ****************************
423 read attributes from classfile
425 *******************************************************************************/
427 static void attribute_load (u4 num, classinfo *c)
431 for (i = 0; i < num; i++) {
432 /* retrieve attribute name */
433 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
435 if ( aname == utf_innerclasses) {
436 /* innerclasses attribute */
438 /* skip attribute length */
440 /* number of records */
441 c->innerclasscount = suck_u2();
442 /* allocate memory for innerclass structure */
443 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
445 for (j=0;j<c->innerclasscount;j++) {
447 /* The innerclass structure contains a class with an encoded name,
448 its defining scope, its simple name and a bitmask of the access flags.
449 If an inner class is not a member, its outer_class is NULL,
450 if a class is anonymous, its name is NULL. */
452 innerclassinfo *info = c->innerclass + j;
454 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
455 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
456 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
457 info->flags = suck_u2 (); /* access_flags bitmask */
460 /* unknown attribute */
461 skipattributebody ();
466 /******************* function: checkfielddescriptor ****************************
468 checks whether a field-descriptor is valid and aborts otherwise
469 all referenced classes are inserted into the list of unloaded classes
471 *******************************************************************************/
473 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
475 char *tstart; /* pointer to start of classname */
478 switch (*utf_ptr++) {
491 /* save start of classname */
494 /* determine length of classname */
495 while ( *utf_ptr++ != ';' )
496 if (utf_ptr>=end_pos)
497 panic ("Missing ';' in objecttype-descriptor");
499 /* cause loading of referenced class */
500 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
505 while ((ch = *utf_ptr++)=='[')
508 /* component type of array */
522 /* save start of classname */
525 /* determine length of classname */
526 while ( *utf_ptr++ != ';' )
527 if (utf_ptr>=end_pos)
528 panic ("Missing ';' in objecttype-descriptor");
530 /* cause loading of referenced class */
531 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
535 panic ("Ill formed methodtype-descriptor");
540 panic ("Ill formed methodtype-descriptor");
543 /* exceeding characters */
544 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
548 /******************* function checkmethoddescriptor ****************************
550 checks whether a method-descriptor is valid and aborts otherwise.
551 All referenced classes are inserted into the list of unloaded classes.
553 *******************************************************************************/
555 static void checkmethoddescriptor (utf *d)
557 char *utf_ptr = d->text; /* current position in utf text */
558 char *end_pos = utf_end(d); /* points behind utf string */
559 char *tstart; /* pointer to start of classname */
562 /* method descriptor must start with parenthesis */
563 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
565 /* check arguments */
566 while ((c = *utf_ptr++) != ')') {
580 /* save start of classname */
583 /* determine length of classname */
584 while ( *utf_ptr++ != ';' )
585 if (utf_ptr>=end_pos)
586 panic ("Missing ';' in objecttype-descriptor");
588 /* cause loading of referenced class */
589 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
594 while ((ch = *utf_ptr++)=='[')
597 /* component type of array */
611 /* save start of classname */
614 /* determine length of classname */
615 while ( *utf_ptr++ != ';' )
616 if (utf_ptr>=end_pos)
617 panic ("Missing ';' in objecttype-descriptor");
619 /* cause loading of referenced class */
620 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
624 panic ("Ill formed methodtype-descriptor");
629 panic ("Ill formed methodtype-descriptor");
633 /* check returntype */
635 /* returntype void */
636 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
639 /* treat as field-descriptor */
640 checkfielddescriptor (utf_ptr,end_pos);
644 /******************** Function: buildarraydescriptor ***************************
646 creates a constant_arraydescriptor structure for the array type named by an
649 *******************************************************************************/
651 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
653 constant_arraydescriptor *d;
655 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
657 d = NEW (constant_arraydescriptor);
658 d -> objectclass = NULL;
659 d -> elementdescriptor = NULL;
662 count_const_pool_len += sizeof(constant_arraydescriptor);
666 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
667 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
668 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
669 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
670 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
671 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
672 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
673 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
676 d -> arraytype = ARRAYTYPE_ARRAY;
677 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
681 d -> arraytype = ARRAYTYPE_OBJECT;
682 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
689 /******************* Function: freearraydescriptor *****************************
691 removes a structure created by buildarraydescriptor from memory
693 *******************************************************************************/
695 static void freearraydescriptor (constant_arraydescriptor *d)
698 constant_arraydescriptor *n = d->elementdescriptor;
699 FREE (d, constant_arraydescriptor);
704 /*********************** Function: displayarraydescriptor *********************/
706 static void displayarraydescriptor (constant_arraydescriptor *d)
708 switch (d->arraytype) {
709 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
710 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
711 case ARRAYTYPE_CHAR: printf ("char[]"); break;
712 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
713 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
714 case ARRAYTYPE_INT: printf ("int[]"); break;
715 case ARRAYTYPE_LONG: printf ("long[]"); break;
716 case ARRAYTYPE_SHORT: printf ("short[]"); break;
717 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
718 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
724 /******************************************************************************/
725 /******************** Functionen fuer Fields **********************************/
726 /******************************************************************************/
729 /************************ Function: field_load *********************************
731 l"adt alle Informationen f"ur eine Feld einer Methode aus dem ClassFile,
732 und f"ullt mit diesen Infos eine schon existierende 'fieldinfo'-Struktur.
733 Bei 'static'-Fields wird auch noch ein Platz auf dem Datensegment
736 *******************************************************************************/
738 static void field_load (fieldinfo *f, classinfo *c)
743 f -> flags = suck_u2 (); /* ACC flags */
744 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
745 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
746 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
747 f -> offset = 0; /* offset from start of object */
750 case TYPE_INT: f->value.i = 0; break;
751 case TYPE_FLOAT: f->value.f = 0.0; break;
752 case TYPE_DOUBLE: f->value.d = 0.0; break;
753 case TYPE_ADDRESS: f->value.a = NULL;
754 heap_addreference (&(f->value.a)); /* make global reference (GC) */
758 f->value.l = 0; break;
760 f->value.l.low = 0; f->value.l.high = 0; break;
764 /* read attributes */
766 for (i=0; i<attrnum; i++) {
770 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
772 if ( aname != utf_constantvalue ) {
773 /* unknown attribute */
774 skipattributebody ();
777 /* constant value attribute */
779 /* skip attribute length */
781 /* index of value in constantpool */
784 /* initialize field with value from constantpool */
787 constant_integer *ci =
788 class_getconstant(c, pindex, CONSTANT_Integer);
789 f->value.i = ci -> value;
795 class_getconstant(c, pindex, CONSTANT_Long);
797 f->value.l = cl -> value;
803 class_getconstant(c, pindex, CONSTANT_Float);
805 f->value.f = cf->value;
810 constant_double *cd =
811 class_getconstant(c, pindex, CONSTANT_Double);
813 f->value.d = cd->value;
818 utf *u = class_getconstant(c, pindex, CONSTANT_String);
819 /* create javastring from compressed utf8-string */
820 f->value.a = literalstring_new(u);
825 log_text ("Invalid Constant - Type");
834 /********************** function: field_free **********************************/
836 static void field_free (fieldinfo *f)
842 /************** Function: field_display (nur zu Debug-Zwecken) ****************/
844 static void field_display (fieldinfo *f)
847 printflags (f -> flags);
849 utf_display (f -> name);
851 utf_display (f -> descriptor);
852 printf (" offset: %ld\n", (long int) (f -> offset) );
856 /******************************************************************************/
857 /************************* Functions for methods ******************************/
858 /******************************************************************************/
861 /*********************** Function: method_load *********************************
863 Loads a method from the class file and fills an existing 'methodinfo'
864 structure. For native methods, the function pointer field is set to the
865 real function pointer, for JavaVM methods a pointer to the compiler is used
868 *******************************************************************************/
870 static void method_load (methodinfo *m, classinfo *c)
880 m -> flags = suck_u2 ();
881 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
882 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
885 m -> exceptiontable = NULL;
886 m -> entrypoint = NULL;
888 m -> stubroutine = NULL;
890 if (! (m->flags & ACC_NATIVE) ) {
891 m -> stubroutine = createcompilerstub (m);
895 functionptr f = native_findfunction
896 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
901 m -> stubroutine = createnativestub (f, m);
904 m -> stubroutine = oldcreatenativestub (f, m);
911 for (i=0; i<attrnum; i++) {
914 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
916 if ( aname != utf_code) {
917 skipattributebody ();
920 if (m -> jcode) panic ("Two code-attributes for one method!");
923 m -> maxstack = suck_u2();
924 m -> maxlocals = suck_u2();
925 m -> jcodelength = suck_u4();
926 m -> jcode = MNEW (u1, m->jcodelength);
927 suck_nbytes (m->jcode, m->jcodelength);
928 m -> exceptiontablelength = suck_u2 ();
929 m -> exceptiontable =
930 MNEW (exceptiontable, m->exceptiontablelength);
933 count_vmcode_len += m->jcodelength + 18;
934 count_extable_len += 8 * m->exceptiontablelength;
937 for (e=0; e < m->exceptiontablelength; e++) {
939 m -> exceptiontable[e].startpc = suck_u2();
940 m -> exceptiontable[e].endpc = suck_u2();
941 m -> exceptiontable[e].handlerpc = suck_u2();
944 if (!idx) m -> exceptiontable[e].catchtype = NULL;
946 m -> exceptiontable[e].catchtype =
947 class_getconstant (c, idx, CONSTANT_Class);
951 skipattributes ( suck_u2() );
958 /********************* Function: method_free ***********************************
960 frees all memory that was allocated for this method
962 *******************************************************************************/
964 static void method_free (methodinfo *m)
966 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
967 if (m->exceptiontable)
968 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
969 if (m->mcode) CFREE (m->mcode, m->mcodelength);
970 if (m->stubroutine) {
971 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
972 else removecompilerstub (m->stubroutine);
977 /************** Function: method_display (debugging only) **************/
979 void method_display (methodinfo *m)
982 printflags (m -> flags);
984 utf_display (m -> name);
986 utf_display (m -> descriptor);
991 /******************** Function: method_canoverwrite ****************************
993 Check if m and old are identical with respect to type and name. This means
994 that old can be overwritten with m.
996 *******************************************************************************/
998 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1000 if (m->name != old->name) return false;
1001 if (m->descriptor != old->descriptor) return false;
1002 if (m->flags & ACC_STATIC) return false;
1009 /******************************************************************************/
1010 /************************ Functions for class *********************************/
1011 /******************************************************************************/
1014 /******************** function: class_getconstant ******************************
1016 retrieves the value at position 'pos' of the constantpool of a class
1017 if the type of the value is other than 'ctype' the system is stopped
1019 *******************************************************************************/
1021 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1023 /* invalid position in constantpool */
1024 if (pos >= c->cpcount)
1025 panic ("Attempt to access constant outside range");
1027 /* check type of constantpool entry */
1028 if (c->cptags[pos] != ctype) {
1029 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1030 (int) ctype, (int) c->cptags[pos] );
1034 return c->cpinfos[pos];
1038 /********************* Function: class_constanttype ****************************
1040 Determines the type of a class entry in the ConstantPool
1042 *******************************************************************************/
1044 u4 class_constanttype (classinfo *c, u4 pos)
1046 if (pos >= c->cpcount)
1047 panic ("Attempt to access constant outside range");
1048 return c->cptags[pos];
1052 /******************** function: class_loadcpool ********************************
1054 loads the constantpool of a class,
1055 the entries are transformed into a simpler format
1056 by resolving references
1057 (a detailed overview of the compact structures can be found in global.h)
1059 *******************************************************************************/
1061 static void class_loadcpool (classinfo *c)
1064 /* The following structures are used to save information which cannot be
1065 processed during the first pass. After the complete constantpool has
1066 been traversed the references can be resolved.
1067 (only in specific order) */
1069 /* CONSTANT_Class_info entries */
1070 typedef struct forward_class {
1071 struct forward_class *next;
1076 /* CONSTANT_String */
1077 typedef struct forward_string {
1078 struct forward_string *next;
1083 /* CONSTANT_NameAndType */
1084 typedef struct forward_nameandtype {
1085 struct forward_nameandtype *next;
1089 } forward_nameandtype;
1091 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1092 typedef struct forward_fieldmethint {
1093 struct forward_fieldmethint *next;
1097 u2 nameandtype_index;
1098 } forward_fieldmethint;
1102 long int dumpsize = dump_size ();
1104 forward_class *forward_classes = NULL;
1105 forward_string *forward_strings = NULL;
1106 forward_nameandtype *forward_nameandtypes = NULL;
1107 forward_fieldmethint *forward_fieldmethints = NULL;
1109 /* number of entries in the constant_pool table */
1110 u4 cpcount = c -> cpcount = suck_u2();
1111 /* allocate memory */
1112 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1113 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1116 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1119 /* initialize constantpool */
1120 for (idx=0; idx<cpcount; idx++) {
1121 cptags[idx] = CONSTANT_UNUSED;
1122 cpinfos[idx] = NULL;
1126 /******* first pass *******/
1127 /* entries which cannot be resolved now are written into
1128 temporary structures and traversed again later */
1131 while (idx < cpcount) {
1132 /* get constant type */
1136 case CONSTANT_Class: {
1137 forward_class *nfc = DNEW(forward_class);
1139 nfc -> next = forward_classes;
1140 forward_classes = nfc;
1142 nfc -> thisindex = idx;
1143 /* reference to CONSTANT_NameAndType */
1144 nfc -> name_index = suck_u2 ();
1150 case CONSTANT_Fieldref:
1151 case CONSTANT_Methodref:
1152 case CONSTANT_InterfaceMethodref: {
1153 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1155 nff -> next = forward_fieldmethints;
1156 forward_fieldmethints = nff;
1158 nff -> thisindex = idx;
1161 /* class or interface type that contains the declaration of the field or method */
1162 nff -> class_index = suck_u2 ();
1163 /* name and descriptor of the field or method */
1164 nff -> nameandtype_index = suck_u2 ();
1170 case CONSTANT_String: {
1171 forward_string *nfs = DNEW (forward_string);
1173 nfs -> next = forward_strings;
1174 forward_strings = nfs;
1176 nfs -> thisindex = idx;
1177 /* reference to CONSTANT_Utf8_info with string characters */
1178 nfs -> string_index = suck_u2 ();
1184 case CONSTANT_NameAndType: {
1185 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1187 nfn -> next = forward_nameandtypes;
1188 forward_nameandtypes = nfn;
1190 nfn -> thisindex = idx;
1191 /* reference to CONSTANT_Utf8_info containing simple name */
1192 nfn -> name_index = suck_u2 ();
1193 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1194 nfn -> sig_index = suck_u2 ();
1200 case CONSTANT_Integer: {
1201 constant_integer *ci = NEW (constant_integer);
1204 count_const_pool_len += sizeof(constant_integer);
1207 ci -> value = suck_s4 ();
1208 cptags [idx] = CONSTANT_Integer;
1215 case CONSTANT_Float: {
1216 constant_float *cf = NEW (constant_float);
1219 count_const_pool_len += sizeof(constant_float);
1222 cf -> value = suck_float ();
1223 cptags [idx] = CONSTANT_Float;
1229 case CONSTANT_Long: {
1230 constant_long *cl = NEW(constant_long);
1233 count_const_pool_len += sizeof(constant_long);
1236 cl -> value = suck_s8 ();
1237 cptags [idx] = CONSTANT_Long;
1243 case CONSTANT_Double: {
1244 constant_double *cd = NEW(constant_double);
1247 count_const_pool_len += sizeof(constant_double);
1250 cd -> value = suck_double ();
1251 cptags [idx] = CONSTANT_Double;
1257 case CONSTANT_Utf8: {
1259 /* number of bytes in the bytes array (not string-length) */
1260 u4 length = suck_u2();
1261 cptags [idx] = CONSTANT_Utf8;
1262 /* insert utf-string into the utf-symboltable */
1263 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1264 /* skip bytes of the string */
1265 skip_nbytes(length);
1271 sprintf (logtext, "Unkown constant type: %d",(int) t);
1280 /* resolve entries in temporary structures */
1282 while (forward_classes) {
1284 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1286 if ( (name->blength>0) && (name->text[0]=='[') ) {
1287 /* check validity of descriptor */
1288 checkfielddescriptor (name->text, utf_end(name));
1290 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1291 cpinfos [forward_classes -> thisindex] =
1292 buildarraydescriptor(name->text, name->blength);
1296 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1297 /* retrieve class from class-table */
1298 cpinfos [forward_classes -> thisindex] = class_new (name);
1300 forward_classes = forward_classes -> next;
1304 while (forward_strings) {
1306 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1308 /* resolve utf-string */
1309 cptags [forward_strings -> thisindex] = CONSTANT_String;
1310 cpinfos [forward_strings -> thisindex] = text;
1312 forward_strings = forward_strings -> next;
1315 while (forward_nameandtypes) {
1316 constant_nameandtype *cn = NEW (constant_nameandtype);
1319 count_const_pool_len += sizeof(constant_nameandtype);
1322 /* resolve simple name and descriptor */
1323 cn -> name = class_getconstant
1324 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1325 cn -> descriptor = class_getconstant
1326 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1328 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1329 cpinfos [forward_nameandtypes -> thisindex] = cn;
1331 forward_nameandtypes = forward_nameandtypes -> next;
1335 while (forward_fieldmethints) {
1336 constant_nameandtype *nat;
1337 constant_FMIref *fmi = NEW (constant_FMIref);
1340 count_const_pool_len += sizeof(constant_FMIref);
1342 /* resolve simple name and descriptor */
1343 nat = class_getconstant
1344 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1346 fmi -> class = class_getconstant
1347 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1348 fmi -> name = nat -> name;
1349 fmi -> descriptor = nat -> descriptor;
1351 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1352 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1354 switch (forward_fieldmethints -> tag) {
1355 case CONSTANT_Fieldref: /* check validity of descriptor */
1356 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1358 case CONSTANT_InterfaceMethodref:
1359 case CONSTANT_Methodref: /* check validity of descriptor */
1360 checkmethoddescriptor (fmi->descriptor);
1364 forward_fieldmethints = forward_fieldmethints -> next;
1369 dump_release (dumpsize);
1373 /********************** Function: class_load ***********************************
1375 Loads everything interesting about a class from the class file. The
1376 'classinfo' structure must have been allocated previously.
1378 The super class and the interfaces implemented by this class need not be
1379 loaded. The link is set later by the function 'class_link'.
1381 The loaded class is removed from the list 'unloadedclasses' and added to
1382 the list 'unlinkedclasses'.
1384 *******************************************************************************/
1386 static int class_load (classinfo *c)
1392 count_class_loads++;
1395 /* output for debugging purposes */
1397 sprintf (logtext, "Loading class: ");
1398 utf_sprint (logtext+strlen(logtext), c->name );
1402 /* load classdata, throw exception on error */
1403 if (!suck_start (c->name)) {
1404 throw_classnotfoundexception();
1408 /* check signature */
1409 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1413 if (ma != MAJOR_VERSION) {
1414 sprintf (logtext, "Can only support major version %d, but not %d",
1415 MAJOR_VERSION, (int) ma);
1418 if (mi > MINOR_VERSION) {
1419 sprintf (logtext, "Minor version %d is not yet supported.", (int) mi);
1424 class_loadcpool (c);
1427 c -> flags = suck_u2 ();
1431 /* retrieve superclass */
1432 if ( (i = suck_u2 () ) ) {
1433 c -> super = class_getconstant (c, i, CONSTANT_Class);
1439 /* retrieve interfaces */
1440 c -> interfacescount = suck_u2 ();
1441 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1442 for (i=0; i < c -> interfacescount; i++) {
1443 c -> interfaces [i] =
1444 class_getconstant (c, suck_u2(), CONSTANT_Class);
1448 c -> fieldscount = suck_u2 ();
1449 c -> fields = MNEW (fieldinfo, c -> fieldscount);
1450 for (i=0; i < c -> fieldscount; i++) {
1451 field_load (&(c->fields[i]), c);
1455 c -> methodscount = suck_u2 ();
1456 c -> methods = MNEW (methodinfo, c -> methodscount);
1457 for (i=0; i < c -> methodscount; i++) {
1458 method_load (&(c -> methods [i]), c);
1462 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1463 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1464 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1467 /* load variable-length attribute structures */
1468 attribute_load (suck_u2(), c);
1473 /* remove class from list of unloaded classes and
1474 add to list of unlinked classes */
1475 list_remove (&unloadedclasses, c);
1476 list_addlast (&unlinkedclasses, c);
1483 /************** internal Function: class_highestinterface ***********************
1485 Used by the function class_link to determine the amount of memory needed
1486 for the interface table.
1488 *******************************************************************************/
1490 static s4 class_highestinterface (classinfo *c)
1495 if ( ! (c->flags & ACC_INTERFACE) ) {
1496 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1497 utf_sprint (logtext+strlen(logtext), c->name);
1502 for (i=0; i<c->interfacescount; i++) {
1503 s4 h2 = class_highestinterface (c->interfaces[i]);
1510 /* class_addinterface **********************************************************
1512 Is needed by class_link for adding a VTBL to a class. All interfaces
1513 implemented by ic are added as well.
1515 *******************************************************************************/
1517 static void class_addinterface (classinfo *c, classinfo *ic)
1521 vftbl *vftbl = c->vftbl;
1523 if (i >= vftbl->interfacetablelength)
1524 panic ("Inernal error: interfacetable overflow");
1525 if (vftbl->interfacetable[-i])
1528 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1529 vftbl->interfacevftbllength[i] = 1;
1530 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1531 vftbl->interfacetable[-i][0] = NULL;
1534 vftbl->interfacevftbllength[i] = ic->methodscount;
1535 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1538 count_vftbl_len += sizeof(methodptr) *
1539 (ic->methodscount + (ic->methodscount == 0));
1542 for (j=0; j<ic->methodscount; j++) {
1545 for (m = 0; m < sc->methodscount; m++) {
1546 methodinfo *mi = &(sc->methods[m]);
1547 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1548 vftbl->interfacetable[-i][j] =
1549 vftbl->table[mi->vftblindex];
1559 for (j = 0; j < ic->interfacescount; j++)
1560 class_addinterface(c, ic->interfaces[j]);
1564 /********************** Function: class_link ***********************************
1566 Tries to link a class. The super class and every implemented interface must
1567 already have been linked. The function calculates the length in bytes that
1568 an instance of this class requires as well as the VTBL for methods and
1571 If the class can be linked, it is removed from the list 'unlinkedclasses'
1572 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1575 Attention: If cyclical class definitions are encountered, the program gets
1576 into an infinite loop (we'll have to work that out)
1578 *******************************************************************************/
1580 static void class_link (classinfo *c)
1582 s4 supervftbllength; /* vftbllegnth of super class */
1583 s4 vftbllength; /* vftbllength of current class */
1584 s4 interfacetablelength; /* interface table length */
1585 classinfo *super = c->super; /* super class */
1586 classinfo *ic, *c2; /* intermediate class variables */
1587 vftbl *v; /* vftbl of current class */
1588 s4 i; /* interface/method/field counter */
1591 /* check if all superclasses are already linked, if not put c at end of
1592 unlinked list and return. Additionally initialize class fields. */
1594 /* check interfaces */
1596 for (i = 0; i < c->interfacescount; i++) {
1597 ic = c->interfaces[i];
1599 list_remove(&unlinkedclasses, c);
1600 list_addlast(&unlinkedclasses, c);
1605 /* check super class */
1607 if (super == NULL) { /* class java.long.Object */
1609 c->instancesize = sizeof(java_objectheader);
1611 vftbllength = supervftbllength = 0;
1613 c->finalizer = NULL;
1616 if (!super->linked) {
1617 list_remove(&unlinkedclasses, c);
1618 list_addlast(&unlinkedclasses, c);
1622 if (c->flags & ACC_INTERFACE)
1623 c->index = interfaceindex++;
1625 c->index = super->index + 1;
1627 c->instancesize = super->instancesize;
1629 vftbllength = supervftbllength = super->vftbl->vftbllength;
1631 c->finalizer = super->finalizer;
1636 sprintf (logtext, "Linking Class: ");
1637 utf_sprint (logtext+strlen(logtext), c->name );
1641 /* compute vftbl length */
1643 for (i = 0; i < c->methodscount; i++) {
1644 methodinfo *m = &(c->methods[i]);
1646 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1647 classinfo *sc = super;
1650 for (j = 0; j < sc->methodscount; j++) {
1651 if (method_canoverwrite(m, &(sc->methods[j]))) {
1652 m->vftblindex = sc->methods[j].vftblindex;
1653 goto foundvftblindex;
1658 m->vftblindex = (vftbllength++);
1664 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1667 /* compute interfacetable length */
1669 interfacetablelength = 0;
1672 for (i = 0; i < c2->interfacescount; i++) {
1673 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1674 if (h > interfacetablelength)
1675 interfacetablelength = h;
1680 /* allocate virtual function table */
1682 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1683 (vftbllength - 1) + sizeof(methodptr*) *
1684 (interfacetablelength - (interfacetablelength > 0)));
1685 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1686 (interfacetablelength > 1));
1687 c->header.vftbl = c->vftbl = v;
1689 v->vftbllength = vftbllength;
1690 v->interfacetablelength = interfacetablelength;
1692 /* copy virtual function table of super class */
1694 for (i = 0; i < supervftbllength; i++)
1695 v->table[i] = super->vftbl->table[i];
1697 /* add method stubs into virtual function table */
1699 for (i = 0; i < c->methodscount; i++) {
1700 methodinfo *m = &(c->methods[i]);
1701 if (!(m->flags & ACC_STATIC)) {
1702 v->table[m->vftblindex] = m->stubroutine;
1706 /* compute instance size and offset of each field */
1708 for (i = 0; i < c->fieldscount; i++) {
1710 fieldinfo *f = &(c->fields[i]);
1712 if (!(f->flags & ACC_STATIC) ) {
1713 dsize = desc_typesize (f->descriptor);
1714 c->instancesize = ALIGN (c->instancesize, dsize);
1715 f->offset = c->instancesize;
1716 c->instancesize += dsize;
1720 /* initialize interfacetable and interfacevftbllength */
1722 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1725 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1728 for (i = 0; i < interfacetablelength; i++) {
1729 v->interfacevftbllength[i] = 0;
1730 v->interfacetable[-i] = NULL;
1733 /* add interfaces */
1735 for (c2 = c; c2 != NULL; c2 = c2->super)
1736 for (i = 0; i < c2->interfacescount; i++) {
1737 class_addinterface (c, c2->interfaces[i]);
1740 /* add finalizer method (not for java.lang.Object) */
1742 if (super != NULL) {
1744 static utf *finame = NULL;
1745 static utf *fidesc = NULL;
1748 finame = utf_finalize;
1750 fidesc = utf_fidesc;
1752 fi = class_findmethod (c, finame, fidesc);
1754 if (!(fi->flags & ACC_STATIC)) {
1764 list_remove (&unlinkedclasses, c);
1765 list_addlast (&linkedclasses, c);
1769 /******************* Function: class_freepool **********************************
1771 Frees all resources used by this classes Constant Pool.
1773 *******************************************************************************/
1775 static void class_freecpool (classinfo *c)
1781 for (idx=0; idx < c->cpcount; idx++) {
1782 tag = c->cptags[idx];
1783 info = c->cpinfos[idx];
1787 case CONSTANT_Fieldref:
1788 case CONSTANT_Methodref:
1789 case CONSTANT_InterfaceMethodref:
1790 FREE (info, constant_FMIref);
1792 case CONSTANT_Integer:
1793 FREE (info, constant_integer);
1795 case CONSTANT_Float:
1796 FREE (info, constant_float);
1799 FREE (info, constant_long);
1801 case CONSTANT_Double:
1802 FREE (info, constant_double);
1804 case CONSTANT_NameAndType:
1805 FREE (info, constant_nameandtype);
1807 case CONSTANT_Arraydescriptor:
1808 freearraydescriptor (info);
1814 MFREE (c -> cptags, u1, c -> cpcount);
1815 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1819 /*********************** Function: class_free **********************************
1821 Frees all resources used by the class.
1823 *******************************************************************************/
1825 static void class_free (classinfo *c)
1830 class_freecpool (c);
1832 MFREE (c->interfaces, classinfo*, c->interfacescount);
1834 for (i = 0; i < c->fieldscount; i++)
1835 field_free(&(c->fields[i]));
1836 MFREE (c->fields, fieldinfo, c->fieldscount);
1838 for (i = 0; i < c->methodscount; i++)
1839 method_free(&(c->methods[i]));
1840 MFREE (c->methods, methodinfo, c->methodscount);
1842 if ((v = c->vftbl) != NULL) {
1843 for (i = 0; i < v->interfacetablelength; i++) {
1844 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1846 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1848 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1849 sizeof(methodptr*) * (v->interfacetablelength -
1850 (v->interfacetablelength > 0));
1851 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1852 (v->interfacetablelength > 1));
1856 if (c->innerclasscount)
1857 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1859 FREE (c, classinfo);
1862 /************************* Function: class_findfield ***************************
1864 Searches a 'classinfo' structure for a field having the given name and
1867 *******************************************************************************/
1870 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1874 for (i = 0; i < c->fieldscount; i++) {
1875 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1876 return &(c->fields[i]);
1879 panic ("Can not find field given in CONSTANT_Fieldref");
1884 /************************* Function: class_findmethod **************************
1886 Searches a 'classinfo' structure for a method having the given name and
1888 If type is NULL, it is ignored.
1890 *******************************************************************************/
1892 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1895 for (i = 0; i < c->methodscount; i++) {
1896 if ((c->methods[i].name == name) && ((desc == NULL) ||
1897 (c->methods[i].descriptor == desc)))
1898 return &(c->methods[i]);
1903 /************************* Function: class_findmethod_approx ******************
1905 like class_findmethod but ignores the return value when comparing the
1908 *******************************************************************************/
1910 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1914 for (i = 0; i < c->methodscount; i++)
1915 if (c->methods[i].name == name) {
1916 utf *meth_descr = c->methods[i].descriptor;
1920 return &(c->methods[i]);
1922 if (desc->blength <= meth_descr->blength) {
1923 /* current position in utf text */
1924 char *desc_utf_ptr = desc->text;
1925 char *meth_utf_ptr = meth_descr->text;
1926 /* points behind utf strings */
1927 char *desc_end = utf_end(desc);
1928 char *meth_end = utf_end(meth_descr);
1931 /* compare argument types */
1932 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1934 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1935 break; /* no match */
1938 return &(c->methods[i]); /* all parameter types equal */
1946 /***************** Function: class_resolvemethod_approx ***********************
1948 Searches a class and every super class for a method (without paying
1949 attention to the return value)
1951 *******************************************************************************/
1953 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
1956 /* search for method (ignore returntype) */
1957 methodinfo *m = class_findmethod_approx (c, name, desc);
1960 /* search superclass */
1967 /************************* Function: class_resolvemethod ***********************
1969 Searches a class and every super class for a method.
1971 *******************************************************************************/
1974 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
1977 methodinfo *m = class_findmethod (c, name, desc);
1979 /* search superclass */
1987 /************************* Function: class_issubclass **************************
1989 Checks if sub is a descendant of super.
1991 *******************************************************************************/
1993 bool class_issubclass (classinfo *sub, classinfo *super)
1996 if (!sub) return false;
1997 if (sub==super) return true;
2004 /****************** Initialization function for classes ******************
2006 In Java, every class can have a static initialization function. This
2007 function has to be called BEFORE calling other methods or accessing static
2010 *******************************************************************************/
2013 extern int blockInts;
2016 void class_init (classinfo *c)
2019 java_objectheader *exceptionptr;
2023 if (!makeinitializations)
2027 c -> initialized = true;
2030 count_class_inits++;
2034 class_init (c->super);
2035 for (i=0; i < c->interfacescount; i++)
2036 class_init(c->interfaces[i]);
2038 m = class_findmethod (c, utf_clinit, utf_fidesc);
2041 sprintf (logtext, "Class ");
2042 utf_sprint (logtext+strlen(logtext), c->name);
2043 sprintf (logtext+strlen(logtext), " has no initializer");
2049 if (! (m->flags & ACC_STATIC))
2050 panic ("Class initializer is not static!");
2053 sprintf (logtext, "Starting initializer for class: ");
2054 utf_sprint (logtext+strlen(logtext), c->name);
2063 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2066 assert(blockInts == 0);
2071 printf ("#### Initializer of ");
2072 utf_display (c->name);
2073 printf (" has thrown: ");
2074 utf_display (exceptionptr->vftbl->class->name);
2080 sprintf (logtext, "Finished initializer for class: ");
2081 utf_sprint (logtext+strlen(logtext), c->name);
2085 if (c->name == utf_systemclass) {
2086 /* class java.lang.System requires explicit initialization */
2089 printf ("#### Initializing class System");
2091 /* find initializing method */
2092 m = class_findmethod (c,
2093 utf_initsystemclass,
2097 /* no method found */
2098 log("initializeSystemClass failed");
2107 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2110 assert(blockInts == 0);
2115 printf ("#### initializeSystemClass has thrown: ");
2116 utf_display (exceptionptr->vftbl->class->name);
2126 /********* Function: class_showconstantpool (debugging only) *********/
2128 void class_showconstantpool (classinfo *c)
2133 printf ("---- dump of constant pool ----\n");
2135 for (i=0; i<c->cpcount; i++) {
2136 printf ("#%d: ", (int) i);
2138 e = c -> cpinfos [i];
2141 switch (c -> cptags [i]) {
2142 case CONSTANT_Class:
2143 printf ("Classreference -> ");
2144 utf_display ( ((classinfo*)e) -> name );
2147 case CONSTANT_Fieldref:
2148 printf ("Fieldref -> "); goto displayFMI;
2149 case CONSTANT_Methodref:
2150 printf ("Methodref -> "); goto displayFMI;
2151 case CONSTANT_InterfaceMethodref:
2152 printf ("InterfaceMethod -> "); goto displayFMI;
2155 constant_FMIref *fmi = e;
2156 utf_display ( fmi->class->name );
2158 utf_display ( fmi->name);
2160 utf_display ( fmi->descriptor );
2164 case CONSTANT_String:
2165 printf ("String -> ");
2168 case CONSTANT_Integer:
2169 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2171 case CONSTANT_Float:
2172 printf ("Float -> %f", ((constant_float*)e) -> value);
2174 case CONSTANT_Double:
2175 printf ("Double -> %f", ((constant_double*)e) -> value);
2179 u8 v = ((constant_long*)e) -> value;
2181 printf ("Long -> %ld", (long int) v);
2183 printf ("Long -> HI: %ld, LO: %ld\n",
2184 (long int) v.high, (long int) v.low);
2188 case CONSTANT_NameAndType:
2189 { constant_nameandtype *cnt = e;
2190 printf ("NameAndType: ");
2191 utf_display (cnt->name);
2193 utf_display (cnt->descriptor);
2197 printf ("Utf8 -> ");
2200 case CONSTANT_Arraydescriptor: {
2201 printf ("Arraydescriptor: ");
2202 displayarraydescriptor (e);
2206 panic ("Invalid type of ConstantPool-Entry");
2218 /********** Function: class_showmethods (debugging only) *************/
2220 void class_showmethods (classinfo *c)
2224 printf ("--------- Fields and Methods ----------------\n");
2225 printf ("Flags: "); printflags (c->flags); printf ("\n");
2227 printf ("This: "); utf_display (c->name); printf ("\n");
2229 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2231 printf ("Index: %d\n", c->index);
2233 printf ("interfaces:\n");
2234 for (i=0; i < c-> interfacescount; i++) {
2236 utf_display (c -> interfaces[i] -> name);
2237 printf (" (%d)\n", c->interfaces[i] -> index);
2240 printf ("fields:\n");
2241 for (i=0; i < c -> fieldscount; i++) {
2242 field_display (&(c -> fields[i]));
2245 printf ("methods:\n");
2246 for (i=0; i < c -> methodscount; i++) {
2247 methodinfo *m = &(c->methods[i]);
2248 if ( !(m->flags & ACC_STATIC))
2249 printf ("vftblindex: %d ", m->vftblindex);
2251 method_display ( m );
2255 printf ("Virtual function table:\n");
2256 for (i=0; i<c->vftbl->vftbllength; i++) {
2257 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2264 /******************************************************************************/
2265 /******************* General functions for the class loader *******************/
2266 /******************************************************************************/
2268 static int loader_inited = 0;
2270 /********************* Function: loader_load ***********************************
2272 Loads and links the class desired class and each class and interface
2274 Returns: a pointer to this class
2276 *******************************************************************************/
2278 classinfo *loader_load (utf *topname)
2282 long int starttime=0,stoptime=0;
2284 intsDisable(); /* schani */
2287 starttime = getcputime();
2289 top = class_new (topname);
2292 while ( (c = list_first(&unloadedclasses)) ) {
2293 if (!class_load (c)) {
2294 list_remove (&unloadedclasses, c);
2300 while ( (c = list_first(&unlinkedclasses)) ) {
2305 loader_compute_subclasses();
2308 if (getloadingtime) {
2309 stoptime = getcputime();
2310 loadingtime += (stoptime-starttime);
2313 intsRestore(); /* schani */
2319 /**************** function: create_primitive_classes ***************************
2321 create classes representing primitive types
2323 ********************************************************************************/
2326 void create_primitive_classes()
2330 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2331 /* create primitive class */
2332 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2334 /* prevent loader from loading primitive class */
2335 list_remove (&unloadedclasses, c);
2336 /* add to unlinked classes */
2337 list_addlast (&unlinkedclasses, c);
2338 c -> super = class_java_lang_Object;
2341 primitivetype_table[i].class_primitive = c;
2343 /* create class for wrapping the primitive type */
2344 primitivetype_table[i].class_wrap =
2345 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2349 /***************** function: create_array_class ********************************
2351 create class representing an array
2353 ********************************************************************************/
2356 classinfo *create_array_class(utf *u)
2358 classinfo *c = class_new (u);
2359 /* prevent loader from loading the array class */
2360 list_remove (&unloadedclasses, c);
2361 /* add to unlinked classes */
2362 list_addlast (&unlinkedclasses, c);
2363 c -> super = class_java_lang_Object;
2369 /********************** Function: loader_init **********************************
2371 Initializes all lists and loads all classes required for the system or the
2374 *******************************************************************************/
2381 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2382 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2383 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2385 /* create utf-symbols for pointer comparison of frequently used strings */
2386 utf_innerclasses = utf_new_char("InnerClasses");
2387 utf_constantvalue = utf_new_char("ConstantValue");
2388 utf_code = utf_new_char("Code");
2389 utf_finalize = utf_new_char("finalize");
2390 utf_fidesc = utf_new_char("()V");
2391 utf_clinit = utf_new_char("<clinit>");
2392 utf_initsystemclass = utf_new_char("initializeSystemClass");
2393 utf_systemclass = utf_new_char("java/lang/System");
2395 /* create class for arrays */
2396 class_array = class_new ( utf_new_char ("The_Array_Class") );
2397 list_remove (&unloadedclasses, class_array);
2399 /* create class for strings, load it after class Object was loaded */
2400 string_class = utf_new_char ("java/lang/String");
2401 class_java_lang_String = class_new(string_class);
2402 list_remove (&unloadedclasses, class_java_lang_String);
2404 class_java_lang_Object =
2405 loader_load ( utf_new_char ("java/lang/Object") );
2407 list_addlast(&unloadedclasses, class_java_lang_String);
2409 class_java_lang_String =
2410 loader_load ( string_class );
2411 class_java_lang_ClassCastException =
2412 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2413 class_java_lang_NullPointerException =
2414 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2415 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2416 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2417 class_java_lang_NegativeArraySizeException = loader_load (
2418 utf_new_char ("java/lang/NegativeArraySizeException") );
2419 class_java_lang_OutOfMemoryError = loader_load (
2420 utf_new_char ("java/lang/OutOfMemoryError") );
2421 class_java_lang_ArrayStoreException =
2422 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2423 class_java_lang_ArithmeticException =
2424 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2425 class_java_lang_ThreadDeath = /* schani */
2426 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2428 /* link class for arrays */
2429 list_addlast (&unlinkedclasses, class_array);
2430 class_array -> super = class_java_lang_Object;
2431 class_link (class_array);
2433 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2434 stringtable_update();
2436 /* create classes representing primitive types */
2437 create_primitive_classes();
2439 proto_java_lang_ClassCastException =
2440 builtin_new(class_java_lang_ClassCastException);
2441 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2443 proto_java_lang_NullPointerException =
2444 builtin_new(class_java_lang_NullPointerException);
2445 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2447 proto_java_lang_ArrayIndexOutOfBoundsException =
2448 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2449 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2451 proto_java_lang_NegativeArraySizeException =
2452 builtin_new(class_java_lang_NegativeArraySizeException);
2453 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2455 proto_java_lang_OutOfMemoryError =
2456 builtin_new(class_java_lang_OutOfMemoryError);
2457 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2459 proto_java_lang_ArithmeticException =
2460 builtin_new(class_java_lang_ArithmeticException);
2461 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2463 proto_java_lang_ArrayStoreException =
2464 builtin_new(class_java_lang_ArrayStoreException);
2465 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2467 proto_java_lang_ThreadDeath = /* schani */
2468 builtin_new(class_java_lang_ThreadDeath);
2469 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2477 /********************* Function: loader_initclasses ****************************
2479 Initializes all loaded but uninitialized classes
2481 *******************************************************************************/
2483 void loader_initclasses ()
2487 intsDisable(); /* schani */
2489 if (makeinitializations) {
2490 c = list_first (&linkedclasses);
2493 c = list_next (&linkedclasses, c);
2497 intsRestore(); /* schani */
2500 static s4 classvalue;
2502 static void loader_compute_class_values (classinfo *c)
2506 c->vftbl->baseval = ++classvalue;
2508 while (subs != NULL) {
2509 loader_compute_class_values(subs);
2510 subs = subs->nextsub;
2512 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2516 for (i = 0; i < c->index; i++)
2518 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2519 utf_display(c->name);
2526 void loader_compute_subclasses ()
2530 intsDisable(); /* schani */
2532 c = list_first (&linkedclasses);
2534 if (!(c->flags & ACC_INTERFACE)) {
2538 c = list_next (&linkedclasses, c);
2541 c = list_first (&linkedclasses);
2543 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2544 c->nextsub = c->super->sub;
2547 c = list_next (&linkedclasses, c);
2551 loader_compute_class_values(class_java_lang_Object);
2553 intsRestore(); /* schani */
2558 /******************** function classloader_buffer ******************************
2560 sets buffer for reading classdata
2562 *******************************************************************************/
2564 void classload_buffer(u1 *buf, int len)
2567 classbuffer_size = len;
2568 classbuf_pos = buf - 1;
2572 /******************** Function: loader_close ***********************************
2576 *******************************************************************************/
2578 void loader_close ()
2582 while ( (c=list_first(&unloadedclasses)) ) {
2583 list_remove (&unloadedclasses,c);
2586 while ( (c=list_first(&unlinkedclasses)) ) {
2587 list_remove (&unlinkedclasses,c);
2590 while ( (c=list_first(&linkedclasses)) ) {
2591 list_remove (&linkedclasses,c);
2598 * These are local overrides for various environment variables in Emacs.
2599 * Please do not remove this and leave it at the end of the file, where
2600 * Emacs will automagically detect them.
2601 * ---------------------------------------------------------------------
2604 * indent-tabs-mode: t