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 */
43 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
45 int count_class_infos = 0; /* variables for measurements */
46 int count_const_pool_len = 0;
47 int count_vftbl_len = 0;
48 int count_all_methods = 0;
49 int count_vmcode_len = 0;
50 int count_extable_len = 0;
51 int count_class_loads = 0;
52 int count_class_inits = 0;
54 bool loadverbose = false; /* switches for debug messages */
55 bool linkverbose = false;
56 bool initverbose = false;
58 bool makeinitializations = true;
60 bool getloadingtime = false; /* to measure the runtime */
61 long int loadingtime = 0;
63 static s4 interfaceindex; /* sequential numbering of interfaces */
65 list unloadedclasses; /* list of all referenced but not loaded classes */
66 list unlinkedclasses; /* list of all loaded but not linked classes */
67 list linkedclasses; /* list of all completely linked classes */
70 /* utf-symbols for pointer comparison of frequently used strings */
72 static utf *utf_innerclasses; /* InnerClasses */
73 static utf *utf_constantvalue; /* ConstantValue */
74 static utf *utf_code; /* Code */
75 static utf *utf_finalize; /* finalize */
76 static utf *utf_fidesc; /* ()V */
77 static utf *utf_clinit; /* <clinit> */
78 static utf *utf_initsystemclass; /* initializeSystemClass */
79 static utf *utf_systemclass; /* java/lang/System */
82 /* important system classes ***************************************************/
84 classinfo *class_java_lang_Object;
85 classinfo *class_java_lang_String;
86 classinfo *class_java_lang_ClassCastException;
87 classinfo *class_java_lang_NullPointerException;
88 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
89 classinfo *class_java_lang_NegativeArraySizeException;
90 classinfo *class_java_lang_OutOfMemoryError;
91 classinfo *class_java_lang_ArithmeticException;
92 classinfo *class_java_lang_ArrayStoreException;
93 classinfo *class_java_lang_ThreadDeath;
94 classinfo *class_array = NULL;
97 /******************************************************************************
99 structure for primitive classes: contains the class for wrapping the
100 primitive type, the primitive class, the name of the class for wrapping,
101 the one character type signature and the name of the primitive class
103 ******************************************************************************/
105 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
106 { NULL, NULL, "java/lang/Double", 'D', "double" },
107 { NULL, NULL, "java/lang/Float", 'F', "float" },
108 { NULL, NULL, "java/lang/Character", 'C', "char" },
109 { NULL, NULL, "java/lang/Integer", 'I', "int" },
110 { NULL, NULL, "java/lang/Long", 'J', "long" },
111 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
112 { NULL, NULL, "java/lang/Short", 'S', "short" },
113 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
114 { NULL, NULL, "java/lang/Void", 'V', "void" }};
117 /* instances of important system classes **************************************/
119 java_objectheader *proto_java_lang_ClassCastException;
120 java_objectheader *proto_java_lang_NullPointerException;
121 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
122 java_objectheader *proto_java_lang_NegativeArraySizeException;
123 java_objectheader *proto_java_lang_OutOfMemoryError;
124 java_objectheader *proto_java_lang_ArithmeticException;
125 java_objectheader *proto_java_lang_ArrayStoreException;
126 java_objectheader *proto_java_lang_ThreadDeath;
129 /************* functions for reading classdata *********************************
131 getting classdata in blocks of variable size
132 (8,16,32,64-bit integer or float)
134 *******************************************************************************/
136 static char *classpath = ""; /* searchpath for classfiles */
137 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
138 static u1 *classbuf_pos; /* current position in classfile buffer */
139 static int classbuffer_size; /* size of classfile-data */
141 /* transfer block of classfile data into a buffer */
143 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
146 /* skip block of classfile data */
148 #define skip_nbytes(len) classbuf_pos+=len;
152 return *++classbuf_pos;
156 u1 a=suck_u1(), b=suck_u1();
157 return ((u2)a<<8)+(u2)b;
161 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
162 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
164 #define suck_s8() (s8) suck_u8()
165 #define suck_s2() (s2) suck_u2()
166 #define suck_s4() (s4) suck_u4()
167 #define suck_s1() (s1) suck_u1()
170 /* get u8 from classfile data */
178 return (hi<<32) + lo;
187 /* get float from classfile data */
189 static float suck_float ()
196 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
197 memcpy ( (u1*) (&f), buffer, 4);
199 suck_nbytes ( (u1*) (&f), 4 );
202 PANICIF (sizeof(float) != 4, "Incompatible float-format");
207 /* get double from classfile data */
208 static double suck_double ()
215 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
216 memcpy ( (u1*) (&d), buffer, 8);
218 suck_nbytes ( (u1*) (&d), 8 );
221 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
226 /************************** function suck_init *********************************
228 called once at startup, sets the searchpath for the classfiles
230 *******************************************************************************/
232 void suck_init (char *cpath)
239 /************************** function suck_start ********************************
241 returns true if classbuffer is already loaded or a file for the
242 specified class has succussfully been read in. All directories of
243 the searchpath are used to find the classfile (<classname>.class).
244 Returns false if no classfile is found and writes an error message.
246 *******************************************************************************/
249 bool suck_start (utf *classname) {
251 #define MAXFILENAME 1000 /* maximum length of a filename */
253 char filename[MAXFILENAME+10]; /* room for '.class' */
254 char *pathpos; /* position in searchpath */
255 char c, *utf_ptr; /* pointer to the next utf8-character */
257 int filenamelen, err;
260 if (classbuffer) /* classbuffer is already valid */
267 /* skip path separator */
269 while (*pathpos == ':')
272 /* extract directory from searchpath */
275 while ((*pathpos) && (*pathpos!=':')) {
276 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
277 filename[filenamelen++] = *(pathpos++);
280 filename[filenamelen++] = '/';
282 /* add classname to filename */
284 utf_ptr = classname->text;
285 while (utf_ptr < utf_end(classname)) {
286 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
288 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
290 filename[filenamelen++] = c;
295 strcpy (filename+filenamelen, ".class");
297 classfile = fopen(filename, "r");
298 if (classfile) { /* file exists */
300 /* determine size of classfile */
302 err = stat (filename, &buffer);
304 if (!err) { /* read classfile data */
305 classbuffer_size = buffer.st_size;
306 classbuffer = MNEW(u1, classbuffer_size);
307 classbuf_pos = classbuffer-1;
308 fread(classbuffer, 1, classbuffer_size, classfile);
316 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
324 /************************** function suck_stop *********************************
326 frees memory for buffer with classfile data.
327 Caution: this function may only be called if buffer has been allocated
328 by suck_start with reading a file
330 *******************************************************************************/
334 /* determine amount of classdata not retrieved by suck-operations */
336 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
338 if (classdata_left > 0) {
340 sprintf (logtext,"There are %d access bytes at end of classfile",
347 MFREE(classbuffer, u1, classbuffer_size);
351 /******************************************************************************/
352 /******************* Some support functions ***********************************/
353 /******************************************************************************/
356 /********** internal function: printflags (only for debugging) ***************/
358 static void printflags (u2 f)
360 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
361 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
362 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
363 if ( f & ACC_STATIC ) printf (" STATIC");
364 if ( f & ACC_FINAL ) printf (" FINAL");
365 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
366 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
367 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
368 if ( f & ACC_NATIVE ) printf (" NATIVE");
369 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
370 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
374 /************************* Function: skipattribute *****************************
376 skips a (1) 'attribute' structure in the class file
378 *******************************************************************************/
380 static void skipattribute ()
383 skip_nbytes(suck_u4());
386 /********************** Function: skipattributebody ****************************
388 skips an attribute after the 16 bit reference to attribute_name has already
391 *******************************************************************************/
393 static void skipattributebody ()
395 skip_nbytes(suck_u4());
398 /************************* Function: skipattributes ****************************
400 skips num attribute structures
402 *******************************************************************************/
404 static void skipattributes (u4 num)
407 for (i = 0; i < num; i++)
411 /******************** function: innerclass_getconstant ************************
413 like class_getconstant, but if cptags is ZERO null is returned
415 *******************************************************************************/
417 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
419 /* invalid position in constantpool */
420 if (pos >= c->cpcount)
421 panic ("Attempt to access constant outside range");
423 /* constantpool entry of type 0 */
427 /* check type of constantpool entry */
428 if (c->cptags[pos] != ctype) {
429 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
430 (int) ctype, (int) c->cptags[pos] );
434 return c->cpinfos[pos];
437 /************************ function: attribute_load ****************************
439 read attributes from classfile
441 *******************************************************************************/
443 static void attribute_load (u4 num, classinfo *c)
447 for (i = 0; i < num; i++) {
448 /* retrieve attribute name */
449 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
451 if ( aname == utf_innerclasses) {
452 /* innerclasses attribute */
454 /* skip attribute length */
456 /* number of records */
457 c->innerclasscount = suck_u2();
458 /* allocate memory for innerclass structure */
459 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
461 for (j=0;j<c->innerclasscount;j++) {
463 /* The innerclass structure contains a class with an encoded name,
464 its defining scope, its simple name and a bitmask of the access flags.
465 If an inner class is not a member, its outer_class is NULL,
466 if a class is anonymous, its name is NULL. */
468 innerclassinfo *info = c->innerclass + j;
470 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
471 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
472 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
473 info->flags = suck_u2 (); /* access_flags bitmask */
476 /* unknown attribute */
477 skipattributebody ();
482 /******************* function: checkfielddescriptor ****************************
484 checks whether a field-descriptor is valid and aborts otherwise
485 all referenced classes are inserted into the list of unloaded classes
487 *******************************************************************************/
489 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
491 char *tstart; /* pointer to start of classname */
494 switch (*utf_ptr++) {
507 /* save start of classname */
510 /* determine length of classname */
511 while ( *utf_ptr++ != ';' )
512 if (utf_ptr>=end_pos)
513 panic ("Missing ';' in objecttype-descriptor");
515 /* cause loading of referenced class */
516 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
521 while ((ch = *utf_ptr++)=='[')
524 /* component type of array */
538 /* save start of classname */
541 /* determine length of classname */
542 while ( *utf_ptr++ != ';' )
543 if (utf_ptr>=end_pos)
544 panic ("Missing ';' in objecttype-descriptor");
546 /* cause loading of referenced class */
547 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
551 panic ("Ill formed methodtype-descriptor");
556 panic ("Ill formed methodtype-descriptor");
559 /* exceeding characters */
560 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
564 /******************* function checkmethoddescriptor ****************************
566 checks whether a method-descriptor is valid and aborts otherwise.
567 All referenced classes are inserted into the list of unloaded classes.
569 *******************************************************************************/
571 static void checkmethoddescriptor (utf *d)
573 char *utf_ptr = d->text; /* current position in utf text */
574 char *end_pos = utf_end(d); /* points behind utf string */
575 char *tstart; /* pointer to start of classname */
578 /* method descriptor must start with parenthesis */
579 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
581 /* check arguments */
582 while ((c = *utf_ptr++) != ')') {
596 /* save start of classname */
599 /* determine length of classname */
600 while ( *utf_ptr++ != ';' )
601 if (utf_ptr>=end_pos)
602 panic ("Missing ';' in objecttype-descriptor");
604 /* cause loading of referenced class */
605 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
610 while ((ch = *utf_ptr++)=='[')
613 /* component type of array */
627 /* save start of classname */
630 /* determine length of classname */
631 while ( *utf_ptr++ != ';' )
632 if (utf_ptr>=end_pos)
633 panic ("Missing ';' in objecttype-descriptor");
635 /* cause loading of referenced class */
636 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
640 panic ("Ill formed methodtype-descriptor");
645 panic ("Ill formed methodtype-descriptor");
649 /* check returntype */
651 /* returntype void */
652 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
655 /* treat as field-descriptor */
656 checkfielddescriptor (utf_ptr,end_pos);
660 /******************** Function: buildarraydescriptor ***************************
662 creates a constant_arraydescriptor structure for the array type named by an
665 *******************************************************************************/
667 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
669 constant_arraydescriptor *d;
671 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
673 d = NEW (constant_arraydescriptor);
674 d -> objectclass = NULL;
675 d -> elementdescriptor = NULL;
678 count_const_pool_len += sizeof(constant_arraydescriptor);
682 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
683 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
684 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
685 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
686 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
687 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
688 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
689 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
692 d -> arraytype = ARRAYTYPE_ARRAY;
693 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
697 d -> arraytype = ARRAYTYPE_OBJECT;
699 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
700 d -> objectclass -> classUsed = 0; /* not used initially CO-RT */
707 /******************* Function: freearraydescriptor *****************************
709 removes a structure created by buildarraydescriptor from memory
711 *******************************************************************************/
713 static void freearraydescriptor (constant_arraydescriptor *d)
716 constant_arraydescriptor *n = d->elementdescriptor;
717 FREE (d, constant_arraydescriptor);
722 /*********************** Function: displayarraydescriptor *********************/
724 static void displayarraydescriptor (constant_arraydescriptor *d)
726 switch (d->arraytype) {
727 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
728 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
729 case ARRAYTYPE_CHAR: printf ("char[]"); break;
730 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
731 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
732 case ARRAYTYPE_INT: printf ("int[]"); break;
733 case ARRAYTYPE_LONG: printf ("long[]"); break;
734 case ARRAYTYPE_SHORT: printf ("short[]"); break;
735 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
736 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
742 /******************************************************************************/
743 /************************** Functions for fields ****************************/
744 /******************************************************************************/
747 /************************ Function: field_load *********************************
749 Load everything about a class field from the class file and fill a
750 'fieldinfo' structure. For static fields, space in the data segment is
753 *******************************************************************************/
755 static void field_load (fieldinfo *f, classinfo *c)
760 f -> flags = suck_u2 (); /* ACC flags */
761 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
762 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
763 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
764 f -> offset = 0; /* offset from start of object */
767 case TYPE_INT: f->value.i = 0; break;
768 case TYPE_FLOAT: f->value.f = 0.0; break;
769 case TYPE_DOUBLE: f->value.d = 0.0; break;
770 case TYPE_ADDRESS: f->value.a = NULL;
771 heap_addreference (&(f->value.a)); /* make global reference (GC) */
775 f->value.l = 0; break;
777 f->value.l.low = 0; f->value.l.high = 0; break;
781 /* read attributes */
783 for (i=0; i<attrnum; i++) {
787 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
789 if ( aname != utf_constantvalue ) {
790 /* unknown attribute */
791 skipattributebody ();
794 /* constant value attribute */
796 /* skip attribute length */
798 /* index of value in constantpool */
801 /* initialize field with value from constantpool */
804 constant_integer *ci =
805 class_getconstant(c, pindex, CONSTANT_Integer);
806 f->value.i = ci -> value;
812 class_getconstant(c, pindex, CONSTANT_Long);
814 f->value.l = cl -> value;
820 class_getconstant(c, pindex, CONSTANT_Float);
822 f->value.f = cf->value;
827 constant_double *cd =
828 class_getconstant(c, pindex, CONSTANT_Double);
830 f->value.d = cd->value;
835 utf *u = class_getconstant(c, pindex, CONSTANT_String);
836 /* create javastring from compressed utf8-string */
837 f->value.a = literalstring_new(u);
842 log_text ("Invalid Constant - Type");
851 /********************** function: field_free **********************************/
853 static void field_free (fieldinfo *f)
859 /**************** Function: field_display (debugging only) ********************/
861 static void field_display (fieldinfo *f)
864 printflags (f -> flags);
866 utf_display (f -> name);
868 utf_display (f -> descriptor);
869 printf (" offset: %ld\n", (long int) (f -> offset) );
873 /******************************************************************************/
874 /************************* Functions for methods ******************************/
875 /******************************************************************************/
878 /*********************** Function: method_load *********************************
880 Loads a method from the class file and fills an existing 'methodinfo'
881 structure. For native methods, the function pointer field is set to the
882 real function pointer, for JavaVM methods a pointer to the compiler is used
885 *******************************************************************************/
887 static void method_load (methodinfo *m, classinfo *c)
897 m -> flags = suck_u2 ();
898 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
899 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
902 m -> exceptiontable = NULL;
903 m -> entrypoint = NULL;
905 m -> stubroutine = NULL;
906 m -> methodUsed = 0; /* not used initially CO-RT*/
908 if (! (m->flags & ACC_NATIVE) ) {
909 m -> stubroutine = createcompilerstub (m);
913 functionptr f = native_findfunction
914 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
919 m -> stubroutine = createnativestub (f, m);
922 m -> stubroutine = oldcreatenativestub (f, m);
929 for (i=0; i<attrnum; i++) {
932 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
934 if ( aname != utf_code) {
935 skipattributebody ();
938 if (m -> jcode) panic ("Two code-attributes for one method!");
941 m -> maxstack = suck_u2();
942 m -> maxlocals = suck_u2();
943 m -> jcodelength = suck_u4();
944 m -> jcode = MNEW (u1, m->jcodelength);
945 suck_nbytes (m->jcode, m->jcodelength);
946 m -> exceptiontablelength = suck_u2 ();
947 m -> exceptiontable =
948 MNEW (exceptiontable, m->exceptiontablelength);
951 count_vmcode_len += m->jcodelength + 18;
952 count_extable_len += 8 * m->exceptiontablelength;
955 for (e=0; e < m->exceptiontablelength; e++) {
957 m -> exceptiontable[e].startpc = suck_u2();
958 m -> exceptiontable[e].endpc = suck_u2();
959 m -> exceptiontable[e].handlerpc = suck_u2();
962 if (!idx) m -> exceptiontable[e].catchtype = NULL;
964 m -> exceptiontable[e].catchtype =
965 class_getconstant (c, idx, CONSTANT_Class);
969 skipattributes ( suck_u2() );
976 /********************* Function: method_free ***********************************
978 frees all memory that was allocated for this method
980 *******************************************************************************/
982 static void method_free (methodinfo *m)
984 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
985 if (m->exceptiontable)
986 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
987 if (m->mcode) CFREE (m->mcode, m->mcodelength);
988 if (m->stubroutine) {
989 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
990 else removecompilerstub (m->stubroutine);
995 /************** Function: method_display (debugging only) **************/
997 void method_display (methodinfo *m)
1000 printflags (m -> flags);
1002 utf_display (m -> name);
1004 utf_display (m -> descriptor);
1009 /******************** Function: method_canoverwrite ****************************
1011 Check if m and old are identical with respect to type and name. This means
1012 that old can be overwritten with m.
1014 *******************************************************************************/
1016 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1018 if (m->name != old->name) return false;
1019 if (m->descriptor != old->descriptor) return false;
1020 if (m->flags & ACC_STATIC) return false;
1027 /******************************************************************************/
1028 /************************ Functions for class *********************************/
1029 /******************************************************************************/
1032 /******************** function: class_getconstant ******************************
1034 retrieves the value at position 'pos' of the constantpool of a class
1035 if the type of the value is other than 'ctype' the system is stopped
1037 *******************************************************************************/
1039 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1041 /* invalid position in constantpool */
1042 if (pos >= c->cpcount)
1043 panic ("Attempt to access constant outside range");
1045 /* check type of constantpool entry */
1046 if (c->cptags[pos] != ctype) {
1047 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1048 (int) ctype, (int) c->cptags[pos] );
1052 return c->cpinfos[pos];
1056 /********************* Function: class_constanttype ****************************
1058 Determines the type of a class entry in the ConstantPool
1060 *******************************************************************************/
1062 u4 class_constanttype (classinfo *c, u4 pos)
1064 if (pos >= c->cpcount)
1065 panic ("Attempt to access constant outside range");
1066 return c->cptags[pos];
1070 /******************** function: class_loadcpool ********************************
1072 loads the constantpool of a class,
1073 the entries are transformed into a simpler format
1074 by resolving references
1075 (a detailed overview of the compact structures can be found in global.h)
1077 *******************************************************************************/
1079 static void class_loadcpool (classinfo *c)
1082 /* The following structures are used to save information which cannot be
1083 processed during the first pass. After the complete constantpool has
1084 been traversed the references can be resolved.
1085 (only in specific order) */
1087 /* CONSTANT_Class_info entries */
1088 typedef struct forward_class {
1089 struct forward_class *next;
1094 /* CONSTANT_String */
1095 typedef struct forward_string {
1096 struct forward_string *next;
1101 /* CONSTANT_NameAndType */
1102 typedef struct forward_nameandtype {
1103 struct forward_nameandtype *next;
1107 } forward_nameandtype;
1109 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1110 typedef struct forward_fieldmethint {
1111 struct forward_fieldmethint *next;
1115 u2 nameandtype_index;
1116 } forward_fieldmethint;
1120 long int dumpsize = dump_size ();
1122 forward_class *forward_classes = NULL;
1123 forward_string *forward_strings = NULL;
1124 forward_nameandtype *forward_nameandtypes = NULL;
1125 forward_fieldmethint *forward_fieldmethints = NULL;
1127 /* number of entries in the constant_pool table */
1128 u4 cpcount = c -> cpcount = suck_u2();
1129 /* allocate memory */
1130 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1131 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1134 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1137 /* initialize constantpool */
1138 for (idx=0; idx<cpcount; idx++) {
1139 cptags[idx] = CONSTANT_UNUSED;
1140 cpinfos[idx] = NULL;
1144 /******* first pass *******/
1145 /* entries which cannot be resolved now are written into
1146 temporary structures and traversed again later */
1149 while (idx < cpcount) {
1150 /* get constant type */
1154 case CONSTANT_Class: {
1155 forward_class *nfc = DNEW(forward_class);
1157 nfc -> next = forward_classes;
1158 forward_classes = nfc;
1160 nfc -> thisindex = idx;
1161 /* reference to CONSTANT_NameAndType */
1162 nfc -> name_index = suck_u2 ();
1168 case CONSTANT_Fieldref:
1169 case CONSTANT_Methodref:
1170 case CONSTANT_InterfaceMethodref: {
1171 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1173 nff -> next = forward_fieldmethints;
1174 forward_fieldmethints = nff;
1176 nff -> thisindex = idx;
1179 /* class or interface type that contains the declaration of the field or method */
1180 nff -> class_index = suck_u2 ();
1181 /* name and descriptor of the field or method */
1182 nff -> nameandtype_index = suck_u2 ();
1188 case CONSTANT_String: {
1189 forward_string *nfs = DNEW (forward_string);
1191 nfs -> next = forward_strings;
1192 forward_strings = nfs;
1194 nfs -> thisindex = idx;
1195 /* reference to CONSTANT_Utf8_info with string characters */
1196 nfs -> string_index = suck_u2 ();
1202 case CONSTANT_NameAndType: {
1203 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1205 nfn -> next = forward_nameandtypes;
1206 forward_nameandtypes = nfn;
1208 nfn -> thisindex = idx;
1209 /* reference to CONSTANT_Utf8_info containing simple name */
1210 nfn -> name_index = suck_u2 ();
1211 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1212 nfn -> sig_index = suck_u2 ();
1218 case CONSTANT_Integer: {
1219 constant_integer *ci = NEW (constant_integer);
1222 count_const_pool_len += sizeof(constant_integer);
1225 ci -> value = suck_s4 ();
1226 cptags [idx] = CONSTANT_Integer;
1233 case CONSTANT_Float: {
1234 constant_float *cf = NEW (constant_float);
1237 count_const_pool_len += sizeof(constant_float);
1240 cf -> value = suck_float ();
1241 cptags [idx] = CONSTANT_Float;
1247 case CONSTANT_Long: {
1248 constant_long *cl = NEW(constant_long);
1251 count_const_pool_len += sizeof(constant_long);
1254 cl -> value = suck_s8 ();
1255 cptags [idx] = CONSTANT_Long;
1261 case CONSTANT_Double: {
1262 constant_double *cd = NEW(constant_double);
1265 count_const_pool_len += sizeof(constant_double);
1268 cd -> value = suck_double ();
1269 cptags [idx] = CONSTANT_Double;
1275 case CONSTANT_Utf8: {
1277 /* number of bytes in the bytes array (not string-length) */
1278 u4 length = suck_u2();
1279 cptags [idx] = CONSTANT_Utf8;
1280 /* insert utf-string into the utf-symboltable */
1281 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1282 /* skip bytes of the string */
1283 skip_nbytes(length);
1289 sprintf (logtext, "Unkown constant type: %d",(int) t);
1298 /* resolve entries in temporary structures */
1300 while (forward_classes) {
1302 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1304 if ( (name->blength>0) && (name->text[0]=='[') ) {
1305 /* check validity of descriptor */
1306 checkfielddescriptor (name->text, utf_end(name));
1308 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1309 cpinfos [forward_classes -> thisindex] =
1310 buildarraydescriptor(name->text, name->blength);
1314 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1315 /* retrieve class from class-table */
1316 cpinfos [forward_classes -> thisindex] = class_new (name);
1318 forward_classes = forward_classes -> next;
1322 while (forward_strings) {
1324 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1326 /* resolve utf-string */
1327 cptags [forward_strings -> thisindex] = CONSTANT_String;
1328 cpinfos [forward_strings -> thisindex] = text;
1330 forward_strings = forward_strings -> next;
1333 while (forward_nameandtypes) {
1334 constant_nameandtype *cn = NEW (constant_nameandtype);
1337 count_const_pool_len += sizeof(constant_nameandtype);
1340 /* resolve simple name and descriptor */
1341 cn -> name = class_getconstant
1342 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1343 cn -> descriptor = class_getconstant
1344 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1346 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1347 cpinfos [forward_nameandtypes -> thisindex] = cn;
1349 forward_nameandtypes = forward_nameandtypes -> next;
1353 while (forward_fieldmethints) {
1354 constant_nameandtype *nat;
1355 constant_FMIref *fmi = NEW (constant_FMIref);
1358 count_const_pool_len += sizeof(constant_FMIref);
1360 /* resolve simple name and descriptor */
1361 nat = class_getconstant
1362 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1364 fmi -> class = class_getconstant
1365 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1366 fmi -> name = nat -> name;
1367 fmi -> descriptor = nat -> descriptor;
1369 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1370 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1372 switch (forward_fieldmethints -> tag) {
1373 case CONSTANT_Fieldref: /* check validity of descriptor */
1374 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1376 case CONSTANT_InterfaceMethodref:
1377 case CONSTANT_Methodref: /* check validity of descriptor */
1378 checkmethoddescriptor (fmi->descriptor);
1382 forward_fieldmethints = forward_fieldmethints -> next;
1387 dump_release (dumpsize);
1391 /********************** Function: class_load ***********************************
1393 Loads everything interesting about a class from the class file. The
1394 'classinfo' structure must have been allocated previously.
1396 The super class and the interfaces implemented by this class need not be
1397 loaded. The link is set later by the function 'class_link'.
1399 The loaded class is removed from the list 'unloadedclasses' and added to
1400 the list 'unlinkedclasses'.
1402 *******************************************************************************/
1404 static int class_load (classinfo *c)
1410 count_class_loads++;
1413 /* output for debugging purposes */
1415 sprintf (logtext, "Loading class: ");
1416 utf_sprint (logtext+strlen(logtext), c->name );
1420 /* load classdata, throw exception on error */
1421 if (!suck_start (c->name)) {
1422 throw_classnotfoundexception();
1426 /* check signature */
1427 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1431 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1432 sprintf (logtext, "File version %d.%d is not supported",
1433 (int) ma, (int) mi);
1438 class_loadcpool (c);
1440 c -> classUsed = 0; /* not used initially CO-RT */
1443 c -> flags = suck_u2 ();
1447 /* retrieve superclass */
1448 if ( (i = suck_u2 () ) ) {
1449 c -> super = class_getconstant (c, i, CONSTANT_Class);
1455 /* retrieve interfaces */
1456 c -> interfacescount = suck_u2 ();
1457 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1458 for (i=0; i < c -> interfacescount; i++) {
1459 c -> interfaces [i] =
1460 class_getconstant (c, suck_u2(), CONSTANT_Class);
1464 c -> fieldscount = suck_u2 ();
1466 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1468 c -> fields = MNEW (fieldinfo, c -> fieldscount);
1470 for (i=0; i < c -> fieldscount; i++) {
1471 field_load (&(c->fields[i]), c);
1475 c -> methodscount = suck_u2 ();
1476 c -> methods = MNEW (methodinfo, c -> methodscount);
1477 for (i=0; i < c -> methodscount; i++) {
1478 method_load (&(c -> methods [i]), c);
1482 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1483 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1484 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1487 /* load variable-length attribute structures */
1488 attribute_load (suck_u2(), c);
1493 /* remove class from list of unloaded classes and
1494 add to list of unlinked classes */
1495 list_remove (&unloadedclasses, c);
1496 list_addlast (&unlinkedclasses, c);
1503 /************** internal Function: class_highestinterface ***********************
1505 Used by the function class_link to determine the amount of memory needed
1506 for the interface table.
1508 *******************************************************************************/
1510 static s4 class_highestinterface (classinfo *c)
1515 if ( ! (c->flags & ACC_INTERFACE) ) {
1516 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1517 utf_sprint (logtext+strlen(logtext), c->name);
1522 for (i=0; i<c->interfacescount; i++) {
1523 s4 h2 = class_highestinterface (c->interfaces[i]);
1530 /* class_addinterface **********************************************************
1532 Is needed by class_link for adding a VTBL to a class. All interfaces
1533 implemented by ic are added as well.
1535 *******************************************************************************/
1537 static void class_addinterface (classinfo *c, classinfo *ic)
1541 vftbl *vftbl = c->vftbl;
1543 if (i >= vftbl->interfacetablelength)
1544 panic ("Inernal error: interfacetable overflow");
1545 if (vftbl->interfacetable[-i])
1548 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1549 vftbl->interfacevftbllength[i] = 1;
1550 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1551 vftbl->interfacetable[-i][0] = NULL;
1554 vftbl->interfacevftbllength[i] = ic->methodscount;
1555 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1558 count_vftbl_len += sizeof(methodptr) *
1559 (ic->methodscount + (ic->methodscount == 0));
1562 for (j=0; j<ic->methodscount; j++) {
1565 for (m = 0; m < sc->methodscount; m++) {
1566 methodinfo *mi = &(sc->methods[m]);
1567 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1568 vftbl->interfacetable[-i][j] =
1569 vftbl->table[mi->vftblindex];
1579 for (j = 0; j < ic->interfacescount; j++)
1580 class_addinterface(c, ic->interfaces[j]);
1584 /********************** Function: class_link ***********************************
1586 Tries to link a class. The super class and every implemented interface must
1587 already have been linked. The function calculates the length in bytes that
1588 an instance of this class requires as well as the VTBL for methods and
1591 If the class can be linked, it is removed from the list 'unlinkedclasses'
1592 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1595 Attention: If cyclical class definitions are encountered, the program gets
1596 into an infinite loop (we'll have to work that out)
1598 *******************************************************************************/
1600 static void class_link (classinfo *c)
1602 s4 supervftbllength; /* vftbllegnth of super class */
1603 s4 vftbllength; /* vftbllength of current class */
1604 s4 interfacetablelength; /* interface table length */
1605 classinfo *super = c->super; /* super class */
1606 classinfo *ic, *c2; /* intermediate class variables */
1607 vftbl *v; /* vftbl of current class */
1608 s4 i; /* interface/method/field counter */
1611 /* check if all superclasses are already linked, if not put c at end of
1612 unlinked list and return. Additionally initialize class fields. */
1614 /* check interfaces */
1616 for (i = 0; i < c->interfacescount; i++) {
1617 ic = c->interfaces[i];
1619 list_remove(&unlinkedclasses, c);
1620 list_addlast(&unlinkedclasses, c);
1625 /* check super class */
1627 if (super == NULL) { /* class java.long.Object */
1629 c->classUsed = 1; /* Object class is always used CO-RT*/
1630 c->instancesize = sizeof(java_objectheader);
1632 vftbllength = supervftbllength = 0;
1634 c->finalizer = NULL;
1637 if (!super->linked) {
1638 list_remove(&unlinkedclasses, c);
1639 list_addlast(&unlinkedclasses, c);
1643 if (c->flags & ACC_INTERFACE)
1644 c->index = interfaceindex++;
1646 c->index = super->index + 1;
1648 c->instancesize = super->instancesize;
1650 vftbllength = supervftbllength = super->vftbl->vftbllength;
1652 c->finalizer = super->finalizer;
1657 sprintf (logtext, "Linking Class: ");
1658 utf_sprint (logtext+strlen(logtext), c->name );
1662 /* compute vftbl length */
1664 for (i = 0; i < c->methodscount; i++) {
1665 methodinfo *m = &(c->methods[i]);
1667 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1668 classinfo *sc = super;
1671 for (j = 0; j < sc->methodscount; j++) {
1672 if (method_canoverwrite(m, &(sc->methods[j]))) {
1673 m->vftblindex = sc->methods[j].vftblindex;
1674 goto foundvftblindex;
1679 m->vftblindex = (vftbllength++);
1685 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1688 /* compute interfacetable length */
1690 interfacetablelength = 0;
1693 for (i = 0; i < c2->interfacescount; i++) {
1694 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1695 if (h > interfacetablelength)
1696 interfacetablelength = h;
1701 /* allocate virtual function table */
1703 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1704 (vftbllength - 1) + sizeof(methodptr*) *
1705 (interfacetablelength - (interfacetablelength > 0)));
1706 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1707 (interfacetablelength > 1));
1708 c->header.vftbl = c->vftbl = v;
1710 v->vftbllength = vftbllength;
1711 v->interfacetablelength = interfacetablelength;
1713 /* copy virtual function table of super class */
1715 for (i = 0; i < supervftbllength; i++)
1716 v->table[i] = super->vftbl->table[i];
1718 /* add method stubs into virtual function table */
1720 for (i = 0; i < c->methodscount; i++) {
1721 methodinfo *m = &(c->methods[i]);
1722 if (!(m->flags & ACC_STATIC)) {
1723 v->table[m->vftblindex] = m->stubroutine;
1727 /* compute instance size and offset of each field */
1729 for (i = 0; i < c->fieldscount; i++) {
1731 fieldinfo *f = &(c->fields[i]);
1733 if (!(f->flags & ACC_STATIC) ) {
1734 dsize = desc_typesize (f->descriptor);
1735 c->instancesize = ALIGN (c->instancesize, dsize);
1736 f->offset = c->instancesize;
1737 c->instancesize += dsize;
1741 /* initialize interfacetable and interfacevftbllength */
1743 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1746 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1749 for (i = 0; i < interfacetablelength; i++) {
1750 v->interfacevftbllength[i] = 0;
1751 v->interfacetable[-i] = NULL;
1754 /* add interfaces */
1756 for (c2 = c; c2 != NULL; c2 = c2->super)
1757 for (i = 0; i < c2->interfacescount; i++) {
1758 class_addinterface (c, c2->interfaces[i]);
1761 /* add finalizer method (not for java.lang.Object) */
1763 if (super != NULL) {
1765 static utf *finame = NULL;
1766 static utf *fidesc = NULL;
1769 finame = utf_finalize;
1771 fidesc = utf_fidesc;
1773 fi = class_findmethod (c, finame, fidesc);
1775 if (!(fi->flags & ACC_STATIC)) {
1785 list_remove (&unlinkedclasses, c);
1786 list_addlast (&linkedclasses, c);
1790 /******************* Function: class_freepool **********************************
1792 Frees all resources used by this classes Constant Pool.
1794 *******************************************************************************/
1796 static void class_freecpool (classinfo *c)
1802 for (idx=0; idx < c->cpcount; idx++) {
1803 tag = c->cptags[idx];
1804 info = c->cpinfos[idx];
1808 case CONSTANT_Fieldref:
1809 case CONSTANT_Methodref:
1810 case CONSTANT_InterfaceMethodref:
1811 FREE (info, constant_FMIref);
1813 case CONSTANT_Integer:
1814 FREE (info, constant_integer);
1816 case CONSTANT_Float:
1817 FREE (info, constant_float);
1820 FREE (info, constant_long);
1822 case CONSTANT_Double:
1823 FREE (info, constant_double);
1825 case CONSTANT_NameAndType:
1826 FREE (info, constant_nameandtype);
1828 case CONSTANT_Arraydescriptor:
1829 freearraydescriptor (info);
1835 MFREE (c -> cptags, u1, c -> cpcount);
1836 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1840 /*********************** Function: class_free **********************************
1842 Frees all resources used by the class.
1844 *******************************************************************************/
1846 static void class_free (classinfo *c)
1851 class_freecpool (c);
1853 MFREE (c->interfaces, classinfo*, c->interfacescount);
1855 for (i = 0; i < c->fieldscount; i++)
1856 field_free(&(c->fields[i]));
1858 MFREE (c->fields, fieldinfo, c->fieldscount);
1861 for (i = 0; i < c->methodscount; i++)
1862 method_free(&(c->methods[i]));
1863 MFREE (c->methods, methodinfo, c->methodscount);
1865 if ((v = c->vftbl) != NULL) {
1866 for (i = 0; i < v->interfacetablelength; i++) {
1867 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1869 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1871 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1872 sizeof(methodptr*) * (v->interfacetablelength -
1873 (v->interfacetablelength > 0));
1874 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1875 (v->interfacetablelength > 1));
1879 if (c->innerclasscount)
1880 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1883 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1));
1885 FREE (c, classinfo);
1888 /************************* Function: class_findfield ***************************
1890 Searches a 'classinfo' structure for a field having the given name and
1893 *******************************************************************************/
1896 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1900 for (i = 0; i < c->fieldscount; i++) {
1901 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1902 return &(c->fields[i]);
1905 panic ("Can not find field given in CONSTANT_Fieldref");
1910 /************************* Function: class_findmethod **************************
1912 Searches a 'classinfo' structure for a method having the given name and
1914 If type is NULL, it is ignored.
1916 *******************************************************************************/
1918 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1921 for (i = 0; i < c->methodscount; i++) {
1922 if ((c->methods[i].name == name) && ((desc == NULL) ||
1923 (c->methods[i].descriptor == desc)))
1924 return &(c->methods[i]);
1929 /************************* Function: class_findmethod_approx ******************
1931 like class_findmethod but ignores the return value when comparing the
1934 *******************************************************************************/
1936 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1940 for (i = 0; i < c->methodscount; i++)
1941 if (c->methods[i].name == name) {
1942 utf *meth_descr = c->methods[i].descriptor;
1946 return &(c->methods[i]);
1948 if (desc->blength <= meth_descr->blength) {
1949 /* current position in utf text */
1950 char *desc_utf_ptr = desc->text;
1951 char *meth_utf_ptr = meth_descr->text;
1952 /* points behind utf strings */
1953 char *desc_end = utf_end(desc);
1954 char *meth_end = utf_end(meth_descr);
1957 /* compare argument types */
1958 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1960 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1961 break; /* no match */
1964 return &(c->methods[i]); /* all parameter types equal */
1972 /***************** Function: class_resolvemethod_approx ***********************
1974 Searches a class and every super class for a method (without paying
1975 attention to the return value)
1977 *******************************************************************************/
1979 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
1982 /* search for method (ignore returntype) */
1983 methodinfo *m = class_findmethod_approx (c, name, desc);
1986 /* search superclass */
1993 /************************* Function: class_resolvemethod ***********************
1995 Searches a class and every super class for a method.
1997 *******************************************************************************/
2000 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2003 methodinfo *m = class_findmethod (c, name, desc);
2005 /* search superclass */
2013 /************************* Function: class_issubclass **************************
2015 Checks if sub is a descendant of super.
2017 *******************************************************************************/
2019 bool class_issubclass (classinfo *sub, classinfo *super)
2022 if (!sub) return false;
2023 if (sub==super) return true;
2030 /****************** Initialization function for classes ******************
2032 In Java, every class can have a static initialization function. This
2033 function has to be called BEFORE calling other methods or accessing static
2036 *******************************************************************************/
2039 extern int blockInts;
2042 void class_init (classinfo *c)
2045 java_objectheader *exceptionptr;
2049 if (!makeinitializations)
2053 c -> initialized = true;
2056 count_class_inits++;
2060 class_init (c->super);
2061 for (i=0; i < c->interfacescount; i++)
2062 class_init(c->interfaces[i]);
2064 m = class_findmethod (c, utf_clinit, utf_fidesc);
2067 sprintf (logtext, "Class ");
2068 utf_sprint (logtext+strlen(logtext), c->name);
2069 sprintf (logtext+strlen(logtext), " has no initializer");
2075 if (! (m->flags & ACC_STATIC))
2076 panic ("Class initializer is not static!");
2079 sprintf (logtext, "Starting initializer for class: ");
2080 utf_sprint (logtext+strlen(logtext), c->name);
2089 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2092 assert(blockInts == 0);
2097 printf ("#### Initializer of ");
2098 utf_display (c->name);
2099 printf (" has thrown: ");
2100 utf_display (exceptionptr->vftbl->class->name);
2106 sprintf (logtext, "Finished initializer for class: ");
2107 utf_sprint (logtext+strlen(logtext), c->name);
2111 if (c->name == utf_systemclass) {
2112 /* class java.lang.System requires explicit initialization */
2115 printf ("#### Initializing class System");
2117 /* find initializing method */
2118 m = class_findmethod (c,
2119 utf_initsystemclass,
2123 /* no method found */
2124 log("initializeSystemClass failed");
2133 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2136 assert(blockInts == 0);
2141 printf ("#### initializeSystemClass has thrown: ");
2142 utf_display (exceptionptr->vftbl->class->name);
2152 /********* Function: class_showconstantpool (debugging only) *********/
2154 void class_showconstantpool (classinfo *c)
2159 printf ("---- dump of constant pool ----\n");
2161 for (i=0; i<c->cpcount; i++) {
2162 printf ("#%d: ", (int) i);
2164 e = c -> cpinfos [i];
2167 switch (c -> cptags [i]) {
2168 case CONSTANT_Class:
2169 printf ("Classreference -> ");
2170 utf_display ( ((classinfo*)e) -> name );
2173 case CONSTANT_Fieldref:
2174 printf ("Fieldref -> "); goto displayFMI;
2175 case CONSTANT_Methodref:
2176 printf ("Methodref -> "); goto displayFMI;
2177 case CONSTANT_InterfaceMethodref:
2178 printf ("InterfaceMethod -> "); goto displayFMI;
2181 constant_FMIref *fmi = e;
2182 utf_display ( fmi->class->name );
2184 utf_display ( fmi->name);
2186 utf_display ( fmi->descriptor );
2190 case CONSTANT_String:
2191 printf ("String -> ");
2194 case CONSTANT_Integer:
2195 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2197 case CONSTANT_Float:
2198 printf ("Float -> %f", ((constant_float*)e) -> value);
2200 case CONSTANT_Double:
2201 printf ("Double -> %f", ((constant_double*)e) -> value);
2205 u8 v = ((constant_long*)e) -> value;
2207 printf ("Long -> %ld", (long int) v);
2209 printf ("Long -> HI: %ld, LO: %ld\n",
2210 (long int) v.high, (long int) v.low);
2214 case CONSTANT_NameAndType:
2215 { constant_nameandtype *cnt = e;
2216 printf ("NameAndType: ");
2217 utf_display (cnt->name);
2219 utf_display (cnt->descriptor);
2223 printf ("Utf8 -> ");
2226 case CONSTANT_Arraydescriptor: {
2227 printf ("Arraydescriptor: ");
2228 displayarraydescriptor (e);
2232 panic ("Invalid type of ConstantPool-Entry");
2244 /********** Function: class_showmethods (debugging only) *************/
2246 void class_showmethods (classinfo *c)
2250 printf ("--------- Fields and Methods ----------------\n");
2251 printf ("Flags: "); printflags (c->flags); printf ("\n");
2253 printf ("This: "); utf_display (c->name); printf ("\n");
2255 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2257 printf ("Index: %d\n", c->index);
2259 printf ("interfaces:\n");
2260 for (i=0; i < c-> interfacescount; i++) {
2262 utf_display (c -> interfaces[i] -> name);
2263 printf (" (%d)\n", c->interfaces[i] -> index);
2266 printf ("fields:\n");
2267 for (i=0; i < c -> fieldscount; i++) {
2268 field_display (&(c -> fields[i]));
2271 printf ("methods:\n");
2272 for (i=0; i < c -> methodscount; i++) {
2273 methodinfo *m = &(c->methods[i]);
2274 if ( !(m->flags & ACC_STATIC))
2275 printf ("vftblindex: %d ", m->vftblindex);
2277 method_display ( m );
2281 printf ("Virtual function table:\n");
2282 for (i=0; i<c->vftbl->vftbllength; i++) {
2283 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2290 /******************************************************************************/
2291 /******************* General functions for the class loader *******************/
2292 /******************************************************************************/
2294 static int loader_inited = 0;
2296 /********************* Function: loader_load ***********************************
2298 Loads and links the class desired class and each class and interface
2300 Returns: a pointer to this class
2302 *******************************************************************************/
2304 classinfo *loader_load (utf *topname)
2308 long int starttime=0,stoptime=0;
2310 intsDisable(); /* schani */
2313 starttime = getcputime();
2315 top = class_new (topname);
2318 while ( (c = list_first(&unloadedclasses)) ) {
2319 if (!class_load (c)) {
2320 list_remove (&unloadedclasses, c);
2326 while ( (c = list_first(&unlinkedclasses)) ) {
2331 loader_compute_subclasses();
2334 if (getloadingtime) {
2335 stoptime = getcputime();
2336 loadingtime += (stoptime-starttime);
2339 intsRestore(); /* schani */
2345 /**************** function: create_primitive_classes ***************************
2347 create classes representing primitive types
2349 ********************************************************************************/
2352 void create_primitive_classes()
2356 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2357 /* create primitive class */
2358 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2359 c -> classUsed = 0; /* not used initially CO-RT */
2361 /* prevent loader from loading primitive class */
2362 list_remove (&unloadedclasses, c);
2363 /* add to unlinked classes */
2364 list_addlast (&unlinkedclasses, c);
2365 c -> super = class_java_lang_Object;
2368 primitivetype_table[i].class_primitive = c;
2370 /* create class for wrapping the primitive type */
2371 primitivetype_table[i].class_wrap =
2372 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2373 primitivetype_table[i].class_wrap -> classUsed = 0; /* not used initially CO-RT */
2377 /***************** function: create_array_class ********************************
2379 create class representing an array
2381 ********************************************************************************/
2384 classinfo *create_array_class(utf *u)
2386 classinfo *c = class_new (u);
2387 /* prevent loader from loading the array class */
2388 list_remove (&unloadedclasses, c);
2389 /* add to unlinked classes */
2390 list_addlast (&unlinkedclasses, c);
2391 c -> super = class_java_lang_Object;
2397 /********************** Function: loader_init **********************************
2399 Initializes all lists and loads all classes required for the system or the
2402 *******************************************************************************/
2409 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2410 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2411 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2413 /* create utf-symbols for pointer comparison of frequently used strings */
2414 utf_innerclasses = utf_new_char("InnerClasses");
2415 utf_constantvalue = utf_new_char("ConstantValue");
2416 utf_code = utf_new_char("Code");
2417 utf_finalize = utf_new_char("finalize");
2418 utf_fidesc = utf_new_char("()V");
2419 utf_clinit = utf_new_char("<clinit>");
2420 utf_initsystemclass = utf_new_char("initializeSystemClass");
2421 utf_systemclass = utf_new_char("java/lang/System");
2423 /* create class for arrays */
2424 class_array = class_new ( utf_new_char ("The_Array_Class") );
2425 class_array -> classUsed = 0; /* not used initially CO-RT */
2427 list_remove (&unloadedclasses, class_array);
2429 /* create class for strings, load it after class Object was loaded */
2430 string_class = utf_new_char ("java/lang/String");
2431 class_java_lang_String = class_new(string_class);
2432 class_java_lang_String -> classUsed = 0; /* not used initially CO-RT */
2434 list_remove (&unloadedclasses, class_java_lang_String);
2436 class_java_lang_Object =
2437 loader_load ( utf_new_char ("java/lang/Object") );
2439 list_addlast(&unloadedclasses, class_java_lang_String);
2441 class_java_lang_String =
2442 loader_load ( string_class );
2443 class_java_lang_ClassCastException =
2444 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2445 class_java_lang_NullPointerException =
2446 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2447 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2448 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2449 class_java_lang_NegativeArraySizeException = loader_load (
2450 utf_new_char ("java/lang/NegativeArraySizeException") );
2451 class_java_lang_OutOfMemoryError = loader_load (
2452 utf_new_char ("java/lang/OutOfMemoryError") );
2453 class_java_lang_ArrayStoreException =
2454 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2455 class_java_lang_ArithmeticException =
2456 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2457 class_java_lang_ThreadDeath = /* schani */
2458 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2460 /* link class for arrays */
2461 list_addlast (&unlinkedclasses, class_array);
2462 class_array -> super = class_java_lang_Object;
2463 class_link (class_array);
2465 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2466 stringtable_update();
2468 /* create classes representing primitive types */
2469 create_primitive_classes();
2471 proto_java_lang_ClassCastException =
2472 builtin_new(class_java_lang_ClassCastException);
2473 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2475 proto_java_lang_NullPointerException =
2476 builtin_new(class_java_lang_NullPointerException);
2477 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2479 proto_java_lang_ArrayIndexOutOfBoundsException =
2480 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2481 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2483 proto_java_lang_NegativeArraySizeException =
2484 builtin_new(class_java_lang_NegativeArraySizeException);
2485 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2487 proto_java_lang_OutOfMemoryError =
2488 builtin_new(class_java_lang_OutOfMemoryError);
2489 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2491 proto_java_lang_ArithmeticException =
2492 builtin_new(class_java_lang_ArithmeticException);
2493 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2495 proto_java_lang_ArrayStoreException =
2496 builtin_new(class_java_lang_ArrayStoreException);
2497 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2499 proto_java_lang_ThreadDeath = /* schani */
2500 builtin_new(class_java_lang_ThreadDeath);
2501 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2509 /********************* Function: loader_initclasses ****************************
2511 Initializes all loaded but uninitialized classes
2513 *******************************************************************************/
2515 void loader_initclasses ()
2519 intsDisable(); /* schani */
2521 if (makeinitializations) {
2522 c = list_first (&linkedclasses);
2525 c = list_next (&linkedclasses, c);
2529 intsRestore(); /* schani */
2532 static s4 classvalue;
2534 static void loader_compute_class_values (classinfo *c)
2538 c->vftbl->baseval = ++classvalue;
2540 while (subs != NULL) {
2541 loader_compute_class_values(subs);
2542 subs = subs->nextsub;
2544 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2548 for (i = 0; i < c->index; i++)
2550 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2551 utf_display(c->name);
2558 void loader_compute_subclasses ()
2562 intsDisable(); /* schani */
2564 c = list_first (&linkedclasses);
2566 if (!(c->flags & ACC_INTERFACE)) {
2570 c = list_next (&linkedclasses, c);
2573 c = list_first (&linkedclasses);
2575 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2576 c->nextsub = c->super->sub;
2579 c = list_next (&linkedclasses, c);
2583 loader_compute_class_values(class_java_lang_Object);
2585 intsRestore(); /* schani */
2590 /******************** function classloader_buffer ******************************
2592 sets buffer for reading classdata
2594 *******************************************************************************/
2596 void classload_buffer(u1 *buf, int len)
2599 classbuffer_size = len;
2600 classbuf_pos = buf - 1;
2604 /******************** Function: loader_close ***********************************
2608 *******************************************************************************/
2610 void loader_close ()
2614 while ( (c=list_first(&unloadedclasses)) ) {
2615 list_remove (&unloadedclasses,c);
2618 while ( (c=list_first(&unlinkedclasses)) ) {
2619 list_remove (&unlinkedclasses,c);
2622 while ( (c=list_first(&linkedclasses)) ) {
2623 list_remove (&linkedclasses,c);
2630 * These are local overrides for various environment variables in Emacs.
2631 * Please do not remove this and leave it at the end of the file, where
2632 * Emacs will automagically detect them.
2633 * ---------------------------------------------------------------------
2636 * indent-tabs-mode: t