2 /* loader.c ********************************************************************
4 Copyright (c) 1999 A. Krall, R. Grafl, R. Obermaiser, M. Probst
6 See file COPYRIGHT for information on usage and disclaimer of warranties
8 Contains the functions of the class loader.
10 Author: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
11 Changes: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
12 Roman Obermaiser EMAIL: cacao@complang.tuwien.ac.at
13 Mark Probst EMAIL: cacao@complang.tuwien.ac.at
15 Last Change: 1999/11/08
17 *******************************************************************************/
34 #include "toolbox/memory.h"
37 #include "toolbox/loging.h"
39 #include "threads/thread.h"
42 /* global variables ***********************************************************/
44 extern bool newcompiler; /* true if new compiler is used */
45 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
46 bool opt_xta = false; /* true if XTA parse should be used XTA-CO */
48 int count_class_infos = 0; /* variables for measurements */
49 int count_const_pool_len = 0;
50 int count_vftbl_len = 0;
51 int count_all_methods = 0;
52 int count_vmcode_len = 0;
53 int count_extable_len = 0;
54 int count_class_loads = 0;
55 int count_class_inits = 0;
57 bool loadverbose = false; /* switches for debug messages */
58 bool linkverbose = false;
59 bool initverbose = false;
61 bool makeinitializations = true;
63 bool getloadingtime = false; /* to measure the runtime */
64 long int loadingtime = 0;
66 static s4 interfaceindex; /* sequential numbering of interfaces */
68 list unloadedclasses; /* list of all referenced but not loaded classes */
69 list unlinkedclasses; /* list of all loaded but not linked classes */
70 list linkedclasses; /* list of all completely linked classes */
73 /* utf-symbols for pointer comparison of frequently used strings */
75 static utf *utf_innerclasses; /* InnerClasses */
76 static utf *utf_constantvalue; /* ConstantValue */
77 static utf *utf_code; /* Code */
78 static utf *utf_finalize; /* finalize */
79 static utf *utf_fidesc; /* ()V */
80 static utf *utf_clinit; /* <clinit> */
81 static utf *utf_initsystemclass; /* initializeSystemClass */
82 static utf *utf_systemclass; /* java/lang/System */
85 /* important system classes ***************************************************/
87 classinfo *class_java_lang_Object;
88 classinfo *class_java_lang_String;
89 classinfo *class_array = NULL;
92 /* These are made static so they cannot be used for throwing in native */
94 static classinfo *class_java_lang_ClassCastException;
95 static classinfo *class_java_lang_NullPointerException;
96 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
97 static classinfo *class_java_lang_NegativeArraySizeException;
98 static classinfo *class_java_lang_OutOfMemoryError;
99 static classinfo *class_java_lang_ArithmeticException;
100 static classinfo *class_java_lang_ArrayStoreException;
101 static classinfo *class_java_lang_ThreadDeath;
104 /******************************************************************************
106 structure for primitive classes: contains the class for wrapping the
107 primitive type, the primitive class, the name of the class for wrapping,
108 the one character type signature and the name of the primitive class
110 ******************************************************************************/
112 primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
113 { NULL, NULL, "java/lang/Double", 'D', "double" },
114 { NULL, NULL, "java/lang/Float", 'F', "float" },
115 { NULL, NULL, "java/lang/Character", 'C', "char" },
116 { NULL, NULL, "java/lang/Integer", 'I', "int" },
117 { NULL, NULL, "java/lang/Long", 'J', "long" },
118 { NULL, NULL, "java/lang/Byte", 'B', "byte" },
119 { NULL, NULL, "java/lang/Short", 'S', "short" },
120 { NULL, NULL, "java/lang/Boolean", 'Z', "boolean" },
121 { NULL, NULL, "java/lang/Void", 'V', "void" }};
124 /* instances of important system classes **************************************/
126 java_objectheader *proto_java_lang_ClassCastException;
127 java_objectheader *proto_java_lang_NullPointerException;
128 java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
129 java_objectheader *proto_java_lang_NegativeArraySizeException;
130 java_objectheader *proto_java_lang_OutOfMemoryError;
131 java_objectheader *proto_java_lang_ArithmeticException;
132 java_objectheader *proto_java_lang_ArrayStoreException;
133 java_objectheader *proto_java_lang_ThreadDeath;
136 /************* functions for reading classdata *********************************
138 getting classdata in blocks of variable size
139 (8,16,32,64-bit integer or float)
141 *******************************************************************************/
143 static char *classpath = ""; /* searchpath for classfiles */
144 static u1 *classbuffer = NULL; /* pointer to buffer with classfile-data */
145 static u1 *classbuf_pos; /* current position in classfile buffer */
146 static int classbuffer_size; /* size of classfile-data */
148 /* transfer block of classfile data into a buffer */
150 #define suck_nbytes(buffer,len) memcpy(buffer,classbuf_pos+1,len); \
153 /* skip block of classfile data */
155 #define skip_nbytes(len) classbuf_pos+=len;
159 return *++classbuf_pos;
163 u1 a=suck_u1(), b=suck_u1();
164 return ((u2)a<<8)+(u2)b;
168 u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
169 return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
171 #define suck_s8() (s8) suck_u8()
172 #define suck_s2() (s2) suck_u2()
173 #define suck_s4() (s4) suck_u4()
174 #define suck_s1() (s1) suck_u1()
177 /* get u8 from classfile data */
185 return (hi<<32) + lo;
194 /* get float from classfile data */
196 static float suck_float ()
203 for (i=0; i<4; i++) buffer[3-i] = suck_u1 ();
204 memcpy ( (u1*) (&f), buffer, 4);
206 suck_nbytes ( (u1*) (&f), 4 );
209 PANICIF (sizeof(float) != 4, "Incompatible float-format");
214 /* get double from classfile data */
215 static double suck_double ()
222 for (i=0; i<8; i++) buffer[7-i] = suck_u1 ();
223 memcpy ( (u1*) (&d), buffer, 8);
225 suck_nbytes ( (u1*) (&d), 8 );
228 PANICIF (sizeof(double) != 8, "Incompatible double-format" );
233 /************************** function suck_init *********************************
235 called once at startup, sets the searchpath for the classfiles
237 *******************************************************************************/
239 void suck_init (char *cpath)
246 /************************** function suck_start ********************************
248 returns true if classbuffer is already loaded or a file for the
249 specified class has succussfully been read in. All directories of
250 the searchpath are used to find the classfile (<classname>.class).
251 Returns false if no classfile is found and writes an error message.
253 *******************************************************************************/
256 bool suck_start (utf *classname) {
258 #define MAXFILENAME 1000 /* maximum length of a filename */
260 char filename[MAXFILENAME+10]; /* room for '.class' */
261 char *pathpos; /* position in searchpath */
262 char c, *utf_ptr; /* pointer to the next utf8-character */
264 int filenamelen, err;
267 if (classbuffer) /* classbuffer is already valid */
274 /* skip path separator */
276 while (*pathpos == ':')
279 /* extract directory from searchpath */
282 while ((*pathpos) && (*pathpos!=':')) {
283 PANICIF (filenamelen >= MAXFILENAME, "Filename too long") ;
284 filename[filenamelen++] = *(pathpos++);
287 filename[filenamelen++] = '/';
289 /* add classname to filename */
291 utf_ptr = classname->text;
292 while (utf_ptr < utf_end(classname)) {
293 PANICIF (filenamelen >= MAXFILENAME, "Filename too long");
295 if ((c <= ' ' || c > 'z') && (c != '/')) /* invalid character */
297 filename[filenamelen++] = c;
302 strcpy (filename+filenamelen, ".class");
304 classfile = fopen(filename, "r");
305 if (classfile) { /* file exists */
307 /* determine size of classfile */
309 err = stat (filename, &buffer);
311 if (!err) { /* read classfile data */
312 classbuffer_size = buffer.st_size;
313 classbuffer = MNEW(u1, classbuffer_size);
314 classbuf_pos = classbuffer-1;
315 fread(classbuffer, 1, classbuffer_size, classfile);
323 sprintf (logtext, "Warning: Can not open class file '%s'", filename);
331 /************************** function suck_stop *********************************
333 frees memory for buffer with classfile data.
334 Caution: this function may only be called if buffer has been allocated
335 by suck_start with reading a file
337 *******************************************************************************/
341 /* determine amount of classdata not retrieved by suck-operations */
343 int classdata_left = ((classbuffer+classbuffer_size)-classbuf_pos-1);
345 if (classdata_left > 0) {
347 sprintf (logtext,"There are %d access bytes at end of classfile",
354 MFREE(classbuffer, u1, classbuffer_size);
358 /******************************************************************************/
359 /******************* Some support functions ***********************************/
360 /******************************************************************************/
363 /********** internal function: printflags (only for debugging) ***************/
365 static void printflags (u2 f)
367 if ( f & ACC_PUBLIC ) printf (" PUBLIC");
368 if ( f & ACC_PRIVATE ) printf (" PRIVATE");
369 if ( f & ACC_PROTECTED ) printf (" PROTECTED");
370 if ( f & ACC_STATIC ) printf (" STATIC");
371 if ( f & ACC_FINAL ) printf (" FINAL");
372 if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
373 if ( f & ACC_VOLATILE ) printf (" VOLATILE");
374 if ( f & ACC_TRANSIENT ) printf (" TRANSIENT");
375 if ( f & ACC_NATIVE ) printf (" NATIVE");
376 if ( f & ACC_INTERFACE ) printf (" INTERFACE");
377 if ( f & ACC_ABSTRACT ) printf (" ABSTRACT");
381 /************************* Function: skipattribute *****************************
383 skips a (1) 'attribute' structure in the class file
385 *******************************************************************************/
387 static void skipattribute ()
390 skip_nbytes(suck_u4());
393 /********************** Function: skipattributebody ****************************
395 skips an attribute after the 16 bit reference to attribute_name has already
398 *******************************************************************************/
400 static void skipattributebody ()
402 skip_nbytes(suck_u4());
405 /************************* Function: skipattributes ****************************
407 skips num attribute structures
409 *******************************************************************************/
411 static void skipattributes (u4 num)
414 for (i = 0; i < num; i++)
418 /******************** function: innerclass_getconstant ************************
420 like class_getconstant, but if cptags is ZERO null is returned
422 *******************************************************************************/
424 voidptr innerclass_getconstant (classinfo *c, u4 pos, u4 ctype)
426 /* invalid position in constantpool */
427 if (pos >= c->cpcount)
428 panic ("Attempt to access constant outside range");
430 /* constantpool entry of type 0 */
434 /* check type of constantpool entry */
435 if (c->cptags[pos] != ctype) {
436 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
437 (int) ctype, (int) c->cptags[pos] );
441 return c->cpinfos[pos];
444 /************************ function: attribute_load ****************************
446 read attributes from classfile
448 *******************************************************************************/
450 static void attribute_load (u4 num, classinfo *c)
454 for (i = 0; i < num; i++) {
455 /* retrieve attribute name */
456 utf *aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
458 if ( aname == utf_innerclasses) {
459 /* innerclasses attribute */
461 /* skip attribute length */
463 /* number of records */
464 c->innerclasscount = suck_u2();
465 /* allocate memory for innerclass structure */
466 c->innerclass = MNEW (innerclassinfo, c->innerclasscount);
468 for (j=0;j<c->innerclasscount;j++) {
470 /* The innerclass structure contains a class with an encoded name,
471 its defining scope, its simple name and a bitmask of the access flags.
472 If an inner class is not a member, its outer_class is NULL,
473 if a class is anonymous, its name is NULL. */
475 innerclassinfo *info = c->innerclass + j;
477 info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
478 info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
479 info->name = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8); /* CONSTANT_Utf8_info index */
480 info->flags = suck_u2 (); /* access_flags bitmask */
483 /* unknown attribute */
484 skipattributebody ();
489 /******************* function: checkfielddescriptor ****************************
491 checks whether a field-descriptor is valid and aborts otherwise
492 all referenced classes are inserted into the list of unloaded classes
494 *******************************************************************************/
496 static void checkfielddescriptor (char *utf_ptr, char *end_pos)
498 char *tstart; /* pointer to start of classname */
501 switch (*utf_ptr++) {
514 /* save start of classname */
517 /* determine length of classname */
518 while ( *utf_ptr++ != ';' )
519 if (utf_ptr>=end_pos)
520 panic ("Missing ';' in objecttype-descriptor");
522 /* cause loading of referenced class */
523 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
528 while ((ch = *utf_ptr++)=='[')
531 /* component type of array */
545 /* save start of classname */
548 /* determine length of classname */
549 while ( *utf_ptr++ != ';' )
550 if (utf_ptr>=end_pos)
551 panic ("Missing ';' in objecttype-descriptor");
553 /* cause loading of referenced class */
554 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
558 panic ("Ill formed methodtype-descriptor");
563 panic ("Ill formed methodtype-descriptor");
566 /* exceeding characters */
567 if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
571 /******************* function checkmethoddescriptor ****************************
573 checks whether a method-descriptor is valid and aborts otherwise.
574 All referenced classes are inserted into the list of unloaded classes.
576 *******************************************************************************/
578 static void checkmethoddescriptor (utf *d)
580 char *utf_ptr = d->text; /* current position in utf text */
581 char *end_pos = utf_end(d); /* points behind utf string */
582 char *tstart; /* pointer to start of classname */
585 /* method descriptor must start with parenthesis */
586 if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
588 /* check arguments */
589 while ((c = *utf_ptr++) != ')') {
603 /* save start of classname */
606 /* determine length of classname */
607 while ( *utf_ptr++ != ';' )
608 if (utf_ptr>=end_pos)
609 panic ("Missing ';' in objecttype-descriptor");
611 /* cause loading of referenced class */
612 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
617 while ((ch = *utf_ptr++)=='[')
620 /* component type of array */
634 /* save start of classname */
637 /* determine length of classname */
638 while ( *utf_ptr++ != ';' )
639 if (utf_ptr>=end_pos)
640 panic ("Missing ';' in objecttype-descriptor");
642 /* cause loading of referenced class */
643 class_new ( utf_new(tstart, utf_ptr-tstart-1) );
647 panic ("Ill formed methodtype-descriptor");
652 panic ("Ill formed methodtype-descriptor");
656 /* check returntype */
658 /* returntype void */
659 if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
662 /* treat as field-descriptor */
663 checkfielddescriptor (utf_ptr,end_pos);
667 /******************** Function: buildarraydescriptor ***************************
669 creates a constant_arraydescriptor structure for the array type named by an
672 *******************************************************************************/
674 constant_arraydescriptor * buildarraydescriptor(char *utf_ptr, u4 namelen)
676 constant_arraydescriptor *d;
678 if (*utf_ptr++ != '[') panic ("Attempt to build arraydescriptor for non-array");
680 d = NEW (constant_arraydescriptor);
681 d -> objectclass = NULL;
682 d -> elementdescriptor = NULL;
685 count_const_pool_len += sizeof(constant_arraydescriptor);
689 case 'Z': d -> arraytype = ARRAYTYPE_BOOLEAN; break;
690 case 'B': d -> arraytype = ARRAYTYPE_BYTE; break;
691 case 'C': d -> arraytype = ARRAYTYPE_CHAR; break;
692 case 'D': d -> arraytype = ARRAYTYPE_DOUBLE; break;
693 case 'F': d -> arraytype = ARRAYTYPE_FLOAT; break;
694 case 'I': d -> arraytype = ARRAYTYPE_INT; break;
695 case 'J': d -> arraytype = ARRAYTYPE_LONG; break;
696 case 'S': d -> arraytype = ARRAYTYPE_SHORT; break;
699 d -> arraytype = ARRAYTYPE_ARRAY;
700 d -> elementdescriptor = buildarraydescriptor (utf_ptr, namelen-1);
704 d -> arraytype = ARRAYTYPE_OBJECT;
706 d -> objectclass = class_new ( utf_new(utf_ptr+1, namelen-3) );
707 d -> objectclass -> classUsed = 0; /* not used initially CO-RT */
714 /******************* Function: freearraydescriptor *****************************
716 removes a structure created by buildarraydescriptor from memory
718 *******************************************************************************/
720 static void freearraydescriptor (constant_arraydescriptor *d)
723 constant_arraydescriptor *n = d->elementdescriptor;
724 FREE (d, constant_arraydescriptor);
729 /*********************** Function: displayarraydescriptor *********************/
731 static void displayarraydescriptor (constant_arraydescriptor *d)
733 switch (d->arraytype) {
734 case ARRAYTYPE_BOOLEAN: printf ("boolean[]"); break;
735 case ARRAYTYPE_BYTE: printf ("byte[]"); break;
736 case ARRAYTYPE_CHAR: printf ("char[]"); break;
737 case ARRAYTYPE_DOUBLE: printf ("double[]"); break;
738 case ARRAYTYPE_FLOAT: printf ("float[]"); break;
739 case ARRAYTYPE_INT: printf ("int[]"); break;
740 case ARRAYTYPE_LONG: printf ("long[]"); break;
741 case ARRAYTYPE_SHORT: printf ("short[]"); break;
742 case ARRAYTYPE_ARRAY: displayarraydescriptor(d->elementdescriptor); printf("[]"); break;
743 case ARRAYTYPE_OBJECT: utf_display(d->objectclass->name); printf("[]"); break;
749 /******************************************************************************/
750 /************************** Functions for fields ****************************/
751 /******************************************************************************/
754 /************************ Function: field_load *********************************
756 Load everything about a class field from the class file and fill a
757 'fieldinfo' structure. For static fields, space in the data segment is
760 *******************************************************************************/
762 static void field_load (fieldinfo *f, classinfo *c)
767 f -> flags = suck_u2 (); /* ACC flags */
768 f -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* name of field */
769 f -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
770 f -> type = jtype = desc_to_type (f->descriptor); /* data type */
771 f -> offset = 0; /* offset from start of object */
774 case TYPE_INT: f->value.i = 0; break;
775 case TYPE_FLOAT: f->value.f = 0.0; break;
776 case TYPE_DOUBLE: f->value.d = 0.0; break;
777 case TYPE_ADDRESS: f->value.a = NULL;
778 heap_addreference (&(f->value.a)); /* make global reference (GC) */
782 f->value.l = 0; break;
784 f->value.l.low = 0; f->value.l.high = 0; break;
788 /* read attributes */
790 for (i=0; i<attrnum; i++) {
794 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
796 if ( aname != utf_constantvalue ) {
797 /* unknown attribute */
798 skipattributebody ();
801 /* constant value attribute */
803 /* skip attribute length */
805 /* index of value in constantpool */
808 /* initialize field with value from constantpool */
811 constant_integer *ci =
812 class_getconstant(c, pindex, CONSTANT_Integer);
813 f->value.i = ci -> value;
819 class_getconstant(c, pindex, CONSTANT_Long);
821 f->value.l = cl -> value;
827 class_getconstant(c, pindex, CONSTANT_Float);
829 f->value.f = cf->value;
834 constant_double *cd =
835 class_getconstant(c, pindex, CONSTANT_Double);
837 f->value.d = cd->value;
842 utf *u = class_getconstant(c, pindex, CONSTANT_String);
843 /* create javastring from compressed utf8-string */
844 f->value.a = literalstring_new(u);
849 log_text ("Invalid Constant - Type");
858 /********************** function: field_free **********************************/
860 static void field_free (fieldinfo *f)
866 /**************** Function: field_display (debugging only) ********************/
868 static void field_display (fieldinfo *f)
871 printflags (f -> flags);
873 utf_display (f -> name);
875 utf_display (f -> descriptor);
876 printf (" offset: %ld\n", (long int) (f -> offset) );
880 /******************************************************************************/
881 /************************* Functions for methods ******************************/
882 /******************************************************************************/
885 /*********************** Function: method_load *********************************
887 Loads a method from the class file and fills an existing 'methodinfo'
888 structure. For native methods, the function pointer field is set to the
889 real function pointer, for JavaVM methods a pointer to the compiler is used
892 *******************************************************************************/
894 static void method_load (methodinfo *m, classinfo *c)
904 m -> flags = suck_u2 ();
905 m -> name = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
906 m -> descriptor = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
909 m -> exceptiontable = NULL;
910 m -> entrypoint = NULL;
912 m -> stubroutine = NULL;
913 m -> methodUsed = 0; /* not used initially CO-RT*/
915 if (! (m->flags & ACC_NATIVE) ) {
916 m -> stubroutine = createcompilerstub (m);
920 functionptr f = native_findfunction
921 (c->name, m->name, m->descriptor, (m->flags & ACC_STATIC) != 0);
926 m -> stubroutine = createnativestub (f, m);
929 m -> stubroutine = oldcreatenativestub (f, m);
936 for (i=0; i<attrnum; i++) {
939 aname = class_getconstant (c, suck_u2(), CONSTANT_Utf8);
941 if ( aname != utf_code) {
942 skipattributebody ();
945 if (m -> jcode) panic ("Two code-attributes for one method!");
948 m -> maxstack = suck_u2();
949 m -> maxlocals = suck_u2();
950 m -> jcodelength = suck_u4();
951 m -> jcode = MNEW (u1, m->jcodelength);
952 suck_nbytes (m->jcode, m->jcodelength);
953 m -> exceptiontablelength = suck_u2 ();
954 m -> exceptiontable =
955 MNEW (exceptiontable, m->exceptiontablelength);
958 count_vmcode_len += m->jcodelength + 18;
959 count_extable_len += 8 * m->exceptiontablelength;
962 for (e=0; e < m->exceptiontablelength; e++) {
964 m -> exceptiontable[e].startpc = suck_u2();
965 m -> exceptiontable[e].endpc = suck_u2();
966 m -> exceptiontable[e].handlerpc = suck_u2();
969 if (!idx) m -> exceptiontable[e].catchtype = NULL;
971 m -> exceptiontable[e].catchtype =
972 class_getconstant (c, idx, CONSTANT_Class);
976 skipattributes ( suck_u2() );
983 /********************* Function: method_free ***********************************
985 frees all memory that was allocated for this method
987 *******************************************************************************/
989 static void method_free (methodinfo *m)
991 if (m->jcode) MFREE (m->jcode, u1, m->jcodelength);
992 if (m->exceptiontable)
993 MFREE (m->exceptiontable, exceptiontable, m->exceptiontablelength);
994 if (m->mcode) CFREE (m->mcode, m->mcodelength);
995 if (m->stubroutine) {
996 if (m->flags & ACC_NATIVE) removenativestub (m->stubroutine);
997 else removecompilerstub (m->stubroutine);
1002 /************** Function: method_display (debugging only) **************/
1004 void method_display (methodinfo *m)
1007 printflags (m -> flags);
1009 utf_display (m -> name);
1011 utf_display (m -> descriptor);
1016 /******************** Function: method_canoverwrite ****************************
1018 Check if m and old are identical with respect to type and name. This means
1019 that old can be overwritten with m.
1021 *******************************************************************************/
1023 static bool method_canoverwrite (methodinfo *m, methodinfo *old)
1025 if (m->name != old->name) return false;
1026 if (m->descriptor != old->descriptor) return false;
1027 if (m->flags & ACC_STATIC) return false;
1034 /******************************************************************************/
1035 /************************ Functions for class *********************************/
1036 /******************************************************************************/
1039 /******************** function: class_getconstant ******************************
1041 retrieves the value at position 'pos' of the constantpool of a class
1042 if the type of the value is other than 'ctype' the system is stopped
1044 *******************************************************************************/
1046 voidptr class_getconstant (classinfo *c, u4 pos, u4 ctype)
1048 /* invalid position in constantpool */
1049 if (pos >= c->cpcount)
1050 panic ("Attempt to access constant outside range");
1052 /* check type of constantpool entry */
1053 if (c->cptags[pos] != ctype) {
1054 sprintf (logtext, "Type mismatch on constant: %d requested, %d here",
1055 (int) ctype, (int) c->cptags[pos] );
1059 return c->cpinfos[pos];
1063 /********************* Function: class_constanttype ****************************
1065 Determines the type of a class entry in the ConstantPool
1067 *******************************************************************************/
1069 u4 class_constanttype (classinfo *c, u4 pos)
1071 if (pos >= c->cpcount)
1072 panic ("Attempt to access constant outside range");
1073 return c->cptags[pos];
1077 /******************** function: class_loadcpool ********************************
1079 loads the constantpool of a class,
1080 the entries are transformed into a simpler format
1081 by resolving references
1082 (a detailed overview of the compact structures can be found in global.h)
1084 *******************************************************************************/
1086 static void class_loadcpool (classinfo *c)
1089 /* The following structures are used to save information which cannot be
1090 processed during the first pass. After the complete constantpool has
1091 been traversed the references can be resolved.
1092 (only in specific order) */
1094 /* CONSTANT_Class_info entries */
1095 typedef struct forward_class {
1096 struct forward_class *next;
1101 /* CONSTANT_String */
1102 typedef struct forward_string {
1103 struct forward_string *next;
1108 /* CONSTANT_NameAndType */
1109 typedef struct forward_nameandtype {
1110 struct forward_nameandtype *next;
1114 } forward_nameandtype;
1116 /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
1117 typedef struct forward_fieldmethint {
1118 struct forward_fieldmethint *next;
1122 u2 nameandtype_index;
1123 } forward_fieldmethint;
1127 long int dumpsize = dump_size ();
1129 forward_class *forward_classes = NULL;
1130 forward_string *forward_strings = NULL;
1131 forward_nameandtype *forward_nameandtypes = NULL;
1132 forward_fieldmethint *forward_fieldmethints = NULL;
1134 /* number of entries in the constant_pool table */
1135 u4 cpcount = c -> cpcount = suck_u2();
1136 /* allocate memory */
1137 u1 *cptags = c -> cptags = MNEW (u1, cpcount);
1138 voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
1141 count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
1144 /* initialize constantpool */
1145 for (idx=0; idx<cpcount; idx++) {
1146 cptags[idx] = CONSTANT_UNUSED;
1147 cpinfos[idx] = NULL;
1151 /******* first pass *******/
1152 /* entries which cannot be resolved now are written into
1153 temporary structures and traversed again later */
1156 while (idx < cpcount) {
1157 /* get constant type */
1161 case CONSTANT_Class: {
1162 forward_class *nfc = DNEW(forward_class);
1164 nfc -> next = forward_classes;
1165 forward_classes = nfc;
1167 nfc -> thisindex = idx;
1168 /* reference to CONSTANT_NameAndType */
1169 nfc -> name_index = suck_u2 ();
1175 case CONSTANT_Fieldref:
1176 case CONSTANT_Methodref:
1177 case CONSTANT_InterfaceMethodref: {
1178 forward_fieldmethint *nff = DNEW (forward_fieldmethint);
1180 nff -> next = forward_fieldmethints;
1181 forward_fieldmethints = nff;
1183 nff -> thisindex = idx;
1186 /* class or interface type that contains the declaration of the field or method */
1187 nff -> class_index = suck_u2 ();
1188 /* name and descriptor of the field or method */
1189 nff -> nameandtype_index = suck_u2 ();
1195 case CONSTANT_String: {
1196 forward_string *nfs = DNEW (forward_string);
1198 nfs -> next = forward_strings;
1199 forward_strings = nfs;
1201 nfs -> thisindex = idx;
1202 /* reference to CONSTANT_Utf8_info with string characters */
1203 nfs -> string_index = suck_u2 ();
1209 case CONSTANT_NameAndType: {
1210 forward_nameandtype *nfn = DNEW (forward_nameandtype);
1212 nfn -> next = forward_nameandtypes;
1213 forward_nameandtypes = nfn;
1215 nfn -> thisindex = idx;
1216 /* reference to CONSTANT_Utf8_info containing simple name */
1217 nfn -> name_index = suck_u2 ();
1218 /* reference to CONSTANT_Utf8_info containing field or method descriptor */
1219 nfn -> sig_index = suck_u2 ();
1225 case CONSTANT_Integer: {
1226 constant_integer *ci = NEW (constant_integer);
1229 count_const_pool_len += sizeof(constant_integer);
1232 ci -> value = suck_s4 ();
1233 cptags [idx] = CONSTANT_Integer;
1240 case CONSTANT_Float: {
1241 constant_float *cf = NEW (constant_float);
1244 count_const_pool_len += sizeof(constant_float);
1247 cf -> value = suck_float ();
1248 cptags [idx] = CONSTANT_Float;
1254 case CONSTANT_Long: {
1255 constant_long *cl = NEW(constant_long);
1258 count_const_pool_len += sizeof(constant_long);
1261 cl -> value = suck_s8 ();
1262 cptags [idx] = CONSTANT_Long;
1268 case CONSTANT_Double: {
1269 constant_double *cd = NEW(constant_double);
1272 count_const_pool_len += sizeof(constant_double);
1275 cd -> value = suck_double ();
1276 cptags [idx] = CONSTANT_Double;
1282 case CONSTANT_Utf8: {
1284 /* number of bytes in the bytes array (not string-length) */
1285 u4 length = suck_u2();
1286 cptags [idx] = CONSTANT_Utf8;
1287 /* insert utf-string into the utf-symboltable */
1288 cpinfos [idx] = utf_new(classbuf_pos+1, length);
1289 /* skip bytes of the string */
1290 skip_nbytes(length);
1296 sprintf (logtext, "Unkown constant type: %d",(int) t);
1305 /* resolve entries in temporary structures */
1307 while (forward_classes) {
1309 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
1311 if ( (name->blength>0) && (name->text[0]=='[') ) {
1312 /* check validity of descriptor */
1313 checkfielddescriptor (name->text, utf_end(name));
1315 cptags [forward_classes -> thisindex] = CONSTANT_Arraydescriptor;
1316 cpinfos [forward_classes -> thisindex] =
1317 buildarraydescriptor(name->text, name->blength);
1321 cptags [forward_classes -> thisindex] = CONSTANT_Class;
1322 /* retrieve class from class-table */
1323 cpinfos [forward_classes -> thisindex] = class_new (name);
1325 forward_classes = forward_classes -> next;
1329 while (forward_strings) {
1331 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
1333 /* resolve utf-string */
1334 cptags [forward_strings -> thisindex] = CONSTANT_String;
1335 cpinfos [forward_strings -> thisindex] = text;
1337 forward_strings = forward_strings -> next;
1340 while (forward_nameandtypes) {
1341 constant_nameandtype *cn = NEW (constant_nameandtype);
1344 count_const_pool_len += sizeof(constant_nameandtype);
1347 /* resolve simple name and descriptor */
1348 cn -> name = class_getconstant
1349 (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
1350 cn -> descriptor = class_getconstant
1351 (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
1353 cptags [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
1354 cpinfos [forward_nameandtypes -> thisindex] = cn;
1356 forward_nameandtypes = forward_nameandtypes -> next;
1360 while (forward_fieldmethints) {
1361 constant_nameandtype *nat;
1362 constant_FMIref *fmi = NEW (constant_FMIref);
1365 count_const_pool_len += sizeof(constant_FMIref);
1367 /* resolve simple name and descriptor */
1368 nat = class_getconstant
1369 (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
1371 fmi -> class = class_getconstant
1372 (c, forward_fieldmethints -> class_index, CONSTANT_Class);
1373 fmi -> name = nat -> name;
1374 fmi -> descriptor = nat -> descriptor;
1376 cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
1377 cpinfos [forward_fieldmethints -> thisindex] = fmi;
1379 switch (forward_fieldmethints -> tag) {
1380 case CONSTANT_Fieldref: /* check validity of descriptor */
1381 checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
1383 case CONSTANT_InterfaceMethodref:
1384 case CONSTANT_Methodref: /* check validity of descriptor */
1385 checkmethoddescriptor (fmi->descriptor);
1389 forward_fieldmethints = forward_fieldmethints -> next;
1394 dump_release (dumpsize);
1398 /********************** Function: class_load ***********************************
1400 Loads everything interesting about a class from the class file. The
1401 'classinfo' structure must have been allocated previously.
1403 The super class and the interfaces implemented by this class need not be
1404 loaded. The link is set later by the function 'class_link'.
1406 The loaded class is removed from the list 'unloadedclasses' and added to
1407 the list 'unlinkedclasses'.
1409 *******************************************************************************/
1411 static int class_load (classinfo *c)
1417 count_class_loads++;
1420 /* output for debugging purposes */
1422 sprintf (logtext, "Loading class: ");
1423 utf_sprint (logtext+strlen(logtext), c->name );
1427 /* load classdata, throw exception on error */
1428 if (!suck_start (c->name)) {
1429 throw_classnotfoundexception();
1433 /* check signature */
1434 if (suck_u4() != MAGIC) panic("Can not find class-file signature");
1438 if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
1439 sprintf (logtext, "File version %d.%d is not supported",
1440 (int) ma, (int) mi);
1445 class_loadcpool (c);
1447 c -> classUsed = 0; /* not used initially CO-RT */
1450 c -> flags = suck_u2 ();
1454 /* retrieve superclass */
1455 if ( (i = suck_u2 () ) ) {
1456 c -> super = class_getconstant (c, i, CONSTANT_Class);
1462 /* retrieve interfaces */
1463 c -> interfacescount = suck_u2 ();
1464 c -> interfaces = MNEW (classinfo*, c -> interfacescount);
1465 for (i=0; i < c -> interfacescount; i++) {
1466 c -> interfaces [i] =
1467 class_getconstant (c, suck_u2(), CONSTANT_Class);
1471 c -> fieldscount = suck_u2 ();
1473 c -> fields = GCNEW (fieldinfo, c -> fieldscount);
1475 c -> fields = MNEW (fieldinfo, c -> fieldscount);
1477 for (i=0; i < c -> fieldscount; i++) {
1478 field_load (&(c->fields[i]), c);
1482 c -> methodscount = suck_u2 ();
1483 c -> methods = MNEW (methodinfo, c -> methodscount);
1484 for (i=0; i < c -> methodscount; i++) {
1485 method_load (&(c -> methods [i]), c);
1489 count_class_infos += sizeof(classinfo*) * c -> interfacescount;
1490 count_class_infos += sizeof(fieldinfo) * c -> fieldscount;
1491 count_class_infos += sizeof(methodinfo) * c -> methodscount;
1494 /* load variable-length attribute structures */
1495 attribute_load (suck_u2(), c);
1500 /* remove class from list of unloaded classes and
1501 add to list of unlinked classes */
1502 list_remove (&unloadedclasses, c);
1503 list_addlast (&unlinkedclasses, c);
1510 /************** internal Function: class_highestinterface ***********************
1512 Used by the function class_link to determine the amount of memory needed
1513 for the interface table.
1515 *******************************************************************************/
1517 static s4 class_highestinterface (classinfo *c)
1522 if ( ! (c->flags & ACC_INTERFACE) ) {
1523 sprintf (logtext, "Interface-methods count requested for non-interface: ");
1524 utf_sprint (logtext+strlen(logtext), c->name);
1529 for (i=0; i<c->interfacescount; i++) {
1530 s4 h2 = class_highestinterface (c->interfaces[i]);
1537 /* class_addinterface **********************************************************
1539 Is needed by class_link for adding a VTBL to a class. All interfaces
1540 implemented by ic are added as well.
1542 *******************************************************************************/
1544 static void class_addinterface (classinfo *c, classinfo *ic)
1548 vftbl *vftbl = c->vftbl;
1550 if (i >= vftbl->interfacetablelength)
1551 panic ("Inernal error: interfacetable overflow");
1552 if (vftbl->interfacetable[-i])
1555 if (ic->methodscount == 0) { /* fake entry needed for subtype test */
1556 vftbl->interfacevftbllength[i] = 1;
1557 vftbl->interfacetable[-i] = MNEW(methodptr, 1);
1558 vftbl->interfacetable[-i][0] = NULL;
1561 vftbl->interfacevftbllength[i] = ic->methodscount;
1562 vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
1565 count_vftbl_len += sizeof(methodptr) *
1566 (ic->methodscount + (ic->methodscount == 0));
1569 for (j=0; j<ic->methodscount; j++) {
1572 for (m = 0; m < sc->methodscount; m++) {
1573 methodinfo *mi = &(sc->methods[m]);
1574 if (method_canoverwrite(mi, &(ic->methods[j]))) {
1575 vftbl->interfacetable[-i][j] =
1576 vftbl->table[mi->vftblindex];
1586 for (j = 0; j < ic->interfacescount; j++)
1587 class_addinterface(c, ic->interfaces[j]);
1591 /********************** Function: class_link ***********************************
1593 Tries to link a class. The super class and every implemented interface must
1594 already have been linked. The function calculates the length in bytes that
1595 an instance of this class requires as well as the VTBL for methods and
1598 If the class can be linked, it is removed from the list 'unlinkedclasses'
1599 and added to 'linkedclasses'. Otherwise, it is moved to the end of
1602 Attention: If cyclical class definitions are encountered, the program gets
1603 into an infinite loop (we'll have to work that out)
1605 *******************************************************************************/
1607 static void class_link (classinfo *c)
1609 s4 supervftbllength; /* vftbllegnth of super class */
1610 s4 vftbllength; /* vftbllength of current class */
1611 s4 interfacetablelength; /* interface table length */
1612 classinfo *super = c->super; /* super class */
1613 classinfo *ic, *c2; /* intermediate class variables */
1614 vftbl *v; /* vftbl of current class */
1615 s4 i; /* interface/method/field counter */
1618 /* check if all superclasses are already linked, if not put c at end of
1619 unlinked list and return. Additionally initialize class fields. */
1621 /* check interfaces */
1623 for (i = 0; i < c->interfacescount; i++) {
1624 ic = c->interfaces[i];
1626 list_remove(&unlinkedclasses, c);
1627 list_addlast(&unlinkedclasses, c);
1632 /* check super class */
1634 if (super == NULL) { /* class java.long.Object */
1636 c->classUsed = 1; /* Object class is always used CO-RT*/
1637 c->instancesize = sizeof(java_objectheader);
1639 vftbllength = supervftbllength = 0;
1641 c->finalizer = NULL;
1644 if (!super->linked) {
1645 list_remove(&unlinkedclasses, c);
1646 list_addlast(&unlinkedclasses, c);
1650 if (c->flags & ACC_INTERFACE)
1651 c->index = interfaceindex++;
1653 c->index = super->index + 1;
1655 c->instancesize = super->instancesize;
1657 vftbllength = supervftbllength = super->vftbl->vftbllength;
1659 c->finalizer = super->finalizer;
1664 sprintf (logtext, "Linking Class: ");
1665 utf_sprint (logtext+strlen(logtext), c->name );
1669 /* compute vftbl length */
1671 for (i = 0; i < c->methodscount; i++) {
1672 methodinfo *m = &(c->methods[i]);
1674 if (!(m->flags & ACC_STATIC)) { /* is instance method */
1675 classinfo *sc = super;
1678 for (j = 0; j < sc->methodscount; j++) {
1679 if (method_canoverwrite(m, &(sc->methods[j]))) {
1680 m->vftblindex = sc->methods[j].vftblindex;
1681 goto foundvftblindex;
1686 m->vftblindex = (vftbllength++);
1692 count_vftbl_len += sizeof(vftbl) + sizeof(methodptr)*(vftbllength-1);
1695 /* compute interfacetable length */
1697 interfacetablelength = 0;
1700 for (i = 0; i < c2->interfacescount; i++) {
1701 s4 h = class_highestinterface (c2->interfaces[i]) + 1;
1702 if (h > interfacetablelength)
1703 interfacetablelength = h;
1708 /* allocate virtual function table */
1710 v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
1711 (vftbllength - 1) + sizeof(methodptr*) *
1712 (interfacetablelength - (interfacetablelength > 0)));
1713 v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
1714 (interfacetablelength > 1));
1715 c->header.vftbl = c->vftbl = v;
1717 v->vftbllength = vftbllength;
1718 v->interfacetablelength = interfacetablelength;
1720 /* copy virtual function table of super class */
1722 for (i = 0; i < supervftbllength; i++)
1723 v->table[i] = super->vftbl->table[i];
1725 /* add method stubs into virtual function table */
1727 for (i = 0; i < c->methodscount; i++) {
1728 methodinfo *m = &(c->methods[i]);
1729 if (!(m->flags & ACC_STATIC)) {
1730 v->table[m->vftblindex] = m->stubroutine;
1734 /* compute instance size and offset of each field */
1736 for (i = 0; i < c->fieldscount; i++) {
1738 fieldinfo *f = &(c->fields[i]);
1740 if (!(f->flags & ACC_STATIC) ) {
1741 dsize = desc_typesize (f->descriptor);
1742 c->instancesize = ALIGN (c->instancesize, dsize);
1743 f->offset = c->instancesize;
1744 c->instancesize += dsize;
1748 /* initialize interfacetable and interfacevftbllength */
1750 v->interfacevftbllength = MNEW (s4, interfacetablelength);
1753 count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
1756 for (i = 0; i < interfacetablelength; i++) {
1757 v->interfacevftbllength[i] = 0;
1758 v->interfacetable[-i] = NULL;
1761 /* add interfaces */
1763 for (c2 = c; c2 != NULL; c2 = c2->super)
1764 for (i = 0; i < c2->interfacescount; i++) {
1765 class_addinterface (c, c2->interfaces[i]);
1768 /* add finalizer method (not for java.lang.Object) */
1770 if (super != NULL) {
1772 static utf *finame = NULL;
1773 static utf *fidesc = NULL;
1776 finame = utf_finalize;
1778 fidesc = utf_fidesc;
1780 fi = class_findmethod (c, finame, fidesc);
1782 if (!(fi->flags & ACC_STATIC)) {
1792 list_remove (&unlinkedclasses, c);
1793 list_addlast (&linkedclasses, c);
1797 /******************* Function: class_freepool **********************************
1799 Frees all resources used by this classes Constant Pool.
1801 *******************************************************************************/
1803 static void class_freecpool (classinfo *c)
1809 for (idx=0; idx < c->cpcount; idx++) {
1810 tag = c->cptags[idx];
1811 info = c->cpinfos[idx];
1815 case CONSTANT_Fieldref:
1816 case CONSTANT_Methodref:
1817 case CONSTANT_InterfaceMethodref:
1818 FREE (info, constant_FMIref);
1820 case CONSTANT_Integer:
1821 FREE (info, constant_integer);
1823 case CONSTANT_Float:
1824 FREE (info, constant_float);
1827 FREE (info, constant_long);
1829 case CONSTANT_Double:
1830 FREE (info, constant_double);
1832 case CONSTANT_NameAndType:
1833 FREE (info, constant_nameandtype);
1835 case CONSTANT_Arraydescriptor:
1836 freearraydescriptor (info);
1842 MFREE (c -> cptags, u1, c -> cpcount);
1843 MFREE (c -> cpinfos, voidptr, c -> cpcount);
1847 /*********************** Function: class_free **********************************
1849 Frees all resources used by the class.
1851 *******************************************************************************/
1853 static void class_free (classinfo *c)
1858 class_freecpool (c);
1860 MFREE (c->interfaces, classinfo*, c->interfacescount);
1862 for (i = 0; i < c->fieldscount; i++)
1863 field_free(&(c->fields[i]));
1865 MFREE (c->fields, fieldinfo, c->fieldscount);
1868 for (i = 0; i < c->methodscount; i++)
1869 method_free(&(c->methods[i]));
1870 MFREE (c->methods, methodinfo, c->methodscount);
1872 if ((v = c->vftbl) != NULL) {
1873 for (i = 0; i < v->interfacetablelength; i++) {
1874 MFREE (v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
1876 MFREE (v->interfacevftbllength, s4, v->interfacetablelength);
1878 i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
1879 sizeof(methodptr*) * (v->interfacetablelength -
1880 (v->interfacetablelength > 0));
1881 v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
1882 (v->interfacetablelength > 1));
1886 if (c->innerclasscount)
1887 MFREE (c->innerclass, innerclassinfo, c->innerclasscount);
1890 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1));
1892 FREE (c, classinfo);
1895 /************************* Function: class_findfield ***************************
1897 Searches a 'classinfo' structure for a field having the given name and
1900 *******************************************************************************/
1903 fieldinfo *class_findfield (classinfo *c, utf *name, utf *desc)
1907 for (i = 0; i < c->fieldscount; i++) {
1908 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
1909 return &(c->fields[i]);
1912 panic ("Can not find field given in CONSTANT_Fieldref");
1917 /************************* Function: class_findmethod **************************
1919 Searches a 'classinfo' structure for a method having the given name and
1921 If type is NULL, it is ignored.
1923 *******************************************************************************/
1925 methodinfo *class_findmethod (classinfo *c, utf *name, utf *desc)
1928 for (i = 0; i < c->methodscount; i++) {
1929 if ((c->methods[i].name == name) && ((desc == NULL) ||
1930 (c->methods[i].descriptor == desc)))
1931 return &(c->methods[i]);
1936 /************************* Function: class_findmethod_approx ******************
1938 like class_findmethod but ignores the return value when comparing the
1941 *******************************************************************************/
1943 methodinfo *class_findmethod_approx (classinfo *c, utf *name, utf *desc)
1947 for (i = 0; i < c->methodscount; i++)
1948 if (c->methods[i].name == name) {
1949 utf *meth_descr = c->methods[i].descriptor;
1953 return &(c->methods[i]);
1955 if (desc->blength <= meth_descr->blength) {
1956 /* current position in utf text */
1957 char *desc_utf_ptr = desc->text;
1958 char *meth_utf_ptr = meth_descr->text;
1959 /* points behind utf strings */
1960 char *desc_end = utf_end(desc);
1961 char *meth_end = utf_end(meth_descr);
1964 /* compare argument types */
1965 while (desc_utf_ptr<desc_end && meth_utf_ptr<meth_end) {
1967 if ((ch=*desc_utf_ptr++) != (*meth_utf_ptr++))
1968 break; /* no match */
1971 return &(c->methods[i]); /* all parameter types equal */
1979 /***************** Function: class_resolvemethod_approx ***********************
1981 Searches a class and every super class for a method (without paying
1982 attention to the return value)
1984 *******************************************************************************/
1986 methodinfo *class_resolvemethod_approx (classinfo *c, utf *name, utf *desc)
1989 /* search for method (ignore returntype) */
1990 methodinfo *m = class_findmethod_approx (c, name, desc);
1993 /* search superclass */
2000 /************************* Function: class_resolvemethod ***********************
2002 Searches a class and every super class for a method.
2004 *******************************************************************************/
2007 methodinfo *class_resolvemethod (classinfo *c, utf *name, utf *desc)
2010 methodinfo *m = class_findmethod (c, name, desc);
2012 /* search superclass */
2020 /************************* Function: class_issubclass **************************
2022 Checks if sub is a descendant of super.
2024 *******************************************************************************/
2026 bool class_issubclass (classinfo *sub, classinfo *super)
2029 if (!sub) return false;
2030 if (sub==super) return true;
2037 /****************** Initialization function for classes ******************
2039 In Java, every class can have a static initialization function. This
2040 function has to be called BEFORE calling other methods or accessing static
2043 *******************************************************************************/
2046 extern int blockInts;
2049 void class_init (classinfo *c)
2052 java_objectheader *exceptionptr;
2056 if (!makeinitializations)
2060 c -> initialized = true;
2063 count_class_inits++;
2067 class_init (c->super);
2068 for (i=0; i < c->interfacescount; i++)
2069 class_init(c->interfaces[i]);
2071 m = class_findmethod (c, utf_clinit, utf_fidesc);
2074 sprintf (logtext, "Class ");
2075 utf_sprint (logtext+strlen(logtext), c->name);
2076 sprintf (logtext+strlen(logtext), " has no initializer");
2082 if (! (m->flags & ACC_STATIC))
2083 panic ("Class initializer is not static!");
2086 sprintf (logtext, "Starting initializer for class: ");
2087 utf_sprint (logtext+strlen(logtext), c->name);
2096 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2099 assert(blockInts == 0);
2104 printf ("#### Initializer of ");
2105 utf_display (c->name);
2106 printf (" has thrown: ");
2107 utf_display (exceptionptr->vftbl->class->name);
2113 sprintf (logtext, "Finished initializer for class: ");
2114 utf_sprint (logtext+strlen(logtext), c->name);
2118 if (c->name == utf_systemclass) {
2119 /* class java.lang.System requires explicit initialization */
2122 printf ("#### Initializing class System");
2124 /* find initializing method */
2125 m = class_findmethod (c,
2126 utf_initsystemclass,
2130 /* no method found */
2131 log("initializeSystemClass failed");
2140 exceptionptr = asm_calljavamethod (m, NULL,NULL,NULL,NULL);
2143 assert(blockInts == 0);
2148 printf ("#### initializeSystemClass has thrown: ");
2149 utf_display (exceptionptr->vftbl->class->name);
2159 /********* Function: class_showconstantpool (debugging only) *********/
2161 void class_showconstantpool (classinfo *c)
2166 printf ("---- dump of constant pool ----\n");
2168 for (i=0; i<c->cpcount; i++) {
2169 printf ("#%d: ", (int) i);
2171 e = c -> cpinfos [i];
2174 switch (c -> cptags [i]) {
2175 case CONSTANT_Class:
2176 printf ("Classreference -> ");
2177 utf_display ( ((classinfo*)e) -> name );
2180 case CONSTANT_Fieldref:
2181 printf ("Fieldref -> "); goto displayFMI;
2182 case CONSTANT_Methodref:
2183 printf ("Methodref -> "); goto displayFMI;
2184 case CONSTANT_InterfaceMethodref:
2185 printf ("InterfaceMethod -> "); goto displayFMI;
2188 constant_FMIref *fmi = e;
2189 utf_display ( fmi->class->name );
2191 utf_display ( fmi->name);
2193 utf_display ( fmi->descriptor );
2197 case CONSTANT_String:
2198 printf ("String -> ");
2201 case CONSTANT_Integer:
2202 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
2204 case CONSTANT_Float:
2205 printf ("Float -> %f", ((constant_float*)e) -> value);
2207 case CONSTANT_Double:
2208 printf ("Double -> %f", ((constant_double*)e) -> value);
2212 u8 v = ((constant_long*)e) -> value;
2214 printf ("Long -> %ld", (long int) v);
2216 printf ("Long -> HI: %ld, LO: %ld\n",
2217 (long int) v.high, (long int) v.low);
2221 case CONSTANT_NameAndType:
2222 { constant_nameandtype *cnt = e;
2223 printf ("NameAndType: ");
2224 utf_display (cnt->name);
2226 utf_display (cnt->descriptor);
2230 printf ("Utf8 -> ");
2233 case CONSTANT_Arraydescriptor: {
2234 printf ("Arraydescriptor: ");
2235 displayarraydescriptor (e);
2239 panic ("Invalid type of ConstantPool-Entry");
2251 /********** Function: class_showmethods (debugging only) *************/
2253 void class_showmethods (classinfo *c)
2257 printf ("--------- Fields and Methods ----------------\n");
2258 printf ("Flags: "); printflags (c->flags); printf ("\n");
2260 printf ("This: "); utf_display (c->name); printf ("\n");
2262 printf ("Super: "); utf_display (c->super->name); printf ("\n");
2264 printf ("Index: %d\n", c->index);
2266 printf ("interfaces:\n");
2267 for (i=0; i < c-> interfacescount; i++) {
2269 utf_display (c -> interfaces[i] -> name);
2270 printf (" (%d)\n", c->interfaces[i] -> index);
2273 printf ("fields:\n");
2274 for (i=0; i < c -> fieldscount; i++) {
2275 field_display (&(c -> fields[i]));
2278 printf ("methods:\n");
2279 for (i=0; i < c -> methodscount; i++) {
2280 methodinfo *m = &(c->methods[i]);
2281 if ( !(m->flags & ACC_STATIC))
2282 printf ("vftblindex: %d ", m->vftblindex);
2284 method_display ( m );
2288 printf ("Virtual function table:\n");
2289 for (i=0; i<c->vftbl->vftbllength; i++) {
2290 printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]) );
2297 /******************************************************************************/
2298 /******************* General functions for the class loader *******************/
2299 /******************************************************************************/
2301 static int loader_inited = 0;
2303 /********************* Function: loader_load ***********************************
2305 Loads and links the class desired class and each class and interface
2307 Returns: a pointer to this class
2309 *******************************************************************************/
2311 classinfo *loader_load (utf *topname)
2315 long int starttime=0,stoptime=0;
2317 intsDisable(); /* schani */
2320 starttime = getcputime();
2322 top = class_new (topname);
2325 while ( (c = list_first(&unloadedclasses)) ) {
2326 if (!class_load (c)) {
2327 list_remove (&unloadedclasses, c);
2333 while ( (c = list_first(&unlinkedclasses)) ) {
2338 loader_compute_subclasses();
2341 if (getloadingtime) {
2342 stoptime = getcputime();
2343 loadingtime += (stoptime-starttime);
2346 intsRestore(); /* schani */
2352 /**************** function: create_primitive_classes ***************************
2354 create classes representing primitive types
2356 ********************************************************************************/
2359 void create_primitive_classes()
2363 for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
2364 /* create primitive class */
2365 classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
2366 c -> classUsed = 0; /* not used initially CO-RT */
2368 /* prevent loader from loading primitive class */
2369 list_remove (&unloadedclasses, c);
2370 /* add to unlinked classes */
2371 list_addlast (&unlinkedclasses, c);
2372 c -> super = class_java_lang_Object;
2375 primitivetype_table[i].class_primitive = c;
2377 /* create class for wrapping the primitive type */
2378 primitivetype_table[i].class_wrap =
2379 class_new( utf_new_char(primitivetype_table[i].wrapname) );
2380 primitivetype_table[i].class_wrap -> classUsed = 0; /* not used initially CO-RT */
2384 /***************** function: create_array_class ********************************
2386 create class representing an array
2388 ********************************************************************************/
2391 classinfo *create_array_class(utf *u)
2393 classinfo *c = class_new (u);
2394 /* prevent loader from loading the array class */
2395 list_remove (&unloadedclasses, c);
2396 /* add to unlinked classes */
2397 list_addlast (&unlinkedclasses, c);
2398 c -> super = class_java_lang_Object;
2404 /********************** Function: loader_init **********************************
2406 Initializes all lists and loads all classes required for the system or the
2409 *******************************************************************************/
2416 list_init (&unloadedclasses, OFFSET(classinfo, listnode) );
2417 list_init (&unlinkedclasses, OFFSET(classinfo, listnode) );
2418 list_init (&linkedclasses, OFFSET(classinfo, listnode) );
2420 /* create utf-symbols for pointer comparison of frequently used strings */
2421 utf_innerclasses = utf_new_char("InnerClasses");
2422 utf_constantvalue = utf_new_char("ConstantValue");
2423 utf_code = utf_new_char("Code");
2424 utf_finalize = utf_new_char("finalize");
2425 utf_fidesc = utf_new_char("()V");
2426 utf_clinit = utf_new_char("<clinit>");
2427 utf_initsystemclass = utf_new_char("initializeSystemClass");
2428 utf_systemclass = utf_new_char("java/lang/System");
2430 /* create class for arrays */
2431 class_array = class_new ( utf_new_char ("The_Array_Class") );
2432 class_array -> classUsed = 0; /* not used initially CO-RT */
2434 list_remove (&unloadedclasses, class_array);
2436 /* create class for strings, load it after class Object was loaded */
2437 string_class = utf_new_char ("java/lang/String");
2438 class_java_lang_String = class_new(string_class);
2439 class_java_lang_String -> classUsed = 0; /* not used initially CO-RT */
2441 list_remove (&unloadedclasses, class_java_lang_String);
2443 class_java_lang_Object =
2444 loader_load ( utf_new_char ("java/lang/Object") );
2446 list_addlast(&unloadedclasses, class_java_lang_String);
2448 class_java_lang_String =
2449 loader_load ( string_class );
2450 class_java_lang_ClassCastException =
2451 loader_load ( utf_new_char ("java/lang/ClassCastException") );
2452 class_java_lang_NullPointerException =
2453 loader_load ( utf_new_char ("java/lang/NullPointerException") );
2454 class_java_lang_ArrayIndexOutOfBoundsException = loader_load (
2455 utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
2456 class_java_lang_NegativeArraySizeException = loader_load (
2457 utf_new_char ("java/lang/NegativeArraySizeException") );
2458 class_java_lang_OutOfMemoryError = loader_load (
2459 utf_new_char ("java/lang/OutOfMemoryError") );
2460 class_java_lang_ArrayStoreException =
2461 loader_load ( utf_new_char ("java/lang/ArrayStoreException") );
2462 class_java_lang_ArithmeticException =
2463 loader_load ( utf_new_char ("java/lang/ArithmeticException") );
2464 class_java_lang_ThreadDeath = /* schani */
2465 loader_load ( utf_new_char ("java/lang/ThreadDeath") );
2467 /* link class for arrays */
2468 list_addlast (&unlinkedclasses, class_array);
2469 class_array -> super = class_java_lang_Object;
2470 class_link (class_array);
2472 /* correct vftbl-entries (retarded loading of class java/lang/String) */
2473 stringtable_update();
2475 /* create classes representing primitive types */
2476 create_primitive_classes();
2478 proto_java_lang_ClassCastException =
2479 builtin_new(class_java_lang_ClassCastException);
2480 heap_addreference ( (void**) &proto_java_lang_ClassCastException);
2482 proto_java_lang_NullPointerException =
2483 builtin_new(class_java_lang_NullPointerException);
2484 heap_addreference ( (void**) &proto_java_lang_NullPointerException);
2486 proto_java_lang_ArrayIndexOutOfBoundsException =
2487 builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
2488 heap_addreference ( (void**) &proto_java_lang_ArrayIndexOutOfBoundsException);
2490 proto_java_lang_NegativeArraySizeException =
2491 builtin_new(class_java_lang_NegativeArraySizeException);
2492 heap_addreference ( (void**) &proto_java_lang_NegativeArraySizeException);
2494 proto_java_lang_OutOfMemoryError =
2495 builtin_new(class_java_lang_OutOfMemoryError);
2496 heap_addreference ( (void**) &proto_java_lang_OutOfMemoryError);
2498 proto_java_lang_ArithmeticException =
2499 builtin_new(class_java_lang_ArithmeticException);
2500 heap_addreference ( (void**) &proto_java_lang_ArithmeticException);
2502 proto_java_lang_ArrayStoreException =
2503 builtin_new(class_java_lang_ArrayStoreException);
2504 heap_addreference ( (void**) &proto_java_lang_ArrayStoreException);
2506 proto_java_lang_ThreadDeath = /* schani */
2507 builtin_new(class_java_lang_ThreadDeath);
2508 heap_addreference ( (void**) &proto_java_lang_ThreadDeath);
2516 /********************* Function: loader_initclasses ****************************
2518 Initializes all loaded but uninitialized classes
2520 *******************************************************************************/
2522 void loader_initclasses ()
2526 intsDisable(); /* schani */
2528 if (makeinitializations) {
2529 c = list_first (&linkedclasses);
2532 c = list_next (&linkedclasses, c);
2536 intsRestore(); /* schani */
2539 static s4 classvalue;
2541 static void loader_compute_class_values (classinfo *c)
2545 c->vftbl->baseval = ++classvalue;
2547 while (subs != NULL) {
2548 loader_compute_class_values(subs);
2549 subs = subs->nextsub;
2551 c->vftbl->diffval = classvalue - c->vftbl->baseval;
2555 for (i = 0; i < c->index; i++)
2557 printf("%3d %3d ", (int) c->vftbl->baseval, c->vftbl->diffval);
2558 utf_display(c->name);
2565 void loader_compute_subclasses ()
2569 intsDisable(); /* schani */
2571 c = list_first (&linkedclasses);
2573 if (!(c->flags & ACC_INTERFACE)) {
2577 c = list_next (&linkedclasses, c);
2580 c = list_first (&linkedclasses);
2582 if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
2583 c->nextsub = c->super->sub;
2586 c = list_next (&linkedclasses, c);
2590 loader_compute_class_values(class_java_lang_Object);
2592 intsRestore(); /* schani */
2597 /******************** function classloader_buffer ******************************
2599 sets buffer for reading classdata
2601 *******************************************************************************/
2603 void classload_buffer(u1 *buf, int len)
2606 classbuffer_size = len;
2607 classbuf_pos = buf - 1;
2611 /******************** Function: loader_close ***********************************
2615 *******************************************************************************/
2617 void loader_close ()
2621 while ( (c=list_first(&unloadedclasses)) ) {
2622 list_remove (&unloadedclasses,c);
2625 while ( (c=list_first(&unlinkedclasses)) ) {
2626 list_remove (&unlinkedclasses,c);
2629 while ( (c=list_first(&linkedclasses)) ) {
2630 list_remove (&linkedclasses,c);
2637 * These are local overrides for various environment variables in Emacs.
2638 * Please do not remove this and leave it at the end of the file, where
2639 * Emacs will automagically detect them.
2640 * ---------------------------------------------------------------------
2643 * indent-tabs-mode: t