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 *******************************************************************************/
31 #include "toolbox/memory.h"
34 #include "toolbox/loging.h"
36 #include "threads/thread.h"
39 /* global variables ***********************************************************/
41 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
42 bool opt_xta = false; /* true if XTA parse should be used XTA-CO */
43 bool opt_vta = false; /* true if VTA parse should be used VTA-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_array = NULL;
89 /* These are made static so they cannot be used for throwing in native */
91 static classinfo *class_java_lang_ClassCastException;
92 static classinfo *class_java_lang_NullPointerException;
93 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
94 static classinfo *class_java_lang_NegativeArraySizeException;
95 static classinfo *class_java_lang_OutOfMemoryError;
96 static classinfo *class_java_lang_ArithmeticException;
97 static classinfo *class_java_lang_ArrayStoreException;
98 static classinfo *class_java_lang_ThreadDeath;
101 /******************************************************************************
103 structure for primitive classes: contains the class for wrapping the
104 primitive type, the primitive class, the name of the class for wrapping,
105 the one character type signature and the name of the primitive class
107 ******************************************************************************/
109 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
110 { NULL, NULL, "java/lang/Double", 'D', "double" },
111 { NULL, NULL, "java/lang/Float", 'F', "float" },
112 { NULL, NULL, "java/lang/Character", 'C', "char" },
113 { NULL, NULL, "java/lang/Integer", 'I', "int" },
114 { NULL, NULL, "java/lang/Long", 'J', "long" },
115 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
116 { NULL, NULL, "java/lang/Short", 'S', "short" },
117 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
118 { NULL, NULL, "java/lang/Void", 'V', "void" }};
121 /* instances of important system classes **************************************/
123 java_objectheader *proto_java_lang_ClassCastException;
124 java_objectheader *proto_java_lang_NullPointerException;
125 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
126 java_objectheader *proto_java_lang_NegativeArraySizeException;
127 java_objectheader *proto_java_lang_OutOfMemoryError;
128 java_objectheader *proto_java_lang_ArithmeticException;
129 java_objectheader *proto_java_lang_ArrayStoreException;
130 java_objectheader *proto_java_lang_ThreadDeath;
133 /************* functions for reading classdata *********************************
135 getting classdata in blocks of variable size
136 (8,16,32,64-bit integer or float)
138 *******************************************************************************/
140 static char *classpath = ""; /* searchpath for classfiles */
141 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
142 static u1 *classbuf_pos; /* current position in classfile buffer */
143 static int classbuffer_size; /* size of classfile-data */
145 /* transfer block of classfile data into a buffer */
147 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
150 /* skip block of classfile data */
152 #define skip_nbytes(len) classbuf_pos+=len;
156 return *++classbuf_pos;
160 u1 a=suck_u1(), b=suck_u1();
161 return ((u2)a<<8)+(u2)b;
165 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
166 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
168 #define suck_s8() (s8) suck_u8()
169 #define suck_s2() (s2) suck_u2()
170 #define suck_s4() (s4) suck_u4()
171 #define suck_s1() (s1) suck_u1()
174 /* get u8 from classfile data */
182 return (hi<<32) + lo;
191 /* get float from classfile data */
193 static float suck_float ()
200 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
201 memcpy ( (u1*) (&f), buffer, 4);
203 suck_nbytes ( (u1*) (&f), 4 );
206 PANICIF (sizeof(float) != 4, "Incompatible float-format");
211 /* get double from classfile data */
212 static double suck_double ()
219 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
220 memcpy ( (u1*) (&d), buffer, 8);
222 suck_nbytes ( (u1*) (&d), 8 );
225 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
230 /************************** function suck_init *********************************
232 called once at startup, sets the searchpath for the classfiles
234 *******************************************************************************/
236 void suck_init (char *cpath)
243 /************************** function suck_start ********************************
245 returns true if classbuffer is already loaded or a file for the
246 specified class has succussfully been read in. All directories of
247 the searchpath are used to find the classfile (<classname>.class).
248 Returns false if no classfile is found and writes an error message.
250 *******************************************************************************/
253 bool suck_start (utf *classname) {
255 #define MAXFILENAME 1000 /* maximum length of a filename */
257 char filename[MAXFILENAME+10]; /* room for '.class' */
258 char *pathpos; /* position in searchpath */
259 char c, *utf_ptr; /* pointer to the next utf8-character */
261 int filenamelen, err;
264 if (classbuffer) /* classbuffer is already valid */
271 /* skip path separator */
273 while (*pathpos == ':')
276 /* extract directory from searchpath */
279 while ((*pathpos) && (*pathpos!=':')) {
280 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
281 filename[filenamelen++] = *(pathpos++);
284 filename[filenamelen++] = '/';
286 /* add classname to filename */
288 utf_ptr = classname->text;
289 while (utf_ptr < utf_end(classname)) {
290 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
292 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
294 filename[filenamelen++] = c;
299 strcpy (filename+filenamelen, ".class");
301 classfile = fopen(filename, "r");
302 if (classfile) { /* file exists */
304 /* determine size of classfile */
306 err = stat (filename, &buffer);
308 if (!err) { /* read classfile data */
309 classbuffer_size = buffer.st_size;
310 classbuffer = MNEW(u1, classbuffer_size);
311 classbuf_pos = classbuffer-1;
312 fread(classbuffer, 1, classbuffer_size, classfile);
320 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
328 /************************** function suck_stop *********************************
330 frees memory for buffer with classfile data.
331 Caution: this function may only be called if buffer has been allocated
332 by suck_start with reading a file
334 *******************************************************************************/
338 /* determine amount of classdata not retrieved by suck-operations */
340 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
342 if (classdata_left > 0) {
344 sprintf (logtext,"There are %d access bytes at end of classfile",
351 MFREE(classbuffer, u1, classbuffer_size);
355 /******************************************************************************/
356 /******************* Some support functions ***********************************/
357 /******************************************************************************/
361 void fprintflags (FILE *fp, u2 f)
363 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
364 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
365 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
366 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
367 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
368 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
369 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
370 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
371 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
372 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
373 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
376 /********** internal function: printflags (only for debugging) ***************/
377 void printflags (u2 f)
379 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
380 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
381 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
382 if ( f & ACC_STATIC ) printf (" STATIC");
383 if ( f & ACC_FINAL ) printf (" FINAL");
384 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
385 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
386 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
387 if ( f & ACC_NATIVE ) printf (" NATIVE");
388 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
389 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
393 /************************* Function: skipattribute *****************************
395 skips a (1) 'attribute' structure in the class file
397 *******************************************************************************/
399 static void skipattribute ()
402 skip_nbytes(suck_u4());
405 /********************** Function: skipattributebody ****************************
407 skips an attribute after the 16 bit reference to attribute_name has already
410 *******************************************************************************/
412 static void skipattributebody ()
414 skip_nbytes(suck_u4());
417 /************************* Function: skipattributes ****************************
419 skips num attribute structures
421 *******************************************************************************/
423 static void skipattributes (u4 num)
426 for (i = 0; i < num; i++)
430 /******************** function: innerclass_getconstant ************************
432 like class_getconstant, but if cptags is ZERO null is returned
434 *******************************************************************************/
436 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
438 /* invalid position in constantpool */
439 if (pos >= c->cpcount)
440 panic ("Attempt to access constant outside range");
442 /* constantpool entry of type 0 */
446 /* check type of constantpool entry */
447 if (c->cptags[pos] != ctype) {
448 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
449 (int) ctype, (int) c->cptags[pos] );
453 return c->cpinfos[pos];
456 /************************ function: attribute_load ****************************
458 read attributes from classfile
460 *******************************************************************************/
462 static void attribute_load (u4 num, classinfo *c)
466 for (i = 0; i < num; i++) {
467 /* retrieve attribute name */
468 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
470 if ( aname == utf_innerclasses) {
471 /* innerclasses attribute */
473 /* skip attribute length */
475 /* number of records */
476 c->innerclasscount = suck_u2();
477 /* allocate memory for innerclass structure */
478 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
480 for (j=0;j<c->innerclasscount;j++) {
482 /* The innerclass structure contains a class with an encoded name,
483 its defining scope, its simple name and a bitmask of the access flags.
484 If an inner class is not a member, its outer_class is NULL,
485 if a class is anonymous, its name is NULL. */
487 innerclassinfo *info = c->innerclass + j;
489 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
490 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
491 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
492 info->flags = suck_u2 (); /* access_flags bitmask */
495 /* unknown attribute */
496 skipattributebody ();
501 /******************* function: checkfielddescriptor ****************************
503 checks whether a field-descriptor is valid and aborts otherwise
504 all referenced classes are inserted into the list of unloaded classes
506 *******************************************************************************/
508 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
510 char *tstart; /* pointer to start of classname */
513 switch (*utf_ptr++) {
526 /* save start of classname */
529 /* determine length of classname */
530 while ( *utf_ptr++ != ';' )
531 if (utf_ptr>=end_pos)
532 panic ("Missing ';' in objecttype-descriptor");
534 /* cause loading of referenced class */
535 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
540 while ((ch = *utf_ptr++)=='[')
543 /* component type of array */
557 /* save start of classname */
560 /* determine length of classname */
561 while ( *utf_ptr++ != ';' )
562 if (utf_ptr>=end_pos)
563 panic ("Missing ';' in objecttype-descriptor");
565 /* cause loading of referenced class */
566 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
570 panic ("Ill formed methodtype-descriptor");
575 panic ("Ill formed methodtype-descriptor");
578 /* exceeding characters */
579 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
583 /******************* function checkmethoddescriptor ****************************
585 checks whether a method-descriptor is valid and aborts otherwise.
586 All referenced classes are inserted into the list of unloaded classes.
588 *******************************************************************************/
590 static void checkmethoddescriptor (utf *d)
592 char *utf_ptr = d->text; /* current position in utf text */
593 char *end_pos = utf_end(d); /* points behind utf string */
594 char *tstart; /* pointer to start of classname */
597 /* method descriptor must start with parenthesis */
598 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
600 /* check arguments */
601 while ((c = *utf_ptr++) != ')') {
615 /* save start of classname */
618 /* determine length of classname */
619 while ( *utf_ptr++ != ';' )
620 if (utf_ptr>=end_pos)
621 panic ("Missing ';' in objecttype-descriptor");
623 /* cause loading of referenced class */
624 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
629 while ((ch = *utf_ptr++)=='[')
632 /* component type of array */
646 /* save start of classname */
649 /* determine length of classname */
650 while ( *utf_ptr++ != ';' )
651 if (utf_ptr>=end_pos)
652 panic ("Missing ';' in objecttype-descriptor");
654 /* cause loading of referenced class */
655 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
659 panic ("Ill formed methodtype-descriptor");
664 panic ("Ill formed methodtype-descriptor");
668 /* check returntype */
670 /* returntype void */
671 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
674 /* treat as field-descriptor */
675 checkfielddescriptor (utf_ptr,end_pos);
679 /******************** Function: buildarraydescriptor ***************************
681 creates a constant_arraydescriptor structure for the array type named by an
684 *******************************************************************************/
686 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
688 constant_arraydescriptor *d;
690 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
692 d = NEW (constant_arraydescriptor);
693 d -> objectclass = NULL;
694 d -> elementdescriptor = NULL;
697 count_const_pool_len += sizeof(constant_arraydescriptor);
701 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
702 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
703 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
704 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
705 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
706 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
707 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
708 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
711 d -> arraytype = ARRAYTYPE_ARRAY;
712 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
716 d -> arraytype = ARRAYTYPE_OBJECT;
718 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
719 d -> objectclass -> classUsed = NOTUSED; /* not used initially CO-RT */
720 d -> objectclass -> impldBy = NULL;
727 /******************* Function: freearraydescriptor *****************************
729 removes a structure created by buildarraydescriptor from memory
731 *******************************************************************************/
733 static void freearraydescriptor (constant_arraydescriptor *d)
736 constant_arraydescriptor *n = d->elementdescriptor;
737 FREE (d, constant_arraydescriptor);
742 /*********************** Function: displayarraydescriptor *********************/
744 static void displayarraydescriptor (constant_arraydescriptor *d)
746 switch (d->arraytype) {
747 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
748 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
749 case ARRAYTYPE_CHAR: printf ("char[]"); break;
750 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
751 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
752 case ARRAYTYPE_INT: printf ("int[]"); break;
753 case ARRAYTYPE_LONG: printf ("long[]"); break;
754 case ARRAYTYPE_SHORT: printf ("short[]"); break;
755 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
756 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
762 /******************************************************************************/
763 /************************** Functions for fields ****************************/
764 /******************************************************************************/
767 /************************ Function: field_load *********************************
769 Load everything about a class field from the class file and fill a
770 'fieldinfo' structure. For static fields, space in the data segment is
773 *******************************************************************************/
775 static void field_load (fieldinfo *f, classinfo *c)
780 f -> flags = suck_u2 (); /* ACC flags */
781 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
782 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
783 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
784 f -> offset = 0; /* offset from start of object */
785 f -> fieldChecked = false; /*XTA*/
786 f -> fldClassType = NULL; /*XTA*/
787 f -> XTAclassSet = NULL; /*XTA*/
788 f -> lastRoundChgd = -1;
791 case TYPE_INT: f->value.i = 0; break;
792 case TYPE_FLOAT: f->value.f = 0.0; break;
793 case TYPE_DOUBLE: f->value.d = 0.0; break;
794 case TYPE_ADDRESS: f->value.a = NULL;
795 heap_addreference (&(f->value.a)); /* make global reference (GC) */
799 f->value.l = 0; break;
801 f->value.l.low = 0; f->value.l.high = 0; break;
805 /* read attributes */
807 for (i=0; i<attrnum; i++) {
811 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
813 if ( aname != utf_constantvalue ) {
814 /* unknown attribute */
815 skipattributebody ();
818 /* constant value attribute */
820 /* skip attribute length */
822 /* index of value in constantpool */
825 /* initialize field with value from constantpool */
828 constant_integer *ci =
829 class_getconstant(c, pindex, CONSTANT_Integer);
830 f->value.i = ci -> value;
836 class_getconstant(c, pindex, CONSTANT_Long);
838 f->value.l = cl -> value;
844 class_getconstant(c, pindex, CONSTANT_Float);
846 f->value.f = cf->value;
851 constant_double *cd =
852 class_getconstant(c, pindex, CONSTANT_Double);
854 f->value.d = cd->value;
859 utf *u = class_getconstant(c, pindex, CONSTANT_String);
860 /* create javastring from compressed utf8-string */
861 f->value.a = literalstring_new(u);
866 log_text ("Invalid Constant - Type");
875 /********************** function: field_free **********************************/
877 static void field_free (fieldinfo *f)
883 /**************** Function: field_display (debugging only) ********************/
885 void field_display (fieldinfo *f)
888 printflags (f -> flags);
890 utf_display (f -> name);
892 utf_display (f -> descriptor);
893 printf (" offset: %ld\n", (long int) (f -> offset) );
897 /******************************************************************************/
898 /************************* Functions for methods ******************************/
899 /******************************************************************************/
902 /*********************** Function: method_load *********************************
904 Loads a method from the class file and fills an existing 'methodinfo'
905 structure. For native methods, the function pointer field is set to the
906 real function pointer, for JavaVM methods a pointer to the compiler is used
909 *******************************************************************************/
911 static void method_load (methodinfo *m, classinfo *c)
921 m -> flags = suck_u2 ();
922 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
923 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
926 m -> exceptiontable = NULL;
927 m -> entrypoint = NULL;
929 m -> stubroutine = NULL;
930 m -> methodUsed = NOTUSED;
931 m -> XTAmethodUsed = NOTUSED;
932 m -> monoPoly = MONO;
934 m -> subRedefsUsed = 0;
938 m -> XTAclassSet = NULL; /*XTA*/
939 m -> paramClassSet = NULL; /*XTA*/
940 m -> calls = NULL; /*XTA*/
941 m -> calledBy = NULL; /*XTA*/
942 m -> chgdSinceLastParse = false; /*XTA*/
944 m -> marked = NULL; /*XTA*/
945 m -> markedBy = NULL; /*XTA*/
946 m -> fldsUsed = NULL; /*XTA*/
947 m -> interfaceCalls = NULL; /*XTA*/
948 m -> lastRoundParsed = -1;
949 m -> interfaceCalls = NULL; /*XTA*/
952 if (! (m->flags & ACC_NATIVE) ) {
953 m -> stubroutine = createcompilerstub (m);
957 functionptr f = native_findfunction
958 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
960 m -> stubroutine = createnativestub (f, m);
966 for (i=0; i<attrnum; i++) {
969 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
971 if ( aname != utf_code) {
972 skipattributebody ();
975 if (m -> jcode) panic ("Two code-attributes for one method!");
978 m -> maxstack = suck_u2();
979 m -> maxlocals = suck_u2();
980 m -> jcodelength = suck_u4();
981 m -> jcode = MNEW (u1, m->jcodelength);
982 suck_nbytes (m->jcode, m->jcodelength);
983 m -> exceptiontablelength = suck_u2 ();
984 m -> exceptiontable =
985 MNEW (exceptiontable, m->exceptiontablelength);
988 count_vmcode_len += m->jcodelength + 18;
989 count_extable_len += 8 * m->exceptiontablelength;
992 for (e=0; e < m->exceptiontablelength; e++) {
994 m -> exceptiontable[e].startpc = suck_u2();
995 m -> exceptiontable[e].endpc = suck_u2();
996 m -> exceptiontable[e].handlerpc = suck_u2();
999 if (!idx) m -> exceptiontable[e].catchtype = NULL;
1001 m -> exceptiontable[e].catchtype =
1002 class_getconstant (c, idx, CONSTANT_Class);
1006 skipattributes ( suck_u2() );
1013 /********************* Function: method_free ***********************************
1015 frees all memory that was allocated for this method
1017 *******************************************************************************/
1019 static void method_free (methodinfo *m)
1021 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
1022 if (m->exceptiontable)
1023 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
1024 if (m->mcode) CFREE (m->mcode, m->mcodelength);
1025 if (m->stubroutine) {
1026 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
1027 else removecompilerstub (m->stubroutine);
1032 /************** Function: method_display (debugging only) **************/
1034 void method_display (methodinfo *m)
1037 printflags (m -> flags);
1039 utf_display (m -> name);
1041 utf_display (m -> descriptor);
1046 /******************** Function: method_canoverwrite ****************************
1048 Check if m and old are identical with respect to type and name. This means
1049 that old can be overwritten with m.
1051 *******************************************************************************/
1053 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1055 if (m->name != old->name) return false;
1056 if (m->descriptor != old->descriptor) return false;
1057 if (m->flags & ACC_STATIC) return false;
1064 /******************************************************************************/
1065 /************************ Functions for class *********************************/
1066 /******************************************************************************/
1069 /******************** function:: class_getconstant ******************************
1071 retrieves the value at position 'pos' of the constantpool of a class
1072 if the type of the value is other than 'ctype' the system is stopped
1074 *******************************************************************************/
1076 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1078 /* invalid position in constantpool */
1079 if (pos >= c->cpcount)
1080 panic ("Attempt to access constant outside range");
1082 /* check type of constantpool entry */
1083 if (c->cptags[pos] != ctype) {
1084 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1085 (int) ctype, (int) c->cptags[pos] );
1089 return c->cpinfos[pos];
1093 /********************* Function: class_constanttype ****************************
1095 Determines the type of a class entry in the ConstantPool
1097 *******************************************************************************/
1099 u4 class_constanttype (classinfo *c, u4 pos)
1101 if (pos >= c->cpcount)
1102 panic ("Attempt to access constant outside range");
1103 return c->cptags[pos];
1107 /******************** function: class_loadcpool ********************************
1109 loads the constantpool of a class,
1110 the entries are transformed into a simpler format
1111 by resolving references
1112 (a detailed overview of the compact structures can be found in global.h)
1114 *******************************************************************************/
1116 static void class_loadcpool (classinfo *c)
1119 /* The following structures are used to save information which cannot be
1120 processed during the first pass. After the complete constantpool has
1121 been traversed the references can be resolved.
1122 (only in specific order) */
1124 /* CONSTANT_Class_info entries */
1125 typedef struct forward_class {
1126 struct forward_class *next;
1131 /* CONSTANT_String */
1132 typedef struct forward_string {
1133 struct forward_string *next;
1138 /* CONSTANT_NameAndType */
1139 typedef struct forward_nameandtype {
1140 struct forward_nameandtype *next;
1144 } forward_nameandtype;
1146 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1147 typedef struct forward_fieldmethint {
1148 struct forward_fieldmethint *next;
1152 u2 nameandtype_index;
1153 } forward_fieldmethint;
1157 long int dumpsize = dump_size ();
1159 forward_class *forward_classes = NULL;
1160 forward_string *forward_strings = NULL;
1161 forward_nameandtype *forward_nameandtypes = NULL;
1162 forward_fieldmethint *forward_fieldmethints = NULL;
1164 /* number of entries in the constant_pool table */
1165 u4 cpcount = c -> cpcount = suck_u2();
1166 /* allocate memory */
1167 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1168 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1171 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1174 /* initialize constantpool */
1175 for (idx=0; idx<cpcount; idx++) {
1176 cptags[idx] = CONSTANT_UNUSED;
1177 cpinfos[idx] = NULL;
1181 /******* first pass *******/
1182 /* entries which cannot be resolved now are written into
1183 temporary structures and traversed again later */
1186 while (idx < cpcount) {
1187 /* get constant type */
1191 case CONSTANT_Class: {
1192 forward_class *nfc = DNEW(forward_class);
1194 nfc -> next = forward_classes;
1195 forward_classes = nfc;
1197 nfc -> thisindex = idx;
1198 /* reference to CONSTANT_NameAndType */
1199 nfc -> name_index = suck_u2 ();
1205 case CONSTANT_Fieldref:
1206 case CONSTANT_Methodref:
1207 case CONSTANT_InterfaceMethodref: {
1208 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1210 nff -> next = forward_fieldmethints;
1211 forward_fieldmethints = nff;
1213 nff -> thisindex = idx;
1216 /* class or interface type that contains the declaration of the field or method */
1217 nff -> class_index = suck_u2 ();
1218 /* name and descriptor of the field or method */
1219 nff -> nameandtype_index = suck_u2 ();
1225 case CONSTANT_String: {
1226 forward_string *nfs = DNEW (forward_string);
1228 nfs -> next = forward_strings;
1229 forward_strings = nfs;
1231 nfs -> thisindex = idx;
1232 /* reference to CONSTANT_Utf8_info with string characters */
1233 nfs -> string_index = suck_u2 ();
1239 case CONSTANT_NameAndType: {
1240 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1242 nfn -> next = forward_nameandtypes;
1243 forward_nameandtypes = nfn;
1245 nfn -> thisindex = idx;
1246 /* reference to CONSTANT_Utf8_info containing simple name */
1247 nfn -> name_index = suck_u2 ();
1248 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1249 nfn -> sig_index = suck_u2 ();
1255 case CONSTANT_Integer: {
1256 constant_integer *ci = NEW (constant_integer);
1259 count_const_pool_len += sizeof(constant_integer);
1262 ci -> value = suck_s4 ();
1263 cptags [idx] = CONSTANT_Integer;
1270 case CONSTANT_Float: {
1271 constant_float *cf = NEW (constant_float);
1274 count_const_pool_len += sizeof(constant_float);
1277 cf -> value = suck_float ();
1278 cptags [idx] = CONSTANT_Float;
1284 case CONSTANT_Long: {
1285 constant_long *cl = NEW(constant_long);
1288 count_const_pool_len += sizeof(constant_long);
1291 cl -> value = suck_s8 ();
1292 cptags [idx] = CONSTANT_Long;
1298 case CONSTANT_Double: {
1299 constant_double *cd = NEW(constant_double);
1302 count_const_pool_len += sizeof(constant_double);
1305 cd -> value = suck_double ();
1306 cptags [idx] = CONSTANT_Double;
1312 case CONSTANT_Utf8: {
1314 /* number of bytes in the bytes array (not string-length) */
1315 u4 length = suck_u2();
1316 cptags [idx] = CONSTANT_Utf8;
1317 /* insert utf-string into the utf-symboltable */
1318 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1319 /* skip bytes of the string */
1320 skip_nbytes(length);
1326 sprintf (logtext, "Unkown constant type: %d",(int) t);
1335 /* resolve entries in temporary structures */
1337 while (forward_classes) {
1339 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1341 if ( (name->blength>0) && (name->text[0]=='[') ) {
1342 /* check validity of descriptor */
1343 checkfielddescriptor (name->text, utf_end(name));
1345 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1346 cpinfos [forward_classes -> thisindex] =
1347 buildarraydescriptor(name->text, name->blength);
1351 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1352 /* retrieve class from class-table */
1353 cpinfos [forward_classes -> thisindex] = class_new (name);
1355 forward_classes = forward_classes -> next;
1359 while (forward_strings) {
1361 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1363 /* resolve utf-string */
1364 cptags [forward_strings -> thisindex] = CONSTANT_String;
1365 cpinfos [forward_strings -> thisindex] = text;
1367 forward_strings = forward_strings -> next;
1370 while (forward_nameandtypes) {
1371 constant_nameandtype *cn = NEW (constant_nameandtype);
1374 count_const_pool_len += sizeof(constant_nameandtype);
1377 /* resolve simple name and descriptor */
1378 cn -> name = class_getconstant
1379 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1380 cn -> descriptor = class_getconstant
1381 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1383 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1384 cpinfos [forward_nameandtypes -> thisindex] = cn;
1386 forward_nameandtypes = forward_nameandtypes -> next;
1390 while (forward_fieldmethints) {
1391 constant_nameandtype *nat;
1392 constant_FMIref *fmi = NEW (constant_FMIref);
1395 count_const_pool_len += sizeof(constant_FMIref);
1397 /* resolve simple name and descriptor */
1398 nat = class_getconstant
1399 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1401 fmi -> class = class_getconstant
1402 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1403 fmi -> name = nat -> name;
1404 fmi -> descriptor = nat -> descriptor;
1406 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1407 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1409 switch (forward_fieldmethints -> tag) {
1410 case CONSTANT_Fieldref: /* check validity of descriptor */
1411 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1413 case CONSTANT_InterfaceMethodref:
1414 case CONSTANT_Methodref: /* check validity of descriptor */
1415 checkmethoddescriptor (fmi->descriptor);
1419 forward_fieldmethints = forward_fieldmethints -> next;
1424 dump_release (dumpsize);
1428 /********************** Function: class_load ***********************************
1430 Loads everything interesting about a class from the class file. The
1431 'classinfo' structure must have been allocated previously.
1433 The super class and the interfaces implemented by this class need not be
1434 loaded. The link is set later by the function 'class_link'.
1436 The loaded class is removed from the list 'unloadedclasses' and added to
1437 the list 'unlinkedclasses'.
1439 *******************************************************************************/
1441 static int class_load (classinfo *c)
1447 count_class_loads++;
1450 /* output for debugging purposes */
1453 sprintf (logtext, "Loading class: ");
1454 utf_sprint (logtext+strlen(logtext), c->name );
1458 /* load classdata, throw exception on error */
1459 if (!suck_start (c->name)) {
1460 throw_classnotfoundexception();
1464 /* check signature */
1465 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1469 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1470 sprintf (logtext, "File version %d.%d is not supported",
1471 (int) ma, (int) mi);
1476 class_loadcpool (c);
1478 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1479 c -> impldBy = NULL;
1482 c -> flags = suck_u2 ();
1486 /* retrieve superclass */
1487 if ( (i = suck_u2 () ) ) {
1488 c -> super = class_getconstant (c, i, CONSTANT_Class);
1494 /* retrieve interfaces */
1495 c -> interfacescount = suck_u2 ();
1496 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1497 for (i=0; i < c -> interfacescount; i++) {
1498 c -> interfaces [i] =
1499 class_getconstant (c, suck_u2(), CONSTANT_Class);
1503 c -> fieldscount = suck_u2 ();
1505 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1507 c -> fields = MNEW (fieldinfo, c -> fieldscount);
1509 for (i=0; i < c -> fieldscount; i++) {
1510 field_load (&(c->fields[i]), c);
1514 c -> methodscount = suck_u2 ();
1515 c -> methods = MNEW (methodinfo, c -> methodscount);
1516 for (i=0; i < c -> methodscount; i++) {
1517 method_load (&(c -> methods [i]), c);
1521 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1522 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1523 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1526 /* load variable-length attribute structures */
1527 attribute_load (suck_u2(), c);
1532 /* remove class from list of unloaded classes and
1533 add to list of unlinked classes */
1534 list_remove (&unloadedclasses, c);
1535 list_addlast (&unlinkedclasses, c);
1542 /************** internal Function: class_highestinterface ***********************
1544 Used by the function class_link to determine the amount of memory needed
1545 for the interface table.
1547 *******************************************************************************/
1549 static s4 class_highestinterface (classinfo *c)
1554 if ( ! (c->flags & ACC_INTERFACE) ) {
1555 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1556 utf_sprint (logtext+strlen(logtext), c->name);
1561 for (i=0; i<c->interfacescount; i++) {
1562 s4 h2 = class_highestinterface (c->interfaces[i]);
1569 /* class_addinterface **********************************************************
1571 Is needed by class_link for adding a VTBL to a class. All interfaces
1572 implemented by ic are added as well.
1574 *******************************************************************************/
1576 static void class_addinterface (classinfo *c, classinfo *ic)
1580 vftbl *vftbl = c->vftbl;
1582 if (i >= vftbl->interfacetablelength)
1583 panic ("Inernal error: interfacetable overflow");
1584 if (vftbl->interfacetable[-i])
1587 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1588 vftbl->interfacevftbllength[i] = 1;
1589 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1590 vftbl->interfacetable[-i][0] = NULL;
1593 vftbl->interfacevftbllength[i] = ic->methodscount;
1594 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1597 count_vftbl_len += sizeof(methodptr) *
1598 (ic->methodscount + (ic->methodscount == 0));
1601 for (j=0; j<ic->methodscount; j++) {
1604 for (m = 0; m < sc->methodscount; m++) {
1605 methodinfo *mi = &(sc->methods[m]);
1606 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1607 vftbl->interfacetable[-i][j] =
1608 vftbl->table[mi->vftblindex];
1618 for (j = 0; j < ic->interfacescount; j++)
1619 class_addinterface(c, ic->interfaces[j]);
1623 /********************** Function: class_link ***********************************
1625 Tries to link a class. The super class and every implemented interface must
1626 already have been linked. The function calculates the length in bytes that
1627 an instance of this class requires as well as the VTBL for methods and
1630 If the class can be linked, it is removed from the list 'unlinkedclasses'
1631 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1634 Attention: If cyclical class definitions are encountered, the program gets
1635 into an infinite loop (we'll have to work that out)
1637 *******************************************************************************/
1639 static void class_link (classinfo *c)
1641 s4 supervftbllength; /* vftbllegnth of super class */
1642 s4 vftbllength; /* vftbllength of current class */
1643 s4 interfacetablelength; /* interface table length */
1644 classinfo *super = c->super; /* super class */
1645 classinfo *ic, *c2; /* intermediate class variables */
1646 vftbl *v; /* vftbl of current class */
1647 s4 i; /* interface/method/field counter */
1650 /* check if all superclasses are already linked, if not put c at end of
1651 unlinked list and return. Additionally initialize class fields. */
1653 /* check interfaces */
1655 for (i = 0; i < c->interfacescount; i++) {
1656 ic = c->interfaces[i];
1658 list_remove(&unlinkedclasses, c);
1659 list_addlast(&unlinkedclasses, c);
1664 /* check super class */
1666 if (super == NULL) { /* class java.long.Object */
1668 c->classUsed = USED; /* Object class is always used CO-RT*/
1669 c -> impldBy = NULL;
1670 c->instancesize = sizeof(java_objectheader);
1672 vftbllength = supervftbllength = 0;
1674 c->finalizer = NULL;
1677 if (!super->linked) {
1678 list_remove(&unlinkedclasses, c);
1679 list_addlast(&unlinkedclasses, c);
1683 if (c->flags & ACC_INTERFACE)
1684 c->index = interfaceindex++;
1686 c->index = super->index + 1;
1688 c->instancesize = super->instancesize;
1690 vftbllength = supervftbllength = super->vftbl->vftbllength;
1692 c->finalizer = super->finalizer;
1697 sprintf (logtext, "Linking Class: ");
1698 utf_sprint (logtext+strlen(logtext), c->name );
1702 /* compute vftbl length */
1704 for (i = 0; i < c->methodscount; i++) {
1705 methodinfo *m = &(c->methods[i]);
1707 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1708 classinfo *sc = super;
1711 for (j = 0; j < sc->methodscount; j++) {
1712 if (method_canoverwrite(m, &(sc->methods[j]))) {
1713 m->vftblindex = sc->methods[j].vftblindex;
1714 goto foundvftblindex;
1719 m->vftblindex = (vftbllength++);
1725 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1728 /* compute interfacetable length */
1730 interfacetablelength = 0;
1733 for (i = 0; i < c2->interfacescount; i++) {
1734 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1735 if (h > interfacetablelength)
1736 interfacetablelength = h;
1741 /* allocate virtual function table */
1743 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1744 (vftbllength - 1) + sizeof(methodptr*) *
1745 (interfacetablelength - (interfacetablelength > 0)));
1746 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1747 (interfacetablelength > 1));
1748 c->header.vftbl = c->vftbl = v;
1750 v->vftbllength = vftbllength;
1751 v->interfacetablelength = interfacetablelength;
1753 /* copy virtual function table of super class */
1755 for (i = 0; i < supervftbllength; i++)
1756 v->table[i] = super->vftbl->table[i];
1758 /* add method stubs into virtual function table */
1760 for (i = 0; i < c->methodscount; i++) {
1761 methodinfo *m = &(c->methods[i]);
1762 if (!(m->flags & ACC_STATIC)) {
1763 v->table[m->vftblindex] = m->stubroutine;
1767 /* compute instance size and offset of each field */
1769 for (i = 0; i < c->fieldscount; i++) {
1771 fieldinfo *f = &(c->fields[i]);
1773 if (!(f->flags & ACC_STATIC) ) {
1774 dsize = desc_typesize (f->descriptor);
1775 c->instancesize = ALIGN (c->instancesize, dsize);
1776 f->offset = c->instancesize;
1777 c->instancesize += dsize;
1781 /* initialize interfacetable and interfacevftbllength */
1783 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1786 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1789 for (i = 0; i < interfacetablelength; i++) {
1790 v->interfacevftbllength[i] = 0;
1791 v->interfacetable[-i] = NULL;
1794 /* add interfaces */
1796 for (c2 = c; c2 != NULL; c2 = c2->super)
1797 for (i = 0; i < c2->interfacescount; i++) {
1798 class_addinterface (c, c2->interfaces[i]);
1801 /* add finalizer method (not for java.lang.Object) */
1803 if (super != NULL) {
1805 static utf *finame = NULL;
1806 static utf *fidesc = NULL;
1809 finame = utf_finalize;
1811 fidesc = utf_fidesc;
1813 fi = class_findmethod (c, finame, fidesc);
1815 if (!(fi->flags & ACC_STATIC)) {
1825 list_remove (&unlinkedclasses, c);
1826 list_addlast (&linkedclasses, c);
1830 /******************* Function: class_freepool **********************************
1832 Frees all resources used by this classes Constant Pool.
1834 *******************************************************************************/
1836 static void class_freecpool (classinfo *c)
1842 for (idx=0; idx < c->cpcount; idx++) {
1843 tag = c->cptags[idx];
1844 info = c->cpinfos[idx];
1848 case CONSTANT_Fieldref:
1849 case CONSTANT_Methodref:
1850 case CONSTANT_InterfaceMethodref:
1851 FREE (info, constant_FMIref);
1853 case CONSTANT_Integer:
1854 FREE (info, constant_integer);
1856 case CONSTANT_Float:
1857 FREE (info, constant_float);
1860 FREE (info, constant_long);
1862 case CONSTANT_Double:
1863 FREE (info, constant_double);
1865 case CONSTANT_NameAndType:
1866 FREE (info, constant_nameandtype);
1868 case CONSTANT_Arraydescriptor:
1869 freearraydescriptor (info);
1875 MFREE (c -> cptags, u1, c -> cpcount);
1876 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1880 /*********************** Function: class_free **********************************
1882 Frees all resources used by the class.
1884 *******************************************************************************/
1886 static void class_free (classinfo *c)
1891 class_freecpool (c);
1893 MFREE (c->interfaces, classinfo*, c->interfacescount);
1895 for (i = 0; i < c->fieldscount; i++)
1896 field_free(&(c->fields[i]));
1898 MFREE (c->fields, fieldinfo, c->fieldscount);
1901 for (i = 0; i < c->methodscount; i++)
1902 method_free(&(c->methods[i]));
1903 MFREE (c->methods, methodinfo, c->methodscount);
1905 if ((v = c->vftbl) != NULL) {
1906 for (i = 0; i < v->interfacetablelength; i++) {
1907 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1909 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1911 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1912 sizeof(methodptr*) * (v->interfacetablelength -
1913 (v->interfacetablelength > 0));
1914 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1915 (v->interfacetablelength > 1));
1919 if (c->innerclasscount)
1920 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1923 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1));
1925 FREE (c, classinfo);
1928 /************************* Function: class_findfield ***************************
1930 Searches a 'classinfo' structure for a field having the given name and
1933 *******************************************************************************/
1936 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1940 for (i = 0; i < c->fieldscount; i++) {
1941 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1942 return &(c->fields[i]);
1945 panic ("Can not find field given in CONSTANT_Fieldref");
1950 /************************* Function: class_findmethod **************************
1952 Searches a 'classinfo' structure for a method having the given name and
1954 If type is NULL, it is ignored.
1956 *******************************************************************************/
1958 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1961 for (i = 0; i < c->methodscount; i++) {
1962 if ((c->methods[i].name == name) && ((desc == NULL) ||
1963 (c->methods[i].descriptor == desc)))
1964 return &(c->methods[i]);
1969 /************************* Function: class_findmethod_approx ******************
1971 like class_findmethod but ignores the return value when comparing the
1974 *******************************************************************************/
1976 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1980 for (i = 0; i < c->methodscount; i++)
1981 if (c->methods[i].name == name) {
1982 utf *meth_descr = c->methods[i].descriptor;
1986 return &(c->methods[i]);
1988 if (desc->blength <= meth_descr->blength) {
1989 /* current position in utf text */
1990 char *desc_utf_ptr = desc->text;
1991 char *meth_utf_ptr = meth_descr->text;
1992 /* points behind utf strings */
1993 char *desc_end = utf_end(desc);
1994 char *meth_end = utf_end(meth_descr);
1997 /* compare argument types */
1998 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
2000 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
2001 break; /* no match */
2004 return &(c->methods[i]); /* all parameter types equal */
2012 /***************** Function: class_resolvemethod_approx ***********************
2014 Searches a class and every super class for a method (without paying
2015 attention to the return value)
2017 *******************************************************************************/
2019 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2022 /* search for method (ignore returntype) */
2023 methodinfo *m = class_findmethod_approx (c, name, desc);
2026 /* search superclass */
2033 /************************* Function: class_resolvemethod ***********************
2035 Searches a class and every super class for a method.
2037 *******************************************************************************/
2040 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2043 methodinfo *m = class_findmethod (c, name, desc);
2045 /* search superclass */
2053 /************************* Function: class_issubclass **************************
2055 Checks if sub is a descendant of super.
2057 *******************************************************************************/
2059 bool class_issubclass (classinfo *sub, classinfo *super)
2062 if (!sub) return false;
2063 if (sub==super) return true;
2070 /****************** Initialization function for classes ******************
2072 In Java, every class can have a static initialization function. This
2073 function has to be called BEFORE calling other methods or accessing static
2076 *******************************************************************************/
2079 extern int blockInts;
2082 void class_init (classinfo *c)
2085 java_objectheader *exceptionptr;
2090 if (!makeinitializations)
2094 c -> initialized = true;
2097 count_class_inits++;
2101 class_init (c->super);
2102 for (i=0; i < c->interfacescount; i++)
2103 class_init(c->interfaces[i]); /* real */
2105 m = class_findmethod (c, utf_clinit, utf_fidesc);
2108 sprintf (logtext, "Class ");
2109 utf_sprint (logtext+strlen(logtext), c->name);
2110 sprintf (logtext+strlen(logtext), " has no initializer");
2116 if (! (m->flags & ACC_STATIC))
2117 panic ("Class initializer is not static!");
2120 sprintf (logtext, "Starting initializer for class: ");
2121 utf_sprint (logtext+strlen(logtext), c->name);
2130 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2133 assert(blockInts == 0);
2138 printf("#### Initializer of ");
2139 utf_display(c->name);
2140 printf(" has thrown: ");
2141 utf_display(exceptionptr->vftbl->class->name);
2147 sprintf(logtext, "Finished initializer for class: ");
2148 utf_sprint(logtext+strlen(logtext), c->name);
2152 if (c->name == utf_systemclass) {
2153 /* class java.lang.System requires explicit initialization */
2156 printf ("#### Initializing class System");
2158 /* find initializing method */
2159 m = class_findmethod (c,
2160 utf_initsystemclass,
2164 /* no method found */
2165 printf("initializeSystemClass failed");
2174 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2177 assert(blockInts == 0);
2182 printf ("#### initializeSystemClass has thrown: ");
2183 utf_display (exceptionptr->vftbl->class->name);
2193 /********* Function: find_class_method_constant *********/
2194 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2200 for (i=0; i<c->cpcount; i++) {
2202 e = c -> cpinfos [i];
2205 switch (c -> cptags [i]) {
2206 case CONSTANT_Methodref:
2208 constant_FMIref *fmi = e;
2209 if ( (fmi->class->name == c1)
2210 && (fmi->name == m1)
2211 && (fmi->descriptor == d1)) {
2217 case CONSTANT_InterfaceMethodref:
2219 constant_FMIref *fmi = e;
2220 if ( (fmi->class->name == c1)
2221 && (fmi->name == m1)
2222 && (fmi->descriptor == d1)) {
2238 void class_showconstanti(classinfo *c, int ii)
2244 e = c -> cpinfos [i];
2245 printf ("#%d: ", (int) i);
2247 switch (c -> cptags [i]) {
2248 case CONSTANT_Class:
2249 printf ("Classreference -> ");
2250 utf_display ( ((classinfo*)e) -> name );
2253 case CONSTANT_Fieldref:
2254 printf ("Fieldref -> "); goto displayFMIi;
2255 case CONSTANT_Methodref:
2256 printf ("Methodref -> "); goto displayFMIi;
2257 case CONSTANT_InterfaceMethodref:
2258 printf ("InterfaceMethod -> "); goto displayFMIi;
2261 constant_FMIref *fmi = e;
2262 utf_display ( fmi->class->name );
2264 utf_display ( fmi->name);
2266 utf_display ( fmi->descriptor );
2270 case CONSTANT_String:
2271 printf ("String -> ");
2274 case CONSTANT_Integer:
2275 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2277 case CONSTANT_Float:
2278 printf ("Float -> %f", ((constant_float*)e) -> value);
2280 case CONSTANT_Double:
2281 printf ("Double -> %f", ((constant_double*)e) -> value);
2285 u8 v = ((constant_long*)e) -> value;
2287 printf ("Long -> %ld", (long int) v);
2289 printf ("Long -> HI: %ld, LO: %ld\n",
2290 (long int) v.high, (long int) v.low);
2294 case CONSTANT_NameAndType:
2295 { constant_nameandtype *cnt = e;
2296 printf ("NameAndType: ");
2297 utf_display (cnt->name);
2299 utf_display (cnt->descriptor);
2303 printf ("Utf8 -> ");
2306 case CONSTANT_Arraydescriptor: {
2307 printf ("Arraydescriptor: ");
2308 displayarraydescriptor (e);
2312 panic ("Invalid type of ConstantPool-Entry");
2318 void class_showconstantpool (classinfo *c)
2323 printf ("---- dump of constant pool ----\n");
2325 for (i=0; i<c->cpcount; i++) {
2326 printf ("#%d: ", (int) i);
2328 e = c -> cpinfos [i];
2331 switch (c -> cptags [i]) {
2332 case CONSTANT_Class:
2333 printf ("Classreference -> ");
2334 utf_display ( ((classinfo*)e) -> name );
2337 case CONSTANT_Fieldref:
2338 printf ("Fieldref -> "); goto displayFMI;
2339 case CONSTANT_Methodref:
2340 printf ("Methodref -> "); goto displayFMI;
2341 case CONSTANT_InterfaceMethodref:
2342 printf ("InterfaceMethod -> "); goto displayFMI;
2345 constant_FMIref *fmi = e;
2346 utf_display ( fmi->class->name );
2348 utf_display ( fmi->name);
2350 utf_display ( fmi->descriptor );
2354 case CONSTANT_String:
2355 printf ("String -> ");
2358 case CONSTANT_Integer:
2359 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2361 case CONSTANT_Float:
2362 printf ("Float -> %f", ((constant_float*)e) -> value);
2364 case CONSTANT_Double:
2365 printf ("Double -> %f", ((constant_double*)e) -> value);
2369 u8 v = ((constant_long*)e) -> value;
2371 printf ("Long -> %ld", (long int) v);
2373 printf ("Long -> HI: %ld, LO: %ld\n",
2374 (long int) v.high, (long int) v.low);
2378 case CONSTANT_NameAndType:
2379 { constant_nameandtype *cnt = e;
2380 printf ("NameAndType: ");
2381 utf_display (cnt->name);
2383 utf_display (cnt->descriptor);
2387 printf ("Utf8 -> ");
2390 case CONSTANT_Arraydescriptor: {
2391 printf ("Arraydescriptor: ");
2392 displayarraydescriptor (e);
2396 panic ("Invalid type of ConstantPool-Entry");
2408 /********** Function: class_showmethods (debugging only) *************/
2410 void class_showmethods (classinfo *c)
2414 printf ("--------- Fields and Methods ----------------\n");
2415 printf ("Flags: "); printflags (c->flags); printf ("\n");
2417 printf ("This: "); utf_display (c->name); printf ("\n");
2419 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2421 printf ("Index: %d\n", c->index);
2423 printf ("interfaces:\n");
2424 for (i=0; i < c-> interfacescount; i++) {
2426 utf_display (c -> interfaces[i] -> name);
2427 printf (" (%d)\n", c->interfaces[i] -> index);
2430 printf ("fields:\n");
2431 for (i=0; i < c -> fieldscount; i++) {
2432 field_display (&(c -> fields[i]));
2435 printf ("methods:\n");
2436 for (i=0; i < c -> methodscount; i++) {
2437 methodinfo *m = &(c->methods[i]);
2438 if ( !(m->flags & ACC_STATIC))
2439 printf ("vftblindex: %d ", m->vftblindex);
2441 method_display ( m );
2445 printf ("Virtual function table:\n");
2446 for (i=0; i<c->vftbl->vftbllength; i++) {
2447 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2454 /******************************************************************************/
2455 /******************* General functions for the class loader *******************/
2456 /******************************************************************************/
2458 static int loader_inited = 0;
2460 /********************* Function: loader_load ***********************************
2462 Loads and links the class desired class and each class and interface
2464 Returns: a pointer to this class
2466 *******************************************************************************/
2468 classinfo *loader_load (utf *topname)
2472 long int starttime=0,stoptime=0;
2474 intsDisable(); /* schani */
2477 starttime = getcputime();
2479 top = class_new (topname);
2482 while ( (c = list_first(&unloadedclasses)) ) {
2483 if (!class_load (c)) {
2484 list_remove (&unloadedclasses, c);
2490 while ( (c = list_first(&unlinkedclasses)) ) {
2495 loader_compute_subclasses();
2498 if (getloadingtime) {
2499 stoptime = getcputime();
2500 loadingtime += (stoptime-starttime);
2503 intsRestore(); /* schani */
2509 /**************** function: create_primitive_classes ***************************
2511 create classes representing primitive types
2513 ********************************************************************************/
2516 void create_primitive_classes()
2520 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2521 /* create primitive class */
2522 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2523 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2524 c -> impldBy = NULL;
2526 /* prevent loader from loading primitive class */
2527 list_remove (&unloadedclasses, c);
2528 /* add to unlinked classes */
2529 list_addlast (&unlinkedclasses, c);
2530 c -> super = class_java_lang_Object;
2533 primitivetype_table[i].class_primitive = c;
2535 /* create class for wrapping the primitive type */
2536 primitivetype_table[i].class_wrap =
2537 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2538 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2539 primitivetype_table[i].class_wrap -> impldBy = NULL;
2543 /***************** function: create_array_class ********************************
2545 create class representing an array
2547 ********************************************************************************/
2550 classinfo *create_array_class(utf *u)
2552 classinfo *c = class_new (u);
2553 /* prevent loader from loading the array class */
2554 list_remove (&unloadedclasses, c);
2555 /* add to unlinked classes */
2556 list_addlast (&unlinkedclasses, c);
2557 c -> super = class_java_lang_Object;
2563 /********************** Function: loader_init **********************************
2565 Initializes all lists and loads all classes required for the system or the
2568 *******************************************************************************/
2575 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2576 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2577 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2579 /* create utf-symbols for pointer comparison of frequently used strings */
2580 utf_innerclasses = utf_new_char("InnerClasses");
2581 utf_constantvalue = utf_new_char("ConstantValue");
2582 utf_code = utf_new_char("Code");
2583 utf_finalize = utf_new_char("finalize");
2584 utf_fidesc = utf_new_char("()V");
2585 utf_clinit = utf_new_char("<clinit>");
2586 utf_initsystemclass = utf_new_char("initializeSystemClass");
2587 utf_systemclass = utf_new_char("java/lang/System");
2589 /* create class for arrays */
2590 class_array = class_new ( utf_new_char ("The_Array_Class") );
2591 class_array -> classUsed = NOTUSED; /* not used initially CO-RT */
2592 class_array -> impldBy = NULL;
2594 list_remove (&unloadedclasses, class_array);
2596 /* create class for strings, load it after class Object was loaded */
2597 string_class = utf_new_char ("java/lang/String");
2598 class_java_lang_String = class_new(string_class);
2599 class_java_lang_String -> classUsed = NOTUSED; /* not used initially CO-RT */
2600 class_java_lang_String -> impldBy = NULL;
2602 list_remove (&unloadedclasses, class_java_lang_String);
2604 class_java_lang_Object =
2605 loader_load ( utf_new_char ("java/lang/Object") );
2607 list_addlast(&unloadedclasses, class_java_lang_String);
2609 class_java_lang_String =
2610 loader_load ( string_class );
2611 class_java_lang_ClassCastException =
2612 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2613 class_java_lang_NullPointerException =
2614 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2615 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2616 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2617 class_java_lang_NegativeArraySizeException = loader_load (
2618 utf_new_char ("java/lang/NegativeArraySizeException") );
2619 class_java_lang_OutOfMemoryError = loader_load (
2620 utf_new_char ("java/lang/OutOfMemoryError") );
2621 class_java_lang_ArrayStoreException =
2622 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2623 class_java_lang_ArithmeticException =
2624 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2625 class_java_lang_ThreadDeath = /* schani */
2626 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2628 /* link class for arrays */
2629 list_addlast (&unlinkedclasses, class_array);
2630 class_array -> super = class_java_lang_Object;
2631 class_link (class_array);
2633 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2634 stringtable_update();
2636 /* create classes representing primitive types */
2637 create_primitive_classes();
2639 proto_java_lang_ClassCastException =
2640 builtin_new(class_java_lang_ClassCastException);
2641 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2643 proto_java_lang_NullPointerException =
2644 builtin_new(class_java_lang_NullPointerException);
2645 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2647 proto_java_lang_ArrayIndexOutOfBoundsException =
2648 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2649 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2651 proto_java_lang_NegativeArraySizeException =
2652 builtin_new(class_java_lang_NegativeArraySizeException);
2653 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2655 proto_java_lang_OutOfMemoryError =
2656 builtin_new(class_java_lang_OutOfMemoryError);
2657 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2659 proto_java_lang_ArithmeticException =
2660 builtin_new(class_java_lang_ArithmeticException);
2661 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2663 proto_java_lang_ArrayStoreException =
2664 builtin_new(class_java_lang_ArrayStoreException);
2665 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2667 proto_java_lang_ThreadDeath = /* schani */
2668 builtin_new(class_java_lang_ThreadDeath);
2669 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2677 /********************* Function: loader_initclasses ****************************
2679 Initializes all loaded but uninitialized classes
2681 *******************************************************************************/
2683 void loader_initclasses ()
2687 intsDisable(); /* schani */
2689 if (makeinitializations) {
2690 c = list_first (&linkedclasses);
2693 c = list_next (&linkedclasses, c);
2697 intsRestore(); /* schani */
2700 static s4 classvalue;
2702 static void loader_compute_class_values (classinfo *c)
2706 c->vftbl->baseval = ++classvalue;
2709 while (subs != NULL) {
2710 loader_compute_class_values(subs);
2711 subs = subs->nextsub;
2713 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2718 for (i = 0; i < c->index; i++)
2720 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2721 utf_display(c->name);
2728 void loader_compute_subclasses ()
2732 intsDisable(); /* schani */
2734 c = list_first (&linkedclasses);
2736 if (!(c->flags & ACC_INTERFACE)) {
2740 c = list_next (&linkedclasses, c);
2743 c = list_first (&linkedclasses);
2745 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2746 c->nextsub = c->super->sub;
2749 c = list_next (&linkedclasses, c);
2752 loader_compute_class_values(class_java_lang_Object);
2754 intsRestore(); /* schani */
2759 /******************** function classloader_buffer ******************************
2761 sets buffer for reading classdata
2763 *******************************************************************************/
2765 void classload_buffer(u1 *buf, int len)
2768 classbuffer_size = len;
2769 classbuf_pos = buf - 1;
2773 /******************** Function: loader_close ***********************************
2777 *******************************************************************************/
2779 void loader_close ()
2783 while ( (c=list_first(&unloadedclasses)) ) {
2784 list_remove (&unloadedclasses,c);
2787 while ( (c=list_first(&unlinkedclasses)) ) {
2788 list_remove (&unlinkedclasses,c);
2791 while ( (c=list_first(&linkedclasses)) ) {
2792 list_remove (&linkedclasses,c);
2799 * These are local overrides for various environment variables in Emacs.
2800 * Please do not remove this and leave it at the end of the file, where
2801 * Emacs will automagically detect them.
2802 * ---------------------------------------------------------------------
2805 * indent-tabs-mode: t