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 */
48 int count_class_infos = 0; /* variables for measurements */
49 int count_const_pool_len = 0;
50 int count_vftbl_len = 0;
51 int count_all_methods = 0;
52 int count_vmcode_len = 0;
53 int count_extable_len = 0;
54 int count_class_loads = 0;
55 int count_class_inits = 0;
57 bool loadverbose = false; /* switches for debug messages */
58 bool linkverbose = false;
59 bool initverbose = false;
61 bool makeinitializations = true;
63 bool getloadingtime = false; /* to measure the runtime */
64 long int loadingtime = 0;
66 static s4 interfaceindex; /* sequential numbering of interfaces */
68 list unloadedclasses; /* list of all referenced but not loaded classes */
69 list unlinkedclasses; /* list of all loaded but not linked classes */
70 list linkedclasses; /* list of all completely linked classes */
73 /* utf-symbols for pointer comparison of frequently used strings */
75 static utf *utf_innerclasses; /* InnerClasses */
76 static utf *utf_constantvalue; /* ConstantValue */
77 static utf *utf_code; /* Code */
78 static utf *utf_finalize; /* finalize */
79 static utf *utf_fidesc; /* ()V */
80 static utf *utf_clinit; /* <clinit> */
81 static utf *utf_initsystemclass; /* initializeSystemClass */
82 static utf *utf_systemclass; /* java/lang/System */
85 /* important system classes ***************************************************/
87 classinfo *class_java_lang_Object;
88 classinfo *class_java_lang_String;
89 classinfo *class_array = NULL;
92 /* These are made static so they cannot be used for throwing in native */
94 static classinfo *class_java_lang_ClassCastException;
95 static classinfo *class_java_lang_NullPointerException;
96 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
97 static classinfo *class_java_lang_NegativeArraySizeException;
98 static classinfo *class_java_lang_OutOfMemoryError;
99 static classinfo *class_java_lang_ArithmeticException;
100 static classinfo *class_java_lang_ArrayStoreException;
101 static classinfo *class_java_lang_ThreadDeath;
104 /******************************************************************************
106 structure for primitive classes: contains the class for wrapping the
107 primitive type, the primitive class, the name of the class for wrapping,
108 the one character type signature and the name of the primitive class
110 ******************************************************************************/
112 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
113 { NULL, NULL, "java/lang/Double", 'D', "double" },
114 { NULL, NULL, "java/lang/Float", 'F', "float" },
115 { NULL, NULL, "java/lang/Character", 'C', "char" },
116 { NULL, NULL, "java/lang/Integer", 'I', "int" },
117 { NULL, NULL, "java/lang/Long", 'J', "long" },
118 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
119 { NULL, NULL, "java/lang/Short", 'S', "short" },
120 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
121 { NULL, NULL, "java/lang/Void", 'V', "void" }};
124 /* instances of important system classes **************************************/
126 java_objectheader *proto_java_lang_ClassCastException;
127 java_objectheader *proto_java_lang_NullPointerException;
128 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
129 java_objectheader *proto_java_lang_NegativeArraySizeException;
130 java_objectheader *proto_java_lang_OutOfMemoryError;
131 java_objectheader *proto_java_lang_ArithmeticException;
132 java_objectheader *proto_java_lang_ArrayStoreException;
133 java_objectheader *proto_java_lang_ThreadDeath;
136 /************* functions for reading classdata *********************************
138 getting classdata in blocks of variable size
139 (8,16,32,64-bit integer or float)
141 *******************************************************************************/
143 static char *classpath = ""; /* searchpath for classfiles */
144 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
145 static u1 *classbuf_pos; /* current position in classfile buffer */
146 static int classbuffer_size; /* size of classfile-data */
148 /* transfer block of classfile data into a buffer */
150 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
153 /* skip block of classfile data */
155 #define skip_nbytes(len) classbuf_pos+=len;
159 return *++classbuf_pos;
163 u1 a=suck_u1(), b=suck_u1();
164 return ((u2)a<<8)+(u2)b;
168 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
169 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
171 #define suck_s8() (s8) suck_u8()
172 #define suck_s2() (s2) suck_u2()
173 #define suck_s4() (s4) suck_u4()
174 #define suck_s1() (s1) suck_u1()
177 /* get u8 from classfile data */
185 return (hi<<32) + lo;
194 /* get float from classfile data */
196 static float suck_float ()
203 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
204 memcpy ( (u1*) (&f), buffer, 4);
206 suck_nbytes ( (u1*) (&f), 4 );
209 PANICIF (sizeof(float) != 4, "Incompatible float-format");
214 /* get double from classfile data */
215 static double suck_double ()
222 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
223 memcpy ( (u1*) (&d), buffer, 8);
225 suck_nbytes ( (u1*) (&d), 8 );
228 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
233 /************************** function suck_init *********************************
235 called once at startup, sets the searchpath for the classfiles
237 *******************************************************************************/
239 void suck_init (char *cpath)
246 /************************** function suck_start ********************************
248 returns true if classbuffer is already loaded or a file for the
249 specified class has succussfully been read in. All directories of
250 the searchpath are used to find the classfile (<classname>.class).
251 Returns false if no classfile is found and writes an error message.
253 *******************************************************************************/
256 bool suck_start (utf *classname) {
258 #define MAXFILENAME 1000 /* maximum length of a filename */
260 char filename[MAXFILENAME+10]; /* room for '.class' */
261 char *pathpos; /* position in searchpath */
262 char c, *utf_ptr; /* pointer to the next utf8-character */
264 int filenamelen, err;
267 if (classbuffer) /* classbuffer is already valid */
274 /* skip path separator */
276 while (*pathpos == ':')
279 /* extract directory from searchpath */
282 while ((*pathpos) && (*pathpos!=':')) {
283 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
284 filename[filenamelen++] = *(pathpos++);
287 filename[filenamelen++] = '/';
289 /* add classname to filename */
291 utf_ptr = classname->text;
292 while (utf_ptr < utf_end(classname)) {
293 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
295 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
297 filename[filenamelen++] = c;
302 strcpy (filename+filenamelen, ".class");
304 classfile = fopen(filename, "r");
305 if (classfile) { /* file exists */
307 /* determine size of classfile */
309 err = stat (filename, &buffer);
311 if (!err) { /* read classfile data */
312 classbuffer_size = buffer.st_size;
313 classbuffer = MNEW(u1, classbuffer_size);
314 classbuf_pos = classbuffer-1;
315 fread(classbuffer, 1, classbuffer_size, classfile);
323 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
331 /************************** function suck_stop *********************************
333 frees memory for buffer with classfile data.
334 Caution: this function may only be called if buffer has been allocated
335 by suck_start with reading a file
337 *******************************************************************************/
341 /* determine amount of classdata not retrieved by suck-operations */
343 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
345 if (classdata_left > 0) {
347 sprintf (logtext,"There are %d access bytes at end of classfile",
354 MFREE(classbuffer, u1, classbuffer_size);
358 /******************************************************************************/
359 /******************* Some support functions ***********************************/
360 /******************************************************************************/
364 void fprintflags (FILE *fp, u2 f)
366 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
367 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
368 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
369 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
370 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
371 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
372 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
373 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
374 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
375 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
376 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
379 /********** internal function: printflags (only for debugging) ***************/
380 void printflags (u2 f)
382 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
383 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
384 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
385 if ( f & ACC_STATIC ) printf (" STATIC");
386 if ( f & ACC_FINAL ) printf (" FINAL");
387 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
388 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
389 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
390 if ( f & ACC_NATIVE ) printf (" NATIVE");
391 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
392 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
396 /************************* Function: skipattribute *****************************
398 skips a (1) 'attribute' structure in the class file
400 *******************************************************************************/
402 static void skipattribute ()
405 skip_nbytes(suck_u4());
408 /********************** Function: skipattributebody ****************************
410 skips an attribute after the 16 bit reference to attribute_name has already
413 *******************************************************************************/
415 static void skipattributebody ()
417 skip_nbytes(suck_u4());
420 /************************* Function: skipattributes ****************************
422 skips num attribute structures
424 *******************************************************************************/
426 static void skipattributes (u4 num)
429 for (i = 0; i < num; i++)
433 /******************** function: innerclass_getconstant ************************
435 like class_getconstant, but if cptags is ZERO null is returned
437 *******************************************************************************/
439 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
441 /* invalid position in constantpool */
442 if (pos >= c->cpcount)
443 panic ("Attempt to access constant outside range");
445 /* constantpool entry of type 0 */
449 /* check type of constantpool entry */
450 if (c->cptags[pos] != ctype) {
451 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
452 (int) ctype, (int) c->cptags[pos] );
456 return c->cpinfos[pos];
459 /************************ function: attribute_load ****************************
461 read attributes from classfile
463 *******************************************************************************/
465 static void attribute_load (u4 num, classinfo *c)
469 for (i = 0; i < num; i++) {
470 /* retrieve attribute name */
471 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
473 if ( aname == utf_innerclasses) {
474 /* innerclasses attribute */
476 /* skip attribute length */
478 /* number of records */
479 c->innerclasscount = suck_u2();
480 /* allocate memory for innerclass structure */
481 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
483 for (j=0;j<c->innerclasscount;j++) {
485 /* The innerclass structure contains a class with an encoded name,
486 its defining scope, its simple name and a bitmask of the access flags.
487 If an inner class is not a member, its outer_class is NULL,
488 if a class is anonymous, its name is NULL. */
490 innerclassinfo *info = c->innerclass + j;
492 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
493 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
494 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
495 info->flags = suck_u2 (); /* access_flags bitmask */
498 /* unknown attribute */
499 skipattributebody ();
504 /******************* function: checkfielddescriptor ****************************
506 checks whether a field-descriptor is valid and aborts otherwise
507 all referenced classes are inserted into the list of unloaded classes
509 *******************************************************************************/
511 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
513 char *tstart; /* pointer to start of classname */
516 switch (*utf_ptr++) {
529 /* save start of classname */
532 /* determine length of classname */
533 while ( *utf_ptr++ != ';' )
534 if (utf_ptr>=end_pos)
535 panic ("Missing ';' in objecttype-descriptor");
537 /* cause loading of referenced class */
538 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
543 while ((ch = *utf_ptr++)=='[')
546 /* component type of array */
560 /* save start of classname */
563 /* determine length of classname */
564 while ( *utf_ptr++ != ';' )
565 if (utf_ptr>=end_pos)
566 panic ("Missing ';' in objecttype-descriptor");
568 /* cause loading of referenced class */
569 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
573 panic ("Ill formed methodtype-descriptor");
578 panic ("Ill formed methodtype-descriptor");
581 /* exceeding characters */
582 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
586 /******************* function checkmethoddescriptor ****************************
588 checks whether a method-descriptor is valid and aborts otherwise.
589 All referenced classes are inserted into the list of unloaded classes.
591 *******************************************************************************/
593 static void checkmethoddescriptor (utf *d)
595 char *utf_ptr = d->text; /* current position in utf text */
596 char *end_pos = utf_end(d); /* points behind utf string */
597 char *tstart; /* pointer to start of classname */
600 /* method descriptor must start with parenthesis */
601 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
603 /* check arguments */
604 while ((c = *utf_ptr++) != ')') {
618 /* save start of classname */
621 /* determine length of classname */
622 while ( *utf_ptr++ != ';' )
623 if (utf_ptr>=end_pos)
624 panic ("Missing ';' in objecttype-descriptor");
626 /* cause loading of referenced class */
627 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
632 while ((ch = *utf_ptr++)=='[')
635 /* component type of array */
649 /* save start of classname */
652 /* determine length of classname */
653 while ( *utf_ptr++ != ';' )
654 if (utf_ptr>=end_pos)
655 panic ("Missing ';' in objecttype-descriptor");
657 /* cause loading of referenced class */
658 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
662 panic ("Ill formed methodtype-descriptor");
667 panic ("Ill formed methodtype-descriptor");
671 /* check returntype */
673 /* returntype void */
674 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
677 /* treat as field-descriptor */
678 checkfielddescriptor (utf_ptr,end_pos);
682 /******************** Function: buildarraydescriptor ***************************
684 creates a constant_arraydescriptor structure for the array type named by an
687 *******************************************************************************/
689 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
691 constant_arraydescriptor *d;
693 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
695 d = NEW (constant_arraydescriptor);
696 d -> objectclass = NULL;
697 d -> elementdescriptor = NULL;
700 count_const_pool_len += sizeof(constant_arraydescriptor);
704 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
705 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
706 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
707 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
708 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
709 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
710 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
711 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
714 d -> arraytype = ARRAYTYPE_ARRAY;
715 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
719 d -> arraytype = ARRAYTYPE_OBJECT;
721 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
722 d -> objectclass -> classUsed = 0; /* not used initially CO-RT */
723 d -> objectclass -> impldBy = NULL;
724 d -> objectclass -> nextimpldBy = 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 */
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;
931 m -> XTAclasscount = 0;
934 if (! (m->flags & ACC_NATIVE) ) {
935 m -> stubroutine = createcompilerstub (m);
939 functionptr f = native_findfunction
940 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
945 m -> stubroutine = createnativestub (f, m);
948 m -> stubroutine = oldcreatenativestub (f, m);
955 for (i=0; i<attrnum; i++) {
958 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
960 if ( aname != utf_code) {
961 skipattributebody ();
964 if (m -> jcode) panic ("Two code-attributes for one method!");
967 m -> maxstack = suck_u2();
968 m -> maxlocals = suck_u2();
969 m -> jcodelength = suck_u4();
970 m -> jcode = MNEW (u1, m->jcodelength);
971 suck_nbytes (m->jcode, m->jcodelength);
972 m -> exceptiontablelength = suck_u2 ();
973 m -> exceptiontable =
974 MNEW (exceptiontable, m->exceptiontablelength);
977 count_vmcode_len += m->jcodelength + 18;
978 count_extable_len += 8 * m->exceptiontablelength;
981 for (e=0; e < m->exceptiontablelength; e++) {
983 m -> exceptiontable[e].startpc = suck_u2();
984 m -> exceptiontable[e].endpc = suck_u2();
985 m -> exceptiontable[e].handlerpc = suck_u2();
988 if (!idx) m -> exceptiontable[e].catchtype = NULL;
990 m -> exceptiontable[e].catchtype =
991 class_getconstant (c, idx, CONSTANT_Class);
995 skipattributes ( suck_u2() );
1002 /********************* Function: method_free ***********************************
1004 frees all memory that was allocated for this method
1006 *******************************************************************************/
1008 static void method_free (methodinfo *m)
1010 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
1011 if (m->exceptiontable)
1012 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
1013 if (m->mcode) CFREE (m->mcode, m->mcodelength);
1014 if (m->stubroutine) {
1015 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
1016 else removecompilerstub (m->stubroutine);
1021 /************** Function: method_display (debugging only) **************/
1023 void method_display (methodinfo *m)
1026 printflags (m -> flags);
1028 utf_display (m -> name);
1030 utf_display (m -> descriptor);
1035 /******************** Function: method_canoverwrite ****************************
1037 Check if m and old are identical with respect to type and name. This means
1038 that old can be overwritten with m.
1040 *******************************************************************************/
1042 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1044 if (m->name != old->name) return false;
1045 if (m->descriptor != old->descriptor) return false;
1046 if (m->flags & ACC_STATIC) return false;
1053 /******************************************************************************/
1054 /************************ Functions for class *********************************/
1055 /******************************************************************************/
1058 /******************** function:: class_getconstant ******************************
1060 retrieves the value at position 'pos' of the constantpool of a class
1061 if the type of the value is other than 'ctype' the system is stopped
1063 *******************************************************************************/
1065 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1067 /* invalid position in constantpool */
1068 if (pos >= c->cpcount)
1069 panic ("Attempt to access constant outside range");
1071 /* check type of constantpool entry */
1072 if (c->cptags[pos] != ctype) {
1073 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1074 (int) ctype, (int) c->cptags[pos] );
1078 return c->cpinfos[pos];
1082 /********************* Function: class_constanttype ****************************
1084 Determines the type of a class entry in the ConstantPool
1086 *******************************************************************************/
1088 u4 class_constanttype (classinfo *c, u4 pos)
1090 if (pos >= c->cpcount)
1091 panic ("Attempt to access constant outside range");
1092 return c->cptags[pos];
1096 /******************** function: class_loadcpool ********************************
1098 loads the constantpool of a class,
1099 the entries are transformed into a simpler format
1100 by resolving references
1101 (a detailed overview of the compact structures can be found in global.h)
1103 *******************************************************************************/
1105 static void class_loadcpool (classinfo *c)
1108 /* The following structures are used to save information which cannot be
1109 processed during the first pass. After the complete constantpool has
1110 been traversed the references can be resolved.
1111 (only in specific order) */
1113 /* CONSTANT_Class_info entries */
1114 typedef struct forward_class {
1115 struct forward_class *next;
1120 /* CONSTANT_String */
1121 typedef struct forward_string {
1122 struct forward_string *next;
1127 /* CONSTANT_NameAndType */
1128 typedef struct forward_nameandtype {
1129 struct forward_nameandtype *next;
1133 } forward_nameandtype;
1135 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1136 typedef struct forward_fieldmethint {
1137 struct forward_fieldmethint *next;
1141 u2 nameandtype_index;
1142 } forward_fieldmethint;
1146 long int dumpsize = dump_size ();
1148 forward_class *forward_classes = NULL;
1149 forward_string *forward_strings = NULL;
1150 forward_nameandtype *forward_nameandtypes = NULL;
1151 forward_fieldmethint *forward_fieldmethints = NULL;
1153 /* number of entries in the constant_pool table */
1154 u4 cpcount = c -> cpcount = suck_u2();
1155 /* allocate memory */
1156 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1157 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1160 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1163 /* initialize constantpool */
1164 for (idx=0; idx<cpcount; idx++) {
1165 cptags[idx] = CONSTANT_UNUSED;
1166 cpinfos[idx] = NULL;
1170 /******* first pass *******/
1171 /* entries which cannot be resolved now are written into
1172 temporary structures and traversed again later */
1175 while (idx < cpcount) {
1176 /* get constant type */
1180 case CONSTANT_Class: {
1181 forward_class *nfc = DNEW(forward_class);
1183 nfc -> next = forward_classes;
1184 forward_classes = nfc;
1186 nfc -> thisindex = idx;
1187 /* reference to CONSTANT_NameAndType */
1188 nfc -> name_index = suck_u2 ();
1194 case CONSTANT_Fieldref:
1195 case CONSTANT_Methodref:
1196 case CONSTANT_InterfaceMethodref: {
1197 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1199 nff -> next = forward_fieldmethints;
1200 forward_fieldmethints = nff;
1202 nff -> thisindex = idx;
1205 /* class or interface type that contains the declaration of the field or method */
1206 nff -> class_index = suck_u2 ();
1207 /* name and descriptor of the field or method */
1208 nff -> nameandtype_index = suck_u2 ();
1214 case CONSTANT_String: {
1215 forward_string *nfs = DNEW (forward_string);
1217 nfs -> next = forward_strings;
1218 forward_strings = nfs;
1220 nfs -> thisindex = idx;
1221 /* reference to CONSTANT_Utf8_info with string characters */
1222 nfs -> string_index = suck_u2 ();
1228 case CONSTANT_NameAndType: {
1229 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1231 nfn -> next = forward_nameandtypes;
1232 forward_nameandtypes = nfn;
1234 nfn -> thisindex = idx;
1235 /* reference to CONSTANT_Utf8_info containing simple name */
1236 nfn -> name_index = suck_u2 ();
1237 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1238 nfn -> sig_index = suck_u2 ();
1244 case CONSTANT_Integer: {
1245 constant_integer *ci = NEW (constant_integer);
1248 count_const_pool_len += sizeof(constant_integer);
1251 ci -> value = suck_s4 ();
1252 cptags [idx] = CONSTANT_Integer;
1259 case CONSTANT_Float: {
1260 constant_float *cf = NEW (constant_float);
1263 count_const_pool_len += sizeof(constant_float);
1266 cf -> value = suck_float ();
1267 cptags [idx] = CONSTANT_Float;
1273 case CONSTANT_Long: {
1274 constant_long *cl = NEW(constant_long);
1277 count_const_pool_len += sizeof(constant_long);
1280 cl -> value = suck_s8 ();
1281 cptags [idx] = CONSTANT_Long;
1287 case CONSTANT_Double: {
1288 constant_double *cd = NEW(constant_double);
1291 count_const_pool_len += sizeof(constant_double);
1294 cd -> value = suck_double ();
1295 cptags [idx] = CONSTANT_Double;
1301 case CONSTANT_Utf8: {
1303 /* number of bytes in the bytes array (not string-length) */
1304 u4 length = suck_u2();
1305 cptags [idx] = CONSTANT_Utf8;
1306 /* insert utf-string into the utf-symboltable */
1307 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1308 /* skip bytes of the string */
1309 skip_nbytes(length);
1315 sprintf (logtext, "Unkown constant type: %d",(int) t);
1324 /* resolve entries in temporary structures */
1326 while (forward_classes) {
1328 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1330 if ( (name->blength>0) && (name->text[0]=='[') ) {
1331 /* check validity of descriptor */
1332 checkfielddescriptor (name->text, utf_end(name));
1334 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1335 cpinfos [forward_classes -> thisindex] =
1336 buildarraydescriptor(name->text, name->blength);
1340 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1341 /* retrieve class from class-table */
1342 cpinfos [forward_classes -> thisindex] = class_new (name);
1344 forward_classes = forward_classes -> next;
1348 while (forward_strings) {
1350 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1352 /* resolve utf-string */
1353 cptags [forward_strings -> thisindex] = CONSTANT_String;
1354 cpinfos [forward_strings -> thisindex] = text;
1356 forward_strings = forward_strings -> next;
1359 while (forward_nameandtypes) {
1360 constant_nameandtype *cn = NEW (constant_nameandtype);
1363 count_const_pool_len += sizeof(constant_nameandtype);
1366 /* resolve simple name and descriptor */
1367 cn -> name = class_getconstant
1368 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1369 cn -> descriptor = class_getconstant
1370 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1372 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1373 cpinfos [forward_nameandtypes -> thisindex] = cn;
1375 forward_nameandtypes = forward_nameandtypes -> next;
1379 while (forward_fieldmethints) {
1380 constant_nameandtype *nat;
1381 constant_FMIref *fmi = NEW (constant_FMIref);
1384 count_const_pool_len += sizeof(constant_FMIref);
1386 /* resolve simple name and descriptor */
1387 nat = class_getconstant
1388 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1390 fmi -> class = class_getconstant
1391 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1392 fmi -> name = nat -> name;
1393 fmi -> descriptor = nat -> descriptor;
1395 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1396 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1398 switch (forward_fieldmethints -> tag) {
1399 case CONSTANT_Fieldref: /* check validity of descriptor */
1400 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1402 case CONSTANT_InterfaceMethodref:
1403 case CONSTANT_Methodref: /* check validity of descriptor */
1404 checkmethoddescriptor (fmi->descriptor);
1408 forward_fieldmethints = forward_fieldmethints -> next;
1413 dump_release (dumpsize);
1417 /********************** Function: class_load ***********************************
1419 Loads everything interesting about a class from the class file. The
1420 'classinfo' structure must have been allocated previously.
1422 The super class and the interfaces implemented by this class need not be
1423 loaded. The link is set later by the function 'class_link'.
1425 The loaded class is removed from the list 'unloadedclasses' and added to
1426 the list 'unlinkedclasses'.
1428 *******************************************************************************/
1430 static int class_load (classinfo *c)
1436 count_class_loads++;
1439 /* output for debugging purposes */
1442 sprintf (logtext, "Loading class: ");
1443 utf_sprint (logtext+strlen(logtext), c->name );
1447 /* load classdata, throw exception on error */
1448 if (!suck_start (c->name)) {
1449 throw_classnotfoundexception();
1453 /* check signature */
1454 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1458 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1459 sprintf (logtext, "File version %d.%d is not supported",
1460 (int) ma, (int) mi);
1465 class_loadcpool (c);
1467 c -> classUsed = 0; /* not used initially CO-RT */
1468 c -> impldBy = NULL;
1469 c -> nextimpldBy = NULL;
1472 c -> flags = suck_u2 ();
1476 /* retrieve superclass */
1477 if ( (i = suck_u2 () ) ) {
1478 c -> super = class_getconstant (c, i, CONSTANT_Class);
1484 /* retrieve interfaces */
1485 c -> interfacescount = suck_u2 ();
1486 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1487 for (i=0; i < c -> interfacescount; i++) {
1488 c -> interfaces [i] =
1489 class_getconstant (c, suck_u2(), CONSTANT_Class);
1493 c -> fieldscount = suck_u2 ();
1495 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1497 c -> fields = MNEW (fieldinfo, c -> fieldscount);
1499 for (i=0; i < c -> fieldscount; i++) {
1500 field_load (&(c->fields[i]), c);
1504 c -> methodscount = suck_u2 ();
1505 c -> methods = MNEW (methodinfo, c -> methodscount);
1506 for (i=0; i < c -> methodscount; i++) {
1507 method_load (&(c -> methods [i]), c);
1511 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1512 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1513 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1516 /* load variable-length attribute structures */
1517 attribute_load (suck_u2(), c);
1522 /* remove class from list of unloaded classes and
1523 add to list of unlinked classes */
1524 list_remove (&unloadedclasses, c);
1525 list_addlast (&unlinkedclasses, c);
1532 /************** internal Function: class_highestinterface ***********************
1534 Used by the function class_link to determine the amount of memory needed
1535 for the interface table.
1537 *******************************************************************************/
1539 static s4 class_highestinterface (classinfo *c)
1544 if ( ! (c->flags & ACC_INTERFACE) ) {
1545 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1546 utf_sprint (logtext+strlen(logtext), c->name);
1551 for (i=0; i<c->interfacescount; i++) {
1552 s4 h2 = class_highestinterface (c->interfaces[i]);
1559 /* class_addinterface **********************************************************
1561 Is needed by class_link for adding a VTBL to a class. All interfaces
1562 implemented by ic are added as well.
1564 *******************************************************************************/
1566 static void class_addinterface (classinfo *c, classinfo *ic)
1570 vftbl *vftbl = c->vftbl;
1572 if (i >= vftbl->interfacetablelength)
1573 panic ("Inernal error: interfacetable overflow");
1574 if (vftbl->interfacetable[-i])
1577 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1578 vftbl->interfacevftbllength[i] = 1;
1579 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1580 vftbl->interfacetable[-i][0] = NULL;
1583 vftbl->interfacevftbllength[i] = ic->methodscount;
1584 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1587 count_vftbl_len += sizeof(methodptr) *
1588 (ic->methodscount + (ic->methodscount == 0));
1591 for (j=0; j<ic->methodscount; j++) {
1594 for (m = 0; m < sc->methodscount; m++) {
1595 methodinfo *mi = &(sc->methods[m]);
1596 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1597 vftbl->interfacetable[-i][j] =
1598 vftbl->table[mi->vftblindex];
1608 for (j = 0; j < ic->interfacescount; j++)
1609 class_addinterface(c, ic->interfaces[j]);
1613 /********************** Function: class_link ***********************************
1615 Tries to link a class. The super class and every implemented interface must
1616 already have been linked. The function calculates the length in bytes that
1617 an instance of this class requires as well as the VTBL for methods and
1620 If the class can be linked, it is removed from the list 'unlinkedclasses'
1621 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1624 Attention: If cyclical class definitions are encountered, the program gets
1625 into an infinite loop (we'll have to work that out)
1627 *******************************************************************************/
1629 static void class_link (classinfo *c)
1631 s4 supervftbllength; /* vftbllegnth of super class */
1632 s4 vftbllength; /* vftbllength of current class */
1633 s4 interfacetablelength; /* interface table length */
1634 classinfo *super = c->super; /* super class */
1635 classinfo *ic, *c2; /* intermediate class variables */
1636 vftbl *v; /* vftbl of current class */
1637 s4 i; /* interface/method/field counter */
1640 /* check if all superclasses are already linked, if not put c at end of
1641 unlinked list and return. Additionally initialize class fields. */
1643 /* check interfaces */
1645 for (i = 0; i < c->interfacescount; i++) {
1646 ic = c->interfaces[i];
1648 list_remove(&unlinkedclasses, c);
1649 list_addlast(&unlinkedclasses, c);
1654 /* check super class */
1656 if (super == NULL) { /* class java.long.Object */
1658 c->classUsed = 1; /* Object class is always used CO-RT*/
1659 c -> impldBy = NULL;
1660 c -> nextimpldBy = NULL;
1661 c->instancesize = sizeof(java_objectheader);
1663 vftbllength = supervftbllength = 0;
1665 c->finalizer = NULL;
1668 if (!super->linked) {
1669 list_remove(&unlinkedclasses, c);
1670 list_addlast(&unlinkedclasses, c);
1674 if (c->flags & ACC_INTERFACE)
1675 c->index = interfaceindex++;
1677 c->index = super->index + 1;
1679 c->instancesize = super->instancesize;
1681 vftbllength = supervftbllength = super->vftbl->vftbllength;
1683 c->finalizer = super->finalizer;
1688 sprintf (logtext, "Linking Class: ");
1689 utf_sprint (logtext+strlen(logtext), c->name );
1693 /* compute vftbl length */
1695 for (i = 0; i < c->methodscount; i++) {
1696 methodinfo *m = &(c->methods[i]);
1698 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1699 classinfo *sc = super;
1702 for (j = 0; j < sc->methodscount; j++) {
1703 if (method_canoverwrite(m, &(sc->methods[j]))) {
1704 m->vftblindex = sc->methods[j].vftblindex;
1705 goto foundvftblindex;
1710 m->vftblindex = (vftbllength++);
1716 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1719 /* compute interfacetable length */
1721 interfacetablelength = 0;
1724 for (i = 0; i < c2->interfacescount; i++) {
1725 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1726 if (h > interfacetablelength)
1727 interfacetablelength = h;
1732 /* allocate virtual function table */
1734 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1735 (vftbllength - 1) + sizeof(methodptr*) *
1736 (interfacetablelength - (interfacetablelength > 0)));
1737 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1738 (interfacetablelength > 1));
1739 c->header.vftbl = c->vftbl = v;
1741 v->vftbllength = vftbllength;
1742 v->interfacetablelength = interfacetablelength;
1744 /* copy virtual function table of super class */
1746 for (i = 0; i < supervftbllength; i++)
1747 v->table[i] = super->vftbl->table[i];
1749 /* add method stubs into virtual function table */
1751 for (i = 0; i < c->methodscount; i++) {
1752 methodinfo *m = &(c->methods[i]);
1753 if (!(m->flags & ACC_STATIC)) {
1754 v->table[m->vftblindex] = m->stubroutine;
1758 /* compute instance size and offset of each field */
1760 for (i = 0; i < c->fieldscount; i++) {
1762 fieldinfo *f = &(c->fields[i]);
1764 if (!(f->flags & ACC_STATIC) ) {
1765 dsize = desc_typesize (f->descriptor);
1766 c->instancesize = ALIGN (c->instancesize, dsize);
1767 f->offset = c->instancesize;
1768 c->instancesize += dsize;
1772 /* initialize interfacetable and interfacevftbllength */
1774 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1777 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1780 for (i = 0; i < interfacetablelength; i++) {
1781 v->interfacevftbllength[i] = 0;
1782 v->interfacetable[-i] = NULL;
1785 /* add interfaces */
1787 for (c2 = c; c2 != NULL; c2 = c2->super)
1788 for (i = 0; i < c2->interfacescount; i++) {
1789 class_addinterface (c, c2->interfaces[i]);
1792 /* add finalizer method (not for java.lang.Object) */
1794 if (super != NULL) {
1796 static utf *finame = NULL;
1797 static utf *fidesc = NULL;
1800 finame = utf_finalize;
1802 fidesc = utf_fidesc;
1804 fi = class_findmethod (c, finame, fidesc);
1806 if (!(fi->flags & ACC_STATIC)) {
1816 list_remove (&unlinkedclasses, c);
1817 list_addlast (&linkedclasses, c);
1821 /******************* Function: class_freepool **********************************
1823 Frees all resources used by this classes Constant Pool.
1825 *******************************************************************************/
1827 static void class_freecpool (classinfo *c)
1833 for (idx=0; idx < c->cpcount; idx++) {
1834 tag = c->cptags[idx];
1835 info = c->cpinfos[idx];
1839 case CONSTANT_Fieldref:
1840 case CONSTANT_Methodref:
1841 case CONSTANT_InterfaceMethodref:
1842 FREE (info, constant_FMIref);
1844 case CONSTANT_Integer:
1845 FREE (info, constant_integer);
1847 case CONSTANT_Float:
1848 FREE (info, constant_float);
1851 FREE (info, constant_long);
1853 case CONSTANT_Double:
1854 FREE (info, constant_double);
1856 case CONSTANT_NameAndType:
1857 FREE (info, constant_nameandtype);
1859 case CONSTANT_Arraydescriptor:
1860 freearraydescriptor (info);
1866 MFREE (c -> cptags, u1, c -> cpcount);
1867 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1871 /*********************** Function: class_free **********************************
1873 Frees all resources used by the class.
1875 *******************************************************************************/
1877 static void class_free (classinfo *c)
1882 class_freecpool (c);
1884 MFREE (c->interfaces, classinfo*, c->interfacescount);
1886 for (i = 0; i < c->fieldscount; i++)
1887 field_free(&(c->fields[i]));
1889 MFREE (c->fields, fieldinfo, c->fieldscount);
1892 for (i = 0; i < c->methodscount; i++)
1893 method_free(&(c->methods[i]));
1894 MFREE (c->methods, methodinfo, c->methodscount);
1896 if ((v = c->vftbl) != NULL) {
1897 for (i = 0; i < v->interfacetablelength; i++) {
1898 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1900 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1902 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1903 sizeof(methodptr*) * (v->interfacetablelength -
1904 (v->interfacetablelength > 0));
1905 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1906 (v->interfacetablelength > 1));
1910 if (c->innerclasscount)
1911 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1914 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1));
1916 FREE (c, classinfo);
1919 /************************* Function: class_findfield ***************************
1921 Searches a 'classinfo' structure for a field having the given name and
1924 *******************************************************************************/
1927 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1931 for (i = 0; i < c->fieldscount; i++) {
1932 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1933 return &(c->fields[i]);
1936 panic ("Can not find field given in CONSTANT_Fieldref");
1941 /************************* Function: class_findmethod **************************
1943 Searches a 'classinfo' structure for a method having the given name and
1945 If type is NULL, it is ignored.
1947 *******************************************************************************/
1949 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1952 for (i = 0; i < c->methodscount; i++) {
1953 if ((c->methods[i].name == name) && ((desc == NULL) ||
1954 (c->methods[i].descriptor == desc)))
1955 return &(c->methods[i]);
1960 /************************* Function: class_findmethod_approx ******************
1962 like class_findmethod but ignores the return value when comparing the
1965 *******************************************************************************/
1967 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1971 for (i = 0; i < c->methodscount; i++)
1972 if (c->methods[i].name == name) {
1973 utf *meth_descr = c->methods[i].descriptor;
1977 return &(c->methods[i]);
1979 if (desc->blength <= meth_descr->blength) {
1980 /* current position in utf text */
1981 char *desc_utf_ptr = desc->text;
1982 char *meth_utf_ptr = meth_descr->text;
1983 /* points behind utf strings */
1984 char *desc_end = utf_end(desc);
1985 char *meth_end = utf_end(meth_descr);
1988 /* compare argument types */
1989 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1991 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1992 break; /* no match */
1995 return &(c->methods[i]); /* all parameter types equal */
2003 /***************** Function: class_resolvemethod_approx ***********************
2005 Searches a class and every super class for a method (without paying
2006 attention to the return value)
2008 *******************************************************************************/
2010 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
2013 /* search for method (ignore returntype) */
2014 methodinfo *m = class_findmethod_approx (c, name, desc);
2017 /* search superclass */
2024 /************************* Function: class_resolvemethod ***********************
2026 Searches a class and every super class for a method.
2028 *******************************************************************************/
2031 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2034 methodinfo *m = class_findmethod (c, name, desc);
2036 /* search superclass */
2044 /************************* Function: class_issubclass **************************
2046 Checks if sub is a descendant of super.
2048 *******************************************************************************/
2050 bool class_issubclass (classinfo *sub, classinfo *super)
2053 if (!sub) return false;
2054 if (sub==super) return true;
2061 /****************** Initialization function for classes ******************
2063 In Java, every class can have a static initialization function. This
2064 function has to be called BEFORE calling other methods or accessing static
2067 *******************************************************************************/
2070 extern int blockInts;
2073 void class_init (classinfo *c)
2076 java_objectheader *exceptionptr;
2081 if (!makeinitializations)
2085 c -> initialized = true;
2088 count_class_inits++;
2092 class_init (c->super);
2093 for (i=0; i < c->interfacescount; i++)
2094 class_init(c->interfaces[i]); // real
2096 m = class_findmethod (c, utf_clinit, utf_fidesc);
2099 sprintf (logtext, "Class ");
2100 utf_sprint (logtext+strlen(logtext), c->name);
2101 sprintf (logtext+strlen(logtext), " has no initializer");
2107 if (! (m->flags & ACC_STATIC))
2108 panic ("Class initializer is not static!");
2111 sprintf (logtext, "Starting initializer for class: ");
2112 utf_sprint (logtext+strlen(logtext), c->name);
2121 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2124 assert(blockInts == 0);
2129 printf ("#### Initializer of ");
2130 utf_display (c->name);
2131 printf (" has thrown: ");
2132 utf_display (exceptionptr->vftbl->class->name);
2138 sprintf (logtext, "Finished initializer for class: ");
2139 utf_sprint (logtext+strlen(logtext), c->name);
2143 if (c->name == utf_systemclass) {
2144 /* class java.lang.System requires explicit initialization */
2147 printf ("#### Initializing class System");
2149 /* find initializing method */
2150 m = class_findmethod (c,
2151 utf_initsystemclass,
2155 /* no method found */
2156 printf("initializeSystemClass failed");
2165 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2168 assert(blockInts == 0);
2173 printf ("#### initializeSystemClass has thrown: ");
2174 utf_display (exceptionptr->vftbl->class->name);
2184 /********* Function: find_class_method_constant *********/
2185 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2191 for (i=0; i<c->cpcount; i++) {
2192 //printf ("#%d: ", (int) i);
2194 e = c -> cpinfos [i];
2197 switch (c -> cptags [i]) {
2198 case CONSTANT_Methodref:
2200 constant_FMIref *fmi = e;
2201 if ( (fmi->class->name == c1)
2202 && (fmi->name == m1)
2203 && (fmi->descriptor == d1)) {
2209 case CONSTANT_InterfaceMethodref:
2211 constant_FMIref *fmi = e;
2212 if ( (fmi->class->name == c1)
2213 && (fmi->name == m1)
2214 && (fmi->descriptor == d1)) {
2230 void class_showconstanti(classinfo *c, int ii)
2235 printf ("#%d: ", (int) i);
2237 e = c -> cpinfos [i];
2239 switch (c -> cptags [i]) {
2240 case CONSTANT_Class:
2241 printf ("Classreference -> ");
2242 utf_display ( ((classinfo*)e) -> name );
2245 case CONSTANT_Fieldref:
2246 printf ("Fieldref -> "); goto displayFMIi;
2247 case CONSTANT_Methodref:
2248 printf ("Methodref -> "); goto displayFMIi;
2249 case CONSTANT_InterfaceMethodref:
2250 printf ("InterfaceMethod -> "); goto displayFMIi;
2253 constant_FMIref *fmi = e;
2254 utf_display ( fmi->class->name );
2256 utf_display ( fmi->name);
2258 utf_display ( fmi->descriptor );
2262 case CONSTANT_String:
2263 printf ("String -> ");
2266 case CONSTANT_Integer:
2267 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2269 case CONSTANT_Float:
2270 printf ("Float -> %f", ((constant_float*)e) -> value);
2272 case CONSTANT_Double:
2273 printf ("Double -> %f", ((constant_double*)e) -> value);
2277 u8 v = ((constant_long*)e) -> value;
2279 printf ("Long -> %ld", (long int) v);
2281 printf ("Long -> HI: %ld, LO: %ld\n",
2282 (long int) v.high, (long int) v.low);
2286 case CONSTANT_NameAndType:
2287 { constant_nameandtype *cnt = e;
2288 printf ("NameAndType: ");
2289 utf_display (cnt->name);
2291 utf_display (cnt->descriptor);
2295 printf ("Utf8 -> ");
2298 case CONSTANT_Arraydescriptor: {
2299 printf ("Arraydescriptor: ");
2300 displayarraydescriptor (e);
2304 panic ("Invalid type of ConstantPool-Entry");
2310 void class_showconstantpool (classinfo *c)
2315 printf ("---- dump of constant pool ----\n");
2317 for (i=0; i<c->cpcount; i++) {
2318 printf ("#%d: ", (int) i);
2320 e = c -> cpinfos [i];
2323 switch (c -> cptags [i]) {
2324 case CONSTANT_Class:
2325 printf ("Classreference -> ");
2326 utf_display ( ((classinfo*)e) -> name );
2329 case CONSTANT_Fieldref:
2330 printf ("Fieldref -> "); goto displayFMI;
2331 case CONSTANT_Methodref:
2332 printf ("Methodref -> "); goto displayFMI;
2333 case CONSTANT_InterfaceMethodref:
2334 printf ("InterfaceMethod -> "); goto displayFMI;
2337 constant_FMIref *fmi = e;
2338 utf_display ( fmi->class->name );
2340 utf_display ( fmi->name);
2342 utf_display ( fmi->descriptor );
2346 case CONSTANT_String:
2347 printf ("String -> ");
2350 case CONSTANT_Integer:
2351 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2353 case CONSTANT_Float:
2354 printf ("Float -> %f", ((constant_float*)e) -> value);
2356 case CONSTANT_Double:
2357 printf ("Double -> %f", ((constant_double*)e) -> value);
2361 u8 v = ((constant_long*)e) -> value;
2363 printf ("Long -> %ld", (long int) v);
2365 printf ("Long -> HI: %ld, LO: %ld\n",
2366 (long int) v.high, (long int) v.low);
2370 case CONSTANT_NameAndType:
2371 { constant_nameandtype *cnt = e;
2372 printf ("NameAndType: ");
2373 utf_display (cnt->name);
2375 utf_display (cnt->descriptor);
2379 printf ("Utf8 -> ");
2382 case CONSTANT_Arraydescriptor: {
2383 printf ("Arraydescriptor: ");
2384 displayarraydescriptor (e);
2388 panic ("Invalid type of ConstantPool-Entry");
2400 /********** Function: class_showmethods (debugging only) *************/
2402 void class_showmethods (classinfo *c)
2406 printf ("--------- Fields and Methods ----------------\n");
2407 printf ("Flags: "); printflags (c->flags); printf ("\n");
2409 printf ("This: "); utf_display (c->name); printf ("\n");
2411 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2413 printf ("Index: %d\n", c->index);
2415 printf ("interfaces:\n");
2416 for (i=0; i < c-> interfacescount; i++) {
2418 utf_display (c -> interfaces[i] -> name);
2419 printf (" (%d)\n", c->interfaces[i] -> index);
2422 printf ("fields:\n");
2423 for (i=0; i < c -> fieldscount; i++) {
2424 field_display (&(c -> fields[i]));
2427 printf ("methods:\n");
2428 for (i=0; i < c -> methodscount; i++) {
2429 methodinfo *m = &(c->methods[i]);
2430 if ( !(m->flags & ACC_STATIC))
2431 printf ("vftblindex: %d ", m->vftblindex);
2433 method_display ( m );
2437 printf ("Virtual function table:\n");
2438 for (i=0; i<c->vftbl->vftbllength; i++) {
2439 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2446 /******************************************************************************/
2447 /******************* General functions for the class loader *******************/
2448 /******************************************************************************/
2450 static int loader_inited = 0;
2452 /********************* Function: loader_load ***********************************
2454 Loads and links the class desired class and each class and interface
2456 Returns: a pointer to this class
2458 *******************************************************************************/
2460 classinfo *loader_load (utf *topname)
2464 long int starttime=0,stoptime=0;
2466 intsDisable(); /* schani */
2469 starttime = getcputime();
2471 top = class_new (topname);
2474 while ( (c = list_first(&unloadedclasses)) ) {
2475 if (!class_load (c)) {
2476 list_remove (&unloadedclasses, c);
2482 while ( (c = list_first(&unlinkedclasses)) ) {
2487 loader_compute_subclasses();
2490 if (getloadingtime) {
2491 stoptime = getcputime();
2492 loadingtime += (stoptime-starttime);
2495 intsRestore(); /* schani */
2501 /**************** function: create_primitive_classes ***************************
2503 create classes representing primitive types
2505 ********************************************************************************/
2508 void create_primitive_classes()
2512 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2513 /* create primitive class */
2514 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2515 c -> classUsed = 0; /* not used initially CO-RT */
2516 c -> impldBy = NULL;
2517 c -> nextimpldBy = NULL;
2519 /* prevent loader from loading primitive class */
2520 list_remove (&unloadedclasses, c);
2521 /* add to unlinked classes */
2522 list_addlast (&unlinkedclasses, c);
2523 c -> super = class_java_lang_Object;
2526 primitivetype_table[i].class_primitive = c;
2528 /* create class for wrapping the primitive type */
2529 primitivetype_table[i].class_wrap =
2530 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2531 primitivetype_table[i].class_wrap -> classUsed = 0; /* not used initially CO-RT */
2532 primitivetype_table[i].class_wrap -> impldBy = NULL;
2533 primitivetype_table[i].class_wrap -> nextimpldBy = NULL;
2537 /***************** function: create_array_class ********************************
2539 create class representing an array
2541 ********************************************************************************/
2544 classinfo *create_array_class(utf *u)
2546 classinfo *c = class_new (u);
2547 /* prevent loader from loading the array class */
2548 list_remove (&unloadedclasses, c);
2549 /* add to unlinked classes */
2550 list_addlast (&unlinkedclasses, c);
2551 c -> super = class_java_lang_Object;
2557 /********************** Function: loader_init **********************************
2559 Initializes all lists and loads all classes required for the system or the
2562 *******************************************************************************/
2569 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2570 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2571 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2573 /* create utf-symbols for pointer comparison of frequently used strings */
2574 utf_innerclasses = utf_new_char("InnerClasses");
2575 utf_constantvalue = utf_new_char("ConstantValue");
2576 utf_code = utf_new_char("Code");
2577 utf_finalize = utf_new_char("finalize");
2578 utf_fidesc = utf_new_char("()V");
2579 utf_clinit = utf_new_char("<clinit>");
2580 utf_initsystemclass = utf_new_char("initializeSystemClass");
2581 utf_systemclass = utf_new_char("java/lang/System");
2583 /* create class for arrays */
2584 class_array = class_new ( utf_new_char ("The_Array_Class") );
2585 class_array -> classUsed = 0; /* not used initially CO-RT */
2586 class_array -> impldBy = NULL;
2587 class_array -> nextimpldBy = NULL;
2589 list_remove (&unloadedclasses, class_array);
2591 /* create class for strings, load it after class Object was loaded */
2592 string_class = utf_new_char ("java/lang/String");
2593 class_java_lang_String = class_new(string_class);
2594 class_java_lang_String -> classUsed = 0; /* not used initially CO-RT */
2595 class_java_lang_String -> impldBy = NULL;
2596 class_java_lang_String -> nextimpldBy = NULL;
2598 list_remove (&unloadedclasses, class_java_lang_String);
2600 class_java_lang_Object =
2601 loader_load ( utf_new_char ("java/lang/Object") );
2603 list_addlast(&unloadedclasses, class_java_lang_String);
2605 class_java_lang_String =
2606 loader_load ( string_class );
2607 class_java_lang_ClassCastException =
2608 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2609 class_java_lang_NullPointerException =
2610 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2611 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2612 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2613 class_java_lang_NegativeArraySizeException = loader_load (
2614 utf_new_char ("java/lang/NegativeArraySizeException") );
2615 class_java_lang_OutOfMemoryError = loader_load (
2616 utf_new_char ("java/lang/OutOfMemoryError") );
2617 class_java_lang_ArrayStoreException =
2618 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2619 class_java_lang_ArithmeticException =
2620 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2621 class_java_lang_ThreadDeath = /* schani */
2622 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2624 /* link class for arrays */
2625 list_addlast (&unlinkedclasses, class_array);
2626 class_array -> super = class_java_lang_Object;
2627 class_link (class_array);
2629 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2630 stringtable_update();
2632 /* create classes representing primitive types */
2633 create_primitive_classes();
2635 proto_java_lang_ClassCastException =
2636 builtin_new(class_java_lang_ClassCastException);
2637 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2639 proto_java_lang_NullPointerException =
2640 builtin_new(class_java_lang_NullPointerException);
2641 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2643 proto_java_lang_ArrayIndexOutOfBoundsException =
2644 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2645 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2647 proto_java_lang_NegativeArraySizeException =
2648 builtin_new(class_java_lang_NegativeArraySizeException);
2649 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2651 proto_java_lang_OutOfMemoryError =
2652 builtin_new(class_java_lang_OutOfMemoryError);
2653 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2655 proto_java_lang_ArithmeticException =
2656 builtin_new(class_java_lang_ArithmeticException);
2657 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2659 proto_java_lang_ArrayStoreException =
2660 builtin_new(class_java_lang_ArrayStoreException);
2661 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2663 proto_java_lang_ThreadDeath = /* schani */
2664 builtin_new(class_java_lang_ThreadDeath);
2665 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2673 /********************* Function: loader_initclasses ****************************
2675 Initializes all loaded but uninitialized classes
2677 *******************************************************************************/
2679 void loader_initclasses ()
2683 intsDisable(); /* schani */
2685 if (makeinitializations) {
2686 c = list_first (&linkedclasses);
2689 c = list_next (&linkedclasses, c);
2693 intsRestore(); /* schani */
2696 static s4 classvalue;
2698 static void loader_compute_class_values (classinfo *c)
2702 c->vftbl->baseval = ++classvalue;
2704 while (subs != NULL) {
2705 loader_compute_class_values(subs);
2706 subs = subs->nextsub;
2708 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2712 for (i = 0; i < c->index; i++)
2714 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2715 utf_display(c->name);
2722 void loader_compute_subclasses ()
2726 intsDisable(); /* schani */
2728 c = list_first (&linkedclasses);
2730 if (!(c->flags & ACC_INTERFACE)) {
2734 c = list_next (&linkedclasses, c);
2737 c = list_first (&linkedclasses);
2739 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2740 c->nextsub = c->super->sub;
2743 c = list_next (&linkedclasses, c);
2746 loader_compute_class_values(class_java_lang_Object);
2748 intsRestore(); /* schani */
2753 /******************** function classloader_buffer ******************************
2755 sets buffer for reading classdata
2757 *******************************************************************************/
2759 void classload_buffer(u1 *buf, int len)
2762 classbuffer_size = len;
2763 classbuf_pos = buf - 1;
2767 /******************** Function: loader_close ***********************************
2771 *******************************************************************************/
2773 void loader_close ()
2777 while ( (c=list_first(&unloadedclasses)) ) {
2778 list_remove (&unloadedclasses,c);
2781 while ( (c=list_first(&unlinkedclasses)) ) {
2782 list_remove (&unlinkedclasses,c);
2785 while ( (c=list_first(&linkedclasses)) ) {
2786 list_remove (&linkedclasses,c);
2793 * These are local overrides for various environment variables in Emacs.
2794 * Please do not remove this and leave it at the end of the file, where
2795 * Emacs will automagically detect them.
2796 * ---------------------------------------------------------------------
2799 * indent-tabs-mode: t