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 *******************************************************************************/
30 #include "toolbox/memory.h"
32 #include "toolbox/loging.h"
34 #include "threads/thread.h"
37 /* global variables ***********************************************************/
39 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
40 bool opt_xta = false; /* true if XTA parse should be used XTA-CO */
41 bool opt_vta = false; /* true if VTA parse should be used VTA-CO */
43 int count_class_infos = 0; /* variables for measurements */
44 int count_const_pool_len = 0;
45 int count_vftbl_len = 0;
46 int count_all_methods = 0;
47 int count_vmcode_len = 0;
48 int count_extable_len = 0;
49 int count_class_loads = 0;
50 int count_class_inits = 0;
52 bool loadverbose = false; /* switches for debug messages */
53 bool linkverbose = false;
54 bool initverbose = false;
56 bool makeinitializations = true;
58 bool getloadingtime = false; /* to measure the runtime */
59 long int loadingtime = 0;
61 static s4 interfaceindex; /* sequential numbering of interfaces */
63 list unloadedclasses; /* list of all referenced but not loaded classes */
64 list unlinkedclasses; /* list of all loaded but not linked classes */
65 list linkedclasses; /* list of all completely linked classes */
68 /* utf-symbols for pointer comparison of frequently used strings */
70 static utf *utf_innerclasses; /* InnerClasses */
71 static utf *utf_constantvalue; /* ConstantValue */
72 static utf *utf_code; /* Code */
73 static utf *utf_finalize; /* finalize */
74 static utf *utf_fidesc; /* ()V */
75 static utf *utf_clinit; /* <clinit> */
76 static utf *utf_initsystemclass; /* initializeSystemClass */
77 static utf *utf_systemclass; /* java/lang/System */
80 /* important system classes ***************************************************/
82 classinfo *class_java_lang_Object;
83 classinfo *class_java_lang_String;
84 classinfo *class_array = NULL;
87 /* These are made static so they cannot be used for throwing in native */
89 static classinfo *class_java_lang_ClassCastException;
90 static classinfo *class_java_lang_NullPointerException;
91 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
92 static classinfo *class_java_lang_NegativeArraySizeException;
93 static classinfo *class_java_lang_OutOfMemoryError;
94 static classinfo *class_java_lang_ArithmeticException;
95 static classinfo *class_java_lang_ArrayStoreException;
96 static classinfo *class_java_lang_ThreadDeath;
99 /******************************************************************************
101 structure for primitive classes: contains the class for wrapping the
102 primitive type, the primitive class, the name of the class for wrapping,
103 the one character type signature and the name of the primitive class
105 ******************************************************************************/
107 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
108 { NULL, NULL, "java/lang/Integer", 'I', "int" },
109 { NULL, NULL, "java/lang/Long", 'J', "long" },
110 { NULL, NULL, "java/lang/Float", 'F', "float" },
111 { NULL, NULL, "java/lang/Double", 'D', "double" },
112 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
113 { NULL, NULL, "java/lang/Character", 'C', "char" },
114 { NULL, NULL, "java/lang/Short", 'S', "short" },
115 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
116 { NULL, NULL, "java/lang/Void", 'V', "void" }};
119 /* instances of important system classes **************************************/
121 java_objectheader *proto_java_lang_ClassCastException;
122 java_objectheader *proto_java_lang_NullPointerException;
123 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
124 java_objectheader *proto_java_lang_NegativeArraySizeException;
125 java_objectheader *proto_java_lang_OutOfMemoryError;
126 java_objectheader *proto_java_lang_ArithmeticException;
127 java_objectheader *proto_java_lang_ArrayStoreException;
128 java_objectheader *proto_java_lang_ThreadDeath;
131 /************* functions for reading classdata *********************************
133 getting classdata in blocks of variable size
134 (8,16,32,64-bit integer or float)
136 *******************************************************************************/
138 static char *classpath = ""; /* searchpath for classfiles */
139 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
140 static u1 *classbuf_pos; /* current position in classfile buffer */
141 static int classbuffer_size; /* size of classfile-data */
143 /* transfer block of classfile data into a buffer */
145 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
148 /* skip block of classfile data */
150 #define skip_nbytes(len) classbuf_pos+=len;
154 return *++classbuf_pos;
158 u1 a=suck_u1(), b=suck_u1();
159 return ((u2)a<<8)+(u2)b;
163 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
164 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
166 #define suck_s8() (s8) suck_u8()
167 #define suck_s2() (s2) suck_u2()
168 #define suck_s4() (s4) suck_u4()
169 #define suck_s1() (s1) suck_u1()
172 /* get u8 from classfile data */
180 return (hi<<32) + lo;
189 /* get float from classfile data */
191 static float suck_float ()
198 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
199 memcpy ( (u1*) (&f), buffer, 4);
201 suck_nbytes ( (u1*) (&f), 4 );
204 PANICIF (sizeof(float) != 4, "Incompatible float-format");
209 /* get double from classfile data */
210 static double suck_double ()
217 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
218 memcpy ( (u1*) (&d), buffer, 8);
220 suck_nbytes ( (u1*) (&d), 8 );
223 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
228 /************************** function suck_init *********************************
230 called once at startup, sets the searchpath for the classfiles
232 *******************************************************************************/
234 void suck_init (char *cpath)
241 /************************** function suck_start ********************************
243 returns true if classbuffer is already loaded or a file for the
244 specified class has succussfully been read in. All directories of
245 the searchpath are used to find the classfile (<classname>.class).
246 Returns false if no classfile is found and writes an error message.
248 *******************************************************************************/
251 bool suck_start (utf *classname) {
253 #define MAXFILENAME 1000 /* maximum length of a filename */
255 char filename[MAXFILENAME+10]; /* room for '.class' */
256 char *pathpos; /* position in searchpath */
257 char c, *utf_ptr; /* pointer to the next utf8-character */
259 int filenamelen, err;
262 if (classbuffer) /* classbuffer is already valid */
269 /* skip path separator */
271 while (*pathpos == ':')
274 /* extract directory from searchpath */
277 while ((*pathpos) && (*pathpos!=':')) {
278 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
279 filename[filenamelen++] = *(pathpos++);
282 filename[filenamelen++] = '/';
284 /* add classname to filename */
286 utf_ptr = classname->text;
287 while (utf_ptr < utf_end(classname)) {
288 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
290 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
292 filename[filenamelen++] = c;
297 strcpy (filename+filenamelen, ".class");
299 classfile = fopen(filename, "r");
300 if (classfile) { /* file exists */
302 /* determine size of classfile */
304 err = stat (filename, &buffer);
306 if (!err) { /* read classfile data */
307 classbuffer_size = buffer.st_size;
308 classbuffer = MNEW(u1, classbuffer_size);
309 classbuf_pos = classbuffer-1;
310 fread(classbuffer, 1, classbuffer_size, classfile);
318 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
326 /************************** function suck_stop *********************************
328 frees memory for buffer with classfile data.
329 Caution: this function may only be called if buffer has been allocated
330 by suck_start with reading a file
332 *******************************************************************************/
336 /* determine amount of classdata not retrieved by suck-operations */
338 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
340 if (classdata_left > 0) {
342 sprintf (logtext,"There are %d access bytes at end of classfile",
349 MFREE(classbuffer, u1, classbuffer_size);
353 /******************************************************************************/
354 /******************* Some support functions ***********************************/
355 /******************************************************************************/
359 void fprintflags (FILE *fp, u2 f)
361 if ( f & ACC_PUBLIC ) fprintf (fp," PUBLIC");
362 if ( f & ACC_PRIVATE ) fprintf (fp," PRIVATE");
363 if ( f & ACC_PROTECTED ) fprintf (fp," PROTECTED");
364 if ( f & ACC_STATIC ) fprintf (fp," STATIC");
365 if ( f & ACC_FINAL ) fprintf (fp," FINAL");
366 if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
367 if ( f & ACC_VOLATILE ) fprintf (fp," VOLATILE");
368 if ( f & ACC_TRANSIENT ) fprintf (fp," TRANSIENT");
369 if ( f & ACC_NATIVE ) fprintf (fp," NATIVE");
370 if ( f & ACC_INTERFACE ) fprintf (fp," INTERFACE");
371 if ( f & ACC_ABSTRACT ) fprintf (fp," ABSTRACT");
374 /********** internal function: printflags (only for debugging) ***************/
375 void printflags (u2 f)
377 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
378 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
379 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
380 if ( f & ACC_STATIC ) printf (" STATIC");
381 if ( f & ACC_FINAL ) printf (" FINAL");
382 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
383 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
384 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
385 if ( f & ACC_NATIVE ) printf (" NATIVE");
386 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
387 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
391 /************************* Function: skipattribute *****************************
393 skips a (1) 'attribute' structure in the class file
395 *******************************************************************************/
397 static void skipattribute ()
400 skip_nbytes(suck_u4());
403 /********************** Function: skipattributebody ****************************
405 skips an attribute after the 16 bit reference to attribute_name has already
408 *******************************************************************************/
410 static void skipattributebody ()
412 skip_nbytes(suck_u4());
415 /************************* Function: skipattributes ****************************
417 skips num attribute structures
419 *******************************************************************************/
421 static void skipattributes (u4 num)
424 for (i = 0; i < num; i++)
428 /******************** function: innerclass_getconstant ************************
430 like class_getconstant, but if cptags is ZERO null is returned
432 *******************************************************************************/
434 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
436 /* invalid position in constantpool */
437 if (pos >= c->cpcount)
438 panic ("Attempt to access constant outside range");
440 /* constantpool entry of type 0 */
444 /* check type of constantpool entry */
445 if (c->cptags[pos] != ctype) {
446 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
447 (int) ctype, (int) c->cptags[pos] );
451 return c->cpinfos[pos];
454 /************************ function: attribute_load ****************************
456 read attributes from classfile
458 *******************************************************************************/
460 static void attribute_load (u4 num, classinfo *c)
464 for (i = 0; i < num; i++) {
465 /* retrieve attribute name */
466 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
468 if ( aname == utf_innerclasses) {
469 /* innerclasses attribute */
471 /* skip attribute length */
473 /* number of records */
474 c->innerclasscount = suck_u2();
475 /* allocate memory for innerclass structure */
476 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
478 for (j=0;j<c->innerclasscount;j++) {
480 /* The innerclass structure contains a class with an encoded name,
481 its defining scope, its simple name and a bitmask of the access flags.
482 If an inner class is not a member, its outer_class is NULL,
483 if a class is anonymous, its name is NULL. */
485 innerclassinfo *info = c->innerclass + j;
487 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
488 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
489 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
490 info->flags = suck_u2 (); /* access_flags bitmask */
493 /* unknown attribute */
494 skipattributebody ();
499 /******************* function: checkfielddescriptor ****************************
501 checks whether a field-descriptor is valid and aborts otherwise
502 all referenced classes are inserted into the list of unloaded classes
504 *******************************************************************************/
506 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
508 char *tstart; /* pointer to start of classname */
511 switch (*utf_ptr++) {
524 /* save start of classname */
527 /* determine length of classname */
528 while ( *utf_ptr++ != ';' )
529 if (utf_ptr>=end_pos)
530 panic ("Missing ';' in objecttype-descriptor");
532 /* cause loading of referenced class */
533 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
538 while ((ch = *utf_ptr++)=='[')
541 /* component type of array */
555 /* save start of classname */
558 /* determine length of classname */
559 while ( *utf_ptr++ != ';' )
560 if (utf_ptr>=end_pos)
561 panic ("Missing ';' in objecttype-descriptor");
563 /* cause loading of referenced class */
564 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
568 panic ("Ill formed methodtype-descriptor");
573 panic ("Ill formed methodtype-descriptor");
576 /* exceeding characters */
577 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
581 /******************* function checkmethoddescriptor ****************************
583 checks whether a method-descriptor is valid and aborts otherwise.
584 All referenced classes are inserted into the list of unloaded classes.
586 *******************************************************************************/
588 static void checkmethoddescriptor (utf *d)
590 char *utf_ptr = d->text; /* current position in utf text */
591 char *end_pos = utf_end(d); /* points behind utf string */
592 char *tstart; /* pointer to start of classname */
595 /* method descriptor must start with parenthesis */
596 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
598 /* check arguments */
599 while ((c = *utf_ptr++) != ')') {
613 /* save start of classname */
616 /* determine length of classname */
617 while ( *utf_ptr++ != ';' )
618 if (utf_ptr>=end_pos)
619 panic ("Missing ';' in objecttype-descriptor");
621 /* cause loading of referenced class */
622 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
627 while ((ch = *utf_ptr++)=='[')
630 /* component type of array */
644 /* save start of classname */
647 /* determine length of classname */
648 while ( *utf_ptr++ != ';' )
649 if (utf_ptr>=end_pos)
650 panic ("Missing ';' in objecttype-descriptor");
652 /* cause loading of referenced class */
653 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
657 panic ("Ill formed methodtype-descriptor");
662 panic ("Ill formed methodtype-descriptor");
666 /* check returntype */
668 /* returntype void */
669 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
672 /* treat as field-descriptor */
673 checkfielddescriptor (utf_ptr,end_pos);
677 /******************** Function: buildarraydescriptor ***************************
679 creates a constant_arraydescriptor structure for the array type named by an
682 *******************************************************************************/
684 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
686 constant_arraydescriptor *d;
688 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
690 d = NEW (constant_arraydescriptor);
691 d -> objectclass = NULL;
692 d -> elementdescriptor = NULL;
695 count_const_pool_len += sizeof(constant_arraydescriptor);
699 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
700 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
701 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
702 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
703 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
704 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
705 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
706 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
709 d -> arraytype = ARRAYTYPE_ARRAY;
710 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
714 d -> arraytype = ARRAYTYPE_OBJECT;
716 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
717 d -> objectclass -> classUsed = NOTUSED; /* not used initially CO-RT */
718 d -> objectclass -> impldBy = NULL;
725 /******************* Function: freearraydescriptor *****************************
727 removes a structure created by buildarraydescriptor from memory
729 *******************************************************************************/
731 static void freearraydescriptor (constant_arraydescriptor *d)
734 constant_arraydescriptor *n = d->elementdescriptor;
735 FREE (d, constant_arraydescriptor);
740 /*********************** Function: displayarraydescriptor *********************/
742 static void displayarraydescriptor (constant_arraydescriptor *d)
744 switch (d->arraytype) {
745 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
746 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
747 case ARRAYTYPE_CHAR: printf ("char[]"); break;
748 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
749 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
750 case ARRAYTYPE_INT: printf ("int[]"); break;
751 case ARRAYTYPE_LONG: printf ("long[]"); break;
752 case ARRAYTYPE_SHORT: printf ("short[]"); break;
753 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
754 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
760 /******************************************************************************/
761 /************************** Functions for fields ****************************/
762 /******************************************************************************/
765 /************************ Function: field_load *********************************
767 Load everything about a class field from the class file and fill a
768 'fieldinfo' structure. For static fields, space in the data segment is
771 *******************************************************************************/
773 static void field_load (fieldinfo *f, classinfo *c)
778 f -> flags = suck_u2 (); /* ACC flags */
779 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
780 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
781 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
782 f -> offset = 0; /* offset from start of object */
786 case TYPE_INT: f->value.i = 0; break;
787 case TYPE_FLOAT: f->value.f = 0.0; break;
788 case TYPE_DOUBLE: f->value.d = 0.0; break;
789 case TYPE_ADDRESS: f->value.a = NULL;
790 heap_addreference (&(f->value.a)); /* make global reference (GC) */
794 f->value.l = 0; break;
796 f->value.l.low = 0; f->value.l.high = 0; break;
800 /* read attributes */
802 for (i=0; i<attrnum; i++) {
806 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
808 if ( aname != utf_constantvalue ) {
809 /* unknown attribute */
810 skipattributebody ();
813 /* constant value attribute */
815 /* skip attribute length */
817 /* index of value in constantpool */
820 /* initialize field with value from constantpool */
823 constant_integer *ci =
824 class_getconstant(c, pindex, CONSTANT_Integer);
825 f->value.i = ci -> value;
831 class_getconstant(c, pindex, CONSTANT_Long);
833 f->value.l = cl -> value;
839 class_getconstant(c, pindex, CONSTANT_Float);
841 f->value.f = cf->value;
846 constant_double *cd =
847 class_getconstant(c, pindex, CONSTANT_Double);
849 f->value.d = cd->value;
854 utf *u = class_getconstant(c, pindex, CONSTANT_String);
855 /* create javastring from compressed utf8-string */
856 f->value.a = literalstring_new(u);
861 log_text ("Invalid Constant - Type");
870 /********************** function: field_free **********************************/
872 static void field_free (fieldinfo *f)
878 /**************** Function: field_display (debugging only) ********************/
880 void field_display (fieldinfo *f)
883 printflags (f -> flags);
885 utf_display (f -> name);
887 utf_display (f -> descriptor);
888 printf (" offset: %ld\n", (long int) (f -> offset) );
892 /******************************************************************************/
893 /************************* Functions for methods ******************************/
894 /******************************************************************************/
897 /*********************** Function: method_load *********************************
899 Loads a method from the class file and fills an existing 'methodinfo'
900 structure. For native methods, the function pointer field is set to the
901 real function pointer, for JavaVM methods a pointer to the compiler is used
904 *******************************************************************************/
906 static void method_load (methodinfo *m, classinfo *c)
916 m -> flags = suck_u2 ();
917 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
918 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
921 m -> exceptiontable = NULL;
922 m -> entrypoint = NULL;
924 m -> stubroutine = NULL;
925 m -> methodUsed = NOTUSED;
926 m -> monoPoly = MONO;
928 m -> subRedefsUsed = 0;
932 if (! (m->flags & ACC_NATIVE) ) {
933 m -> stubroutine = createcompilerstub (m);
937 functionptr f = native_findfunction
938 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
940 m -> stubroutine = createnativestub (f, m);
946 for (i=0; i<attrnum; i++) {
949 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
951 if ( aname != utf_code) {
952 skipattributebody ();
955 if (m -> jcode) panic ("Two code-attributes for one method!");
958 m -> maxstack = suck_u2();
959 m -> maxlocals = suck_u2();
960 m -> jcodelength = suck_u4();
961 m -> jcode = MNEW (u1, m->jcodelength);
962 suck_nbytes (m->jcode, m->jcodelength);
963 m -> exceptiontablelength = suck_u2 ();
964 m -> exceptiontable =
965 MNEW (exceptiontable, m->exceptiontablelength);
968 count_vmcode_len += m->jcodelength + 18;
969 count_extable_len += 8 * m->exceptiontablelength;
972 for (e=0; e < m->exceptiontablelength; e++) {
974 m -> exceptiontable[e].startpc = suck_u2();
975 m -> exceptiontable[e].endpc = suck_u2();
976 m -> exceptiontable[e].handlerpc = suck_u2();
979 if (!idx) m -> exceptiontable[e].catchtype = NULL;
981 m -> exceptiontable[e].catchtype =
982 class_getconstant (c, idx, CONSTANT_Class);
986 skipattributes ( suck_u2() );
993 /********************* Function: method_free ***********************************
995 frees all memory that was allocated for this method
997 *******************************************************************************/
999 static void method_free (methodinfo *m)
1001 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
1002 if (m->exceptiontable)
1003 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
1004 if (m->mcode) CFREE (m->mcode, m->mcodelength);
1005 if (m->stubroutine) {
1006 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
1007 else removecompilerstub (m->stubroutine);
1012 /************** Function: method_display (debugging only) **************/
1014 void method_display (methodinfo *m)
1017 printflags (m -> flags);
1019 utf_display (m -> name);
1021 utf_display (m -> descriptor);
1026 /******************** Function: method_canoverwrite ****************************
1028 Check if m and old are identical with respect to type and name. This means
1029 that old can be overwritten with m.
1031 *******************************************************************************/
1033 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1035 if (m->name != old->name) return false;
1036 if (m->descriptor != old->descriptor) return false;
1037 if (m->flags & ACC_STATIC) return false;
1044 /******************************************************************************/
1045 /************************ Functions for class *********************************/
1046 /******************************************************************************/
1049 /******************** function:: class_getconstant ******************************
1051 retrieves the value at position 'pos' of the constantpool of a class
1052 if the type of the value is other than 'ctype' the system is stopped
1054 *******************************************************************************/
1056 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1058 /* invalid position in constantpool */
1059 if (pos >= c->cpcount)
1060 panic ("Attempt to access constant outside range");
1062 /* check type of constantpool entry */
1063 if (c->cptags[pos] != ctype) {
1064 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1065 (int) ctype, (int) c->cptags[pos] );
1069 return c->cpinfos[pos];
1073 /********************* Function: class_constanttype ****************************
1075 Determines the type of a class entry in the ConstantPool
1077 *******************************************************************************/
1079 u4 class_constanttype (classinfo *c, u4 pos)
1081 if (pos >= c->cpcount)
1082 panic ("Attempt to access constant outside range");
1083 return c->cptags[pos];
1087 /******************** function: class_loadcpool ********************************
1089 loads the constantpool of a class,
1090 the entries are transformed into a simpler format
1091 by resolving references
1092 (a detailed overview of the compact structures can be found in global.h)
1094 *******************************************************************************/
1096 static void class_loadcpool (classinfo *c)
1099 /* The following structures are used to save information which cannot be
1100 processed during the first pass. After the complete constantpool has
1101 been traversed the references can be resolved.
1102 (only in specific order) */
1104 /* CONSTANT_Class_info entries */
1105 typedef struct forward_class {
1106 struct forward_class *next;
1111 /* CONSTANT_String */
1112 typedef struct forward_string {
1113 struct forward_string *next;
1118 /* CONSTANT_NameAndType */
1119 typedef struct forward_nameandtype {
1120 struct forward_nameandtype *next;
1124 } forward_nameandtype;
1126 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1127 typedef struct forward_fieldmethint {
1128 struct forward_fieldmethint *next;
1132 u2 nameandtype_index;
1133 } forward_fieldmethint;
1137 long int dumpsize = dump_size ();
1139 forward_class *forward_classes = NULL;
1140 forward_string *forward_strings = NULL;
1141 forward_nameandtype *forward_nameandtypes = NULL;
1142 forward_fieldmethint *forward_fieldmethints = NULL;
1144 /* number of entries in the constant_pool table */
1145 u4 cpcount = c -> cpcount = suck_u2();
1146 /* allocate memory */
1147 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1148 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1151 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1154 /* initialize constantpool */
1155 for (idx=0; idx<cpcount; idx++) {
1156 cptags[idx] = CONSTANT_UNUSED;
1157 cpinfos[idx] = NULL;
1161 /******* first pass *******/
1162 /* entries which cannot be resolved now are written into
1163 temporary structures and traversed again later */
1166 while (idx < cpcount) {
1167 /* get constant type */
1171 case CONSTANT_Class: {
1172 forward_class *nfc = DNEW(forward_class);
1174 nfc -> next = forward_classes;
1175 forward_classes = nfc;
1177 nfc -> thisindex = idx;
1178 /* reference to CONSTANT_NameAndType */
1179 nfc -> name_index = suck_u2 ();
1185 case CONSTANT_Fieldref:
1186 case CONSTANT_Methodref:
1187 case CONSTANT_InterfaceMethodref: {
1188 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1190 nff -> next = forward_fieldmethints;
1191 forward_fieldmethints = nff;
1193 nff -> thisindex = idx;
1196 /* class or interface type that contains the declaration of the field or method */
1197 nff -> class_index = suck_u2 ();
1198 /* name and descriptor of the field or method */
1199 nff -> nameandtype_index = suck_u2 ();
1205 case CONSTANT_String: {
1206 forward_string *nfs = DNEW (forward_string);
1208 nfs -> next = forward_strings;
1209 forward_strings = nfs;
1211 nfs -> thisindex = idx;
1212 /* reference to CONSTANT_Utf8_info with string characters */
1213 nfs -> string_index = suck_u2 ();
1219 case CONSTANT_NameAndType: {
1220 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1222 nfn -> next = forward_nameandtypes;
1223 forward_nameandtypes = nfn;
1225 nfn -> thisindex = idx;
1226 /* reference to CONSTANT_Utf8_info containing simple name */
1227 nfn -> name_index = suck_u2 ();
1228 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1229 nfn -> sig_index = suck_u2 ();
1235 case CONSTANT_Integer: {
1236 constant_integer *ci = NEW (constant_integer);
1239 count_const_pool_len += sizeof(constant_integer);
1242 ci -> value = suck_s4 ();
1243 cptags [idx] = CONSTANT_Integer;
1250 case CONSTANT_Float: {
1251 constant_float *cf = NEW (constant_float);
1254 count_const_pool_len += sizeof(constant_float);
1257 cf -> value = suck_float ();
1258 cptags [idx] = CONSTANT_Float;
1264 case CONSTANT_Long: {
1265 constant_long *cl = NEW(constant_long);
1268 count_const_pool_len += sizeof(constant_long);
1271 cl -> value = suck_s8 ();
1272 cptags [idx] = CONSTANT_Long;
1278 case CONSTANT_Double: {
1279 constant_double *cd = NEW(constant_double);
1282 count_const_pool_len += sizeof(constant_double);
1285 cd -> value = suck_double ();
1286 cptags [idx] = CONSTANT_Double;
1292 case CONSTANT_Utf8: {
1294 /* number of bytes in the bytes array (not string-length) */
1295 u4 length = suck_u2();
1296 cptags [idx] = CONSTANT_Utf8;
1297 /* insert utf-string into the utf-symboltable */
1298 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1299 /* skip bytes of the string */
1300 skip_nbytes(length);
1306 sprintf (logtext, "Unkown constant type: %d",(int) t);
1315 /* resolve entries in temporary structures */
1317 while (forward_classes) {
1319 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1321 if ( (name->blength>0) && (name->text[0]=='[') ) {
1322 /* check validity of descriptor */
1323 checkfielddescriptor (name->text, utf_end(name));
1325 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1326 cpinfos [forward_classes -> thisindex] =
1327 buildarraydescriptor(name->text, name->blength);
1331 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1332 /* retrieve class from class-table */
1333 cpinfos [forward_classes -> thisindex] = class_new (name);
1335 forward_classes = forward_classes -> next;
1339 while (forward_strings) {
1341 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1343 /* resolve utf-string */
1344 cptags [forward_strings -> thisindex] = CONSTANT_String;
1345 cpinfos [forward_strings -> thisindex] = text;
1347 forward_strings = forward_strings -> next;
1350 while (forward_nameandtypes) {
1351 constant_nameandtype *cn = NEW (constant_nameandtype);
1354 count_const_pool_len += sizeof(constant_nameandtype);
1357 /* resolve simple name and descriptor */
1358 cn -> name = class_getconstant
1359 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1360 cn -> descriptor = class_getconstant
1361 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1363 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1364 cpinfos [forward_nameandtypes -> thisindex] = cn;
1366 forward_nameandtypes = forward_nameandtypes -> next;
1370 while (forward_fieldmethints) {
1371 constant_nameandtype *nat;
1372 constant_FMIref *fmi = NEW (constant_FMIref);
1375 count_const_pool_len += sizeof(constant_FMIref);
1377 /* resolve simple name and descriptor */
1378 nat = class_getconstant
1379 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1381 fmi -> class = class_getconstant
1382 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1383 fmi -> name = nat -> name;
1384 fmi -> descriptor = nat -> descriptor;
1386 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1387 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1389 switch (forward_fieldmethints -> tag) {
1390 case CONSTANT_Fieldref: /* check validity of descriptor */
1391 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1393 case CONSTANT_InterfaceMethodref:
1394 case CONSTANT_Methodref: /* check validity of descriptor */
1395 checkmethoddescriptor (fmi->descriptor);
1399 forward_fieldmethints = forward_fieldmethints -> next;
1404 dump_release (dumpsize);
1408 /********************** Function: class_load ***********************************
1410 Loads everything interesting about a class from the class file. The
1411 'classinfo' structure must have been allocated previously.
1413 The super class and the interfaces implemented by this class need not be
1414 loaded. The link is set later by the function 'class_link'.
1416 The loaded class is removed from the list 'unloadedclasses' and added to
1417 the list 'unlinkedclasses'.
1419 *******************************************************************************/
1421 static int class_load (classinfo *c)
1427 count_class_loads++;
1430 /* output for debugging purposes */
1433 sprintf (logtext, "Loading class: ");
1434 utf_sprint (logtext+strlen(logtext), c->name );
1438 /* load classdata, throw exception on error */
1439 if (!suck_start (c->name)) {
1440 throw_classnotfoundexception();
1444 /* check signature */
1445 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1449 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1450 sprintf (logtext, "File version %d.%d is not supported",
1451 (int) ma, (int) mi);
1456 class_loadcpool (c);
1458 c -> classUsed = NOTUSED; /* not used initially CO-RT */
1459 c -> impldBy = NULL;
1462 c -> flags = suck_u2 ();
1466 /* retrieve superclass */
1467 if ( (i = suck_u2 () ) ) {
1468 c -> super = class_getconstant (c, i, CONSTANT_Class);
1474 /* retrieve interfaces */
1475 c -> interfacescount = suck_u2 ();
1476 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1477 for (i=0; i < c -> interfacescount; i++) {
1478 c -> interfaces [i] =
1479 class_getconstant (c, suck_u2(), CONSTANT_Class);
1483 c -> fieldscount = suck_u2 ();
1484 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1485 for (i=0; i < c -> fieldscount; i++) {
1486 field_load (&(c->fields[i]), c);
1490 c -> methodscount = suck_u2 ();
1491 c -> methods = MNEW (methodinfo, c -> methodscount);
1492 for (i=0; i < c -> methodscount; i++) {
1493 method_load (&(c -> methods [i]), c);
1497 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1498 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1499 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1502 /* load variable-length attribute structures */
1503 attribute_load (suck_u2(), c);
1508 /* remove class from list of unloaded classes and
1509 add to list of unlinked classes */
1510 list_remove (&unloadedclasses, c);
1511 list_addlast (&unlinkedclasses, c);
1518 /************** internal Function: class_highestinterface ***********************
1520 Used by the function class_link to determine the amount of memory needed
1521 for the interface table.
1523 *******************************************************************************/
1525 static s4 class_highestinterface (classinfo *c)
1530 if ( ! (c->flags & ACC_INTERFACE) ) {
1531 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1532 utf_sprint (logtext+strlen(logtext), c->name);
1537 for (i=0; i<c->interfacescount; i++) {
1538 s4 h2 = class_highestinterface (c->interfaces[i]);
1545 /* class_addinterface **********************************************************
1547 Is needed by class_link for adding a VTBL to a class. All interfaces
1548 implemented by ic are added as well.
1550 *******************************************************************************/
1552 static void class_addinterface (classinfo *c, classinfo *ic)
1556 vftbl *vftbl = c->vftbl;
1558 if (i >= vftbl->interfacetablelength)
1559 panic ("Inernal error: interfacetable overflow");
1560 if (vftbl->interfacetable[-i])
1563 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1564 vftbl->interfacevftbllength[i] = 1;
1565 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1566 vftbl->interfacetable[-i][0] = NULL;
1569 vftbl->interfacevftbllength[i] = ic->methodscount;
1570 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1573 count_vftbl_len += sizeof(methodptr) *
1574 (ic->methodscount + (ic->methodscount == 0));
1577 for (j=0; j<ic->methodscount; j++) {
1580 for (m = 0; m < sc->methodscount; m++) {
1581 methodinfo *mi = &(sc->methods[m]);
1582 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1583 vftbl->interfacetable[-i][j] =
1584 vftbl->table[mi->vftblindex];
1594 for (j = 0; j < ic->interfacescount; j++)
1595 class_addinterface(c, ic->interfaces[j]);
1599 /********************** Function: class_link ***********************************
1601 Tries to link a class. The super class and every implemented interface must
1602 already have been linked. The function calculates the length in bytes that
1603 an instance of this class requires as well as the VTBL for methods and
1606 If the class can be linked, it is removed from the list 'unlinkedclasses'
1607 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1610 Attention: If cyclical class definitions are encountered, the program gets
1611 into an infinite loop (we'll have to work that out)
1613 *******************************************************************************/
1615 void class_link (classinfo *c)
1617 s4 supervftbllength; /* vftbllegnth of super class */
1618 s4 vftbllength; /* vftbllength of current class */
1619 s4 interfacetablelength; /* interface table length */
1620 classinfo *super = c->super; /* super class */
1621 classinfo *ic, *c2; /* intermediate class variables */
1622 vftbl *v; /* vftbl of current class */
1623 s4 i; /* interface/method/field counter */
1626 /* check if all superclasses are already linked, if not put c at end of
1627 unlinked list and return. Additionally initialize class fields. */
1629 /* check interfaces */
1631 for (i = 0; i < c->interfacescount; i++) {
1632 ic = c->interfaces[i];
1634 list_remove(&unlinkedclasses, c);
1635 list_addlast(&unlinkedclasses, c);
1640 /* check super class */
1642 if (super == NULL) { /* class java.long.Object */
1644 c->classUsed = USED; /* Object class is always used CO-RT*/
1645 c -> impldBy = NULL;
1646 c->instancesize = sizeof(java_objectheader);
1648 vftbllength = supervftbllength = 0;
1650 c->finalizer = NULL;
1653 if (!super->linked) {
1654 list_remove(&unlinkedclasses, c);
1655 list_addlast(&unlinkedclasses, c);
1659 if (c->flags & ACC_INTERFACE)
1660 c->index = interfaceindex++;
1662 c->index = super->index + 1;
1664 c->instancesize = super->instancesize;
1666 vftbllength = supervftbllength = super->vftbl->vftbllength;
1668 c->finalizer = super->finalizer;
1673 sprintf (logtext, "Linking Class: ");
1674 utf_sprint (logtext+strlen(logtext), c->name );
1678 /* compute vftbl length */
1680 for (i = 0; i < c->methodscount; i++) {
1681 methodinfo *m = &(c->methods[i]);
1683 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1684 classinfo *sc = super;
1687 for (j = 0; j < sc->methodscount; j++) {
1688 if (method_canoverwrite(m, &(sc->methods[j]))) {
1689 m->vftblindex = sc->methods[j].vftblindex;
1690 goto foundvftblindex;
1695 m->vftblindex = (vftbllength++);
1701 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1704 /* compute interfacetable length */
1706 interfacetablelength = 0;
1709 for (i = 0; i < c2->interfacescount; i++) {
1710 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1711 if (h > interfacetablelength)
1712 interfacetablelength = h;
1717 /* allocate virtual function table */
1719 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1720 (vftbllength - 1) + sizeof(methodptr*) *
1721 (interfacetablelength - (interfacetablelength > 0)));
1722 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1723 (interfacetablelength > 1));
1724 c->header.vftbl = c->vftbl = v;
1726 v->vftbllength = vftbllength;
1727 v->interfacetablelength = interfacetablelength;
1729 /* copy virtual function table of super class */
1731 for (i = 0; i < supervftbllength; i++)
1732 v->table[i] = super->vftbl->table[i];
1734 /* add method stubs into virtual function table */
1736 for (i = 0; i < c->methodscount; i++) {
1737 methodinfo *m = &(c->methods[i]);
1738 if (!(m->flags & ACC_STATIC)) {
1739 v->table[m->vftblindex] = m->stubroutine;
1743 /* compute instance size and offset of each field */
1745 for (i = 0; i < c->fieldscount; i++) {
1747 fieldinfo *f = &(c->fields[i]);
1749 if (!(f->flags & ACC_STATIC) ) {
1750 dsize = desc_typesize (f->descriptor);
1751 c->instancesize = ALIGN (c->instancesize, dsize);
1752 f->offset = c->instancesize;
1753 c->instancesize += dsize;
1757 /* initialize interfacetable and interfacevftbllength */
1759 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1762 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1765 for (i = 0; i < interfacetablelength; i++) {
1766 v->interfacevftbllength[i] = 0;
1767 v->interfacetable[-i] = NULL;
1770 /* add interfaces */
1772 for (c2 = c; c2 != NULL; c2 = c2->super)
1773 for (i = 0; i < c2->interfacescount; i++) {
1774 class_addinterface (c, c2->interfaces[i]);
1777 /* add finalizer method (not for java.lang.Object) */
1779 if (super != NULL) {
1781 static utf *finame = NULL;
1782 static utf *fidesc = NULL;
1785 finame = utf_finalize;
1787 fidesc = utf_fidesc;
1789 fi = class_findmethod (c, finame, fidesc);
1791 if (!(fi->flags & ACC_STATIC)) {
1801 list_remove (&unlinkedclasses, c);
1802 list_addlast (&linkedclasses, c);
1806 /******************* Function: class_freepool **********************************
1808 Frees all resources used by this classes Constant Pool.
1810 *******************************************************************************/
1812 static void class_freecpool (classinfo *c)
1818 for (idx=0; idx < c->cpcount; idx++) {
1819 tag = c->cptags[idx];
1820 info = c->cpinfos[idx];
1824 case CONSTANT_Fieldref:
1825 case CONSTANT_Methodref:
1826 case CONSTANT_InterfaceMethodref:
1827 FREE (info, constant_FMIref);
1829 case CONSTANT_Integer:
1830 FREE (info, constant_integer);
1832 case CONSTANT_Float:
1833 FREE (info, constant_float);
1836 FREE (info, constant_long);
1838 case CONSTANT_Double:
1839 FREE (info, constant_double);
1841 case CONSTANT_NameAndType:
1842 FREE (info, constant_nameandtype);
1844 case CONSTANT_Arraydescriptor:
1845 freearraydescriptor (info);
1851 MFREE (c -> cptags, u1, c -> cpcount);
1852 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1856 /*********************** Function: class_free **********************************
1858 Frees all resources used by the class.
1860 *******************************************************************************/
1862 static void class_free (classinfo *c)
1867 class_freecpool (c);
1869 MFREE (c->interfaces, classinfo*, c->interfacescount);
1871 for (i = 0; i < c->fieldscount; i++)
1872 field_free(&(c->fields[i]));
1874 for (i = 0; i < c->methodscount; i++)
1875 method_free(&(c->methods[i]));
1876 MFREE (c->methods, methodinfo, c->methodscount);
1878 if ((v = c->vftbl) != NULL) {
1879 for (i = 0; i < v->interfacetablelength; i++) {
1880 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1882 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1884 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1885 sizeof(methodptr*) * (v->interfacetablelength -
1886 (v->interfacetablelength > 0));
1887 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1888 (v->interfacetablelength > 1));
1892 if (c->innerclasscount)
1893 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1896 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1));
1898 FREE (c, classinfo);
1901 /************************* Function: class_findfield ***************************
1903 Searches a 'classinfo' structure for a field having the given name and
1906 *******************************************************************************/
1909 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1913 for (i = 0; i < c->fieldscount; i++) {
1914 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1915 return &(c->fields[i]);
1918 panic ("Can not find field given in CONSTANT_Fieldref");
1923 /************************* Function: class_findmethod **************************
1925 Searches a 'classinfo' structure for a method having the given name and
1927 If type is NULL, it is ignored.
1929 *******************************************************************************/
1931 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1934 for (i = 0; i < c->methodscount; i++) {
1935 if ((c->methods[i].name == name) && ((desc == NULL) ||
1936 (c->methods[i].descriptor == desc)))
1937 return &(c->methods[i]);
1942 /************************* Function: class_findmethod_approx ******************
1944 like class_findmethod but ignores the return value when comparing the
1947 *******************************************************************************/
1949 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1953 for (i = 0; i < c->methodscount; i++)
1954 if (c->methods[i].name == name) {
1955 utf *meth_descr = c->methods[i].descriptor;
1959 return &(c->methods[i]);
1961 if (desc->blength <= meth_descr->blength) {
1962 /* current position in utf text */
1963 char *desc_utf_ptr = desc->text;
1964 char *meth_utf_ptr = meth_descr->text;
1965 /* points behind utf strings */
1966 char *desc_end = utf_end(desc);
1967 char *meth_end = utf_end(meth_descr);
1970 /* compare argument types */
1971 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1973 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1974 break; /* no match */
1977 return &(c->methods[i]); /* all parameter types equal */
1985 /***************** Function: class_resolvemethod_approx ***********************
1987 Searches a class and every super class for a method (without paying
1988 attention to the return value)
1990 *******************************************************************************/
1992 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
1995 /* search for method (ignore returntype) */
1996 methodinfo *m = class_findmethod_approx (c, name, desc);
1999 /* search superclass */
2006 /************************* Function: class_resolvemethod ***********************
2008 Searches a class and every super class for a method.
2010 *******************************************************************************/
2013 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2016 methodinfo *m = class_findmethod (c, name, desc);
2018 /* search superclass */
2026 /************************* Function: class_issubclass **************************
2028 Checks if sub is a descendant of super.
2030 *******************************************************************************/
2032 bool class_issubclass (classinfo *sub, classinfo *super)
2035 if (!sub) return false;
2036 if (sub==super) return true;
2043 /****************** Initialization function for classes ******************
2045 In Java, every class can have a static initialization function. This
2046 function has to be called BEFORE calling other methods or accessing static
2049 *******************************************************************************/
2052 extern int blockInts;
2055 void class_init (classinfo *c)
2058 java_objectheader *exceptionptr;
2063 if (!makeinitializations)
2067 c -> initialized = true;
2070 count_class_inits++;
2074 class_init (c->super);
2075 for (i=0; i < c->interfacescount; i++)
2076 class_init(c->interfaces[i]); /* real */
2078 m = class_findmethod (c, utf_clinit, utf_fidesc);
2081 sprintf (logtext, "Class ");
2082 utf_sprint (logtext+strlen(logtext), c->name);
2083 sprintf (logtext+strlen(logtext), " has no initializer");
2089 if (! (m->flags & ACC_STATIC))
2090 panic ("Class initializer is not static!");
2093 sprintf (logtext, "Starting initializer for class: ");
2094 utf_sprint (logtext+strlen(logtext), c->name);
2103 exceptionptr = asm_calljavamethod(m, NULL, NULL, NULL, NULL);
2106 assert(blockInts == 0);
2111 printf("#### Initializer of ");
2112 utf_display(c->name);
2113 printf(" has thrown: ");
2114 utf_display(exceptionptr->vftbl->class->name);
2120 sprintf(logtext, "Finished initializer for class: ");
2121 utf_sprint(logtext+strlen(logtext), c->name);
2125 if (c->name == utf_systemclass) {
2126 /* class java.lang.System requires explicit initialization */
2129 printf ("#### Initializing class System");
2131 /* find initializing method */
2132 m = class_findmethod (c,
2133 utf_initsystemclass,
2137 /* no method found */
2138 printf("initializeSystemClass failed");
2147 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2150 assert(blockInts == 0);
2155 printf ("#### initializeSystemClass has thrown: ");
2156 utf_display (exceptionptr->vftbl->class->name);
2166 /********* Function: find_class_method_constant *********/
2167 int find_class_method_constant (classinfo *c, utf * c1, utf* m1, utf* d1)
2173 for (i=0; i<c->cpcount; i++) {
2175 e = c -> cpinfos [i];
2178 switch (c -> cptags [i]) {
2179 case CONSTANT_Methodref:
2181 constant_FMIref *fmi = e;
2182 if ( (fmi->class->name == c1)
2183 && (fmi->name == m1)
2184 && (fmi->descriptor == d1)) {
2190 case CONSTANT_InterfaceMethodref:
2192 constant_FMIref *fmi = e;
2193 if ( (fmi->class->name == c1)
2194 && (fmi->name == m1)
2195 && (fmi->descriptor == d1)) {
2209 void class_showconstanti(classinfo *c, int ii)
2215 e = c -> cpinfos [i];
2216 printf ("#%d: ", (int) i);
2218 switch (c -> cptags [i]) {
2219 case CONSTANT_Class:
2220 printf ("Classreference -> ");
2221 utf_display ( ((classinfo*)e) -> name );
2224 case CONSTANT_Fieldref:
2225 printf ("Fieldref -> "); goto displayFMIi;
2226 case CONSTANT_Methodref:
2227 printf ("Methodref -> "); goto displayFMIi;
2228 case CONSTANT_InterfaceMethodref:
2229 printf ("InterfaceMethod -> "); goto displayFMIi;
2232 constant_FMIref *fmi = e;
2233 utf_display ( fmi->class->name );
2235 utf_display ( fmi->name);
2237 utf_display ( fmi->descriptor );
2241 case CONSTANT_String:
2242 printf ("String -> ");
2245 case CONSTANT_Integer:
2246 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2248 case CONSTANT_Float:
2249 printf ("Float -> %f", ((constant_float*)e) -> value);
2251 case CONSTANT_Double:
2252 printf ("Double -> %f", ((constant_double*)e) -> value);
2256 u8 v = ((constant_long*)e) -> value;
2258 printf ("Long -> %ld", (long int) v);
2260 printf ("Long -> HI: %ld, LO: %ld\n",
2261 (long int) v.high, (long int) v.low);
2265 case CONSTANT_NameAndType:
2266 { constant_nameandtype *cnt = e;
2267 printf ("NameAndType: ");
2268 utf_display (cnt->name);
2270 utf_display (cnt->descriptor);
2274 printf ("Utf8 -> ");
2277 case CONSTANT_Arraydescriptor: {
2278 printf ("Arraydescriptor: ");
2279 displayarraydescriptor (e);
2283 panic ("Invalid type of ConstantPool-Entry");
2289 void class_showconstantpool (classinfo *c)
2294 printf ("---- dump of constant pool ----\n");
2296 for (i=0; i<c->cpcount; i++) {
2297 printf ("#%d: ", (int) i);
2299 e = c -> cpinfos [i];
2302 switch (c -> cptags [i]) {
2303 case CONSTANT_Class:
2304 printf ("Classreference -> ");
2305 utf_display ( ((classinfo*)e) -> name );
2308 case CONSTANT_Fieldref:
2309 printf ("Fieldref -> "); goto displayFMI;
2310 case CONSTANT_Methodref:
2311 printf ("Methodref -> "); goto displayFMI;
2312 case CONSTANT_InterfaceMethodref:
2313 printf ("InterfaceMethod -> "); goto displayFMI;
2316 constant_FMIref *fmi = e;
2317 utf_display ( fmi->class->name );
2319 utf_display ( fmi->name);
2321 utf_display ( fmi->descriptor );
2325 case CONSTANT_String:
2326 printf ("String -> ");
2329 case CONSTANT_Integer:
2330 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2332 case CONSTANT_Float:
2333 printf ("Float -> %f", ((constant_float*)e) -> value);
2335 case CONSTANT_Double:
2336 printf ("Double -> %f", ((constant_double*)e) -> value);
2340 u8 v = ((constant_long*)e) -> value;
2342 printf ("Long -> %ld", (long int) v);
2344 printf ("Long -> HI: %ld, LO: %ld\n",
2345 (long int) v.high, (long int) v.low);
2349 case CONSTANT_NameAndType:
2350 { constant_nameandtype *cnt = e;
2351 printf ("NameAndType: ");
2352 utf_display (cnt->name);
2354 utf_display (cnt->descriptor);
2358 printf ("Utf8 -> ");
2361 case CONSTANT_Arraydescriptor: {
2362 printf ("Arraydescriptor: ");
2363 displayarraydescriptor (e);
2367 panic ("Invalid type of ConstantPool-Entry");
2379 /********** Function: class_showmethods (debugging only) *************/
2381 void class_showmethods (classinfo *c)
2385 printf ("--------- Fields and Methods ----------------\n");
2386 printf ("Flags: "); printflags (c->flags); printf ("\n");
2388 printf ("This: "); utf_display (c->name); printf ("\n");
2390 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2392 printf ("Index: %d\n", c->index);
2394 printf ("interfaces:\n");
2395 for (i=0; i < c-> interfacescount; i++) {
2397 utf_display (c -> interfaces[i] -> name);
2398 printf (" (%d)\n", c->interfaces[i] -> index);
2401 printf ("fields:\n");
2402 for (i=0; i < c -> fieldscount; i++) {
2403 field_display (&(c -> fields[i]));
2406 printf ("methods:\n");
2407 for (i=0; i < c -> methodscount; i++) {
2408 methodinfo *m = &(c->methods[i]);
2409 if ( !(m->flags & ACC_STATIC))
2410 printf ("vftblindex: %d ", m->vftblindex);
2412 method_display ( m );
2416 printf ("Virtual function table:\n");
2417 for (i=0; i<c->vftbl->vftbllength; i++) {
2418 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2425 /******************************************************************************/
2426 /******************* General functions for the class loader *******************/
2427 /******************************************************************************/
2429 static int loader_inited = 0;
2431 /********************* Function: loader_load ***********************************
2433 Loads and links the class desired class and each class and interface
2435 Returns: a pointer to this class
2437 *******************************************************************************/
2439 classinfo *loader_load (utf *topname)
2443 long int starttime=0,stoptime=0;
2445 intsDisable(); /* schani */
2448 starttime = getcputime();
2450 top = class_new (topname);
2453 while ( (c = list_first(&unloadedclasses)) ) {
2454 if (!class_load (c)) {
2455 list_remove (&unloadedclasses, c);
2461 while ( (c = list_first(&unlinkedclasses)) ) {
2466 loader_compute_subclasses();
2469 if (getloadingtime) {
2470 stoptime = getcputime();
2471 loadingtime += (stoptime-starttime);
2474 intsRestore(); /* schani */
2480 /**************** function: create_primitive_classes ***************************
2482 create classes representing primitive types
2484 ********************************************************************************/
2487 void create_primitive_classes()
2491 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2492 /* create primitive class */
2493 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2494 c -> classUsed = NOTUSED; /* not used initially CO-RT */
2495 c -> impldBy = NULL;
2497 /* prevent loader from loading primitive class */
2498 list_remove (&unloadedclasses, c);
2499 /* add to unlinked classes */
2500 list_addlast (&unlinkedclasses, c);
2501 c -> super = class_java_lang_Object;
2504 primitivetype_table[i].class_primitive = c;
2506 /* create class for wrapping the primitive type */
2507 primitivetype_table[i].class_wrap =
2508 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2509 primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
2510 primitivetype_table[i].class_wrap -> impldBy = NULL;
2514 /***************** function: create_array_class ********************************
2516 create class representing an array
2518 ********************************************************************************/
2521 classinfo *create_array_class(utf *u)
2523 classinfo *c = class_new (u);
2524 /* prevent loader from loading the array class */
2525 list_remove (&unloadedclasses, c);
2526 /* add to unlinked classes */
2527 list_addlast (&unlinkedclasses, c);
2528 c -> super = class_java_lang_Object;
2534 /********************** Function: loader_init **********************************
2536 Initializes all lists and loads all classes required for the system or the
2539 *******************************************************************************/
2546 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2547 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2548 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2550 /* create utf-symbols for pointer comparison of frequently used strings */
2551 utf_innerclasses = utf_new_char("InnerClasses");
2552 utf_constantvalue = utf_new_char("ConstantValue");
2553 utf_code = utf_new_char("Code");
2554 utf_finalize = utf_new_char("finalize");
2555 utf_fidesc = utf_new_char("()V");
2556 utf_clinit = utf_new_char("<clinit>");
2557 utf_initsystemclass = utf_new_char("initializeSystemClass");
2558 utf_systemclass = utf_new_char("java/lang/System");
2560 /* create class for arrays */
2561 class_array = class_new ( utf_new_char ("The_Array_Class") );
2562 class_array -> classUsed = NOTUSED; /* not used initially CO-RT */
2563 class_array -> impldBy = NULL;
2565 list_remove (&unloadedclasses, class_array);
2567 /* create class for strings, load it after class Object was loaded */
2568 string_class = utf_new_char ("java/lang/String");
2569 class_java_lang_String = class_new(string_class);
2570 class_java_lang_String -> classUsed = NOTUSED; /* not used initially CO-RT */
2571 class_java_lang_String -> impldBy = NULL;
2573 list_remove (&unloadedclasses, class_java_lang_String);
2575 class_java_lang_Object =
2576 loader_load ( utf_new_char ("java/lang/Object") );
2578 list_addlast(&unloadedclasses, class_java_lang_String);
2580 class_java_lang_String =
2581 loader_load ( string_class );
2582 class_java_lang_ClassCastException =
2583 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2584 class_java_lang_NullPointerException =
2585 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2586 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2587 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2588 class_java_lang_NegativeArraySizeException = loader_load (
2589 utf_new_char ("java/lang/NegativeArraySizeException") );
2590 class_java_lang_OutOfMemoryError = loader_load (
2591 utf_new_char ("java/lang/OutOfMemoryError") );
2592 class_java_lang_ArrayStoreException =
2593 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2594 class_java_lang_ArithmeticException =
2595 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2596 class_java_lang_ThreadDeath = /* schani */
2597 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2599 /* link class for arrays */
2600 list_addlast (&unlinkedclasses, class_array);
2601 class_array -> super = class_java_lang_Object;
2602 class_link (class_array);
2604 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2605 stringtable_update();
2607 /* create classes representing primitive types */
2608 create_primitive_classes();
2610 proto_java_lang_ClassCastException =
2611 builtin_new(class_java_lang_ClassCastException);
2612 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2614 proto_java_lang_NullPointerException =
2615 builtin_new(class_java_lang_NullPointerException);
2616 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2618 proto_java_lang_ArrayIndexOutOfBoundsException =
2619 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2620 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2622 proto_java_lang_NegativeArraySizeException =
2623 builtin_new(class_java_lang_NegativeArraySizeException);
2624 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2626 proto_java_lang_OutOfMemoryError =
2627 builtin_new(class_java_lang_OutOfMemoryError);
2628 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2630 proto_java_lang_ArithmeticException =
2631 builtin_new(class_java_lang_ArithmeticException);
2632 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2634 proto_java_lang_ArrayStoreException =
2635 builtin_new(class_java_lang_ArrayStoreException);
2636 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2638 proto_java_lang_ThreadDeath = /* schani */
2639 builtin_new(class_java_lang_ThreadDeath);
2640 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2648 /********************* Function: loader_initclasses ****************************
2650 Initializes all loaded but uninitialized classes
2652 *******************************************************************************/
2654 void loader_initclasses ()
2658 intsDisable(); /* schani */
2660 if (makeinitializations) {
2661 c = list_first (&linkedclasses);
2664 c = list_next (&linkedclasses, c);
2668 intsRestore(); /* schani */
2671 static s4 classvalue;
2673 static void loader_compute_class_values (classinfo *c)
2677 c->vftbl->baseval = ++classvalue;
2680 while (subs != NULL) {
2681 loader_compute_class_values(subs);
2682 subs = subs->nextsub;
2684 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2688 for (i = 0; i < c->index; i++)
2690 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2691 utf_display(c->name);
2698 void loader_compute_subclasses ()
2702 intsDisable(); /* schani */
2704 c = list_first (&linkedclasses);
2706 if (!(c->flags & ACC_INTERFACE)) {
2710 c = list_next (&linkedclasses, c);
2713 c = list_first (&linkedclasses);
2715 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2716 c->nextsub = c->super->sub;
2719 c = list_next (&linkedclasses, c);
2722 loader_compute_class_values(class_java_lang_Object);
2724 intsRestore(); /* schani */
2729 /******************** function classloader_buffer ******************************
2731 sets buffer for reading classdata
2733 *******************************************************************************/
2735 void classload_buffer(u1 *buf, int len)
2738 classbuffer_size = len;
2739 classbuf_pos = buf - 1;
2743 /******************** Function: loader_close ***********************************
2747 *******************************************************************************/
2749 void loader_close ()
2753 while ( (c=list_first(&unloadedclasses)) ) {
2754 list_remove (&unloadedclasses,c);
2757 while ( (c=list_first(&unlinkedclasses)) ) {
2758 list_remove (&unlinkedclasses,c);
2761 while ( (c=list_first(&linkedclasses)) ) {
2762 list_remove (&linkedclasses,c);
2769 * These are local overrides for various environment variables in Emacs.
2770 * Please do not remove this and leave it at the end of the file, where
2771 * Emacs will automagically detect them.
2772 * ---------------------------------------------------------------------
2775 * indent-tabs-mode: t