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++) {
2193 e = c -> cpinfos [i];
2196 switch (c -> cptags [i]) {
2197 case CONSTANT_Methodref:
2199 constant_FMIref *fmi = e;
2200 if ( (fmi->class->name == c1)
2201 && (fmi->name == m1)
2202 && (fmi->descriptor == d1)) {
2208 case CONSTANT_InterfaceMethodref:
2210 constant_FMIref *fmi = e;
2211 if ( (fmi->class->name == c1)
2212 && (fmi->name == m1)
2213 && (fmi->descriptor == d1)) {
2229 void class_showconstanti(classinfo *c, int ii)
2234 printf ("#%d: ", (int) i);
2236 e = c -> cpinfos [i];
2238 switch (c -> cptags [i]) {
2239 case CONSTANT_Class:
2240 printf ("Classreference -> ");
2241 utf_display ( ((classinfo*)e) -> name );
2244 case CONSTANT_Fieldref:
2245 printf ("Fieldref -> "); goto displayFMIi;
2246 case CONSTANT_Methodref:
2247 printf ("Methodref -> "); goto displayFMIi;
2248 case CONSTANT_InterfaceMethodref:
2249 printf ("InterfaceMethod -> "); goto displayFMIi;
2252 constant_FMIref *fmi = e;
2253 utf_display ( fmi->class->name );
2255 utf_display ( fmi->name);
2257 utf_display ( fmi->descriptor );
2261 case CONSTANT_String:
2262 printf ("String -> ");
2265 case CONSTANT_Integer:
2266 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2268 case CONSTANT_Float:
2269 printf ("Float -> %f", ((constant_float*)e) -> value);
2271 case CONSTANT_Double:
2272 printf ("Double -> %f", ((constant_double*)e) -> value);
2276 u8 v = ((constant_long*)e) -> value;
2278 printf ("Long -> %ld", (long int) v);
2280 printf ("Long -> HI: %ld, LO: %ld\n",
2281 (long int) v.high, (long int) v.low);
2285 case CONSTANT_NameAndType:
2286 { constant_nameandtype *cnt = e;
2287 printf ("NameAndType: ");
2288 utf_display (cnt->name);
2290 utf_display (cnt->descriptor);
2294 printf ("Utf8 -> ");
2297 case CONSTANT_Arraydescriptor: {
2298 printf ("Arraydescriptor: ");
2299 displayarraydescriptor (e);
2303 panic ("Invalid type of ConstantPool-Entry");
2309 void class_showconstantpool (classinfo *c)
2314 printf ("---- dump of constant pool ----\n");
2316 for (i=0; i<c->cpcount; i++) {
2317 printf ("#%d: ", (int) i);
2319 e = c -> cpinfos [i];
2322 switch (c -> cptags [i]) {
2323 case CONSTANT_Class:
2324 printf ("Classreference -> ");
2325 utf_display ( ((classinfo*)e) -> name );
2328 case CONSTANT_Fieldref:
2329 printf ("Fieldref -> "); goto displayFMI;
2330 case CONSTANT_Methodref:
2331 printf ("Methodref -> "); goto displayFMI;
2332 case CONSTANT_InterfaceMethodref:
2333 printf ("InterfaceMethod -> "); goto displayFMI;
2336 constant_FMIref *fmi = e;
2337 utf_display ( fmi->class->name );
2339 utf_display ( fmi->name);
2341 utf_display ( fmi->descriptor );
2345 case CONSTANT_String:
2346 printf ("String -> ");
2349 case CONSTANT_Integer:
2350 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2352 case CONSTANT_Float:
2353 printf ("Float -> %f", ((constant_float*)e) -> value);
2355 case CONSTANT_Double:
2356 printf ("Double -> %f", ((constant_double*)e) -> value);
2360 u8 v = ((constant_long*)e) -> value;
2362 printf ("Long -> %ld", (long int) v);
2364 printf ("Long -> HI: %ld, LO: %ld\n",
2365 (long int) v.high, (long int) v.low);
2369 case CONSTANT_NameAndType:
2370 { constant_nameandtype *cnt = e;
2371 printf ("NameAndType: ");
2372 utf_display (cnt->name);
2374 utf_display (cnt->descriptor);
2378 printf ("Utf8 -> ");
2381 case CONSTANT_Arraydescriptor: {
2382 printf ("Arraydescriptor: ");
2383 displayarraydescriptor (e);
2387 panic ("Invalid type of ConstantPool-Entry");
2399 /********** Function: class_showmethods (debugging only) *************/
2401 void class_showmethods (classinfo *c)
2405 printf ("--------- Fields and Methods ----------------\n");
2406 printf ("Flags: "); printflags (c->flags); printf ("\n");
2408 printf ("This: "); utf_display (c->name); printf ("\n");
2410 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2412 printf ("Index: %d\n", c->index);
2414 printf ("interfaces:\n");
2415 for (i=0; i < c-> interfacescount; i++) {
2417 utf_display (c -> interfaces[i] -> name);
2418 printf (" (%d)\n", c->interfaces[i] -> index);
2421 printf ("fields:\n");
2422 for (i=0; i < c -> fieldscount; i++) {
2423 field_display (&(c -> fields[i]));
2426 printf ("methods:\n");
2427 for (i=0; i < c -> methodscount; i++) {
2428 methodinfo *m = &(c->methods[i]);
2429 if ( !(m->flags & ACC_STATIC))
2430 printf ("vftblindex: %d ", m->vftblindex);
2432 method_display ( m );
2436 printf ("Virtual function table:\n");
2437 for (i=0; i<c->vftbl->vftbllength; i++) {
2438 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2445 /******************************************************************************/
2446 /******************* General functions for the class loader *******************/
2447 /******************************************************************************/
2449 static int loader_inited = 0;
2451 /********************* Function: loader_load ***********************************
2453 Loads and links the class desired class and each class and interface
2455 Returns: a pointer to this class
2457 *******************************************************************************/
2459 classinfo *loader_load (utf *topname)
2463 long int starttime=0,stoptime=0;
2465 intsDisable(); /* schani */
2468 starttime = getcputime();
2470 top = class_new (topname);
2473 while ( (c = list_first(&unloadedclasses)) ) {
2474 if (!class_load (c)) {
2475 list_remove (&unloadedclasses, c);
2481 while ( (c = list_first(&unlinkedclasses)) ) {
2486 loader_compute_subclasses();
2489 if (getloadingtime) {
2490 stoptime = getcputime();
2491 loadingtime += (stoptime-starttime);
2494 intsRestore(); /* schani */
2500 /**************** function: create_primitive_classes ***************************
2502 create classes representing primitive types
2504 ********************************************************************************/
2507 void create_primitive_classes()
2511 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2512 /* create primitive class */
2513 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2514 c -> classUsed = 0; /* not used initially CO-RT */
2515 c -> impldBy = NULL;
2516 c -> nextimpldBy = NULL;
2518 /* prevent loader from loading primitive class */
2519 list_remove (&unloadedclasses, c);
2520 /* add to unlinked classes */
2521 list_addlast (&unlinkedclasses, c);
2522 c -> super = class_java_lang_Object;
2525 primitivetype_table[i].class_primitive = c;
2527 /* create class for wrapping the primitive type */
2528 primitivetype_table[i].class_wrap =
2529 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2530 primitivetype_table[i].class_wrap -> classUsed = 0; /* not used initially CO-RT */
2531 primitivetype_table[i].class_wrap -> impldBy = NULL;
2532 primitivetype_table[i].class_wrap -> nextimpldBy = NULL;
2536 /***************** function: create_array_class ********************************
2538 create class representing an array
2540 ********************************************************************************/
2543 classinfo *create_array_class(utf *u)
2545 classinfo *c = class_new (u);
2546 /* prevent loader from loading the array class */
2547 list_remove (&unloadedclasses, c);
2548 /* add to unlinked classes */
2549 list_addlast (&unlinkedclasses, c);
2550 c -> super = class_java_lang_Object;
2556 /********************** Function: loader_init **********************************
2558 Initializes all lists and loads all classes required for the system or the
2561 *******************************************************************************/
2568 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2569 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2570 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2572 /* create utf-symbols for pointer comparison of frequently used strings */
2573 utf_innerclasses = utf_new_char("InnerClasses");
2574 utf_constantvalue = utf_new_char("ConstantValue");
2575 utf_code = utf_new_char("Code");
2576 utf_finalize = utf_new_char("finalize");
2577 utf_fidesc = utf_new_char("()V");
2578 utf_clinit = utf_new_char("<clinit>");
2579 utf_initsystemclass = utf_new_char("initializeSystemClass");
2580 utf_systemclass = utf_new_char("java/lang/System");
2582 /* create class for arrays */
2583 class_array = class_new ( utf_new_char ("The_Array_Class") );
2584 class_array -> classUsed = 0; /* not used initially CO-RT */
2585 class_array -> impldBy = NULL;
2586 class_array -> nextimpldBy = NULL;
2588 list_remove (&unloadedclasses, class_array);
2590 /* create class for strings, load it after class Object was loaded */
2591 string_class = utf_new_char ("java/lang/String");
2592 class_java_lang_String = class_new(string_class);
2593 class_java_lang_String -> classUsed = 0; /* not used initially CO-RT */
2594 class_java_lang_String -> impldBy = NULL;
2595 class_java_lang_String -> nextimpldBy = NULL;
2597 list_remove (&unloadedclasses, class_java_lang_String);
2599 class_java_lang_Object =
2600 loader_load ( utf_new_char ("java/lang/Object") );
2602 list_addlast(&unloadedclasses, class_java_lang_String);
2604 class_java_lang_String =
2605 loader_load ( string_class );
2606 class_java_lang_ClassCastException =
2607 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2608 class_java_lang_NullPointerException =
2609 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2610 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2611 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2612 class_java_lang_NegativeArraySizeException = loader_load (
2613 utf_new_char ("java/lang/NegativeArraySizeException") );
2614 class_java_lang_OutOfMemoryError = loader_load (
2615 utf_new_char ("java/lang/OutOfMemoryError") );
2616 class_java_lang_ArrayStoreException =
2617 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2618 class_java_lang_ArithmeticException =
2619 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2620 class_java_lang_ThreadDeath = /* schani */
2621 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2623 /* link class for arrays */
2624 list_addlast (&unlinkedclasses, class_array);
2625 class_array -> super = class_java_lang_Object;
2626 class_link (class_array);
2628 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2629 stringtable_update();
2631 /* create classes representing primitive types */
2632 create_primitive_classes();
2634 proto_java_lang_ClassCastException =
2635 builtin_new(class_java_lang_ClassCastException);
2636 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2638 proto_java_lang_NullPointerException =
2639 builtin_new(class_java_lang_NullPointerException);
2640 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2642 proto_java_lang_ArrayIndexOutOfBoundsException =
2643 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2644 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2646 proto_java_lang_NegativeArraySizeException =
2647 builtin_new(class_java_lang_NegativeArraySizeException);
2648 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2650 proto_java_lang_OutOfMemoryError =
2651 builtin_new(class_java_lang_OutOfMemoryError);
2652 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2654 proto_java_lang_ArithmeticException =
2655 builtin_new(class_java_lang_ArithmeticException);
2656 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2658 proto_java_lang_ArrayStoreException =
2659 builtin_new(class_java_lang_ArrayStoreException);
2660 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2662 proto_java_lang_ThreadDeath = /* schani */
2663 builtin_new(class_java_lang_ThreadDeath);
2664 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2672 /********************* Function: loader_initclasses ****************************
2674 Initializes all loaded but uninitialized classes
2676 *******************************************************************************/
2678 void loader_initclasses ()
2682 intsDisable(); /* schani */
2684 if (makeinitializations) {
2685 c = list_first (&linkedclasses);
2688 c = list_next (&linkedclasses, c);
2692 intsRestore(); /* schani */
2695 static s4 classvalue;
2697 static void loader_compute_class_values (classinfo *c)
2701 c->vftbl->baseval = ++classvalue;
2703 while (subs != NULL) {
2704 loader_compute_class_values(subs);
2705 subs = subs->nextsub;
2707 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2711 for (i = 0; i < c->index; i++)
2713 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2714 utf_display(c->name);
2721 void loader_compute_subclasses ()
2725 intsDisable(); /* schani */
2727 c = list_first (&linkedclasses);
2729 if (!(c->flags & ACC_INTERFACE)) {
2733 c = list_next (&linkedclasses, c);
2736 c = list_first (&linkedclasses);
2738 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2739 c->nextsub = c->super->sub;
2742 c = list_next (&linkedclasses, c);
2745 loader_compute_class_values(class_java_lang_Object);
2747 intsRestore(); /* schani */
2752 /******************** function classloader_buffer ******************************
2754 sets buffer for reading classdata
2756 *******************************************************************************/
2758 void classload_buffer(u1 *buf, int len)
2761 classbuffer_size = len;
2762 classbuf_pos = buf - 1;
2766 /******************** Function: loader_close ***********************************
2770 *******************************************************************************/
2772 void loader_close ()
2776 while ( (c=list_first(&unloadedclasses)) ) {
2777 list_remove (&unloadedclasses,c);
2780 while ( (c=list_first(&unlinkedclasses)) ) {
2781 list_remove (&unlinkedclasses,c);
2784 while ( (c=list_first(&linkedclasses)) ) {
2785 list_remove (&linkedclasses,c);
2792 * These are local overrides for various environment variables in Emacs.
2793 * Please do not remove this and leave it at the end of the file, where
2794 * Emacs will automagically detect them.
2795 * ---------------------------------------------------------------------
2798 * indent-tabs-mode: t