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_java_lang_ClassCastException;
90 classinfo *class_java_lang_NullPointerException;
91 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
92 classinfo *class_java_lang_NegativeArraySizeException;
93 classinfo *class_java_lang_OutOfMemoryError;
94 classinfo *class_java_lang_ArithmeticException;
95 classinfo *class_java_lang_ArrayStoreException;
96 classinfo *class_java_lang_ThreadDeath;
97 classinfo *class_array = NULL;
100 /******************************************************************************
102 structure for primitive classes: contains the class for wrapping the
103 primitive type, the primitive class, the name of the class for wrapping,
104 the one character type signature and the name of the primitive class
106 ******************************************************************************/
108 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
109 { NULL, NULL, "java/lang/Double", 'D', "double" },
110 { NULL, NULL, "java/lang/Float", 'F', "float" },
111 { NULL, NULL, "java/lang/Character", 'C', "char" },
112 { NULL, NULL, "java/lang/Integer", 'I', "int" },
113 { NULL, NULL, "java/lang/Long", 'J', "long" },
114 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
115 { NULL, NULL, "java/lang/Short", 'S', "short" },
116 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
117 { NULL, NULL, "java/lang/Void", 'V', "void" }};
120 /* instances of important system classes **************************************/
122 java_objectheader *proto_java_lang_ClassCastException;
123 java_objectheader *proto_java_lang_NullPointerException;
124 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
125 java_objectheader *proto_java_lang_NegativeArraySizeException;
126 java_objectheader *proto_java_lang_OutOfMemoryError;
127 java_objectheader *proto_java_lang_ArithmeticException;
128 java_objectheader *proto_java_lang_ArrayStoreException;
129 java_objectheader *proto_java_lang_ThreadDeath;
132 /************* functions for reading classdata *********************************
134 getting classdata in blocks of variable size
135 (8,16,32,64-bit integer or float)
137 *******************************************************************************/
139 static char *classpath = ""; /* searchpath for classfiles */
140 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
141 static u1 *classbuf_pos; /* current position in classfile buffer */
142 static int classbuffer_size; /* size of classfile-data */
144 /* transfer block of classfile data into a buffer */
146 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
149 /* skip block of classfile data */
151 #define skip_nbytes(len) classbuf_pos+=len;
155 return *++classbuf_pos;
159 u1 a=suck_u1(), b=suck_u1();
160 return ((u2)a<<8)+(u2)b;
164 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
165 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
167 #define suck_s8() (s8) suck_u8()
168 #define suck_s2() (s2) suck_u2()
169 #define suck_s4() (s4) suck_u4()
170 #define suck_s1() (s1) suck_u1()
173 /* get u8 from classfile data */
181 return (hi<<32) + lo;
190 /* get float from classfile data */
192 static float suck_float ()
199 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
200 memcpy ( (u1*) (&f), buffer, 4);
202 suck_nbytes ( (u1*) (&f), 4 );
205 PANICIF (sizeof(float) != 4, "Incompatible float-format");
210 /* get double from classfile data */
211 static double suck_double ()
218 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
219 memcpy ( (u1*) (&d), buffer, 8);
221 suck_nbytes ( (u1*) (&d), 8 );
224 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
229 /************************** function suck_init *********************************
231 called once at startup, sets the searchpath for the classfiles
233 *******************************************************************************/
235 void suck_init (char *cpath)
242 /************************** function suck_start ********************************
244 returns true if classbuffer is already loaded or a file for the
245 specified class has succussfully been read in. All directories of
246 the searchpath are used to find the classfile (<classname>.class).
247 Returns false if no classfile is found and writes an error message.
249 *******************************************************************************/
252 bool suck_start (utf *classname) {
254 #define MAXFILENAME 1000 /* maximum length of a filename */
256 char filename[MAXFILENAME+10]; /* room for '.class' */
257 char *pathpos; /* position in searchpath */
258 char c, *utf_ptr; /* pointer to the next utf8-character */
260 int filenamelen, err;
263 if (classbuffer) /* classbuffer is already valid */
270 /* skip path separator */
272 while (*pathpos == ':')
275 /* extract directory from searchpath */
278 while ((*pathpos) && (*pathpos!=':')) {
279 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
280 filename[filenamelen++] = *(pathpos++);
283 filename[filenamelen++] = '/';
285 /* add classname to filename */
287 utf_ptr = classname->text;
288 while (utf_ptr < utf_end(classname)) {
289 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
291 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
293 filename[filenamelen++] = c;
298 strcpy (filename+filenamelen, ".class");
300 classfile = fopen(filename, "r");
301 if (classfile) { /* file exists */
303 /* determine size of classfile */
305 err = stat (filename, &buffer);
307 if (!err) { /* read classfile data */
308 classbuffer_size = buffer.st_size;
309 classbuffer = MNEW(u1, classbuffer_size);
310 classbuf_pos = classbuffer-1;
311 fread(classbuffer, 1, classbuffer_size, classfile);
319 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
327 /************************** function suck_stop *********************************
329 frees memory for buffer with classfile data.
330 Caution: this function may only be called if buffer has been allocated
331 by suck_start with reading a file
333 *******************************************************************************/
337 /* determine amount of classdata not retrieved by suck-operations */
339 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
341 if (classdata_left > 0) {
343 sprintf (logtext,"There are %d access bytes at end of classfile",
350 MFREE(classbuffer, u1, classbuffer_size);
354 /******************************************************************************/
355 /******************* Some support functions ***********************************/
356 /******************************************************************************/
359 /********** internal function: printflags (only for debugging) ***************/
361 static void printflags (u2 f)
363 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
364 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
365 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
366 if ( f & ACC_STATIC ) printf (" STATIC");
367 if ( f & ACC_FINAL ) printf (" FINAL");
368 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
369 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
370 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
371 if ( f & ACC_NATIVE ) printf (" NATIVE");
372 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
373 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
377 /************************* Function: skipattribute *****************************
379 skips a (1) 'attribute' structure in the class file
381 *******************************************************************************/
383 static void skipattribute ()
386 skip_nbytes(suck_u4());
389 /********************** Function: skipattributebody ****************************
391 skips an attribute after the 16 bit reference to attribute_name has already
394 *******************************************************************************/
396 static void skipattributebody ()
398 skip_nbytes(suck_u4());
401 /************************* Function: skipattributes ****************************
403 skips num attribute structures
405 *******************************************************************************/
407 static void skipattributes (u4 num)
410 for (i = 0; i < num; i++)
414 /******************** function: innerclass_getconstant ************************
416 like class_getconstant, but if cptags is ZERO null is returned
418 *******************************************************************************/
420 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
422 /* invalid position in constantpool */
423 if (pos >= c->cpcount)
424 panic ("Attempt to access constant outside range");
426 /* constantpool entry of type 0 */
430 /* check type of constantpool entry */
431 if (c->cptags[pos] != ctype) {
432 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
433 (int) ctype, (int) c->cptags[pos] );
437 return c->cpinfos[pos];
440 /************************ function: attribute_load ****************************
442 read attributes from classfile
444 *******************************************************************************/
446 static void attribute_load (u4 num, classinfo *c)
450 for (i = 0; i < num; i++) {
451 /* retrieve attribute name */
452 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
454 if ( aname == utf_innerclasses) {
455 /* innerclasses attribute */
457 /* skip attribute length */
459 /* number of records */
460 c->innerclasscount = suck_u2();
461 /* allocate memory for innerclass structure */
462 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
464 for (j=0;j<c->innerclasscount;j++) {
466 /* The innerclass structure contains a class with an encoded name,
467 its defining scope, its simple name and a bitmask of the access flags.
468 If an inner class is not a member, its outer_class is NULL,
469 if a class is anonymous, its name is NULL. */
471 innerclassinfo *info = c->innerclass + j;
473 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
474 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
475 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
476 info->flags = suck_u2 (); /* access_flags bitmask */
479 /* unknown attribute */
480 skipattributebody ();
485 /******************* function: checkfielddescriptor ****************************
487 checks whether a field-descriptor is valid and aborts otherwise
488 all referenced classes are inserted into the list of unloaded classes
490 *******************************************************************************/
492 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
494 char *tstart; /* pointer to start of classname */
497 switch (*utf_ptr++) {
510 /* save start of classname */
513 /* determine length of classname */
514 while ( *utf_ptr++ != ';' )
515 if (utf_ptr>=end_pos)
516 panic ("Missing ';' in objecttype-descriptor");
518 /* cause loading of referenced class */
519 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
524 while ((ch = *utf_ptr++)=='[')
527 /* component type of array */
541 /* save start of classname */
544 /* determine length of classname */
545 while ( *utf_ptr++ != ';' )
546 if (utf_ptr>=end_pos)
547 panic ("Missing ';' in objecttype-descriptor");
549 /* cause loading of referenced class */
550 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
554 panic ("Ill formed methodtype-descriptor");
559 panic ("Ill formed methodtype-descriptor");
562 /* exceeding characters */
563 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
567 /******************* function checkmethoddescriptor ****************************
569 checks whether a method-descriptor is valid and aborts otherwise.
570 All referenced classes are inserted into the list of unloaded classes.
572 *******************************************************************************/
574 static void checkmethoddescriptor (utf *d)
576 char *utf_ptr = d->text; /* current position in utf text */
577 char *end_pos = utf_end(d); /* points behind utf string */
578 char *tstart; /* pointer to start of classname */
581 /* method descriptor must start with parenthesis */
582 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
584 /* check arguments */
585 while ((c = *utf_ptr++) != ')') {
599 /* save start of classname */
602 /* determine length of classname */
603 while ( *utf_ptr++ != ';' )
604 if (utf_ptr>=end_pos)
605 panic ("Missing ';' in objecttype-descriptor");
607 /* cause loading of referenced class */
608 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
613 while ((ch = *utf_ptr++)=='[')
616 /* component type of array */
630 /* save start of classname */
633 /* determine length of classname */
634 while ( *utf_ptr++ != ';' )
635 if (utf_ptr>=end_pos)
636 panic ("Missing ';' in objecttype-descriptor");
638 /* cause loading of referenced class */
639 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
643 panic ("Ill formed methodtype-descriptor");
648 panic ("Ill formed methodtype-descriptor");
652 /* check returntype */
654 /* returntype void */
655 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
658 /* treat as field-descriptor */
659 checkfielddescriptor (utf_ptr,end_pos);
663 /******************** Function: buildarraydescriptor ***************************
665 creates a constant_arraydescriptor structure for the array type named by an
668 *******************************************************************************/
670 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
672 constant_arraydescriptor *d;
674 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
676 d = NEW (constant_arraydescriptor);
677 d -> objectclass = NULL;
678 d -> elementdescriptor = NULL;
681 count_const_pool_len += sizeof(constant_arraydescriptor);
685 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
686 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
687 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
688 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
689 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
690 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
691 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
692 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
695 d -> arraytype = ARRAYTYPE_ARRAY;
696 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
700 d -> arraytype = ARRAYTYPE_OBJECT;
702 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
703 d -> objectclass -> classUsed = 0; /* not used initially CO-RT */
710 /******************* Function: freearraydescriptor *****************************
712 removes a structure created by buildarraydescriptor from memory
714 *******************************************************************************/
716 static void freearraydescriptor (constant_arraydescriptor *d)
719 constant_arraydescriptor *n = d->elementdescriptor;
720 FREE (d, constant_arraydescriptor);
725 /*********************** Function: displayarraydescriptor *********************/
727 static void displayarraydescriptor (constant_arraydescriptor *d)
729 switch (d->arraytype) {
730 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
731 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
732 case ARRAYTYPE_CHAR: printf ("char[]"); break;
733 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
734 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
735 case ARRAYTYPE_INT: printf ("int[]"); break;
736 case ARRAYTYPE_LONG: printf ("long[]"); break;
737 case ARRAYTYPE_SHORT: printf ("short[]"); break;
738 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
739 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
745 /******************************************************************************/
746 /************************** Functions for fields ****************************/
747 /******************************************************************************/
750 /************************ Function: field_load *********************************
752 Load everything about a class field from the class file and fill a
753 'fieldinfo' structure. For static fields, space in the data segment is
756 *******************************************************************************/
758 static void field_load (fieldinfo *f, classinfo *c)
763 f -> flags = suck_u2 (); /* ACC flags */
764 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
765 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
766 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
767 f -> offset = 0; /* offset from start of object */
770 case TYPE_INT: f->value.i = 0; break;
771 case TYPE_FLOAT: f->value.f = 0.0; break;
772 case TYPE_DOUBLE: f->value.d = 0.0; break;
773 case TYPE_ADDRESS: f->value.a = NULL;
774 heap_addreference (&(f->value.a)); /* make global reference (GC) */
778 f->value.l = 0; break;
780 f->value.l.low = 0; f->value.l.high = 0; break;
784 /* read attributes */
786 for (i=0; i<attrnum; i++) {
790 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
792 if ( aname != utf_constantvalue ) {
793 /* unknown attribute */
794 skipattributebody ();
797 /* constant value attribute */
799 /* skip attribute length */
801 /* index of value in constantpool */
804 /* initialize field with value from constantpool */
807 constant_integer *ci =
808 class_getconstant(c, pindex, CONSTANT_Integer);
809 f->value.i = ci -> value;
815 class_getconstant(c, pindex, CONSTANT_Long);
817 f->value.l = cl -> value;
823 class_getconstant(c, pindex, CONSTANT_Float);
825 f->value.f = cf->value;
830 constant_double *cd =
831 class_getconstant(c, pindex, CONSTANT_Double);
833 f->value.d = cd->value;
838 utf *u = class_getconstant(c, pindex, CONSTANT_String);
839 /* create javastring from compressed utf8-string */
840 f->value.a = literalstring_new(u);
845 log_text ("Invalid Constant - Type");
854 /********************** function: field_free **********************************/
856 static void field_free (fieldinfo *f)
862 /**************** Function: field_display (debugging only) ********************/
864 static void field_display (fieldinfo *f)
867 printflags (f -> flags);
869 utf_display (f -> name);
871 utf_display (f -> descriptor);
872 printf (" offset: %ld\n", (long int) (f -> offset) );
876 /******************************************************************************/
877 /************************* Functions for methods ******************************/
878 /******************************************************************************/
881 /*********************** Function: method_load *********************************
883 Loads a method from the class file and fills an existing 'methodinfo'
884 structure. For native methods, the function pointer field is set to the
885 real function pointer, for JavaVM methods a pointer to the compiler is used
888 *******************************************************************************/
890 static void method_load (methodinfo *m, classinfo *c)
900 m -> flags = suck_u2 ();
901 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
902 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
905 m -> exceptiontable = NULL;
906 m -> entrypoint = NULL;
908 m -> stubroutine = NULL;
909 m -> methodUsed = 0; /* not used initially CO-RT*/
911 if (! (m->flags & ACC_NATIVE) ) {
912 m -> stubroutine = createcompilerstub (m);
916 functionptr f = native_findfunction
917 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
922 m -> stubroutine = createnativestub (f, m);
925 m -> stubroutine = oldcreatenativestub (f, m);
932 for (i=0; i<attrnum; i++) {
935 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
937 if ( aname != utf_code) {
938 skipattributebody ();
941 if (m -> jcode) panic ("Two code-attributes for one method!");
944 m -> maxstack = suck_u2();
945 m -> maxlocals = suck_u2();
946 m -> jcodelength = suck_u4();
947 m -> jcode = MNEW (u1, m->jcodelength);
948 suck_nbytes (m->jcode, m->jcodelength);
949 m -> exceptiontablelength = suck_u2 ();
950 m -> exceptiontable =
951 MNEW (exceptiontable, m->exceptiontablelength);
954 count_vmcode_len += m->jcodelength + 18;
955 count_extable_len += 8 * m->exceptiontablelength;
958 for (e=0; e < m->exceptiontablelength; e++) {
960 m -> exceptiontable[e].startpc = suck_u2();
961 m -> exceptiontable[e].endpc = suck_u2();
962 m -> exceptiontable[e].handlerpc = suck_u2();
965 if (!idx) m -> exceptiontable[e].catchtype = NULL;
967 m -> exceptiontable[e].catchtype =
968 class_getconstant (c, idx, CONSTANT_Class);
972 skipattributes ( suck_u2() );
979 /********************* Function: method_free ***********************************
981 frees all memory that was allocated for this method
983 *******************************************************************************/
985 static void method_free (methodinfo *m)
987 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
988 if (m->exceptiontable)
989 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
990 if (m->mcode) CFREE (m->mcode, m->mcodelength);
991 if (m->stubroutine) {
992 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
993 else removecompilerstub (m->stubroutine);
998 /************** Function: method_display (debugging only) **************/
1000 void method_display (methodinfo *m)
1003 printflags (m -> flags);
1005 utf_display (m -> name);
1007 utf_display (m -> descriptor);
1012 /******************** Function: method_canoverwrite ****************************
1014 Check if m and old are identical with respect to type and name. This means
1015 that old can be overwritten with m.
1017 *******************************************************************************/
1019 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1021 if (m->name != old->name) return false;
1022 if (m->descriptor != old->descriptor) return false;
1023 if (m->flags & ACC_STATIC) return false;
1030 /******************************************************************************/
1031 /************************ Functions for class *********************************/
1032 /******************************************************************************/
1035 /******************** function: class_getconstant ******************************
1037 retrieves the value at position 'pos' of the constantpool of a class
1038 if the type of the value is other than 'ctype' the system is stopped
1040 *******************************************************************************/
1042 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1044 /* invalid position in constantpool */
1045 if (pos >= c->cpcount)
1046 panic ("Attempt to access constant outside range");
1048 /* check type of constantpool entry */
1049 if (c->cptags[pos] != ctype) {
1050 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1051 (int) ctype, (int) c->cptags[pos] );
1055 return c->cpinfos[pos];
1059 /********************* Function: class_constanttype ****************************
1061 Determines the type of a class entry in the ConstantPool
1063 *******************************************************************************/
1065 u4 class_constanttype (classinfo *c, u4 pos)
1067 if (pos >= c->cpcount)
1068 panic ("Attempt to access constant outside range");
1069 return c->cptags[pos];
1073 /******************** function: class_loadcpool ********************************
1075 loads the constantpool of a class,
1076 the entries are transformed into a simpler format
1077 by resolving references
1078 (a detailed overview of the compact structures can be found in global.h)
1080 *******************************************************************************/
1082 static void class_loadcpool (classinfo *c)
1085 /* The following structures are used to save information which cannot be
1086 processed during the first pass. After the complete constantpool has
1087 been traversed the references can be resolved.
1088 (only in specific order) */
1090 /* CONSTANT_Class_info entries */
1091 typedef struct forward_class {
1092 struct forward_class *next;
1097 /* CONSTANT_String */
1098 typedef struct forward_string {
1099 struct forward_string *next;
1104 /* CONSTANT_NameAndType */
1105 typedef struct forward_nameandtype {
1106 struct forward_nameandtype *next;
1110 } forward_nameandtype;
1112 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1113 typedef struct forward_fieldmethint {
1114 struct forward_fieldmethint *next;
1118 u2 nameandtype_index;
1119 } forward_fieldmethint;
1123 long int dumpsize = dump_size ();
1125 forward_class *forward_classes = NULL;
1126 forward_string *forward_strings = NULL;
1127 forward_nameandtype *forward_nameandtypes = NULL;
1128 forward_fieldmethint *forward_fieldmethints = NULL;
1130 /* number of entries in the constant_pool table */
1131 u4 cpcount = c -> cpcount = suck_u2();
1132 /* allocate memory */
1133 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1134 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1137 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1140 /* initialize constantpool */
1141 for (idx=0; idx<cpcount; idx++) {
1142 cptags[idx] = CONSTANT_UNUSED;
1143 cpinfos[idx] = NULL;
1147 /******* first pass *******/
1148 /* entries which cannot be resolved now are written into
1149 temporary structures and traversed again later */
1152 while (idx < cpcount) {
1153 /* get constant type */
1157 case CONSTANT_Class: {
1158 forward_class *nfc = DNEW(forward_class);
1160 nfc -> next = forward_classes;
1161 forward_classes = nfc;
1163 nfc -> thisindex = idx;
1164 /* reference to CONSTANT_NameAndType */
1165 nfc -> name_index = suck_u2 ();
1171 case CONSTANT_Fieldref:
1172 case CONSTANT_Methodref:
1173 case CONSTANT_InterfaceMethodref: {
1174 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1176 nff -> next = forward_fieldmethints;
1177 forward_fieldmethints = nff;
1179 nff -> thisindex = idx;
1182 /* class or interface type that contains the declaration of the field or method */
1183 nff -> class_index = suck_u2 ();
1184 /* name and descriptor of the field or method */
1185 nff -> nameandtype_index = suck_u2 ();
1191 case CONSTANT_String: {
1192 forward_string *nfs = DNEW (forward_string);
1194 nfs -> next = forward_strings;
1195 forward_strings = nfs;
1197 nfs -> thisindex = idx;
1198 /* reference to CONSTANT_Utf8_info with string characters */
1199 nfs -> string_index = suck_u2 ();
1205 case CONSTANT_NameAndType: {
1206 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1208 nfn -> next = forward_nameandtypes;
1209 forward_nameandtypes = nfn;
1211 nfn -> thisindex = idx;
1212 /* reference to CONSTANT_Utf8_info containing simple name */
1213 nfn -> name_index = suck_u2 ();
1214 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1215 nfn -> sig_index = suck_u2 ();
1221 case CONSTANT_Integer: {
1222 constant_integer *ci = NEW (constant_integer);
1225 count_const_pool_len += sizeof(constant_integer);
1228 ci -> value = suck_s4 ();
1229 cptags [idx] = CONSTANT_Integer;
1236 case CONSTANT_Float: {
1237 constant_float *cf = NEW (constant_float);
1240 count_const_pool_len += sizeof(constant_float);
1243 cf -> value = suck_float ();
1244 cptags [idx] = CONSTANT_Float;
1250 case CONSTANT_Long: {
1251 constant_long *cl = NEW(constant_long);
1254 count_const_pool_len += sizeof(constant_long);
1257 cl -> value = suck_s8 ();
1258 cptags [idx] = CONSTANT_Long;
1264 case CONSTANT_Double: {
1265 constant_double *cd = NEW(constant_double);
1268 count_const_pool_len += sizeof(constant_double);
1271 cd -> value = suck_double ();
1272 cptags [idx] = CONSTANT_Double;
1278 case CONSTANT_Utf8: {
1280 /* number of bytes in the bytes array (not string-length) */
1281 u4 length = suck_u2();
1282 cptags [idx] = CONSTANT_Utf8;
1283 /* insert utf-string into the utf-symboltable */
1284 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1285 /* skip bytes of the string */
1286 skip_nbytes(length);
1292 sprintf (logtext, "Unkown constant type: %d",(int) t);
1301 /* resolve entries in temporary structures */
1303 while (forward_classes) {
1305 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1307 if ( (name->blength>0) && (name->text[0]=='[') ) {
1308 /* check validity of descriptor */
1309 checkfielddescriptor (name->text, utf_end(name));
1311 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1312 cpinfos [forward_classes -> thisindex] =
1313 buildarraydescriptor(name->text, name->blength);
1317 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1318 /* retrieve class from class-table */
1319 cpinfos [forward_classes -> thisindex] = class_new (name);
1321 forward_classes = forward_classes -> next;
1325 while (forward_strings) {
1327 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1329 /* resolve utf-string */
1330 cptags [forward_strings -> thisindex] = CONSTANT_String;
1331 cpinfos [forward_strings -> thisindex] = text;
1333 forward_strings = forward_strings -> next;
1336 while (forward_nameandtypes) {
1337 constant_nameandtype *cn = NEW (constant_nameandtype);
1340 count_const_pool_len += sizeof(constant_nameandtype);
1343 /* resolve simple name and descriptor */
1344 cn -> name = class_getconstant
1345 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1346 cn -> descriptor = class_getconstant
1347 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1349 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1350 cpinfos [forward_nameandtypes -> thisindex] = cn;
1352 forward_nameandtypes = forward_nameandtypes -> next;
1356 while (forward_fieldmethints) {
1357 constant_nameandtype *nat;
1358 constant_FMIref *fmi = NEW (constant_FMIref);
1361 count_const_pool_len += sizeof(constant_FMIref);
1363 /* resolve simple name and descriptor */
1364 nat = class_getconstant
1365 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1367 fmi -> class = class_getconstant
1368 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1369 fmi -> name = nat -> name;
1370 fmi -> descriptor = nat -> descriptor;
1372 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1373 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1375 switch (forward_fieldmethints -> tag) {
1376 case CONSTANT_Fieldref: /* check validity of descriptor */
1377 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1379 case CONSTANT_InterfaceMethodref:
1380 case CONSTANT_Methodref: /* check validity of descriptor */
1381 checkmethoddescriptor (fmi->descriptor);
1385 forward_fieldmethints = forward_fieldmethints -> next;
1390 dump_release (dumpsize);
1394 /********************** Function: class_load ***********************************
1396 Loads everything interesting about a class from the class file. The
1397 'classinfo' structure must have been allocated previously.
1399 The super class and the interfaces implemented by this class need not be
1400 loaded. The link is set later by the function 'class_link'.
1402 The loaded class is removed from the list 'unloadedclasses' and added to
1403 the list 'unlinkedclasses'.
1405 *******************************************************************************/
1407 static int class_load (classinfo *c)
1413 count_class_loads++;
1416 /* output for debugging purposes */
1418 sprintf (logtext, "Loading class: ");
1419 utf_sprint (logtext+strlen(logtext), c->name );
1423 /* load classdata, throw exception on error */
1424 if (!suck_start (c->name)) {
1425 throw_classnotfoundexception();
1429 /* check signature */
1430 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1434 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1435 sprintf (logtext, "File version %d.%d is not supported",
1436 (int) ma, (int) mi);
1441 class_loadcpool (c);
1443 c -> classUsed = 0; /* not used initially CO-RT */
1446 c -> flags = suck_u2 ();
1450 /* retrieve superclass */
1451 if ( (i = suck_u2 () ) ) {
1452 c -> super = class_getconstant (c, i, CONSTANT_Class);
1458 /* retrieve interfaces */
1459 c -> interfacescount = suck_u2 ();
1460 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1461 for (i=0; i < c -> interfacescount; i++) {
1462 c -> interfaces [i] =
1463 class_getconstant (c, suck_u2(), CONSTANT_Class);
1467 c -> fieldscount = suck_u2 ();
1469 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1471 c -> fields = MNEW (fieldinfo, c -> fieldscount);
1473 for (i=0; i < c -> fieldscount; i++) {
1474 field_load (&(c->fields[i]), c);
1478 c -> methodscount = suck_u2 ();
1479 c -> methods = MNEW (methodinfo, c -> methodscount);
1480 for (i=0; i < c -> methodscount; i++) {
1481 method_load (&(c -> methods [i]), c);
1485 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1486 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1487 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1490 /* load variable-length attribute structures */
1491 attribute_load (suck_u2(), c);
1496 /* remove class from list of unloaded classes and
1497 add to list of unlinked classes */
1498 list_remove (&unloadedclasses, c);
1499 list_addlast (&unlinkedclasses, c);
1506 /************** internal Function: class_highestinterface ***********************
1508 Used by the function class_link to determine the amount of memory needed
1509 for the interface table.
1511 *******************************************************************************/
1513 static s4 class_highestinterface (classinfo *c)
1518 if ( ! (c->flags & ACC_INTERFACE) ) {
1519 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1520 utf_sprint (logtext+strlen(logtext), c->name);
1525 for (i=0; i<c->interfacescount; i++) {
1526 s4 h2 = class_highestinterface (c->interfaces[i]);
1533 /* class_addinterface **********************************************************
1535 Is needed by class_link for adding a VTBL to a class. All interfaces
1536 implemented by ic are added as well.
1538 *******************************************************************************/
1540 static void class_addinterface (classinfo *c, classinfo *ic)
1544 vftbl *vftbl = c->vftbl;
1546 if (i >= vftbl->interfacetablelength)
1547 panic ("Inernal error: interfacetable overflow");
1548 if (vftbl->interfacetable[-i])
1551 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1552 vftbl->interfacevftbllength[i] = 1;
1553 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1554 vftbl->interfacetable[-i][0] = NULL;
1557 vftbl->interfacevftbllength[i] = ic->methodscount;
1558 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1561 count_vftbl_len += sizeof(methodptr) *
1562 (ic->methodscount + (ic->methodscount == 0));
1565 for (j=0; j<ic->methodscount; j++) {
1568 for (m = 0; m < sc->methodscount; m++) {
1569 methodinfo *mi = &(sc->methods[m]);
1570 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1571 vftbl->interfacetable[-i][j] =
1572 vftbl->table[mi->vftblindex];
1582 for (j = 0; j < ic->interfacescount; j++)
1583 class_addinterface(c, ic->interfaces[j]);
1587 /********************** Function: class_link ***********************************
1589 Tries to link a class. The super class and every implemented interface must
1590 already have been linked. The function calculates the length in bytes that
1591 an instance of this class requires as well as the VTBL for methods and
1594 If the class can be linked, it is removed from the list 'unlinkedclasses'
1595 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1598 Attention: If cyclical class definitions are encountered, the program gets
1599 into an infinite loop (we'll have to work that out)
1601 *******************************************************************************/
1603 static void class_link (classinfo *c)
1605 s4 supervftbllength; /* vftbllegnth of super class */
1606 s4 vftbllength; /* vftbllength of current class */
1607 s4 interfacetablelength; /* interface table length */
1608 classinfo *super = c->super; /* super class */
1609 classinfo *ic, *c2; /* intermediate class variables */
1610 vftbl *v; /* vftbl of current class */
1611 s4 i; /* interface/method/field counter */
1614 /* check if all superclasses are already linked, if not put c at end of
1615 unlinked list and return. Additionally initialize class fields. */
1617 /* check interfaces */
1619 for (i = 0; i < c->interfacescount; i++) {
1620 ic = c->interfaces[i];
1622 list_remove(&unlinkedclasses, c);
1623 list_addlast(&unlinkedclasses, c);
1628 /* check super class */
1630 if (super == NULL) { /* class java.long.Object */
1632 c->classUsed = 1; /* Object class is always used CO-RT*/
1633 c->instancesize = sizeof(java_objectheader);
1635 vftbllength = supervftbllength = 0;
1637 c->finalizer = NULL;
1640 if (!super->linked) {
1641 list_remove(&unlinkedclasses, c);
1642 list_addlast(&unlinkedclasses, c);
1646 if (c->flags & ACC_INTERFACE)
1647 c->index = interfaceindex++;
1649 c->index = super->index + 1;
1651 c->instancesize = super->instancesize;
1653 vftbllength = supervftbllength = super->vftbl->vftbllength;
1655 c->finalizer = super->finalizer;
1660 sprintf (logtext, "Linking Class: ");
1661 utf_sprint (logtext+strlen(logtext), c->name );
1665 /* compute vftbl length */
1667 for (i = 0; i < c->methodscount; i++) {
1668 methodinfo *m = &(c->methods[i]);
1670 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1671 classinfo *sc = super;
1674 for (j = 0; j < sc->methodscount; j++) {
1675 if (method_canoverwrite(m, &(sc->methods[j]))) {
1676 m->vftblindex = sc->methods[j].vftblindex;
1677 goto foundvftblindex;
1682 m->vftblindex = (vftbllength++);
1688 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1691 /* compute interfacetable length */
1693 interfacetablelength = 0;
1696 for (i = 0; i < c2->interfacescount; i++) {
1697 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1698 if (h > interfacetablelength)
1699 interfacetablelength = h;
1704 /* allocate virtual function table */
1706 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1707 (vftbllength - 1) + sizeof(methodptr*) *
1708 (interfacetablelength - (interfacetablelength > 0)));
1709 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1710 (interfacetablelength > 1));
1711 c->header.vftbl = c->vftbl = v;
1713 v->vftbllength = vftbllength;
1714 v->interfacetablelength = interfacetablelength;
1716 /* copy virtual function table of super class */
1718 for (i = 0; i < supervftbllength; i++)
1719 v->table[i] = super->vftbl->table[i];
1721 /* add method stubs into virtual function table */
1723 for (i = 0; i < c->methodscount; i++) {
1724 methodinfo *m = &(c->methods[i]);
1725 if (!(m->flags & ACC_STATIC)) {
1726 v->table[m->vftblindex] = m->stubroutine;
1730 /* compute instance size and offset of each field */
1732 for (i = 0; i < c->fieldscount; i++) {
1734 fieldinfo *f = &(c->fields[i]);
1736 if (!(f->flags & ACC_STATIC) ) {
1737 dsize = desc_typesize (f->descriptor);
1738 c->instancesize = ALIGN (c->instancesize, dsize);
1739 f->offset = c->instancesize;
1740 c->instancesize += dsize;
1744 /* initialize interfacetable and interfacevftbllength */
1746 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1749 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1752 for (i = 0; i < interfacetablelength; i++) {
1753 v->interfacevftbllength[i] = 0;
1754 v->interfacetable[-i] = NULL;
1757 /* add interfaces */
1759 for (c2 = c; c2 != NULL; c2 = c2->super)
1760 for (i = 0; i < c2->interfacescount; i++) {
1761 class_addinterface (c, c2->interfaces[i]);
1764 /* add finalizer method (not for java.lang.Object) */
1766 if (super != NULL) {
1768 static utf *finame = NULL;
1769 static utf *fidesc = NULL;
1772 finame = utf_finalize;
1774 fidesc = utf_fidesc;
1776 fi = class_findmethod (c, finame, fidesc);
1778 if (!(fi->flags & ACC_STATIC)) {
1788 list_remove (&unlinkedclasses, c);
1789 list_addlast (&linkedclasses, c);
1793 /******************* Function: class_freepool **********************************
1795 Frees all resources used by this classes Constant Pool.
1797 *******************************************************************************/
1799 static void class_freecpool (classinfo *c)
1805 for (idx=0; idx < c->cpcount; idx++) {
1806 tag = c->cptags[idx];
1807 info = c->cpinfos[idx];
1811 case CONSTANT_Fieldref:
1812 case CONSTANT_Methodref:
1813 case CONSTANT_InterfaceMethodref:
1814 FREE (info, constant_FMIref);
1816 case CONSTANT_Integer:
1817 FREE (info, constant_integer);
1819 case CONSTANT_Float:
1820 FREE (info, constant_float);
1823 FREE (info, constant_long);
1825 case CONSTANT_Double:
1826 FREE (info, constant_double);
1828 case CONSTANT_NameAndType:
1829 FREE (info, constant_nameandtype);
1831 case CONSTANT_Arraydescriptor:
1832 freearraydescriptor (info);
1838 MFREE (c -> cptags, u1, c -> cpcount);
1839 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1843 /*********************** Function: class_free **********************************
1845 Frees all resources used by the class.
1847 *******************************************************************************/
1849 static void class_free (classinfo *c)
1854 class_freecpool (c);
1856 MFREE (c->interfaces, classinfo*, c->interfacescount);
1858 for (i = 0; i < c->fieldscount; i++)
1859 field_free(&(c->fields[i]));
1861 MFREE (c->fields, fieldinfo, c->fieldscount);
1864 for (i = 0; i < c->methodscount; i++)
1865 method_free(&(c->methods[i]));
1866 MFREE (c->methods, methodinfo, c->methodscount);
1868 if ((v = c->vftbl) != NULL) {
1869 for (i = 0; i < v->interfacetablelength; i++) {
1870 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1872 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1874 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1875 sizeof(methodptr*) * (v->interfacetablelength -
1876 (v->interfacetablelength > 0));
1877 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1878 (v->interfacetablelength > 1));
1882 if (c->innerclasscount)
1883 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1886 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1));
1888 FREE (c, classinfo);
1891 /************************* Function: class_findfield ***************************
1893 Searches a 'classinfo' structure for a field having the given name and
1896 *******************************************************************************/
1899 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1903 for (i = 0; i < c->fieldscount; i++) {
1904 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1905 return &(c->fields[i]);
1908 panic ("Can not find field given in CONSTANT_Fieldref");
1913 /************************* Function: class_findmethod **************************
1915 Searches a 'classinfo' structure for a method having the given name and
1917 If type is NULL, it is ignored.
1919 *******************************************************************************/
1921 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1924 for (i = 0; i < c->methodscount; i++) {
1925 if ((c->methods[i].name == name) && ((desc == NULL) ||
1926 (c->methods[i].descriptor == desc)))
1927 return &(c->methods[i]);
1932 /************************* Function: class_findmethod_approx ******************
1934 like class_findmethod but ignores the return value when comparing the
1937 *******************************************************************************/
1939 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1943 for (i = 0; i < c->methodscount; i++)
1944 if (c->methods[i].name == name) {
1945 utf *meth_descr = c->methods[i].descriptor;
1949 return &(c->methods[i]);
1951 if (desc->blength <= meth_descr->blength) {
1952 /* current position in utf text */
1953 char *desc_utf_ptr = desc->text;
1954 char *meth_utf_ptr = meth_descr->text;
1955 /* points behind utf strings */
1956 char *desc_end = utf_end(desc);
1957 char *meth_end = utf_end(meth_descr);
1960 /* compare argument types */
1961 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1963 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1964 break; /* no match */
1967 return &(c->methods[i]); /* all parameter types equal */
1975 /***************** Function: class_resolvemethod_approx ***********************
1977 Searches a class and every super class for a method (without paying
1978 attention to the return value)
1980 *******************************************************************************/
1982 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
1985 /* search for method (ignore returntype) */
1986 methodinfo *m = class_findmethod_approx (c, name, desc);
1989 /* search superclass */
1996 /************************* Function: class_resolvemethod ***********************
1998 Searches a class and every super class for a method.
2000 *******************************************************************************/
2003 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2006 methodinfo *m = class_findmethod (c, name, desc);
2008 /* search superclass */
2016 /************************* Function: class_issubclass **************************
2018 Checks if sub is a descendant of super.
2020 *******************************************************************************/
2022 bool class_issubclass (classinfo *sub, classinfo *super)
2025 if (!sub) return false;
2026 if (sub==super) return true;
2033 /****************** Initialization function for classes ******************
2035 In Java, every class can have a static initialization function. This
2036 function has to be called BEFORE calling other methods or accessing static
2039 *******************************************************************************/
2042 extern int blockInts;
2045 void class_init (classinfo *c)
2048 java_objectheader *exceptionptr;
2052 if (!makeinitializations)
2056 c -> initialized = true;
2059 count_class_inits++;
2063 class_init (c->super);
2064 for (i=0; i < c->interfacescount; i++)
2065 class_init(c->interfaces[i]);
2067 m = class_findmethod (c, utf_clinit, utf_fidesc);
2070 sprintf (logtext, "Class ");
2071 utf_sprint (logtext+strlen(logtext), c->name);
2072 sprintf (logtext+strlen(logtext), " has no initializer");
2078 if (! (m->flags & ACC_STATIC))
2079 panic ("Class initializer is not static!");
2082 sprintf (logtext, "Starting initializer for class: ");
2083 utf_sprint (logtext+strlen(logtext), c->name);
2092 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2095 assert(blockInts == 0);
2100 printf ("#### Initializer of ");
2101 utf_display (c->name);
2102 printf (" has thrown: ");
2103 utf_display (exceptionptr->vftbl->class->name);
2109 sprintf (logtext, "Finished initializer for class: ");
2110 utf_sprint (logtext+strlen(logtext), c->name);
2114 if (c->name == utf_systemclass) {
2115 /* class java.lang.System requires explicit initialization */
2118 printf ("#### Initializing class System");
2120 /* find initializing method */
2121 m = class_findmethod (c,
2122 utf_initsystemclass,
2126 /* no method found */
2127 log("initializeSystemClass failed");
2136 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2139 assert(blockInts == 0);
2144 printf ("#### initializeSystemClass has thrown: ");
2145 utf_display (exceptionptr->vftbl->class->name);
2155 /********* Function: class_showconstantpool (debugging only) *********/
2157 void class_showconstantpool (classinfo *c)
2162 printf ("---- dump of constant pool ----\n");
2164 for (i=0; i<c->cpcount; i++) {
2165 printf ("#%d: ", (int) i);
2167 e = c -> cpinfos [i];
2170 switch (c -> cptags [i]) {
2171 case CONSTANT_Class:
2172 printf ("Classreference -> ");
2173 utf_display ( ((classinfo*)e) -> name );
2176 case CONSTANT_Fieldref:
2177 printf ("Fieldref -> "); goto displayFMI;
2178 case CONSTANT_Methodref:
2179 printf ("Methodref -> "); goto displayFMI;
2180 case CONSTANT_InterfaceMethodref:
2181 printf ("InterfaceMethod -> "); goto displayFMI;
2184 constant_FMIref *fmi = e;
2185 utf_display ( fmi->class->name );
2187 utf_display ( fmi->name);
2189 utf_display ( fmi->descriptor );
2193 case CONSTANT_String:
2194 printf ("String -> ");
2197 case CONSTANT_Integer:
2198 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2200 case CONSTANT_Float:
2201 printf ("Float -> %f", ((constant_float*)e) -> value);
2203 case CONSTANT_Double:
2204 printf ("Double -> %f", ((constant_double*)e) -> value);
2208 u8 v = ((constant_long*)e) -> value;
2210 printf ("Long -> %ld", (long int) v);
2212 printf ("Long -> HI: %ld, LO: %ld\n",
2213 (long int) v.high, (long int) v.low);
2217 case CONSTANT_NameAndType:
2218 { constant_nameandtype *cnt = e;
2219 printf ("NameAndType: ");
2220 utf_display (cnt->name);
2222 utf_display (cnt->descriptor);
2226 printf ("Utf8 -> ");
2229 case CONSTANT_Arraydescriptor: {
2230 printf ("Arraydescriptor: ");
2231 displayarraydescriptor (e);
2235 panic ("Invalid type of ConstantPool-Entry");
2247 /********** Function: class_showmethods (debugging only) *************/
2249 void class_showmethods (classinfo *c)
2253 printf ("--------- Fields and Methods ----------------\n");
2254 printf ("Flags: "); printflags (c->flags); printf ("\n");
2256 printf ("This: "); utf_display (c->name); printf ("\n");
2258 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2260 printf ("Index: %d\n", c->index);
2262 printf ("interfaces:\n");
2263 for (i=0; i < c-> interfacescount; i++) {
2265 utf_display (c -> interfaces[i] -> name);
2266 printf (" (%d)\n", c->interfaces[i] -> index);
2269 printf ("fields:\n");
2270 for (i=0; i < c -> fieldscount; i++) {
2271 field_display (&(c -> fields[i]));
2274 printf ("methods:\n");
2275 for (i=0; i < c -> methodscount; i++) {
2276 methodinfo *m = &(c->methods[i]);
2277 if ( !(m->flags & ACC_STATIC))
2278 printf ("vftblindex: %d ", m->vftblindex);
2280 method_display ( m );
2284 printf ("Virtual function table:\n");
2285 for (i=0; i<c->vftbl->vftbllength; i++) {
2286 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2293 /******************************************************************************/
2294 /******************* General functions for the class loader *******************/
2295 /******************************************************************************/
2297 static int loader_inited = 0;
2299 /********************* Function: loader_load ***********************************
2301 Loads and links the class desired class and each class and interface
2303 Returns: a pointer to this class
2305 *******************************************************************************/
2307 classinfo *loader_load (utf *topname)
2311 long int starttime=0,stoptime=0;
2313 intsDisable(); /* schani */
2316 starttime = getcputime();
2318 top = class_new (topname);
2321 while ( (c = list_first(&unloadedclasses)) ) {
2322 if (!class_load (c)) {
2323 list_remove (&unloadedclasses, c);
2329 while ( (c = list_first(&unlinkedclasses)) ) {
2334 loader_compute_subclasses();
2337 if (getloadingtime) {
2338 stoptime = getcputime();
2339 loadingtime += (stoptime-starttime);
2342 intsRestore(); /* schani */
2348 /**************** function: create_primitive_classes ***************************
2350 create classes representing primitive types
2352 ********************************************************************************/
2355 void create_primitive_classes()
2359 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2360 /* create primitive class */
2361 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2362 c -> classUsed = 0; /* not used initially CO-RT */
2364 /* prevent loader from loading primitive class */
2365 list_remove (&unloadedclasses, c);
2366 /* add to unlinked classes */
2367 list_addlast (&unlinkedclasses, c);
2368 c -> super = class_java_lang_Object;
2371 primitivetype_table[i].class_primitive = c;
2373 /* create class for wrapping the primitive type */
2374 primitivetype_table[i].class_wrap =
2375 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2376 primitivetype_table[i].class_wrap -> classUsed = 0; /* not used initially CO-RT */
2380 /***************** function: create_array_class ********************************
2382 create class representing an array
2384 ********************************************************************************/
2387 classinfo *create_array_class(utf *u)
2389 classinfo *c = class_new (u);
2390 /* prevent loader from loading the array class */
2391 list_remove (&unloadedclasses, c);
2392 /* add to unlinked classes */
2393 list_addlast (&unlinkedclasses, c);
2394 c -> super = class_java_lang_Object;
2400 /********************** Function: loader_init **********************************
2402 Initializes all lists and loads all classes required for the system or the
2405 *******************************************************************************/
2412 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2413 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2414 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2416 /* create utf-symbols for pointer comparison of frequently used strings */
2417 utf_innerclasses = utf_new_char("InnerClasses");
2418 utf_constantvalue = utf_new_char("ConstantValue");
2419 utf_code = utf_new_char("Code");
2420 utf_finalize = utf_new_char("finalize");
2421 utf_fidesc = utf_new_char("()V");
2422 utf_clinit = utf_new_char("<clinit>");
2423 utf_initsystemclass = utf_new_char("initializeSystemClass");
2424 utf_systemclass = utf_new_char("java/lang/System");
2426 /* create class for arrays */
2427 class_array = class_new ( utf_new_char ("The_Array_Class") );
2428 class_array -> classUsed = 0; /* not used initially CO-RT */
2430 list_remove (&unloadedclasses, class_array);
2432 /* create class for strings, load it after class Object was loaded */
2433 string_class = utf_new_char ("java/lang/String");
2434 class_java_lang_String = class_new(string_class);
2435 class_java_lang_String -> classUsed = 0; /* not used initially CO-RT */
2437 list_remove (&unloadedclasses, class_java_lang_String);
2439 class_java_lang_Object =
2440 loader_load ( utf_new_char ("java/lang/Object") );
2442 list_addlast(&unloadedclasses, class_java_lang_String);
2444 class_java_lang_String =
2445 loader_load ( string_class );
2446 class_java_lang_ClassCastException =
2447 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2448 class_java_lang_NullPointerException =
2449 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2450 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2451 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2452 class_java_lang_NegativeArraySizeException = loader_load (
2453 utf_new_char ("java/lang/NegativeArraySizeException") );
2454 class_java_lang_OutOfMemoryError = loader_load (
2455 utf_new_char ("java/lang/OutOfMemoryError") );
2456 class_java_lang_ArrayStoreException =
2457 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2458 class_java_lang_ArithmeticException =
2459 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2460 class_java_lang_ThreadDeath = /* schani */
2461 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2463 /* link class for arrays */
2464 list_addlast (&unlinkedclasses, class_array);
2465 class_array -> super = class_java_lang_Object;
2466 class_link (class_array);
2468 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2469 stringtable_update();
2471 /* create classes representing primitive types */
2472 create_primitive_classes();
2474 proto_java_lang_ClassCastException =
2475 builtin_new(class_java_lang_ClassCastException);
2476 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2478 proto_java_lang_NullPointerException =
2479 builtin_new(class_java_lang_NullPointerException);
2480 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2482 proto_java_lang_ArrayIndexOutOfBoundsException =
2483 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2484 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2486 proto_java_lang_NegativeArraySizeException =
2487 builtin_new(class_java_lang_NegativeArraySizeException);
2488 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2490 proto_java_lang_OutOfMemoryError =
2491 builtin_new(class_java_lang_OutOfMemoryError);
2492 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2494 proto_java_lang_ArithmeticException =
2495 builtin_new(class_java_lang_ArithmeticException);
2496 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2498 proto_java_lang_ArrayStoreException =
2499 builtin_new(class_java_lang_ArrayStoreException);
2500 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2502 proto_java_lang_ThreadDeath = /* schani */
2503 builtin_new(class_java_lang_ThreadDeath);
2504 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2512 /********************* Function: loader_initclasses ****************************
2514 Initializes all loaded but uninitialized classes
2516 *******************************************************************************/
2518 void loader_initclasses ()
2522 intsDisable(); /* schani */
2524 if (makeinitializations) {
2525 c = list_first (&linkedclasses);
2528 c = list_next (&linkedclasses, c);
2532 intsRestore(); /* schani */
2535 static s4 classvalue;
2537 static void loader_compute_class_values (classinfo *c)
2541 c->vftbl->baseval = ++classvalue;
2543 while (subs != NULL) {
2544 loader_compute_class_values(subs);
2545 subs = subs->nextsub;
2547 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2551 for (i = 0; i < c->index; i++)
2553 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2554 utf_display(c->name);
2561 void loader_compute_subclasses ()
2565 intsDisable(); /* schani */
2567 c = list_first (&linkedclasses);
2569 if (!(c->flags & ACC_INTERFACE)) {
2573 c = list_next (&linkedclasses, c);
2576 c = list_first (&linkedclasses);
2578 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2579 c->nextsub = c->super->sub;
2582 c = list_next (&linkedclasses, c);
2586 loader_compute_class_values(class_java_lang_Object);
2588 intsRestore(); /* schani */
2593 /******************** function classloader_buffer ******************************
2595 sets buffer for reading classdata
2597 *******************************************************************************/
2599 void classload_buffer(u1 *buf, int len)
2602 classbuffer_size = len;
2603 classbuf_pos = buf - 1;
2607 /******************** Function: loader_close ***********************************
2611 *******************************************************************************/
2613 void loader_close ()
2617 while ( (c=list_first(&unloadedclasses)) ) {
2618 list_remove (&unloadedclasses,c);
2621 while ( (c=list_first(&unlinkedclasses)) ) {
2622 list_remove (&unlinkedclasses,c);
2625 while ( (c=list_first(&linkedclasses)) ) {
2626 list_remove (&linkedclasses,c);
2633 * These are local overrides for various environment variables in Emacs.
2634 * Please do not remove this and leave it at the end of the file, where
2635 * Emacs will automagically detect them.
2636 * ---------------------------------------------------------------------
2639 * indent-tabs-mode: t