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 "toolbox/loging.h"
39 #include "threads/thread.h"
42 /* global variables ***********************************************************/
44 extern bool newcompiler; /* true if new compiler is used */
45 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
46 bool opt_xta = false; /* true if XTA parse should be used XTA-CO */
47 bool opt_vta = false; /* true if VTA parse should be used VTA-CO */
49 int count_class_infos = 0; /* variables for measurements */
50 int count_const_pool_len = 0;
51 int count_vftbl_len = 0;
52 int count_all_methods = 0;
53 int count_vmcode_len = 0;
54 int count_extable_len = 0;
55 int count_class_loads = 0;
56 int count_class_inits = 0;
58 bool loadverbose = false; /* switches for debug messages */
59 bool linkverbose = false;
60 bool initverbose = false;
62 bool makeinitializations = true;
64 bool getloadingtime = false; /* to measure the runtime */
65 long int loadingtime = 0;
67 static s4 interfaceindex; /* sequential numbering of interfaces */
69 list unloadedclasses; /* list of all referenced but not loaded classes */
70 list unlinkedclasses; /* list of all loaded but not linked classes */
71 list linkedclasses; /* list of all completely linked classes */
74 /* utf-symbols for pointer comparison of frequently used strings */
76 static utf *utf_innerclasses; /* InnerClasses */
77 static utf *utf_constantvalue; /* ConstantValue */
78 static utf *utf_code; /* Code */
79 static utf *utf_finalize; /* finalize */
80 static utf *utf_fidesc; /* ()V */
81 static utf *utf_clinit; /* <clinit> */
82 static utf *utf_initsystemclass; /* initializeSystemClass */
83 static utf *utf_systemclass; /* java/lang/System */
86 /* important system classes ***************************************************/
88 classinfo *class_java_lang_Object;
89 classinfo *class_java_lang_String;
90 classinfo *class_array = NULL;
93 /* These are made static so they cannot be used for throwing in native */
95 static classinfo *class_java_lang_ClassCastException;
96 static classinfo *class_java_lang_NullPointerException;
97 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
98 static classinfo *class_java_lang_NegativeArraySizeException;
99 static classinfo *class_java_lang_OutOfMemoryError;
100 static classinfo *class_java_lang_ArithmeticException;
101 static classinfo *class_java_lang_ArrayStoreException;
102 static classinfo *class_java_lang_ThreadDeath;
105 /******************************************************************************
107 structure for primitive classes: contains the class for wrapping the
108 primitive type, the primitive class, the name of the class for wrapping,
109 the one character type signature and the name of the primitive class
111 ******************************************************************************/
113 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
114 { NULL, NULL, "java/lang/Double", 'D', "double" },
115 { NULL, NULL, "java/lang/Float", 'F', "float" },
116 { NULL, NULL, "java/lang/Character", 'C', "char" },
117 { NULL, NULL, "java/lang/Integer", 'I', "int" },
118 { NULL, NULL, "java/lang/Long", 'J', "long" },
119 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
120 { NULL, NULL, "java/lang/Short", 'S', "short" },
121 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
122 { NULL, NULL, "java/lang/Void", 'V', "void" }};
125 /* instances of important system classes **************************************/
127 java_objectheader *proto_java_lang_ClassCastException;
128 java_objectheader *proto_java_lang_NullPointerException;
129 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
130 java_objectheader *proto_java_lang_NegativeArraySizeException;
131 java_objectheader *proto_java_lang_OutOfMemoryError;
132 java_objectheader *proto_java_lang_ArithmeticException;
133 java_objectheader *proto_java_lang_ArrayStoreException;
134 java_objectheader *proto_java_lang_ThreadDeath;
137 /************* functions for reading classdata *********************************
139 getting classdata in blocks of variable size
140 (8,16,32,64-bit integer or float)
142 *******************************************************************************/
144 static char *classpath = ""; /* searchpath for classfiles */
145 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
146 static u1 *classbuf_pos; /* current position in classfile buffer */
147 static int classbuffer_size; /* size of classfile-data */
149 /* transfer block of classfile data into a buffer */
151 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
154 /* skip block of classfile data */
156 #define skip_nbytes(len) classbuf_pos+=len;
160 return *++classbuf_pos;
164 u1 a=suck_u1(), b=suck_u1();
165 return ((u2)a<<8)+(u2)b;
169 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
170 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
172 #define suck_s8() (s8) suck_u8()
173 #define suck_s2() (s2) suck_u2()
174 #define suck_s4() (s4) suck_u4()
175 #define suck_s1() (s1) suck_u1()
178 /* get u8 from classfile data */
186 return (hi<<32) + lo;
195 /* get float from classfile data */
197 static float suck_float ()
204 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
205 memcpy ( (u1*) (&f), buffer, 4);
207 suck_nbytes ( (u1*) (&f), 4 );
210 PANICIF (sizeof(float) != 4, "Incompatible float-format");
215 /* get double from classfile data */
216 static double suck_double ()
223 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
224 memcpy ( (u1*) (&d), buffer, 8);
226 suck_nbytes ( (u1*) (&d), 8 );
229 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
234 /************************** function suck_init *********************************
236 called once at startup, sets the searchpath for the classfiles
238 *******************************************************************************/
240 void suck_init (char *cpath)
247 /************************** function suck_start ********************************
249 returns true if classbuffer is already loaded or a file for the
250 specified class has succussfully been read in. All directories of
251 the searchpath are used to find the classfile (<classname>.class).
252 Returns false if no classfile is found and writes an error message.
254 *******************************************************************************/
257 bool suck_start (utf *classname) {
259 #define MAXFILENAME 1000 /* maximum length of a filename */
261 char filename[MAXFILENAME+10]; /* room for '.class' */
262 char *pathpos; /* position in searchpath */
263 char c, *utf_ptr; /* pointer to the next utf8-character */
265 int filenamelen, err;
268 if (classbuffer) /* classbuffer is already valid */
275 /* skip path separator */
277 while (*pathpos == ':')
280 /* extract directory from searchpath */
283 while ((*pathpos) && (*pathpos!=':')) {
284 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
285 filename[filenamelen++] = *(pathpos++);
288 filename[filenamelen++] = '/';
290 /* add classname to filename */
292 utf_ptr = classname->text;
293 while (utf_ptr < utf_end(classname)) {
294 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
296 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
298 filename[filenamelen++] = c;
303 strcpy (filename+filenamelen, ".class");
305 classfile = fopen(filename, "r");
306 if (classfile) { /* file exists */
308 /* determine size of classfile */
310 err = stat (filename, &buffer);
312 if (!err) { /* read classfile data */
313 classbuffer_size = buffer.st_size;
314 classbuffer = MNEW(u1, classbuffer_size);
315 classbuf_pos = classbuffer-1;
316 fread(classbuffer, 1, classbuffer_size, classfile);
324 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
332 /************************** function suck_stop *********************************
334 frees memory for buffer with classfile data.
335 Caution: this function may only be called if buffer has been allocated
336 by suck_start with reading a file
338 *******************************************************************************/
342 /* determine amount of classdata not retrieved by suck-operations */
344 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
346 if (classdata_left > 0) {
348 sprintf (logtext,"There are %d access bytes at end of classfile",
355 MFREE(classbuffer, u1, classbuffer_size);
359 /******************************************************************************/
360 /******************* Some support functions ***********************************/
361 /******************************************************************************/
365 void fprintflags (FILE *fp, u2 f)
367 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
368 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
369 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
370 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
371 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
372 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
373 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
374 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
375 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
376 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
377 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
380 /********** internal function: printflags (only for debugging) ***************/
381 void printflags (u2 f)
383 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
384 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
385 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
386 if ( f & ACC_STATIC ) printf (" STATIC");
387 if ( f & ACC_FINAL ) printf (" FINAL");
388 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
389 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
390 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
391 if ( f & ACC_NATIVE ) printf (" NATIVE");
392 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
393 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
397 /************************* Function: skipattribute *****************************
399 skips a (1) 'attribute' structure in the class file
401 *******************************************************************************/
403 static void skipattribute ()
406 skip_nbytes(suck_u4());
409 /********************** Function: skipattributebody ****************************
411 skips an attribute after the 16 bit reference to attribute_name has already
414 *******************************************************************************/
416 static void skipattributebody ()
418 skip_nbytes(suck_u4());
421 /************************* Function: skipattributes ****************************
423 skips num attribute structures
425 *******************************************************************************/
427 static void skipattributes (u4 num)
430 for (i = 0; i < num; i++)
434 /******************** function: innerclass_getconstant ************************
436 like class_getconstant, but if cptags is ZERO null is returned
438 *******************************************************************************/
440 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
442 /* invalid position in constantpool */
443 if (pos >= c->cpcount)
444 panic ("Attempt to access constant outside range");
446 /* constantpool entry of type 0 */
450 /* check type of constantpool entry */
451 if (c->cptags[pos] != ctype) {
452 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
453 (int) ctype, (int) c->cptags[pos] );
457 return c->cpinfos[pos];
460 /************************ function: attribute_load ****************************
462 read attributes from classfile
464 *******************************************************************************/
466 static void attribute_load (u4 num, classinfo *c)
470 for (i = 0; i < num; i++) {
471 /* retrieve attribute name */
472 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
474 if ( aname == utf_innerclasses) {
475 /* innerclasses attribute */
477 /* skip attribute length */
479 /* number of records */
480 c->innerclasscount = suck_u2();
481 /* allocate memory for innerclass structure */
482 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
484 for (j=0;j<c->innerclasscount;j++) {
486 /* The innerclass structure contains a class with an encoded name,
487 its defining scope, its simple name and a bitmask of the access flags.
488 If an inner class is not a member, its outer_class is NULL,
489 if a class is anonymous, its name is NULL. */
491 innerclassinfo *info = c->innerclass + j;
493 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
494 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
495 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
496 info->flags = suck_u2 (); /* access_flags bitmask */
499 /* unknown attribute */
500 skipattributebody ();
505 /******************* function: checkfielddescriptor ****************************
507 checks whether a field-descriptor is valid and aborts otherwise
508 all referenced classes are inserted into the list of unloaded classes
510 *******************************************************************************/
512 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
514 char *tstart; /* pointer to start of classname */
517 switch (*utf_ptr++) {
530 /* save start of classname */
533 /* determine length of classname */
534 while ( *utf_ptr++ != ';' )
535 if (utf_ptr>=end_pos)
536 panic ("Missing ';' in objecttype-descriptor");
538 /* cause loading of referenced class */
539 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
544 while ((ch = *utf_ptr++)=='[')
547 /* component type of array */
561 /* save start of classname */
564 /* determine length of classname */
565 while ( *utf_ptr++ != ';' )
566 if (utf_ptr>=end_pos)
567 panic ("Missing ';' in objecttype-descriptor");
569 /* cause loading of referenced class */
570 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
574 panic ("Ill formed methodtype-descriptor");
579 panic ("Ill formed methodtype-descriptor");
582 /* exceeding characters */
583 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
587 /******************* function checkmethoddescriptor ****************************
589 checks whether a method-descriptor is valid and aborts otherwise.
590 All referenced classes are inserted into the list of unloaded classes.
592 *******************************************************************************/
594 static void checkmethoddescriptor (utf *d)
596 char *utf_ptr = d->text; /* current position in utf text */
597 char *end_pos = utf_end(d); /* points behind utf string */
598 char *tstart; /* pointer to start of classname */
601 /* method descriptor must start with parenthesis */
602 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
604 /* check arguments */
605 while ((c = *utf_ptr++) != ')') {
619 /* save start of classname */
622 /* determine length of classname */
623 while ( *utf_ptr++ != ';' )
624 if (utf_ptr>=end_pos)
625 panic ("Missing ';' in objecttype-descriptor");
627 /* cause loading of referenced class */
628 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
633 while ((ch = *utf_ptr++)=='[')
636 /* component type of array */
650 /* save start of classname */
653 /* determine length of classname */
654 while ( *utf_ptr++ != ';' )
655 if (utf_ptr>=end_pos)
656 panic ("Missing ';' in objecttype-descriptor");
658 /* cause loading of referenced class */
659 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
663 panic ("Ill formed methodtype-descriptor");
668 panic ("Ill formed methodtype-descriptor");
672 /* check returntype */
674 /* returntype void */
675 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
678 /* treat as field-descriptor */
679 checkfielddescriptor (utf_ptr,end_pos);
683 /******************** Function: buildarraydescriptor ***************************
685 creates a constant_arraydescriptor structure for the array type named by an
688 *******************************************************************************/
690 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
692 constant_arraydescriptor *d;
694 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
696 d = NEW (constant_arraydescriptor);
697 d -> objectclass = NULL;
698 d -> elementdescriptor = NULL;
701 count_const_pool_len += sizeof(constant_arraydescriptor);
705 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
706 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
707 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
708 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
709 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
710 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
711 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
712 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
715 d -> arraytype = ARRAYTYPE_ARRAY;
716 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
720 d -> arraytype = ARRAYTYPE_OBJECT;
722 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
723 d -> objectclass -> classUsed = NOTUSED; /* not used initially CO-RT */
724 d -> objectclass -> impldBy = NULL;
731 /******************* Function: freearraydescriptor *****************************
733 removes a structure created by buildarraydescriptor from memory
735 *******************************************************************************/
737 static void freearraydescriptor (constant_arraydescriptor *d)
740 constant_arraydescriptor *n = d->elementdescriptor;
741 FREE (d, constant_arraydescriptor);
746 /*********************** Function: displayarraydescriptor *********************/
748 static void displayarraydescriptor (constant_arraydescriptor *d)
750 switch (d->arraytype) {
751 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
752 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
753 case ARRAYTYPE_CHAR: printf ("char[]"); break;
754 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
755 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
756 case ARRAYTYPE_INT: printf ("int[]"); break;
757 case ARRAYTYPE_LONG: printf ("long[]"); break;
758 case ARRAYTYPE_SHORT: printf ("short[]"); break;
759 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
760 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
766 /******************************************************************************/
767 /************************** Functions for fields ****************************/
768 /******************************************************************************/
771 /************************ Function: field_load *********************************
773 Load everything about a class field from the class file and fill a
774 'fieldinfo' structure. For static fields, space in the data segment is
777 *******************************************************************************/
779 static void field_load (fieldinfo *f, classinfo *c)
784 f -> flags = suck_u2 (); /* ACC flags */
785 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
786 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
787 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
788 f -> offset = 0; /* offset from start of object */
789 f -> fieldUsed = NOTUSED; /*XTA*/
790 f -> fldClassType = NULL; /*XTA*/
791 f -> XTAclassSet = NULL; /*XTA*/
792 f -> lastRoundChgd = -1;
795 case TYPE_INT: f->value.i = 0; break;
796 case TYPE_FLOAT: f->value.f = 0.0; break;
797 case TYPE_DOUBLE: f->value.d = 0.0; break;
798 case TYPE_ADDRESS: f->value.a = NULL;
799 heap_addreference (&(f->value.a)); /* make global reference (GC) */
803 f->value.l = 0; break;
805 f->value.l.low = 0; f->value.l.high = 0; break;
809 /* read attributes */
811 for (i=0; i<attrnum; i++) {
815 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
817 if ( aname != utf_constantvalue ) {
818 /* unknown attribute */
819 skipattributebody ();
822 /* constant value attribute */
824 /* skip attribute length */
826 /* index of value in constantpool */
829 /* initialize field with value from constantpool */
832 constant_integer *ci =
833 class_getconstant(c, pindex, CONSTANT_Integer);
834 f->value.i = ci -> value;
840 class_getconstant(c, pindex, CONSTANT_Long);
842 f->value.l = cl -> value;
848 class_getconstant(c, pindex, CONSTANT_Float);
850 f->value.f = cf->value;
855 constant_double *cd =
856 class_getconstant(c, pindex, CONSTANT_Double);
858 f->value.d = cd->value;
863 utf *u = class_getconstant(c, pindex, CONSTANT_String);
864 /* create javastring from compressed utf8-string */
865 f->value.a = literalstring_new(u);
870 log_text ("Invalid Constant - Type");
879 /********************** function: field_free **********************************/
881 static void field_free (fieldinfo *f)
887 /**************** Function: field_display (debugging only) ********************/
889 void field_display (fieldinfo *f)
892 printflags (f -> flags);
894 utf_display (f -> name);
896 utf_display (f -> descriptor);
897 printf (" offset: %ld\n", (long int) (f -> offset) );
901 /******************************************************************************/
902 /************************* Functions for methods ******************************/
903 /******************************************************************************/
906 /*********************** Function: method_load *********************************
908 Loads a method from the class file and fills an existing 'methodinfo'
909 structure. For native methods, the function pointer field is set to the
910 real function pointer, for JavaVM methods a pointer to the compiler is used
913 *******************************************************************************/
915 static void method_load (methodinfo *m, classinfo *c)
925 m -> flags = suck_u2 ();
926 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
927 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
930 m -> exceptiontable = NULL;
931 m -> entrypoint = NULL;
933 m -> stubroutine = NULL;
934 m -> methodUsed = NOTUSED;
935 m -> XTAmethodUsed = NOTUSED;
936 m -> monoPoly = MONO;
938 m -> subRedefsUsed = 0;
942 m -> XTAclassSet = NULL; /*XTA*/
943 m -> paramClassSet = NULL; /*XTA*/
944 m -> calls = NULL; /*XTA*/
945 m -> calledBy = NULL; /*XTA*/
946 m -> chgdSinceLastParse = false; /*XTA*/
948 m -> marked = NULL; /*XTA*/
949 m -> markedBy = NULL; /*XTA*/
950 m -> fldsUsed = NULL; /*XTA*/
951 m -> interfaceCalls = NULL; /*XTA*/
952 m -> lastRoundParsed = -1;
953 m -> interfaceCalls = NULL; /*XTA*/
956 if (! (m->flags & ACC_NATIVE) ) {
957 m -> stubroutine = createcompilerstub (m);
961 functionptr f = native_findfunction
962 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
967 m -> stubroutine = createnativestub (f, m);
970 m -> stubroutine = oldcreatenativestub (f, m);
977 for (i=0; i<attrnum; i++) {
980 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
982 if ( aname != utf_code) {
983 skipattributebody ();
986 if (m -> jcode) panic ("Two code-attributes for one method!");
989 m -> maxstack = suck_u2();
990 m -> maxlocals = suck_u2();
991 m -> jcodelength = suck_u4();
992 m -> jcode = MNEW (u1, m->jcodelength);
993 suck_nbytes (m->jcode, m->jcodelength);
994 m -> exceptiontablelength = suck_u2 ();
995 m -> exceptiontable =
996 MNEW (exceptiontable, m->exceptiontablelength);
999 count_vmcode_len += m->jcodelength + 18;
1000 count_extable_len += 8 * m->exceptiontablelength;
1003 for (e=0; e < m->exceptiontablelength; e++) {
1005 m -> exceptiontable[e].startpc = suck_u2();
1006 m -> exceptiontable[e].endpc = suck_u2();
1007 m -> exceptiontable[e].handlerpc = suck_u2();
1010 if (!idx) m -> exceptiontable[e].catchtype = NULL;
1012 m -> exceptiontable[e].catchtype =
1013 class_getconstant (c, idx, CONSTANT_Class);
1017 skipattributes ( suck_u2() );
1024 /********************* Function: method_free ***********************************
1026 frees all memory that was allocated for this method
1028 *******************************************************************************/
1030 static void method_free (methodinfo *m)
1032 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
1033 if (m->exceptiontable)
1034 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
1035 if (m->mcode) CFREE (m->mcode, m->mcodelength);
1036 if (m->stubroutine) {
1037 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
1038 else removecompilerstub (m->stubroutine);
1043 /************** Function: method_display (debugging only) **************/
1045 void method_display (methodinfo *m)
1048 printflags (m -> flags);
1050 utf_display (m -> name);
1052 utf_display (m -> descriptor);
1057 /******************** Function: method_canoverwrite ****************************
1059 Check if m and old are identical with respect to type and name. This means
1060 that old can be overwritten with m.
1062 *******************************************************************************/
1064 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1066 if (m->name != old->name) return false;
1067 if (m->descriptor != old->descriptor) return false;
1068 if (m->flags & ACC_STATIC) return false;
1075 /******************************************************************************/
1076 /************************ Functions for class *********************************/
1077 /******************************************************************************/
1080 /******************** function:: class_getconstant ******************************
1082 retrieves the value at position 'pos' of the constantpool of a class
1083 if the type of the value is other than 'ctype' the system is stopped
1085 *******************************************************************************/
1087 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1089 /* invalid position in constantpool */
1090 if (pos >= c->cpcount)
1091 panic ("Attempt to access constant outside range");
1093 /* check type of constantpool entry */
1094 if (c->cptags[pos] != ctype) {
1095 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1096 (int) ctype, (int) c->cptags[pos] );
1100 return c->cpinfos[pos];
1104 /********************* Function: class_constanttype ****************************
1106 Determines the type of a class entry in the ConstantPool
1108 *******************************************************************************/
1110 u4 class_constanttype (classinfo *c, u4 pos)
1112 if (pos >= c->cpcount)
1113 panic ("Attempt to access constant outside range");
1114 return c->cptags[pos];
1118 /******************** function: class_loadcpool ********************************
1120 loads the constantpool of a class,
1121 the entries are transformed into a simpler format
1122 by resolving references
1123 (a detailed overview of the compact structures can be found in global.h)
1125 *******************************************************************************/
1127 static void class_loadcpool (classinfo *c)
1130 /* The following structures are used to save information which cannot be
1131 processed during the first pass. After the complete constantpool has
1132 been traversed the references can be resolved.
1133 (only in specific order) */
1135 /* CONSTANT_Class_info entries */
1136 typedef struct forward_class {
1137 struct forward_class *next;
1142 /* CONSTANT_String */
1143 typedef struct forward_string {
1144 struct forward_string *next;
1149 /* CONSTANT_NameAndType */
1150 typedef struct forward_nameandtype {
1151 struct forward_nameandtype *next;
1155 } forward_nameandtype;
1157 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1158 typedef struct forward_fieldmethint {
1159 struct forward_fieldmethint *next;
1163 u2 nameandtype_index;
1164 } forward_fieldmethint;
1168 long int dumpsize = dump_size ();
1170 forward_class *forward_classes = NULL;
1171 forward_string *forward_strings = NULL;
1172 forward_nameandtype *forward_nameandtypes = NULL;
1173 forward_fieldmethint *forward_fieldmethints = NULL;
1175 /* number of entries in the constant_pool table */
1176 u4 cpcount = c -> cpcount = suck_u2();
1177 /* allocate memory */
1178 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1179 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1182 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1185 /* initialize constantpool */
1186 for (idx=0; idx<cpcount; idx++) {
1187 cptags[idx] = CONSTANT_UNUSED;
1188 cpinfos[idx] = NULL;
1192 /******* first pass *******/
1193 /* entries which cannot be resolved now are written into
1194 temporary structures and traversed again later */
1197 while (idx < cpcount) {
1198 /* get constant type */
1202 case CONSTANT_Class: {
1203 forward_class *nfc = DNEW(forward_class);
1205 nfc -> next = forward_classes;
1206 forward_classes = nfc;
1208 nfc -> thisindex = idx;
1209 /* reference to CONSTANT_NameAndType */
1210 nfc -> name_index = suck_u2 ();
1216 case CONSTANT_Fieldref:
1217 case CONSTANT_Methodref:
1218 case CONSTANT_InterfaceMethodref: {
1219 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1221 nff -> next = forward_fieldmethints;
1222 forward_fieldmethints = nff;
1224 nff -> thisindex = idx;
1227 /* class or interface type that contains the declaration of the field or method */
1228 nff -> class_index = suck_u2 ();
1229 /* name and descriptor of the field or method */
1230 nff -> nameandtype_index = suck_u2 ();
1236 case CONSTANT_String: {
1237 forward_string *nfs = DNEW (forward_string);
1239 nfs -> next = forward_strings;
1240 forward_strings = nfs;
1242 nfs -> thisindex = idx;
1243 /* reference to CONSTANT_Utf8_info with string characters */
1244 nfs -> string_index = suck_u2 ();
1250 case CONSTANT_NameAndType: {
1251 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1253 nfn -> next = forward_nameandtypes;
1254 forward_nameandtypes = nfn;
1256 nfn -> thisindex = idx;
1257 /* reference to CONSTANT_Utf8_info containing simple name */
1258 nfn -> name_index = suck_u2 ();
1259 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1260 nfn -> sig_index = suck_u2 ();
1266 case CONSTANT_Integer: {
1267 constant_integer *ci = NEW (constant_integer);
1270 count_const_pool_len += sizeof(constant_integer);
1273 ci -> value = suck_s4 ();
1274 cptags [idx] = CONSTANT_Integer;
1281 case CONSTANT_Float: {
1282 constant_float *cf = NEW (constant_float);
1285 count_const_pool_len += sizeof(constant_float);
1288 cf -> value = suck_float ();
1289 cptags [idx] = CONSTANT_Float;
1295 case CONSTANT_Long: {
1296 constant_long *cl = NEW(constant_long);
1299 count_const_pool_len += sizeof(constant_long);
1302 cl -> value = suck_s8 ();
1303 cptags [idx] = CONSTANT_Long;
1309 case CONSTANT_Double: {
1310 constant_double *cd = NEW(constant_double);
1313 count_const_pool_len += sizeof(constant_double);
1316 cd -> value = suck_double ();
1317 cptags [idx] = CONSTANT_Double;
1323 case CONSTANT_Utf8: {
1325 /* number of bytes in the bytes array (not string-length) */
1326 u4 length = suck_u2();
1327 cptags [idx] = CONSTANT_Utf8;
1328 /* insert utf-string into the utf-symboltable */
1329 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1330 /* skip bytes of the string */
1331 skip_nbytes(length);
1337 sprintf (logtext, "Unkown constant type: %d",(int) t);
1346 /* resolve entries in temporary structures */
1348 while (forward_classes) {
1350 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1352 if ( (name->blength>0) && (name->text[0]=='[') ) {
1353 /* check validity of descriptor */
1354 checkfielddescriptor (name->text, utf_end(name));
1356 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1357 cpinfos [forward_classes -> thisindex] =
1358 buildarraydescriptor(name->text, name->blength);
1362 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1363 /* retrieve class from class-table */
1364 cpinfos [forward_classes -> thisindex] = class_new (name);
1366 forward_classes = forward_classes -> next;
1370 while (forward_strings) {
1372 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1374 /* resolve utf-string */
1375 cptags [forward_strings -> thisindex] = CONSTANT_String;
1376 cpinfos [forward_strings -> thisindex] = text;
1378 forward_strings = forward_strings -> next;
1381 while (forward_nameandtypes) {
1382 constant_nameandtype *cn = NEW (constant_nameandtype);
1385 count_const_pool_len += sizeof(constant_nameandtype);
1388 /* resolve simple name and descriptor */
1389 cn -> name = class_getconstant
1390 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1391 cn -> descriptor = class_getconstant
1392 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1394 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1395 cpinfos [forward_nameandtypes -> thisindex] = cn;
1397 forward_nameandtypes = forward_nameandtypes -> next;
1401 while (forward_fieldmethints) {
1402 constant_nameandtype *nat;
1403 constant_FMIref *fmi = NEW (constant_FMIref);
1406 count_const_pool_len += sizeof(constant_FMIref);
1408 /* resolve simple name and descriptor */
1409 nat = class_getconstant
1410 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1412 fmi -> class = class_getconstant
1413 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1414 fmi -> name = nat -> name;
1415 fmi -> descriptor = nat -> descriptor;
1417 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1418 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1420 switch (forward_fieldmethints -> tag) {
1421 case CONSTANT_Fieldref: /* check validity of descriptor */
1422 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1424 case CONSTANT_InterfaceMethodref:
1425 case CONSTANT_Methodref: /* check validity of descriptor */
1426 checkmethoddescriptor (fmi->descriptor);
1430 forward_fieldmethints = forward_fieldmethints -> next;
1435 dump_release (dumpsize);
1439 /********************** Function: class_load ***********************************
1441 Loads everything interesting about a class from the class file. The
1442 'classinfo' structure must have been allocated previously.
1444 The super class and the interfaces implemented by this class need not be
1445 loaded. The link is set later by the function 'class_link'.
1447 The loaded class is removed from the list 'unloadedclasses' and added to
1448 the list 'unlinkedclasses'.
1450 *******************************************************************************/
1452 static int class_load (classinfo *c)
1458 count_class_loads++;
1461 /* output for debugging purposes */
1464 sprintf (logtext, "Loading class: ");
1465 utf_sprint (logtext+strlen(logtext), c->name );
1469 /* load classdata, throw exception on error */
1470 if (!suck_start (c->name)) {
1471 throw_classnotfoundexception();
1475 /* check signature */
1476 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1480 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1481 sprintf (logtext, "File version %d.%d is not supported",
1482 (int) ma, (int) mi);
1487 class_loadcpool (c);
1489 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1490 c -> impldBy = NULL;
1493 c -> flags = suck_u2 ();
1497 /* retrieve superclass */
1498 if ( (i = suck_u2 () ) ) {
1499 c -> super = class_getconstant (c, i, CONSTANT_Class);
1505 /* retrieve interfaces */
1506 c -> interfacescount = suck_u2 ();
1507 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1508 for (i=0; i < c -> interfacescount; i++) {
1509 c -> interfaces [i] =
1510 class_getconstant (c, suck_u2(), CONSTANT_Class);
1514 c -> fieldscount = suck_u2 ();
1516 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1518 c -> fields = MNEW (fieldinfo, c -> fieldscount);
1520 for (i=0; i < c -> fieldscount; i++) {
1521 field_load (&(c->fields[i]), c);
1525 c -> methodscount = suck_u2 ();
1526 c -> methods = MNEW (methodinfo, c -> methodscount);
1527 for (i=0; i < c -> methodscount; i++) {
1528 method_load (&(c -> methods [i]), c);
1532 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1533 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1534 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1537 /* load variable-length attribute structures */
1538 attribute_load (suck_u2(), c);
1543 /* remove class from list of unloaded classes and
1544 add to list of unlinked classes */
1545 list_remove (&unloadedclasses, c);
1546 list_addlast (&unlinkedclasses, c);
1553 /************** internal Function: class_highestinterface ***********************
1555 Used by the function class_link to determine the amount of memory needed
1556 for the interface table.
1558 *******************************************************************************/
1560 static s4 class_highestinterface (classinfo *c)
1565 if ( ! (c->flags & ACC_INTERFACE) ) {
1566 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1567 utf_sprint (logtext+strlen(logtext), c->name);
1572 for (i=0; i<c->interfacescount; i++) {
1573 s4 h2 = class_highestinterface (c->interfaces[i]);
1580 /* class_addinterface **********************************************************
1582 Is needed by class_link for adding a VTBL to a class. All interfaces
1583 implemented by ic are added as well.
1585 *******************************************************************************/
1587 static void class_addinterface (classinfo *c, classinfo *ic)
1591 vftbl *vftbl = c->vftbl;
1593 if (i >= vftbl->interfacetablelength)
1594 panic ("Inernal error: interfacetable overflow");
1595 if (vftbl->interfacetable[-i])
1598 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1599 vftbl->interfacevftbllength[i] = 1;
1600 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1601 vftbl->interfacetable[-i][0] = NULL;
1604 vftbl->interfacevftbllength[i] = ic->methodscount;
1605 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1608 count_vftbl_len += sizeof(methodptr) *
1609 (ic->methodscount + (ic->methodscount == 0));
1612 for (j=0; j<ic->methodscount; j++) {
1615 for (m = 0; m < sc->methodscount; m++) {
1616 methodinfo *mi = &(sc->methods[m]);
1617 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1618 vftbl->interfacetable[-i][j] =
1619 vftbl->table[mi->vftblindex];
1629 for (j = 0; j < ic->interfacescount; j++)
1630 class_addinterface(c, ic->interfaces[j]);
1634 /********************** Function: class_link ***********************************
1636 Tries to link a class. The super class and every implemented interface must
1637 already have been linked. The function calculates the length in bytes that
1638 an instance of this class requires as well as the VTBL for methods and
1641 If the class can be linked, it is removed from the list 'unlinkedclasses'
1642 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1645 Attention: If cyclical class definitions are encountered, the program gets
1646 into an infinite loop (we'll have to work that out)
1648 *******************************************************************************/
1650 static void class_link (classinfo *c)
1652 s4 supervftbllength; /* vftbllegnth of super class */
1653 s4 vftbllength; /* vftbllength of current class */
1654 s4 interfacetablelength; /* interface table length */
1655 classinfo *super = c->super; /* super class */
1656 classinfo *ic, *c2; /* intermediate class variables */
1657 vftbl *v; /* vftbl of current class */
1658 s4 i; /* interface/method/field counter */
1661 /* check if all superclasses are already linked, if not put c at end of
1662 unlinked list and return. Additionally initialize class fields. */
1664 /* check interfaces */
1666 for (i = 0; i < c->interfacescount; i++) {
1667 ic = c->interfaces[i];
1669 list_remove(&unlinkedclasses, c);
1670 list_addlast(&unlinkedclasses, c);
1675 /* check super class */
1677 if (super == NULL) { /* class java.long.Object */
1679 c->classUsed = USED; /* Object class is always used CO-RT*/
1680 c -> impldBy = NULL;
1681 c->instancesize = sizeof(java_objectheader);
1683 vftbllength = supervftbllength = 0;
1685 c->finalizer = NULL;
1688 if (!super->linked) {
1689 list_remove(&unlinkedclasses, c);
1690 list_addlast(&unlinkedclasses, c);
1694 if (c->flags & ACC_INTERFACE)
1695 c->index = interfaceindex++;
1697 c->index = super->index + 1;
1699 c->instancesize = super->instancesize;
1701 vftbllength = supervftbllength = super->vftbl->vftbllength;
1703 c->finalizer = super->finalizer;
1708 sprintf (logtext, "Linking Class: ");
1709 utf_sprint (logtext+strlen(logtext), c->name );
1713 /* compute vftbl length */
1715 for (i = 0; i < c->methodscount; i++) {
1716 methodinfo *m = &(c->methods[i]);
1718 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1719 classinfo *sc = super;
1722 for (j = 0; j < sc->methodscount; j++) {
1723 if (method_canoverwrite(m, &(sc->methods[j]))) {
1724 m->vftblindex = sc->methods[j].vftblindex;
1725 goto foundvftblindex;
1730 m->vftblindex = (vftbllength++);
1736 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1739 /* compute interfacetable length */
1741 interfacetablelength = 0;
1744 for (i = 0; i < c2->interfacescount; i++) {
1745 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1746 if (h > interfacetablelength)
1747 interfacetablelength = h;
1752 /* allocate virtual function table */
1754 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1755 (vftbllength - 1) + sizeof(methodptr*) *
1756 (interfacetablelength - (interfacetablelength > 0)));
1757 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1758 (interfacetablelength > 1));
1759 c->header.vftbl = c->vftbl = v;
1761 v->vftbllength = vftbllength;
1762 v->interfacetablelength = interfacetablelength;
1764 /* copy virtual function table of super class */
1766 for (i = 0; i < supervftbllength; i++)
1767 v->table[i] = super->vftbl->table[i];
1769 /* add method stubs into virtual function table */
1771 for (i = 0; i < c->methodscount; i++) {
1772 methodinfo *m = &(c->methods[i]);
1773 if (!(m->flags & ACC_STATIC)) {
1774 v->table[m->vftblindex] = m->stubroutine;
1778 /* compute instance size and offset of each field */
1780 for (i = 0; i < c->fieldscount; i++) {
1782 fieldinfo *f = &(c->fields[i]);
1784 if (!(f->flags & ACC_STATIC) ) {
1785 dsize = desc_typesize (f->descriptor);
1786 c->instancesize = ALIGN (c->instancesize, dsize);
1787 f->offset = c->instancesize;
1788 c->instancesize += dsize;
1792 /* initialize interfacetable and interfacevftbllength */
1794 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1797 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1800 for (i = 0; i < interfacetablelength; i++) {
1801 v->interfacevftbllength[i] = 0;
1802 v->interfacetable[-i] = NULL;
1805 /* add interfaces */
1807 for (c2 = c; c2 != NULL; c2 = c2->super)
1808 for (i = 0; i < c2->interfacescount; i++) {
1809 class_addinterface (c, c2->interfaces[i]);
1812 /* add finalizer method (not for java.lang.Object) */
1814 if (super != NULL) {
1816 static utf *finame = NULL;
1817 static utf *fidesc = NULL;
1820 finame = utf_finalize;
1822 fidesc = utf_fidesc;
1824 fi = class_findmethod (c, finame, fidesc);
1826 if (!(fi->flags & ACC_STATIC)) {
1836 list_remove (&unlinkedclasses, c);
1837 list_addlast (&linkedclasses, c);
1841 /******************* Function: class_freepool **********************************
1843 Frees all resources used by this classes Constant Pool.
1845 *******************************************************************************/
1847 static void class_freecpool (classinfo *c)
1853 for (idx=0; idx < c->cpcount; idx++) {
1854 tag = c->cptags[idx];
1855 info = c->cpinfos[idx];
1859 case CONSTANT_Fieldref:
1860 case CONSTANT_Methodref:
1861 case CONSTANT_InterfaceMethodref:
1862 FREE (info, constant_FMIref);
1864 case CONSTANT_Integer:
1865 FREE (info, constant_integer);
1867 case CONSTANT_Float:
1868 FREE (info, constant_float);
1871 FREE (info, constant_long);
1873 case CONSTANT_Double:
1874 FREE (info, constant_double);
1876 case CONSTANT_NameAndType:
1877 FREE (info, constant_nameandtype);
1879 case CONSTANT_Arraydescriptor:
1880 freearraydescriptor (info);
1886 MFREE (c -> cptags, u1, c -> cpcount);
1887 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1891 /*********************** Function: class_free **********************************
1893 Frees all resources used by the class.
1895 *******************************************************************************/
1897 static void class_free (classinfo *c)
1902 class_freecpool (c);
1904 MFREE (c->interfaces, classinfo*, c->interfacescount);
1906 for (i = 0; i < c->fieldscount; i++)
1907 field_free(&(c->fields[i]));
1909 MFREE (c->fields, fieldinfo, c->fieldscount);
1912 for (i = 0; i < c->methodscount; i++)
1913 method_free(&(c->methods[i]));
1914 MFREE (c->methods, methodinfo, c->methodscount);
1916 if ((v = c->vftbl) != NULL) {
1917 for (i = 0; i < v->interfacetablelength; i++) {
1918 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1920 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1922 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1923 sizeof(methodptr*) * (v->interfacetablelength -
1924 (v->interfacetablelength > 0));
1925 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1926 (v->interfacetablelength > 1));
1930 if (c->innerclasscount)
1931 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1934 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1));
1936 FREE (c, classinfo);
1939 /************************* Function: class_findfield ***************************
1941 Searches a 'classinfo' structure for a field having the given name and
1944 *******************************************************************************/
1947 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1951 for (i = 0; i < c->fieldscount; i++) {
1952 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1953 return &(c->fields[i]);
1956 panic ("Can not find field given in CONSTANT_Fieldref");
1961 /************************* Function: class_findmethod **************************
1963 Searches a 'classinfo' structure for a method having the given name and
1965 If type is NULL, it is ignored.
1967 *******************************************************************************/
1969 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1972 for (i = 0; i < c->methodscount; i++) {
1973 if ((c->methods[i].name == name) && ((desc == NULL) ||
1974 (c->methods[i].descriptor == desc)))
1975 return &(c->methods[i]);
1980 /************************* Function: class_findmethod_approx ******************
1982 like class_findmethod but ignores the return value when comparing the
1985 *******************************************************************************/
1987 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1991 for (i = 0; i < c->methodscount; i++)
1992 if (c->methods[i].name == name) {
1993 utf *meth_descr = c->methods[i].descriptor;
1997 return &(c->methods[i]);
1999 if (desc->blength <= meth_descr->blength) {
2000 /* current position in utf text */
2001 char *desc_utf_ptr = desc->text;
2002 char *meth_utf_ptr = meth_descr->text;
2003 /* points behind utf strings */
2004 char *desc_end = utf_end(desc);
2005 char *meth_end = utf_end(meth_descr);
2008 /* compare argument types */
2009 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2011 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2012 break; /* no match */
2015 return &(c->methods[i]); /* all parameter types equal */
2023 /***************** Function: class_resolvemethod_approx ***********************
2025 Searches a class and every super class for a method (without paying
2026 attention to the return value)
2028 *******************************************************************************/
2030 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2033 /* search for method (ignore returntype) */
2034 methodinfo *m = class_findmethod_approx (c, name, desc);
2037 /* search superclass */
2044 /************************* Function: class_resolvemethod ***********************
2046 Searches a class and every super class for a method.
2048 *******************************************************************************/
2051 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2054 methodinfo *m = class_findmethod (c, name, desc);
2056 /* search superclass */
2064 /************************* Function: class_issubclass **************************
2066 Checks if sub is a descendant of super.
2068 *******************************************************************************/
2070 bool class_issubclass (classinfo *sub, classinfo *super)
2073 if (!sub) return false;
2074 if (sub==super) return true;
2081 /****************** Initialization function for classes ******************
2083 In Java, every class can have a static initialization function. This
2084 function has to be called BEFORE calling other methods or accessing static
2087 *******************************************************************************/
2090 extern int blockInts;
2093 void class_init (classinfo *c)
2096 java_objectheader *exceptionptr;
2101 if (!makeinitializations)
2105 c -> initialized = true;
2108 count_class_inits++;
2112 class_init (c->super);
2113 for (i=0; i < c->interfacescount; i++)
2114 class_init(c->interfaces[i]); /* real */
2116 m = class_findmethod (c, utf_clinit, utf_fidesc);
2119 sprintf (logtext, "Class ");
2120 utf_sprint (logtext+strlen(logtext), c->name);
2121 sprintf (logtext+strlen(logtext), " has no initializer");
2127 if (! (m->flags & ACC_STATIC))
2128 panic ("Class initializer is not static!");
2131 sprintf (logtext, "Starting initializer for class: ");
2132 utf_sprint (logtext+strlen(logtext), c->name);
2141 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2144 assert(blockInts == 0);
2149 printf ("#### Initializer of ");
2150 utf_display (c->name);
2151 printf (" has thrown: ");
2152 utf_display (exceptionptr->vftbl->class->name);
2158 sprintf (logtext, "Finished initializer for class: ");
2159 utf_sprint (logtext+strlen(logtext), c->name);
2163 if (c->name == utf_systemclass) {
2164 /* class java.lang.System requires explicit initialization */
2167 printf ("#### Initializing class System");
2169 /* find initializing method */
2170 m = class_findmethod (c,
2171 utf_initsystemclass,
2175 /* no method found */
2176 printf("initializeSystemClass failed");
2185 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2188 assert(blockInts == 0);
2193 printf ("#### initializeSystemClass has thrown: ");
2194 utf_display (exceptionptr->vftbl->class->name);
2204 /********* Function: find_class_method_constant *********/
2205 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2211 for (i=0; i<c->cpcount; i++) {
2213 e = c -> cpinfos [i];
2216 switch (c -> cptags [i]) {
2217 case CONSTANT_Methodref:
2219 constant_FMIref *fmi = e;
2220 if ( (fmi->class->name == c1)
2221 && (fmi->name == m1)
2222 && (fmi->descriptor == d1)) {
2228 case CONSTANT_InterfaceMethodref:
2230 constant_FMIref *fmi = e;
2231 if ( (fmi->class->name == c1)
2232 && (fmi->name == m1)
2233 && (fmi->descriptor == d1)) {
2249 void class_showconstanti(classinfo *c, int ii)
2255 e = c -> cpinfos [i];
2256 printf ("#%d: ", (int) i);
2258 switch (c -> cptags [i]) {
2259 case CONSTANT_Class:
2260 printf ("Classreference -> ");
2261 utf_display ( ((classinfo*)e) -> name );
2264 case CONSTANT_Fieldref:
2265 printf ("Fieldref -> "); goto displayFMIi;
2266 case CONSTANT_Methodref:
2267 printf ("Methodref -> "); goto displayFMIi;
2268 case CONSTANT_InterfaceMethodref:
2269 printf ("InterfaceMethod -> "); goto displayFMIi;
2272 constant_FMIref *fmi = e;
2273 utf_display ( fmi->class->name );
2275 utf_display ( fmi->name);
2277 utf_display ( fmi->descriptor );
2281 case CONSTANT_String:
2282 printf ("String -> ");
2285 case CONSTANT_Integer:
2286 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2288 case CONSTANT_Float:
2289 printf ("Float -> %f", ((constant_float*)e) -> value);
2291 case CONSTANT_Double:
2292 printf ("Double -> %f", ((constant_double*)e) -> value);
2296 u8 v = ((constant_long*)e) -> value;
2298 printf ("Long -> %ld", (long int) v);
2300 printf ("Long -> HI: %ld, LO: %ld\n",
2301 (long int) v.high, (long int) v.low);
2305 case CONSTANT_NameAndType:
2306 { constant_nameandtype *cnt = e;
2307 printf ("NameAndType: ");
2308 utf_display (cnt->name);
2310 utf_display (cnt->descriptor);
2314 printf ("Utf8 -> ");
2317 case CONSTANT_Arraydescriptor: {
2318 printf ("Arraydescriptor: ");
2319 displayarraydescriptor (e);
2323 panic ("Invalid type of ConstantPool-Entry");
2329 void class_showconstantpool (classinfo *c)
2334 printf ("---- dump of constant pool ----\n");
2336 for (i=0; i<c->cpcount; i++) {
2337 printf ("#%d: ", (int) i);
2339 e = c -> cpinfos [i];
2342 switch (c -> cptags [i]) {
2343 case CONSTANT_Class:
2344 printf ("Classreference -> ");
2345 utf_display ( ((classinfo*)e) -> name );
2348 case CONSTANT_Fieldref:
2349 printf ("Fieldref -> "); goto displayFMI;
2350 case CONSTANT_Methodref:
2351 printf ("Methodref -> "); goto displayFMI;
2352 case CONSTANT_InterfaceMethodref:
2353 printf ("InterfaceMethod -> "); goto displayFMI;
2356 constant_FMIref *fmi = e;
2357 utf_display ( fmi->class->name );
2359 utf_display ( fmi->name);
2361 utf_display ( fmi->descriptor );
2365 case CONSTANT_String:
2366 printf ("String -> ");
2369 case CONSTANT_Integer:
2370 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2372 case CONSTANT_Float:
2373 printf ("Float -> %f", ((constant_float*)e) -> value);
2375 case CONSTANT_Double:
2376 printf ("Double -> %f", ((constant_double*)e) -> value);
2380 u8 v = ((constant_long*)e) -> value;
2382 printf ("Long -> %ld", (long int) v);
2384 printf ("Long -> HI: %ld, LO: %ld\n",
2385 (long int) v.high, (long int) v.low);
2389 case CONSTANT_NameAndType:
2390 { constant_nameandtype *cnt = e;
2391 printf ("NameAndType: ");
2392 utf_display (cnt->name);
2394 utf_display (cnt->descriptor);
2398 printf ("Utf8 -> ");
2401 case CONSTANT_Arraydescriptor: {
2402 printf ("Arraydescriptor: ");
2403 displayarraydescriptor (e);
2407 panic ("Invalid type of ConstantPool-Entry");
2419 /********** Function: class_showmethods (debugging only) *************/
2421 void class_showmethods (classinfo *c)
2425 printf ("--------- Fields and Methods ----------------\n");
2426 printf ("Flags: "); printflags (c->flags); printf ("\n");
2428 printf ("This: "); utf_display (c->name); printf ("\n");
2430 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2432 printf ("Index: %d\n", c->index);
2434 printf ("interfaces:\n");
2435 for (i=0; i < c-> interfacescount; i++) {
2437 utf_display (c -> interfaces[i] -> name);
2438 printf (" (%d)\n", c->interfaces[i] -> index);
2441 printf ("fields:\n");
2442 for (i=0; i < c -> fieldscount; i++) {
2443 field_display (&(c -> fields[i]));
2446 printf ("methods:\n");
2447 for (i=0; i < c -> methodscount; i++) {
2448 methodinfo *m = &(c->methods[i]);
2449 if ( !(m->flags & ACC_STATIC))
2450 printf ("vftblindex: %d ", m->vftblindex);
2452 method_display ( m );
2456 printf ("Virtual function table:\n");
2457 for (i=0; i<c->vftbl->vftbllength; i++) {
2458 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2465 /******************************************************************************/
2466 /******************* General functions for the class loader *******************/
2467 /******************************************************************************/
2469 static int loader_inited = 0;
2471 /********************* Function: loader_load ***********************************
2473 Loads and links the class desired class and each class and interface
2475 Returns: a pointer to this class
2477 *******************************************************************************/
2479 classinfo *loader_load (utf *topname)
2483 long int starttime=0,stoptime=0;
2485 intsDisable(); /* schani */
2488 starttime = getcputime();
2490 top = class_new (topname);
2493 while ( (c = list_first(&unloadedclasses)) ) {
2494 if (!class_load (c)) {
2495 list_remove (&unloadedclasses, c);
2501 while ( (c = list_first(&unlinkedclasses)) ) {
2506 loader_compute_subclasses();
2509 if (getloadingtime) {
2510 stoptime = getcputime();
2511 loadingtime += (stoptime-starttime);
2514 intsRestore(); /* schani */
2520 /**************** function: create_primitive_classes ***************************
2522 create classes representing primitive types
2524 ********************************************************************************/
2527 void create_primitive_classes()
2531 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2532 /* create primitive class */
2533 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2534 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2535 c -> impldBy = NULL;
2537 /* prevent loader from loading primitive class */
2538 list_remove (&unloadedclasses, c);
2539 /* add to unlinked classes */
2540 list_addlast (&unlinkedclasses, c);
2541 c -> super = class_java_lang_Object;
2544 primitivetype_table[i].class_primitive = c;
2546 /* create class for wrapping the primitive type */
2547 primitivetype_table[i].class_wrap =
2548 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2549 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2550 primitivetype_table[i].class_wrap -> impldBy = NULL;
2554 /***************** function: create_array_class ********************************
2556 create class representing an array
2558 ********************************************************************************/
2561 classinfo *create_array_class(utf *u)
2563 classinfo *c = class_new (u);
2564 /* prevent loader from loading the array class */
2565 list_remove (&unloadedclasses, c);
2566 /* add to unlinked classes */
2567 list_addlast (&unlinkedclasses, c);
2568 c -> super = class_java_lang_Object;
2574 /********************** Function: loader_init **********************************
2576 Initializes all lists and loads all classes required for the system or the
2579 *******************************************************************************/
2586 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2587 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2588 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2590 /* create utf-symbols for pointer comparison of frequently used strings */
2591 utf_innerclasses = utf_new_char("InnerClasses");
2592 utf_constantvalue = utf_new_char("ConstantValue");
2593 utf_code = utf_new_char("Code");
2594 utf_finalize = utf_new_char("finalize");
2595 utf_fidesc = utf_new_char("()V");
2596 utf_clinit = utf_new_char("<clinit>");
2597 utf_initsystemclass = utf_new_char("initializeSystemClass");
2598 utf_systemclass = utf_new_char("java/lang/System");
2600 /* create class for arrays */
2601 class_array = class_new ( utf_new_char ("The_Array_Class") );
2602 class_array -> classUsed = NOTUSED; /* not used initially CO-RT */
2603 class_array -> impldBy = NULL;
2605 list_remove (&unloadedclasses, class_array);
2607 /* create class for strings, load it after class Object was loaded */
2608 string_class = utf_new_char ("java/lang/String");
2609 class_java_lang_String = class_new(string_class);
2610 class_java_lang_String -> classUsed = NOTUSED; /* not used initially CO-RT */
2611 class_java_lang_String -> impldBy = NULL;
2613 list_remove (&unloadedclasses, class_java_lang_String);
2615 class_java_lang_Object =
2616 loader_load ( utf_new_char ("java/lang/Object") );
2618 list_addlast(&unloadedclasses, class_java_lang_String);
2620 class_java_lang_String =
2621 loader_load ( string_class );
2622 class_java_lang_ClassCastException =
2623 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2624 class_java_lang_NullPointerException =
2625 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2626 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2627 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2628 class_java_lang_NegativeArraySizeException = loader_load (
2629 utf_new_char ("java/lang/NegativeArraySizeException") );
2630 class_java_lang_OutOfMemoryError = loader_load (
2631 utf_new_char ("java/lang/OutOfMemoryError") );
2632 class_java_lang_ArrayStoreException =
2633 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2634 class_java_lang_ArithmeticException =
2635 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2636 class_java_lang_ThreadDeath = /* schani */
2637 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2639 /* link class for arrays */
2640 list_addlast (&unlinkedclasses, class_array);
2641 class_array -> super = class_java_lang_Object;
2642 class_link (class_array);
2644 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2645 stringtable_update();
2647 /* create classes representing primitive types */
2648 create_primitive_classes();
2650 proto_java_lang_ClassCastException =
2651 builtin_new(class_java_lang_ClassCastException);
2652 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2654 proto_java_lang_NullPointerException =
2655 builtin_new(class_java_lang_NullPointerException);
2656 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2658 proto_java_lang_ArrayIndexOutOfBoundsException =
2659 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2660 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2662 proto_java_lang_NegativeArraySizeException =
2663 builtin_new(class_java_lang_NegativeArraySizeException);
2664 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2666 proto_java_lang_OutOfMemoryError =
2667 builtin_new(class_java_lang_OutOfMemoryError);
2668 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2670 proto_java_lang_ArithmeticException =
2671 builtin_new(class_java_lang_ArithmeticException);
2672 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2674 proto_java_lang_ArrayStoreException =
2675 builtin_new(class_java_lang_ArrayStoreException);
2676 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2678 proto_java_lang_ThreadDeath = /* schani */
2679 builtin_new(class_java_lang_ThreadDeath);
2680 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2688 /********************* Function: loader_initclasses ****************************
2690 Initializes all loaded but uninitialized classes
2692 *******************************************************************************/
2694 void loader_initclasses ()
2698 intsDisable(); /* schani */
2700 if (makeinitializations) {
2701 c = list_first (&linkedclasses);
2704 c = list_next (&linkedclasses, c);
2708 intsRestore(); /* schani */
2711 static s4 classvalue;
2713 static void loader_compute_class_values (classinfo *c)
2717 c->vftbl->baseval = ++classvalue;
2720 while (subs != NULL) {
2721 loader_compute_class_values(subs);
2722 subs = subs->nextsub;
2724 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2729 for (i = 0; i < c->index; i++)
2731 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2732 utf_display(c->name);
2739 void loader_compute_subclasses ()
2743 intsDisable(); /* schani */
2745 c = list_first (&linkedclasses);
2747 if (!(c->flags & ACC_INTERFACE)) {
2751 c = list_next (&linkedclasses, c);
2754 c = list_first (&linkedclasses);
2756 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2757 c->nextsub = c->super->sub;
2760 c = list_next (&linkedclasses, c);
2763 loader_compute_class_values(class_java_lang_Object);
2765 intsRestore(); /* schani */
2770 /******************** function classloader_buffer ******************************
2772 sets buffer for reading classdata
2774 *******************************************************************************/
2776 void classload_buffer(u1 *buf, int len)
2779 classbuffer_size = len;
2780 classbuf_pos = buf - 1;
2784 /******************** Function: loader_close ***********************************
2788 *******************************************************************************/
2790 void loader_close ()
2794 while ( (c=list_first(&unloadedclasses)) ) {
2795 list_remove (&unloadedclasses,c);
2798 while ( (c=list_first(&unlinkedclasses)) ) {
2799 list_remove (&unlinkedclasses,c);
2802 while ( (c=list_first(&linkedclasses)) ) {
2803 list_remove (&linkedclasses,c);
2810 * These are local overrides for various environment variables in Emacs.
2811 * Please do not remove this and leave it at the end of the file, where
2812 * Emacs will automagically detect them.
2813 * ---------------------------------------------------------------------
2816 * indent-tabs-mode: t